From 4bfa263e38811b164f080ae6516e32c9387fe6cc Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 15 Apr 2021 17:17:38 +0800 Subject: [PATCH 001/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index f80c88110..52e3867a4 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -229,7 +229,7 @@ svn co https://github.com/immortalwrt/luci/branches/openwrt-18.06/applications/l svn co https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/lean/luci-app-ssr-plus rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans pushd package/lean -#wget -qO - https://patch-diff.githubusercontent.com/raw/fw876/helloworld/pull/473.patch | patch -p1 +wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/101b1d9.patch | patch -p1 popd pushd package/lean/luci-app-ssr-plus sed -i 's,default n,default y,g' Makefile From b0af263c86f1abb6629b261392bc871f8252f74d Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 15 Apr 2021 22:37:43 +0800 Subject: [PATCH 002/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 52e3867a4..a8966fa79 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -230,6 +230,7 @@ svn co https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/lean/ rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans pushd package/lean wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/101b1d9.patch | patch -p1 +wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/6dc760f.patch | patch -p1 popd pushd package/lean/luci-app-ssr-plus sed -i 's,default n,default y,g' Makefile From 54d955671692ae1e9b484c4da28e9b433b36ee7f Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 15 Apr 2021 23:15:19 +0800 Subject: [PATCH 003/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index a8966fa79..4be239d80 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -229,8 +229,8 @@ svn co https://github.com/immortalwrt/luci/branches/openwrt-18.06/applications/l svn co https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/lean/luci-app-ssr-plus rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans pushd package/lean -wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/101b1d9.patch | patch -p1 -wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/6dc760f.patch | patch -p1 +wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/72bee5e.patch | patch -p1 +wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/deacdd3.patch | patch -p1 popd pushd package/lean/luci-app-ssr-plus sed -i 's,default n,default y,g' Makefile From c0e7bd41887f472cdf3ab3fe2142f20f4bdb3b38 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 15 Apr 2021 23:49:32 +0800 Subject: [PATCH 004/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 4be239d80..d552a05d3 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -229,8 +229,8 @@ svn co https://github.com/immortalwrt/luci/branches/openwrt-18.06/applications/l svn co https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/lean/luci-app-ssr-plus rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans pushd package/lean -wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/72bee5e.patch | patch -p1 -wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/deacdd3.patch | patch -p1 +wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/b1130e9.patch | patch -p1 +wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/cc37231.patch | patch -p1 popd pushd package/lean/luci-app-ssr-plus sed -i 's,default n,default y,g' Makefile From 318d087e568e57f9bdd181add50fbbabbfb8ecab Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 16 Apr 2021 00:09:51 +0800 Subject: [PATCH 005/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index d552a05d3..e193dfd64 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -229,8 +229,8 @@ svn co https://github.com/immortalwrt/luci/branches/openwrt-18.06/applications/l svn co https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/lean/luci-app-ssr-plus rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans pushd package/lean -wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/b1130e9.patch | patch -p1 -wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/cc37231.patch | patch -p1 +wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/b1a2d3c.patch | patch -p1 +wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/c1674ad.patch | patch -p1 popd pushd package/lean/luci-app-ssr-plus sed -i 's,default n,default y,g' Makefile From 94f8a93b0d2e992962bbb8a761fc3ee7379656f1 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 16 Apr 2021 11:16:05 +0800 Subject: [PATCH 006/244] Update R4S-OpenWrt.yml --- .github/workflows/R4S-OpenWrt.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/R4S-OpenWrt.yml b/.github/workflows/R4S-OpenWrt.yml index 17fd905b1..638bdb367 100644 --- a/.github/workflows/R4S-OpenWrt.yml +++ b/.github/workflows/R4S-OpenWrt.yml @@ -87,12 +87,12 @@ jobs: run: | df -h cd openwrt - make download -j10 + make download -j250 - name: Make Toolchain run: | df -h cd openwrt - let make_process=$(nproc)+1 + let make_process=$(nproc)+2 make toolchain/install -j${make_process} V=s - name: Compile Openwrt id: compileopenwrt From ed83571511cb71d34f557e5965befab5cc515d15 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 16 Apr 2021 11:16:30 +0800 Subject: [PATCH 007/244] Update R2S-OpenWrt.yml --- .github/workflows/R2S-OpenWrt.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/R2S-OpenWrt.yml b/.github/workflows/R2S-OpenWrt.yml index 276b4c656..6f57ffd14 100644 --- a/.github/workflows/R2S-OpenWrt.yml +++ b/.github/workflows/R2S-OpenWrt.yml @@ -87,7 +87,7 @@ jobs: run: | df -h cd openwrt - make download -j10 + make download -j250 - name: Make Toolchain run: | df -h @@ -100,7 +100,7 @@ jobs: run: | df -h cd openwrt - let Make_Process=$(nproc)+1 + let Make_Process=$(nproc)+2 make -j${Make_Process} V=w echo $? - name: If Error From 88471a3ea09fcd9759000aedb34c19994b9f6ac5 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 16 Apr 2021 11:16:59 +0800 Subject: [PATCH 008/244] Update X86-OpenWrt.yml --- .github/workflows/X86-OpenWrt.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/X86-OpenWrt.yml b/.github/workflows/X86-OpenWrt.yml index 32b4778aa..e7f21a9a0 100644 --- a/.github/workflows/X86-OpenWrt.yml +++ b/.github/workflows/X86-OpenWrt.yml @@ -87,12 +87,12 @@ jobs: run: | df -h cd openwrt - make download -j10 + make download -j250 - name: Make Toolchain run: | df -h cd openwrt - let make_process=$(nproc)+1 + let make_process=$(nproc)+2 make toolchain/install -j${make_process} V=s - name: Compile Openwrt id: compileopenwrt @@ -100,7 +100,7 @@ jobs: run: | df -h cd openwrt - let Make_Process=$(nproc)+1 + let Make_Process=$(nproc)+2 make -j${Make_Process} V=w echo $? - name: If Error From fa7e350cd85211b6d3338b031876badaac615192 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 16 Apr 2021 11:17:18 +0800 Subject: [PATCH 009/244] Update R4S-OpenWrt.yml --- .github/workflows/R4S-OpenWrt.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/R4S-OpenWrt.yml b/.github/workflows/R4S-OpenWrt.yml index 638bdb367..bc872e182 100644 --- a/.github/workflows/R4S-OpenWrt.yml +++ b/.github/workflows/R4S-OpenWrt.yml @@ -100,7 +100,7 @@ jobs: run: | df -h cd openwrt - let Make_Process=$(nproc)+1 + let Make_Process=$(nproc)+2 make -j${Make_Process} V=w echo $? - name: If Error From c9666763f61448e6f414c72979c84de4c5fcc3f6 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 16 Apr 2021 11:17:37 +0800 Subject: [PATCH 010/244] Update R2S-OpenWrt.yml --- .github/workflows/R2S-OpenWrt.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/R2S-OpenWrt.yml b/.github/workflows/R2S-OpenWrt.yml index 6f57ffd14..fba70009f 100644 --- a/.github/workflows/R2S-OpenWrt.yml +++ b/.github/workflows/R2S-OpenWrt.yml @@ -92,7 +92,7 @@ jobs: run: | df -h cd openwrt - let make_process=$(nproc)+1 + let make_process=$(nproc)+2 make toolchain/install -j${make_process} V=s - name: Compile Openwrt id: compileopenwrt From 882f72e5df427c8b9f5fff3b12702c976b5959e0 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 16 Apr 2021 11:26:40 +0800 Subject: [PATCH 011/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index e193dfd64..c637820b6 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -18,6 +18,7 @@ rm -rf ./include/download.mk wget -P scripts/ https://github.com/immortalwrt/immortalwrt/raw/master/scripts/download.pl wget -P include/ https://github.com/immortalwrt/immortalwrt/raw/master/include/download.mk wget -P include/ https://github.com/immortalwrt/immortalwrt/raw/master/include/package-immortalwrt.mk +sed -i '/unshift/d' scripts/download.pl #临时补丁 #wget -qO - https://github.com/openwrt/openwrt/commit/7fae64.patch | patch -p1 From bf24d90f357c535f590031666222b50a3f7168a0 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 16 Apr 2021 11:40:19 +0800 Subject: [PATCH 012/244] Update R2S-OpenWrt.yml --- .github/workflows/R2S-OpenWrt.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/R2S-OpenWrt.yml b/.github/workflows/R2S-OpenWrt.yml index fba70009f..499d70c68 100644 --- a/.github/workflows/R2S-OpenWrt.yml +++ b/.github/workflows/R2S-OpenWrt.yml @@ -87,7 +87,7 @@ jobs: run: | df -h cd openwrt - make download -j250 + make download -j50 - name: Make Toolchain run: | df -h From a4b68a773b06bb81edaa02f4cf2d634256ead29f Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 16 Apr 2021 11:40:35 +0800 Subject: [PATCH 013/244] Update R4S-OpenWrt.yml --- .github/workflows/R4S-OpenWrt.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/R4S-OpenWrt.yml b/.github/workflows/R4S-OpenWrt.yml index bc872e182..4d96d47cd 100644 --- a/.github/workflows/R4S-OpenWrt.yml +++ b/.github/workflows/R4S-OpenWrt.yml @@ -87,7 +87,7 @@ jobs: run: | df -h cd openwrt - make download -j250 + make download -j50 - name: Make Toolchain run: | df -h From 4ebf5d891bb619468154c3e2ea86f5bb0cae6dce Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 16 Apr 2021 11:40:52 +0800 Subject: [PATCH 014/244] Update X86-OpenWrt.yml --- .github/workflows/X86-OpenWrt.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/X86-OpenWrt.yml b/.github/workflows/X86-OpenWrt.yml index e7f21a9a0..aba4e2c08 100644 --- a/.github/workflows/X86-OpenWrt.yml +++ b/.github/workflows/X86-OpenWrt.yml @@ -87,7 +87,7 @@ jobs: run: | df -h cd openwrt - make download -j250 + make download -j50 - name: Make Toolchain run: | df -h From c1db3e30c0972e5f71acdf80b90566e146ebb2ee Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 16 Apr 2021 15:12:37 +0800 Subject: [PATCH 015/244] Update config.seed --- SEED/R2S/config.seed | 1 + 1 file changed, 1 insertion(+) diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 0cd0e0145..4852ae236 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -10,6 +10,7 @@ CONFIG_TARGET_ROOTFS_PARTSIZE=864 ### AGGRESSIVE ### CONFIG_PACKAGE_node=y CONFIG_NODEJS_14=y +CONFIG_NODEJS_ICU_NONE=y CONFIG_DEVEL=y CONFIG_TOOLCHAINOPTS=y CONFIG_GCC_USE_VERSION_9=y From fa05fb2b4dd374ad243a73f4bd5c7e10961c4a5e Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 16 Apr 2021 15:12:54 +0800 Subject: [PATCH 016/244] Update config.seed --- SEED/R4S/config.seed | 1 + 1 file changed, 1 insertion(+) diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index 338bffaa6..727b07408 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -10,6 +10,7 @@ CONFIG_TARGET_ROOTFS_PARTSIZE=864 ### AGGRESSIVE ### CONFIG_PACKAGE_node=y CONFIG_NODEJS_14=y +CONFIG_NODEJS_ICU_NONE=y CONFIG_DEVEL=y CONFIG_TOOLCHAINOPTS=y CONFIG_GCC_USE_VERSION_9=y From 8e06f3366ecb03479acfd2752d5790fb5704396a Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 16 Apr 2021 15:13:33 +0800 Subject: [PATCH 017/244] Update config.seed --- SEED/X86/config.seed | 1 + 1 file changed, 1 insertion(+) diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index 58685ac06..7a20f4a60 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -11,6 +11,7 @@ CONFIG_GRUB_TIMEOUT="0" ### AGGRESSIVE ### CONFIG_PACKAGE_node=y CONFIG_NODEJS_14=y +CONFIG_NODEJS_ICU_NONE=y CONFIG_DEVEL=y CONFIG_TOOLCHAINOPTS=y CONFIG_GCC_USE_VERSION_9=y From e0201b917c186205079cee134975d55bee77579c Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sat, 17 Apr 2021 01:15:19 +0800 Subject: [PATCH 018/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index c637820b6..bb981b204 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -230,7 +230,7 @@ svn co https://github.com/immortalwrt/luci/branches/openwrt-18.06/applications/l svn co https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/lean/luci-app-ssr-plus rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans pushd package/lean -wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/b1a2d3c.patch | patch -p1 +#wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/b1a2d3c.patch | patch -p1 wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/c1674ad.patch | patch -p1 popd pushd package/lean/luci-app-ssr-plus From da7a8d876bda7056869f239ca999f4b3b927b93b Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sun, 18 Apr 2021 17:48:17 +0800 Subject: [PATCH 019/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index bb981b204..a89bda46b 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -261,7 +261,8 @@ svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/simple-obfs packa svn co https://github.com/coolsnowwolf/packages/trunk/net/shadowsocks-libev package/lean/shadowsocks-libev svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/trojan package/lean/trojan svn co https://github.com/fw876/helloworld/trunk/naiveproxy package/lean/naiveproxy -svn co https://github.com/fw876/helloworld/trunk/shadowsocks-rust package/lean/shadowsocks-rust +svn co https://github.com/immortalwrt/packages/trunk/net/shadowsocks-rust package/lean/shadowsocks-rust +#svn co https://github.com/fw876/helloworld/trunk/shadowsocks-rust package/lean/shadowsocks-rust # 订阅转换 svn co https://github.com/immortalwrt/packages/trunk/net/subconverter package/new/subconverter svn co https://github.com/immortalwrt/packages/trunk/libs/jpcre2 package/new/jpcre2 From b3a030fc5c1143bf9dcc7d9fb606cad7bd2b879d Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 20 Apr 2021 10:21:25 +0800 Subject: [PATCH 020/244] Update 01_get_ready.sh --- SCRIPTS/01_get_ready.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/SCRIPTS/01_get_ready.sh b/SCRIPTS/01_get_ready.sh index f818b5773..57b5834cb 100644 --- a/SCRIPTS/01_get_ready.sh +++ b/SCRIPTS/01_get_ready.sh @@ -1,6 +1,5 @@ #!/bin/bash -<<'COMMENT' latest_release="$(curl -s https://github.com/openwrt/openwrt/releases |grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" |sed -n '/21/p' |sed -n 1p)" curl -LO "https://github.com/openwrt/openwrt/archive/${latest_release}" mkdir openwrt_back @@ -18,10 +17,9 @@ cp -f ./openwrt_back/package/base-files/image-config.in ./openwrt_new/package/ba cp -rf ./openwrt_back/target/linux/* ./openwrt_new/target/linux/ mkdir openwrt cp -rf ./openwrt_new/* ./openwrt/ -COMMENT # 获取源代码 -git clone --single-branch -b openwrt-21.02 https://github.com/openwrt/openwrt openwrt +#git clone --single-branch -b openwrt-21.02 https://github.com/openwrt/openwrt openwrt git clone -b main --depth 1 https://github.com/Lienol/openwrt.git openwrt-lienol git clone -b main --depth 1 https://github.com/Lienol/openwrt-packages packages-lienol git clone -b main --depth 1 https://github.com/Lienol/openwrt-luci luci-lienol From dad8ea60e136a050e9c999e10a880030884a31ac Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 20 Apr 2021 10:24:16 +0800 Subject: [PATCH 021/244] Update 02_target_only.sh --- SCRIPTS/R2S/02_target_only.sh | 7 ------- 1 file changed, 7 deletions(-) diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index 46b4dc756..e78b0e63b 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -49,18 +49,11 @@ cp -rf ../PATCH/duplicate/addition-trans-zh ./package/lean/lean-translate rm -rf ./package/kernel/linux/modules/video.mk wget -P package/kernel/linux/modules/ https://github.com/immortalwrt/immortalwrt/raw/master/package/kernel/linux/modules/video.mk -<<'COMMENT' #Vermagic latest_version="$(curl -s https://github.com/openwrt/openwrt/releases |grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" |sed -n '/21/p' |sed -n 1p |sed 's/v//g' |sed 's/.tar.gz//g')" wget https://downloads.openwrt.org/releases/${latest_version}/targets/rockchip/armv8/packages/Packages.gz zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' > .vermagic sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic/' include/kernel-defaults.mk -COMMENT - -# 对齐内核 Vermagic -wget https://downloads.openwrt.org/releases/21.02-SNAPSHOT/targets/rockchip/armv8/packages/Packages.gz -zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' > .vermagic -sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic/' include/kernel-defaults.mk # 内核加解密组件 echo ' From 0923a6e8e647b4b2cb4e5c231087e82ec5735f67 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 20 Apr 2021 10:24:45 +0800 Subject: [PATCH 022/244] Update 02_target_only.sh --- SCRIPTS/R4S/02_target_only.sh | 7 ------- 1 file changed, 7 deletions(-) diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index a745e10eb..5c0881645 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -60,18 +60,11 @@ CONFIG_CRYPTO_NHPOLY1305_NEON=y CONFIG_CRYPTO_AES_ARM64_BS=y ' >> ./target/linux/rockchip/armv8/config-5.4 -<<'COMMENT' #Vermagic latest_version="$(curl -s https://github.com/openwrt/openwrt/releases |grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" |sed -n '/21/p' |sed -n 1p |sed 's/v//g' |sed 's/.tar.gz//g')" wget https://downloads.openwrt.org/releases/${latest_version}/targets/rockchip/armv8/packages/Packages.gz zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' > .vermagic sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic/' include/kernel-defaults.mk -COMMENT - -# 对齐内核 Vermagic -wget https://downloads.openwrt.org/releases/21.02-SNAPSHOT/targets/rockchip/armv8/packages/Packages.gz -zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' > .vermagic -sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic/' include/kernel-defaults.mk # 预配置一些插件 cp -rf ../PATCH/R4S/files ./files From 3322b4bea9c43a695f50e8aff44aed0ff64c1b2b Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 20 Apr 2021 10:25:10 +0800 Subject: [PATCH 023/244] Update 02_target_only.sh --- SCRIPTS/X86/02_target_only.sh | 7 ------- 1 file changed, 7 deletions(-) diff --git a/SCRIPTS/X86/02_target_only.sh b/SCRIPTS/X86/02_target_only.sh index d70fa23f9..a80a86855 100644 --- a/SCRIPTS/X86/02_target_only.sh +++ b/SCRIPTS/X86/02_target_only.sh @@ -11,18 +11,11 @@ sed -i '/Rust:/d' package/lean/luci-app-ssr-plus/Makefile sed -i '/Rust:/d' package/new/luci-app-passwall/Makefile sed -i '/Rust:/d' package/lean/luci-app-vssr/Makefile -<<'COMMENT' #Vermagic latest_version="$(curl -s https://github.com/openwrt/openwrt/releases |grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" |sed -n '/21/p' |sed -n 1p |sed 's/v//g' |sed 's/.tar.gz//g')" wget https://downloads.openwrt.org/releases/${latest_version}/targets/x86/64/packages/Packages.gz zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' > .vermagic sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic/' include/kernel-defaults.mk -COMMENT - -# 对齐内核 Vermagic -wget https://downloads.openwrt.org/releases/21.02-SNAPSHOT/targets/x86/64/packages/Packages.gz -zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' > .vermagic -sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic/' include/kernel-defaults.mk # 预配置一些插件 cp -rf ../PATCH/X86/files ./files From 71d32b19ee33e4050d5d8479f7707704ea2b974f Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 20 Apr 2021 10:25:56 +0800 Subject: [PATCH 024/244] Update zzz-default-settings --- PATCH/duplicate/addition-trans-zh/files/zzz-default-settings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings b/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings index b349102b1..53e74068a 100644 --- a/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings +++ b/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings @@ -15,7 +15,7 @@ uci set shadowsocksr.@global[0].chnroute_url='https://cdn.jsdelivr.net/gh/QiuSim uci commit shadowsocksr #Feeds 更换镜像源 -sed -i 's,21.02,21.02-SNAPSHOT,g' /etc/opkg/distfeeds.conf +#sed -i 's,21.02,21.02-SNAPSHOT,g' /etc/opkg/distfeeds.conf sed -i 's,downloads.openwrt.org,mirror.sjtu.edu.cn/openwrt,g' /etc/opkg/distfeeds.conf #uhttpd 设置 From 1bac03e32445d99cb368c3103100679f31d569a7 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 21 Apr 2021 14:01:46 +0800 Subject: [PATCH 025/244] Update R2S-OpenWrt.yml --- .github/workflows/R2S-OpenWrt.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/R2S-OpenWrt.yml b/.github/workflows/R2S-OpenWrt.yml index 499d70c68..4c547fd02 100644 --- a/.github/workflows/R2S-OpenWrt.yml +++ b/.github/workflows/R2S-OpenWrt.yml @@ -1,8 +1,8 @@ name: R2S-OpenWrt on: - schedule: - - cron: 5 6 * * 0 +# schedule: +# - cron: 5 6 * * 0 watch: types: started From 776dbde319399aaf767429ccb866e0526d22c69b Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 21 Apr 2021 14:02:02 +0800 Subject: [PATCH 026/244] Update R4S-OpenWrt.yml --- .github/workflows/R4S-OpenWrt.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/R4S-OpenWrt.yml b/.github/workflows/R4S-OpenWrt.yml index 4d96d47cd..7782394bf 100644 --- a/.github/workflows/R4S-OpenWrt.yml +++ b/.github/workflows/R4S-OpenWrt.yml @@ -1,8 +1,8 @@ name: R4S-OpenWrt on: - schedule: - - cron: 5 6 * * 0 +# schedule: +# - cron: 5 6 * * 0 watch: types: started From 33ae76b15035360a21ca32e93a8c7c45553bf428 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 21 Apr 2021 14:02:25 +0800 Subject: [PATCH 027/244] Update X86-OpenWrt.yml --- .github/workflows/X86-OpenWrt.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/X86-OpenWrt.yml b/.github/workflows/X86-OpenWrt.yml index aba4e2c08..00b317a00 100644 --- a/.github/workflows/X86-OpenWrt.yml +++ b/.github/workflows/X86-OpenWrt.yml @@ -1,8 +1,8 @@ name: X86-OpenWrt on: - schedule: - - cron: 5 6 * * 0 +# schedule: +# - cron: 5 6 * * 0 watch: types: started From 4c97f4ee56e24b81578bd90af056157db82ec4ef Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 21 Apr 2021 14:03:21 +0800 Subject: [PATCH 028/244] Update Cleaning.yml --- .github/workflows/Cleaning.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Cleaning.yml b/.github/workflows/Cleaning.yml index 81ff7d5f6..de378b72b 100644 --- a/.github/workflows/Cleaning.yml +++ b/.github/workflows/Cleaning.yml @@ -28,7 +28,7 @@ jobs: uses: kolpav/purge-artifacts-action@master with: token: ${{ github.token }} - expire-in: 7d + expire-in: 3d Cleanup-Workflow-Logs: runs-on: ubuntu-20.04 @@ -39,4 +39,4 @@ jobs: with: token: ${{ github.token }} repository: ${{ github.repository }} - retain_days: 7 + retain_days: 3 From 4211994b998b1cbc2d2dcf4071591bef0ba55e82 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 21 Apr 2021 16:45:44 +0800 Subject: [PATCH 029/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index a89bda46b..cfc265a0f 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -19,6 +19,7 @@ wget -P scripts/ https://github.com/immortalwrt/immortalwrt/raw/master/scripts/d wget -P include/ https://github.com/immortalwrt/immortalwrt/raw/master/include/download.mk wget -P include/ https://github.com/immortalwrt/immortalwrt/raw/master/include/package-immortalwrt.mk sed -i '/unshift/d' scripts/download.pl +sed -i '/mirror02/d' scripts/download.pl #临时补丁 #wget -qO - https://github.com/openwrt/openwrt/commit/7fae64.patch | patch -p1 @@ -221,9 +222,7 @@ svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-ramfree git clone -b master --depth 1 https://github.com/tty228/luci-app-serverchan.git package/new/luci-app-serverchan # SmartDNS rm -rf ./feeds/packages/net/smartdns -mkdir package/new/smartdns -wget -P package/new/smartdns/ https://github.com/HiGarfield/lede-17.01.4-Mod/raw/master/package/extra/smartdns/Makefile -sed -i 's,files/etc/config,$(PKG_BUILD_DIR)/package/openwrt/files/etc/config,g' ./package/new/smartdns/Makefile +svn co https://github.com/Lienol/openwrt-packages/trunk/net/smartdns feeds/packages/net/smartdns rm -rf ./feeds/luci/applications/luci-app-smartdns svn co https://github.com/immortalwrt/luci/branches/openwrt-18.06/applications/luci-app-smartdns feeds/luci/applications/luci-app-smartdns # ShadowsocksR Plus+ From 283ee8e4e94a90c43744458aec59561200509c10 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 21 Apr 2021 18:00:17 +0800 Subject: [PATCH 030/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index cfc265a0f..34c0f4199 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -143,7 +143,8 @@ git clone --depth 1 https://github.com/small-5/ddns-scripts-aliyun package/lean/ svn co https://github.com/openwrt/packages/branches/openwrt-18.06/net/ddns-scripts feeds/packages/net/ddns-scripts svn co https://github.com/openwrt/luci/branches/openwrt-18.06/applications/luci-app-ddns feeds/luci/applications/luci-app-ddns svn co https://github.com/QiuSimons/OpenWrt_luci-app/trunk/others/luci-app-tencentddns package/lean/luci-app-tencentddns -svn co https://github.com/kenzok8/openwrt-packages/trunk/luci-app-aliddns package/new/luci-app-aliddns +svn co https://github.com/kenzok8/openwrt-packages/trunk/luci-app-aliddns feeds/luci/applications/luci-app-aliddns +ln -sf ../../../feeds/luci/applications/luci-app-aliddns ./package/feeds/luci/luci-app-aliddns # Docker 容器(会导致 OpenWrt 出现 UDP 转发问题,慎用) sed -i 's/+docker/+docker \\\n\t+dockerd/g' ./feeds/luci/applications/luci-app-dockerman/Makefile # Edge 主题 From 70c7584b0a3729a30876bc1eb5409fb5876897d5 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 21 Apr 2021 18:06:00 +0800 Subject: [PATCH 031/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 34c0f4199..e41af2c0d 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -188,9 +188,9 @@ git clone -b master --depth 1 https://github.com/NateLol/luci-app-oled.git packa # OpenClash git clone -b master --depth 1 https://github.com/vernesong/OpenClash.git package/new/luci-app-openclash # 花生壳内网穿透 -svn co https://github.com/teasiu/dragino2/trunk/package/teasiu/luci-app-phtunnel package/new/luci-app-phtunnel +svn co https://github.com/QiuSimons/dragino2-teasiu/trunk/package/teasiu/luci-app-phtunnel package/new/luci-app-phtunnel svn co https://github.com/QiuSimons/dragino2-teasiu/trunk/package/teasiu/luci-app-oray package/new/luci-app-oray -svn co https://github.com/teasiu/dragino2/trunk/package/teasiu/phtunnel package/new/phtunnel +svn co https://github.com/QiuSimons/dragino2-teasiu/trunk/package/teasiu/phtunnel package/new/phtunnel # Pandownload svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/lean/pandownload-fake-server package/lean/pandownload-fake-server # Passwall @@ -210,7 +210,7 @@ svn co https://github.com/xiaorouji/openwrt-passwall/trunk/brook package/new/bro svn co https://github.com/xiaorouji/openwrt-passwall/trunk/trojan-plus package/new/trojan-plus svn co https://github.com/xiaorouji/openwrt-passwall/trunk/ssocks package/new/ssocks svn co https://github.com/xiaorouji/openwrt-passwall/trunk/xray-core package/new/xray-core -svn co https://github.com/xiaorouji/openwrt-passwall/trunk/v2ray package/new/v2ray +svn co https://github.com/immortalwrt/immortalwrt/trunk/package/lean/v2ray package/new/v2ray svn co https://github.com/xiaorouji/openwrt-passwall/trunk/v2ray-plugin package/new/v2ray-plugin svn co https://github.com/xiaorouji/openwrt-passwall/trunk/xray-plugin package/new/xray-plugin # qBittorrent 下载 From 71be9fb720b5e871182ff093b018095e5facc9ed Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 21 Apr 2021 18:15:13 +0800 Subject: [PATCH 032/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index e41af2c0d..961acc027 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -188,9 +188,11 @@ git clone -b master --depth 1 https://github.com/NateLol/luci-app-oled.git packa # OpenClash git clone -b master --depth 1 https://github.com/vernesong/OpenClash.git package/new/luci-app-openclash # 花生壳内网穿透 -svn co https://github.com/QiuSimons/dragino2-teasiu/trunk/package/teasiu/luci-app-phtunnel package/new/luci-app-phtunnel +#svn co https://github.com/QiuSimons/dragino2-teasiu/trunk/package/teasiu/luci-app-phtunnel package/new/luci-app-phtunnel +#svn co https://github.com/QiuSimons/dragino2-teasiu/trunk/package/teasiu/phtunnel package/new/phtunnel +svn co https://github.com/teasiu/dragino2/trunk/devices/common/diy/package/teasiu/luci-app-phtunnel package/new/luci-app-phtunnel +svn co https://github.com/teasiu/dragino2/trunk/devices/common/diy/package/teasiu/phtunnel package/new/phtunnel svn co https://github.com/QiuSimons/dragino2-teasiu/trunk/package/teasiu/luci-app-oray package/new/luci-app-oray -svn co https://github.com/QiuSimons/dragino2-teasiu/trunk/package/teasiu/phtunnel package/new/phtunnel # Pandownload svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/lean/pandownload-fake-server package/lean/pandownload-fake-server # Passwall From 60db120d96cb52a8926151f61797dde9d4394227 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 21 Apr 2021 21:18:01 +0800 Subject: [PATCH 033/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 961acc027..2c5e37744 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -167,6 +167,8 @@ svn co -r131 https://github.com/jerrykuku/luci-app-jd-dailybonus/trunk package/n pushd package/new/luci-app-jd-dailybonus sed -i 's/wget-ssl/wget/g' root/usr/share/jd-dailybonus/newapp.sh luasrc/controller/jd-dailybonus.lua popd +rm -rf ./package/new/luci-app-jd-dailybonus/root/usr/share/jd-dailybonus/JD_DailyBonus.js +wget -P package/new/luci-app-jd-dailybonus/root/usr/share/jd-dailybonus/ https://github.com/Nancyhnson478/Mirror/raw/main/data/NobyDa/JD_DailyBonus.js # 回滚通用即插即用 #rm -rf ./feeds/packages/net/miniupnpd #svn co https://github.com/coolsnowwolf/packages/trunk/net/miniupnpd feeds/packages/net/miniupnpd From 489a099d2bfeb94fffa8388671d51aa553a34f29 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 21 Apr 2021 21:26:34 +0800 Subject: [PATCH 034/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 2c5e37744..1217cf8ac 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -168,7 +168,7 @@ pushd package/new/luci-app-jd-dailybonus sed -i 's/wget-ssl/wget/g' root/usr/share/jd-dailybonus/newapp.sh luasrc/controller/jd-dailybonus.lua popd rm -rf ./package/new/luci-app-jd-dailybonus/root/usr/share/jd-dailybonus/JD_DailyBonus.js -wget -P package/new/luci-app-jd-dailybonus/root/usr/share/jd-dailybonus/ https://github.com/Nancyhnson478/Mirror/raw/main/data/NobyDa/JD_DailyBonus.js +wget -P package/new/luci-app-jd-dailybonus/root/usr/share/jd-dailybonus/ https://github.com/NobyDa/Script/raw/master/JD-DailyBonus/JD_DailyBonus.js # 回滚通用即插即用 #rm -rf ./feeds/packages/net/miniupnpd #svn co https://github.com/coolsnowwolf/packages/trunk/net/miniupnpd feeds/packages/net/miniupnpd From 1c6a78ec8c364105b3f1ce4586330733f33315ce Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 22 Apr 2021 12:56:04 +0800 Subject: [PATCH 035/244] Update R2S-OpenWrt.yml --- .github/workflows/R2S-OpenWrt.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/R2S-OpenWrt.yml b/.github/workflows/R2S-OpenWrt.yml index 4c547fd02..e8221499e 100644 --- a/.github/workflows/R2S-OpenWrt.yml +++ b/.github/workflows/R2S-OpenWrt.yml @@ -136,9 +136,9 @@ jobs: id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-R2S-R4S-X86-21.02 + name: OpenWRT-R2S-R4S-X86-21.02.0-RC1 allowUpdates: true - tag: 2102 + tag: 21.02.0-rc1 commit: master replacesArtifacts: true token: ${{ secrets.workflow_token }} From ebbfe2553a8f48de7e8f5882bc1b9f83ae799609 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 22 Apr 2021 12:56:29 +0800 Subject: [PATCH 036/244] Update R4S-OpenWrt.yml --- .github/workflows/R4S-OpenWrt.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/R4S-OpenWrt.yml b/.github/workflows/R4S-OpenWrt.yml index 7782394bf..ad124dafb 100644 --- a/.github/workflows/R4S-OpenWrt.yml +++ b/.github/workflows/R4S-OpenWrt.yml @@ -136,9 +136,9 @@ jobs: id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-R2S-R4S-X86-21.02 + name: OpenWRT-R2S-R4S-X86-21.02.0-RC1 allowUpdates: true - tag: 2102 + tag: 21.02.0-rc1 commit: master replacesArtifacts: true token: ${{ secrets.workflow_token }} From 3f667ffcae46b19b7c5f2de10a0ce0e216794ccb Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 22 Apr 2021 12:56:49 +0800 Subject: [PATCH 037/244] Update X86-OpenWrt.yml --- .github/workflows/X86-OpenWrt.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/X86-OpenWrt.yml b/.github/workflows/X86-OpenWrt.yml index 00b317a00..61be22341 100644 --- a/.github/workflows/X86-OpenWrt.yml +++ b/.github/workflows/X86-OpenWrt.yml @@ -136,9 +136,9 @@ jobs: id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-R2S-R4S-X86-21.02 + name: OpenWRT-R2S-R4S-X86-21.02.0-RC1 allowUpdates: true - tag: 2102 + tag: 21.02.0-rc1 commit: master replacesArtifacts: true token: ${{ secrets.workflow_token }} From 0cb4efb91111df7c5d5a02d7617bed7ee01653da Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 26 Apr 2021 10:15:50 +0800 Subject: [PATCH 038/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 1217cf8ac..979416469 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -117,6 +117,8 @@ svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-autorebo # Boost 通用即插即用 svn co https://github.com/ryohuang/slim-wrt/trunk/slimapps/application/luci-app-boostupnp package/new/luci-app-boostupnp sed -i 's,api.ipify.org,myip.ipip.net/s,g' ./package/new/luci-app-boostupnp/root/usr/sbin/boostupnp.sh +rm -rf ./feeds/packages/net/miniupnpd +svn co https://github.com/openwrt/packages/trunk/net/miniupnpd feeds/packages/net/miniupnpd # ChinaDNS git clone -b luci --depth 1 https://github.com/pexcn/openwrt-chinadns-ng.git package/new/luci-app-chinadns-ng svn co https://github.com/xiaorouji/openwrt-passwall/trunk/chinadns-ng package/new/chinadns-ng From 1056adbb37b349143b8d09b5571809d8972fb3e1 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 26 Apr 2021 15:33:11 +0800 Subject: [PATCH 039/244] Update config.seed --- SEED/R4S/config.seed | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index 727b07408..887d0c11e 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -59,6 +59,8 @@ CONFIG_PACKAGE_rpcd-mod-rrdns=y CONFIG_PACKAGE_uhttpd=y CONFIG_PACKAGE_wget-ssl=y CONFIG_PACKAGE_lua=y +# CONFIG_PACKAGE_miniupnpd is not set +CONFIG_PACKAGE_miniupnpd-igdv1=y ### LUCI ### CONFIG_LUCI_LANG_zh_Hans=y From 7e3beaea3fc6f8e3a273b33861d9ca05fed41a33 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 26 Apr 2021 15:34:38 +0800 Subject: [PATCH 040/244] Update config.seed --- SEED/R2S/config.seed | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 4852ae236..502995045 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -58,6 +58,8 @@ CONFIG_PACKAGE_rpcd-mod-rrdns=y CONFIG_PACKAGE_uhttpd=y CONFIG_PACKAGE_wget-ssl=y CONFIG_PACKAGE_lua=y +# CONFIG_PACKAGE_miniupnpd is not set +CONFIG_PACKAGE_miniupnpd-igdv1=y ### LUCI ### CONFIG_LUCI_LANG_zh_Hans=y From 48b646b18455559fcf30b783193add866ea5e3b0 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 26 Apr 2021 15:34:59 +0800 Subject: [PATCH 041/244] Update config.seed --- SEED/X86/config.seed | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index 7a20f4a60..08b56caf1 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -60,6 +60,8 @@ CONFIG_PACKAGE_wget-ssl=y CONFIG_PACKAGE_lua=y CONFIG_PACKAGE_qemu-ga=y CONFIG_PACKAGE_irqbalance=y +# CONFIG_PACKAGE_miniupnpd is not set +CONFIG_PACKAGE_miniupnpd-igdv1=y ### LUCI ### CONFIG_LUCI_LANG_zh_Hans=y From 5a730261385f8e47eb1598764d84950533cee7f5 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 29 Apr 2021 15:05:50 +0800 Subject: [PATCH 042/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 979416469..6cb284101 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -85,7 +85,7 @@ svn co https://github.com/nxhack/openwrt-node-packages/trunk/node-yarn feeds/pac ln -sf ../../../feeds/packages/lang/node-yarn ./package/feeds/packages/node-yarn # R8168驱动 svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/kernel/r8168 package/new/r8168 -patch -p1 < ../PATCH/new/main/r8168-fix_LAN_led-for_r4s-from_TL.patch +#patch -p1 < ../PATCH/new/main/r8168-fix_LAN_led-for_r4s-from_TL.patch # UPX 可执行软件压缩 sed -i '/patchelf pkgconf/i\tools-y += ucl upx' ./tools/Makefile sed -i '\/autoconf\/compile :=/i\$(curdir)/upx/compile := $(curdir)/ucl/compile' ./tools/Makefile From a828f866b7806c4eee172e22856e92725d8200bb Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 30 Apr 2021 14:43:44 +0800 Subject: [PATCH 043/244] Update zzz-default-settings --- PATCH/duplicate/addition-trans-zh/files/zzz-default-settings | 1 + 1 file changed, 1 insertion(+) diff --git a/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings b/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings index 53e74068a..605a4a504 100644 --- a/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings +++ b/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings @@ -43,6 +43,7 @@ uci commit upnpd #网易云音乐 #echo "59.111.239.62 httpdns.n.netease.com" >> /etc/hosts && cat /etc/hosts | sort | uniq > /tmp/tmp_hosts && cat /tmp/tmp_hosts > /etc/hosts +echo "10 2 * * * cd /usr/share/unblockneteasemusic/core/ && openssl req -new -x509 -key server.key -out server.crt -days 3650 -subj "/CN=*.music.163.com" && cd" >> /etc/crontabs/root && cat /etc/crontabs/root | sort | uniq > /tmp/tmp_cron_root && cat /tmp/tmp_cron_root > /etc/crontabs/root #OpenClash 设置 echo "/etc/openclash/" >> /etc/sysupgrade.conf && cat /etc/sysupgrade.conf | sort | uniq > /tmp/tmp_sysupgrade_conf && cat /tmp/tmp_sysupgrade_conf > /etc/sysupgrade.conf From 23eb7542c19339981fbd808d9f6d650116bb7376 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 4 May 2021 14:38:25 +0800 Subject: [PATCH 044/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 6cb284101..6cbeeec6e 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -237,6 +237,9 @@ svn co https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/lean/ rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans pushd package/lean #wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/b1a2d3c.patch | patch -p1 +wget -qO - https://github.com/fw876/helloworld/pull/504.patch | patch -p1 +wget -qO - https://github.com/fw876/helloworld/pull/505.patch | patch -p1 +wget -qO - https://github.com/fw876/helloworld/pull/506.patch | patch -p1 wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/c1674ad.patch | patch -p1 popd pushd package/lean/luci-app-ssr-plus From a4d83f51b86e5a9c47e78f473e622d35a1757ea4 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 4 May 2021 20:50:30 +0800 Subject: [PATCH 045/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 6cbeeec6e..2c5198813 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -237,9 +237,9 @@ svn co https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/lean/ rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans pushd package/lean #wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/b1a2d3c.patch | patch -p1 -wget -qO - https://github.com/fw876/helloworld/pull/504.patch | patch -p1 -wget -qO - https://github.com/fw876/helloworld/pull/505.patch | patch -p1 -wget -qO - https://github.com/fw876/helloworld/pull/506.patch | patch -p1 +#wget -qO - https://github.com/fw876/helloworld/pull/504.patch | patch -p1 +#wget -qO - https://github.com/fw876/helloworld/pull/505.patch | patch -p1 +#wget -qO - https://github.com/fw876/helloworld/pull/506.patch | patch -p1 wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/c1674ad.patch | patch -p1 popd pushd package/lean/luci-app-ssr-plus From b4474f8e9c47412745c6bbe2a47633764b83fb39 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 4 May 2021 21:00:29 +0800 Subject: [PATCH 046/244] Update 02_target_only.sh --- SCRIPTS/R2S/02_target_only.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index e78b0e63b..b39d3e643 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -86,5 +86,7 @@ CONFIG_CRYPTO_SM4_ARM64_CE=y cp -rf ../PATCH/R2S/files ./files chmod -R 755 ./ +find ./ -name *.orig | xargs rm -f +find ./ -name *.rej | xargs rm -f exit 0 From 873202038d691d63f6eb6b17e9e7428f8b1a1ebf Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 4 May 2021 21:00:53 +0800 Subject: [PATCH 047/244] Update 02_target_only.sh --- SCRIPTS/R4S/02_target_only.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index 5c0881645..b72f9ae27 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -70,5 +70,7 @@ sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic cp -rf ../PATCH/R4S/files ./files chmod -R 755 ./ +find ./ -name *.orig | xargs rm -f +find ./ -name *.rej | xargs rm -f exit 0 From 454f97bd630f8d8b2ae1e4d91b0f6d16b4f3cc03 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 4 May 2021 21:01:12 +0800 Subject: [PATCH 048/244] Update 02_target_only.sh --- SCRIPTS/X86/02_target_only.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SCRIPTS/X86/02_target_only.sh b/SCRIPTS/X86/02_target_only.sh index a80a86855..77fbc80d7 100644 --- a/SCRIPTS/X86/02_target_only.sh +++ b/SCRIPTS/X86/02_target_only.sh @@ -21,5 +21,7 @@ sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic cp -rf ../PATCH/X86/files ./files chmod -R 755 ./ +find ./ -name *.orig | xargs rm -f +find ./ -name *.rej | xargs rm -f exit 0 From 5f3468bf8c0cb1ad08400bc2c49118ee03aced7d Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 5 May 2021 17:27:11 +0800 Subject: [PATCH 049/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 2c5198813..2a655faf1 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -249,7 +249,7 @@ sed -i '/V2ray:v2ray/d' Makefile sed -i '/plugin:v2ray/d' Makefile #sed -i '/result.encrypt_method/a\result.fast_open = "1"' root/usr/share/shadowsocksr/subscribe.lua sed -i 's,ispip.clang.cn/all_cn,cdn.jsdelivr.net/gh/QiuSimons/Chnroute@master/dist/chnroute/chnroute,' root/etc/init.d/shadowsocksr -sed -i 's,ghproxy.com/https://raw.githubusercontent.com/YW5vbnltb3Vz/domain-list-community/release/gfwlist,cdn.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/gfw,' root/etc/init.d/shadowsocksr luasrc/model/cbi/shadowsocksr/advanced.lua +sed -i 's,YW5vbnltb3Vz/domain-list-community/release/gfwlist.txt,Loyalsoldier/v2ray-rules-dat/release/gfw.txt,' root/etc/init.d/shadowsocksr luasrc/model/cbi/shadowsocksr/advanced.lua sed -i '/Clang.CN.CIDR/a\o:value("https://cdn.jsdelivr.net/gh/QiuSimons/Chnroute@master/dist/chnroute/chnroute.txt", translate("QiuSimons/Chnroute"))' luasrc/model/cbi/shadowsocksr/advanced.lua popd # ShadowsocksR Plus+ 依赖 From f1805a400ffcc7aa654c286f349f0cd6523b822c Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 5 May 2021 18:30:29 +0800 Subject: [PATCH 050/244] Update 900-add-filter-aaaa-option.patch --- .../package/900-add-filter-aaaa-option.patch | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/PATCH/new/package/900-add-filter-aaaa-option.patch b/PATCH/new/package/900-add-filter-aaaa-option.patch index 315fa5133..4995b593c 100644 --- a/PATCH/new/package/900-add-filter-aaaa-option.patch +++ b/PATCH/new/package/900-add-filter-aaaa-option.patch @@ -2,12 +2,12 @@ diff -rNEZbwBdu3 a/src/dnsmasq.h b/src/dnsmasq.h --- a/src/dnsmasq.h 2020-04-09 00:32:53.000000000 +0800 +++ b/src/dnsmasq.h 2020-06-05 23:03:45.941176855 +0800 @@ -269,7 +269,8 @@ - #define OPT_IGNORE_CLID 59 #define OPT_SINGLE_PORT 60 #define OPT_LEASE_RENEW 61 --#define OPT_LAST 62 -+#define OPT_FILTER_AAAA 62 -+#define OPT_LAST 63 + #define OPT_LOG_DEBUG 62 +-#define OPT_LAST 63 ++#define OPT_FILTER_AAAA 63 ++#define OPT_LAST 64 #define OPTION_BITS (sizeof(unsigned int)*8) #define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) ) @@ -15,17 +15,17 @@ diff -rNEZbwBdu3 a/src/option.c b/src/option.c --- a/src/option.c 2020-04-09 00:32:53.000000000 +0800 +++ b/src/option.c 2020-06-05 23:06:29.880350271 +0800 @@ -167,6 +167,7 @@ - #define LOPT_SINGLE_PORT 359 - #define LOPT_SCRIPT_TIME 360 #define LOPT_PXE_VENDOR 361 -+#define LOPT_FILTER_AAAA 362 + #define LOPT_DYNHOST 362 + #define LOPT_LOG_DEBUG 363 ++#define LOPT_FILTER_AAAA 364 #ifdef HAVE_GETOPT_LONG static const struct option opts[] = @@ -339,6 +340,7 @@ - { "dumpfile", 1, 0, LOPT_DUMPFILE }, - { "dumpmask", 1, 0, LOPT_DUMPMASK }, { "dhcp-ignore-clid", 0, 0, LOPT_IGNORE_CLID }, + { "dynamic-host", 1, 0, LOPT_DYNHOST }, + { "log-debug", 0, 0, LOPT_LOG_DEBUG }, + { "filter-aaaa", 0, 0, LOPT_FILTER_AAAA }, { NULL, 0, 0, 0 } }; From 2d3efe926abb9513c06994cbaa316f02c8e60691 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 5 May 2021 18:34:19 +0800 Subject: [PATCH 051/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 2a655faf1..1b27af1aa 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -236,10 +236,7 @@ svn co https://github.com/immortalwrt/luci/branches/openwrt-18.06/applications/l svn co https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/lean/luci-app-ssr-plus rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans pushd package/lean -#wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/b1a2d3c.patch | patch -p1 -#wget -qO - https://github.com/fw876/helloworld/pull/504.patch | patch -p1 -#wget -qO - https://github.com/fw876/helloworld/pull/505.patch | patch -p1 -#wget -qO - https://github.com/fw876/helloworld/pull/506.patch | patch -p1 +wget -qO - https://github.com/fw876/helloworld/pull/509.patch | patch -p1 wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/c1674ad.patch | patch -p1 popd pushd package/lean/luci-app-ssr-plus From 0ffc13bd1bdf48da12f0b32c7002307b9334c911 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 5 May 2021 18:42:27 +0800 Subject: [PATCH 052/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 36 +++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 1b27af1aa..332da726c 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -216,7 +216,6 @@ svn co https://github.com/xiaorouji/openwrt-passwall/trunk/brook package/new/bro svn co https://github.com/xiaorouji/openwrt-passwall/trunk/trojan-plus package/new/trojan-plus svn co https://github.com/xiaorouji/openwrt-passwall/trunk/ssocks package/new/ssocks svn co https://github.com/xiaorouji/openwrt-passwall/trunk/xray-core package/new/xray-core -svn co https://github.com/immortalwrt/immortalwrt/trunk/package/lean/v2ray package/new/v2ray svn co https://github.com/xiaorouji/openwrt-passwall/trunk/v2ray-plugin package/new/v2ray-plugin svn co https://github.com/xiaorouji/openwrt-passwall/trunk/xray-plugin package/new/xray-plugin # qBittorrent 下载 @@ -232,23 +231,6 @@ rm -rf ./feeds/packages/net/smartdns svn co https://github.com/Lienol/openwrt-packages/trunk/net/smartdns feeds/packages/net/smartdns rm -rf ./feeds/luci/applications/luci-app-smartdns svn co https://github.com/immortalwrt/luci/branches/openwrt-18.06/applications/luci-app-smartdns feeds/luci/applications/luci-app-smartdns -# ShadowsocksR Plus+ -svn co https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/lean/luci-app-ssr-plus -rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans -pushd package/lean -wget -qO - https://github.com/fw876/helloworld/pull/509.patch | patch -p1 -wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/c1674ad.patch | patch -p1 -popd -pushd package/lean/luci-app-ssr-plus -sed -i 's,default n,default y,g' Makefile -sed -i 's,Xray:xray ,Xray:xray-core ,g' Makefile -sed -i '/V2ray:v2ray/d' Makefile -sed -i '/plugin:v2ray/d' Makefile -#sed -i '/result.encrypt_method/a\result.fast_open = "1"' root/usr/share/shadowsocksr/subscribe.lua -sed -i 's,ispip.clang.cn/all_cn,cdn.jsdelivr.net/gh/QiuSimons/Chnroute@master/dist/chnroute/chnroute,' root/etc/init.d/shadowsocksr -sed -i 's,YW5vbnltb3Vz/domain-list-community/release/gfwlist.txt,Loyalsoldier/v2ray-rules-dat/release/gfw.txt,' root/etc/init.d/shadowsocksr luasrc/model/cbi/shadowsocksr/advanced.lua -sed -i '/Clang.CN.CIDR/a\o:value("https://cdn.jsdelivr.net/gh/QiuSimons/Chnroute@master/dist/chnroute/chnroute.txt", translate("QiuSimons/Chnroute"))' luasrc/model/cbi/shadowsocksr/advanced.lua -popd # ShadowsocksR Plus+ 依赖 rm -rf ./feeds/packages/net/kcptun rm -rf ./feeds/packages/net/proxychains-ng @@ -267,8 +249,26 @@ svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/simple-obfs packa svn co https://github.com/coolsnowwolf/packages/trunk/net/shadowsocks-libev package/lean/shadowsocks-libev svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/trojan package/lean/trojan svn co https://github.com/fw876/helloworld/trunk/naiveproxy package/lean/naiveproxy +svn co https://github.com/fw876/helloworld/trunk/v2ray-core package/lean/v2ray-core svn co https://github.com/immortalwrt/packages/trunk/net/shadowsocks-rust package/lean/shadowsocks-rust #svn co https://github.com/fw876/helloworld/trunk/shadowsocks-rust package/lean/shadowsocks-rust +# ShadowsocksR Plus+ +svn co https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/lean/luci-app-ssr-plus +rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans +pushd package/lean +wget -qO - https://github.com/fw876/helloworld/pull/509.patch | patch -p1 +wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/c1674ad.patch | patch -p1 +popd +pushd package/lean/luci-app-ssr-plus +sed -i 's,default n,default y,g' Makefile +sed -i 's,Xray:xray ,Xray:xray-core ,g' Makefile +sed -i '/V2ray:v2ray/d' Makefile +sed -i '/plugin:v2ray/d' Makefile +#sed -i '/result.encrypt_method/a\result.fast_open = "1"' root/usr/share/shadowsocksr/subscribe.lua +sed -i 's,ispip.clang.cn/all_cn,cdn.jsdelivr.net/gh/QiuSimons/Chnroute@master/dist/chnroute/chnroute,' root/etc/init.d/shadowsocksr +sed -i 's,YW5vbnltb3Vz/domain-list-community/release/gfwlist.txt,Loyalsoldier/v2ray-rules-dat/release/gfw.txt,' root/etc/init.d/shadowsocksr luasrc/model/cbi/shadowsocksr/advanced.lua +sed -i '/Clang.CN.CIDR/a\o:value("https://cdn.jsdelivr.net/gh/QiuSimons/Chnroute@master/dist/chnroute/chnroute.txt", translate("QiuSimons/Chnroute"))' luasrc/model/cbi/shadowsocksr/advanced.lua +popd # 订阅转换 svn co https://github.com/immortalwrt/packages/trunk/net/subconverter package/new/subconverter svn co https://github.com/immortalwrt/packages/trunk/libs/jpcre2 package/new/jpcre2 From 31998b8c2484f08229f7b2d4bbf440b1791f736a Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 5 May 2021 21:13:14 +0800 Subject: [PATCH 053/244] Update zzz-default-settings --- .../duplicate/addition-trans-zh/files/zzz-default-settings | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings b/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings index 605a4a504..b4874021b 100644 --- a/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings +++ b/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings @@ -26,7 +26,7 @@ uci commit uhttpd #在防火墙默认开启全锥形 NAT 以及 Flow Offloading uci set firewall.@defaults[0].fullcone='1' -uci set firewall.@defaults[0].flow_offloading='1' +#uci set firewall.@defaults[0].flow_offloading='1' uci commit firewall #默认开启 Packet Steering @@ -77,8 +77,8 @@ opkg flag hold dnsmasq-full #sync; echo 3 > /proc/sys/vm/drop_caches #默认关闭 Shortcut-FE -service shortcut-fe stop -rm -rf /etc/rc.d/S90shortcut-fe +#service shortcut-fe stop +#rm -rf /etc/rc.d/S90shortcut-fe #自用 [ -f '/rom/etc/rpcd_10_system.js' ] && rm -f /etc/rpcd_10_system.js From 74c6968350115f5643745c8b01a5f22334a5193c Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 6 May 2021 17:57:42 +0800 Subject: [PATCH 054/244] Update smartdns --- PATCH/R2S/files/etc/config/smartdns | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PATCH/R2S/files/etc/config/smartdns b/PATCH/R2S/files/etc/config/smartdns index 807e9e130..322845e62 100644 --- a/PATCH/R2S/files/etc/config/smartdns +++ b/PATCH/R2S/files/etc/config/smartdns @@ -1,7 +1,7 @@ config smartdns option server_name 'smartdns' - option port '6051' + option port '6051 -force-aaaa-soa -group oversea' option dualstack_ip_selection '0' option server_group 'oversea' option seconddns_port '6050' From fa72bcc50aa55472c9c6e89773fb9141a2993320 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 6 May 2021 17:58:59 +0800 Subject: [PATCH 055/244] Update smartdns --- PATCH/R4S/files/etc/config/smartdns | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PATCH/R4S/files/etc/config/smartdns b/PATCH/R4S/files/etc/config/smartdns index cab19dce3..34e37efd2 100644 --- a/PATCH/R4S/files/etc/config/smartdns +++ b/PATCH/R4S/files/etc/config/smartdns @@ -1,7 +1,7 @@ config smartdns option server_name 'smartdns' - option port '6051' + option port '6051 -force-aaaa-soa -group oversea' option dualstack_ip_selection '0' option server_group 'oversea' option seconddns_port '6050' From 47cc7505459831120494ee49a032b1d2ebe23fa2 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 6 May 2021 17:59:40 +0800 Subject: [PATCH 056/244] Update smartdns --- PATCH/X86/files/etc/config/smartdns | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PATCH/X86/files/etc/config/smartdns b/PATCH/X86/files/etc/config/smartdns index cab19dce3..34e37efd2 100644 --- a/PATCH/X86/files/etc/config/smartdns +++ b/PATCH/X86/files/etc/config/smartdns @@ -1,7 +1,7 @@ config smartdns option server_name 'smartdns' - option port '6051' + option port '6051 -force-aaaa-soa -group oversea' option dualstack_ip_selection '0' option server_group 'oversea' option seconddns_port '6050' From c32e3d1f829b72aea52c23c6854f8cf2aace711f Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 6 May 2021 18:08:22 +0800 Subject: [PATCH 057/244] Update zzz-default-settings --- PATCH/duplicate/addition-trans-zh/files/zzz-default-settings | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings b/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings index b4874021b..10cf0f519 100644 --- a/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings +++ b/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings @@ -59,7 +59,8 @@ uci set dhcp.lan.ra='hybrid' uci set dhcp.lan.ndp='hybrid' uci set dhcp.lan.dhcpv6='hybrid' uci set dhcp.lan.ra_management='1' -uci del dhcp.@dnsmasq[0].rebind_protection='1' +uci del dhcp.@dnsmasq[0].rebind_protection +uci del dhcp.@dnsmasq[0].filteraaaa uci commit dhcp sed -i '/log-facility/d' /etc/dnsmasq.conf echo "log-facility=/dev/null" >> /etc/dnsmasq.conf From 317d68d7f31e93047371c4a02edc5530860ec989 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 6 May 2021 18:23:23 +0800 Subject: [PATCH 058/244] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d009cf35e..5c555d08d 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ ### 特性 - 基于原生 OpenWrt 21.02 编译,默认管理地址192.168.1.1 -- 同时支持 SFE/Software Offload (选则其一开启,默认开启Software Offload) +- 同时支持 SFE/Software Offload (选则其一开启,默认开启SFE) - 内置升级功能可用,物理 Reset 按键可用 - 预配置了部分插件(包括但不限于 DNS 套娃,使用时先将 SSRP 的 DNS 上游提前选成本机5335端口,然后再 ADG 中勾上启用就好*“管理账户root,密码admin”,如果要作用于路由器本身,可以把lan和wan的dns都配置成127.0.0.1,dhcp高级里设置下发dns 6,192.168.1.1。注:这里取决于你设定的路由的ip地址) - 正式 Release 版本将具有可无脑 opkg kmod 的特性 From 5ffa0d9ca6072a4c749fdf4f5c681d2536c2f003 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 6 May 2021 21:45:15 +0800 Subject: [PATCH 059/244] Update smartdns --- PATCH/R2S/files/etc/config/smartdns | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/PATCH/R2S/files/etc/config/smartdns b/PATCH/R2S/files/etc/config/smartdns index 322845e62..06020c975 100644 --- a/PATCH/R2S/files/etc/config/smartdns +++ b/PATCH/R2S/files/etc/config/smartdns @@ -2,24 +2,16 @@ config smartdns option server_name 'smartdns' option port '6051 -force-aaaa-soa -group oversea' - option dualstack_ip_selection '0' option server_group 'oversea' option seconddns_port '6050' option seconddns_tcp_server '1' - option seconddns_no_speed_check '0' - option coredump '0' option seconddns_enabled '1' - option seconddns_no_dualstack_selection '1' - option ipv6_server '0' option redirect 'none' option seconddns_server_group 'mainland' option prefetch_domain '1' option serve_expired '1' option tcp_server '1' option seconddns_no_cache '1' - option rr_ttl_min '3600' - option rr_ttl '3600' - option rr_ttl_max '36000' option cache_size '4194304' option enabled '1' @@ -27,7 +19,6 @@ config server option type 'udp' option name 'DNSPod' option ip '119.29.29.29' - option blacklist_ip '0' option server_group 'mainland' option enabled '1' option addition_arg '-exclude-default-group' @@ -36,7 +27,6 @@ config server option type 'udp' option name 'AliDNS' option ip '223.5.5.5' - option blacklist_ip '0' option server_group 'mainland' option enabled '1' option addition_arg '-exclude-default-group' @@ -44,8 +34,6 @@ config server config server option type 'tls' option server_group 'oversea' - option blacklist_ip '0' - option no_check_certificate '0' option name 'Google TLS' option enabled '1' option ip '8.8.4.4' @@ -53,8 +41,6 @@ config server config server option type 'tls' option server_group 'oversea' - option blacklist_ip '0' - option no_check_certificate '0' option ip '1.1.1.1' option enabled '1' option name 'Cloudflare TLS' @@ -62,7 +48,6 @@ config server config server option enabled '1' option server_group 'oversea' - option blacklist_ip '0' option type 'udp' option port '5353' option name 'USTC' From b43169b854697a018510211d823e5c07bb7f967d Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 6 May 2021 21:45:40 +0800 Subject: [PATCH 060/244] Update smartdns --- PATCH/R4S/files/etc/config/smartdns | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/PATCH/R4S/files/etc/config/smartdns b/PATCH/R4S/files/etc/config/smartdns index 34e37efd2..06020c975 100644 --- a/PATCH/R4S/files/etc/config/smartdns +++ b/PATCH/R4S/files/etc/config/smartdns @@ -2,24 +2,16 @@ config smartdns option server_name 'smartdns' option port '6051 -force-aaaa-soa -group oversea' - option dualstack_ip_selection '0' option server_group 'oversea' option seconddns_port '6050' option seconddns_tcp_server '1' - option seconddns_no_speed_check '0' - option coredump '0' option seconddns_enabled '1' - option seconddns_no_dualstack_selection '1' - option ipv6_server '0' option redirect 'none' option seconddns_server_group 'mainland' option prefetch_domain '1' option serve_expired '1' option tcp_server '1' option seconddns_no_cache '1' - option rr_ttl_min '3600' - option rr_ttl '3600' - option rr_ttl_max '36000' option cache_size '4194304' option enabled '1' @@ -27,7 +19,6 @@ config server option type 'udp' option name 'DNSPod' option ip '119.29.29.29' - option blacklist_ip '0' option server_group 'mainland' option enabled '1' option addition_arg '-exclude-default-group' @@ -36,7 +27,6 @@ config server option type 'udp' option name 'AliDNS' option ip '223.5.5.5' - option blacklist_ip '0' option server_group 'mainland' option enabled '1' option addition_arg '-exclude-default-group' @@ -44,8 +34,6 @@ config server config server option type 'tls' option server_group 'oversea' - option blacklist_ip '0' - option no_check_certificate '0' option name 'Google TLS' option enabled '1' option ip '8.8.4.4' @@ -53,16 +41,13 @@ config server config server option type 'tls' option server_group 'oversea' - option blacklist_ip '0' - option no_check_certificate '0' option ip '1.1.1.1' option enabled '1' option name 'Cloudflare TLS' - + config server option enabled '1' option server_group 'oversea' - option blacklist_ip '0' option type 'udp' option port '5353' option name 'USTC' From c6eb6a6d8c575fdb19aebfc5cb85025102c6f580 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 6 May 2021 21:46:09 +0800 Subject: [PATCH 061/244] Update smartdns --- PATCH/X86/files/etc/config/smartdns | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/PATCH/X86/files/etc/config/smartdns b/PATCH/X86/files/etc/config/smartdns index 34e37efd2..06020c975 100644 --- a/PATCH/X86/files/etc/config/smartdns +++ b/PATCH/X86/files/etc/config/smartdns @@ -2,24 +2,16 @@ config smartdns option server_name 'smartdns' option port '6051 -force-aaaa-soa -group oversea' - option dualstack_ip_selection '0' option server_group 'oversea' option seconddns_port '6050' option seconddns_tcp_server '1' - option seconddns_no_speed_check '0' - option coredump '0' option seconddns_enabled '1' - option seconddns_no_dualstack_selection '1' - option ipv6_server '0' option redirect 'none' option seconddns_server_group 'mainland' option prefetch_domain '1' option serve_expired '1' option tcp_server '1' option seconddns_no_cache '1' - option rr_ttl_min '3600' - option rr_ttl '3600' - option rr_ttl_max '36000' option cache_size '4194304' option enabled '1' @@ -27,7 +19,6 @@ config server option type 'udp' option name 'DNSPod' option ip '119.29.29.29' - option blacklist_ip '0' option server_group 'mainland' option enabled '1' option addition_arg '-exclude-default-group' @@ -36,7 +27,6 @@ config server option type 'udp' option name 'AliDNS' option ip '223.5.5.5' - option blacklist_ip '0' option server_group 'mainland' option enabled '1' option addition_arg '-exclude-default-group' @@ -44,8 +34,6 @@ config server config server option type 'tls' option server_group 'oversea' - option blacklist_ip '0' - option no_check_certificate '0' option name 'Google TLS' option enabled '1' option ip '8.8.4.4' @@ -53,16 +41,13 @@ config server config server option type 'tls' option server_group 'oversea' - option blacklist_ip '0' - option no_check_certificate '0' option ip '1.1.1.1' option enabled '1' option name 'Cloudflare TLS' - + config server option enabled '1' option server_group 'oversea' - option blacklist_ip '0' option type 'udp' option port '5353' option name 'USTC' From 061f6f507cc8f422a279a770dff4860b3df00d1a Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 6 May 2021 21:49:20 +0800 Subject: [PATCH 062/244] Update AdGuardHome.yaml --- PATCH/X86/files/etc/config/AdGuardHome.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/PATCH/X86/files/etc/config/AdGuardHome.yaml b/PATCH/X86/files/etc/config/AdGuardHome.yaml index 2bd020e83..17cfecd5f 100644 --- a/PATCH/X86/files/etc/config/AdGuardHome.yaml +++ b/PATCH/X86/files/etc/config/AdGuardHome.yaml @@ -42,8 +42,6 @@ dns: - id.server - hostname.bind cache_size: 4194304 - cache_ttl_min: 3600 - cache_ttl_max: 36000 bogus_nxdomain: [] aaaa_disabled: false enable_dnssec: false @@ -55,9 +53,6 @@ dns: parental_enabled: false safesearch_enabled: false safebrowsing_enabled: false - safebrowsing_cache_size: 1048576 - safesearch_cache_size: 1048576 - parental_cache_size: 1048576 cache_time: 30 rewrites: - domain: wifi.weixin.qq.com From c15563b8166d92353929297b9dbce3be63b044a3 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 6 May 2021 21:49:50 +0800 Subject: [PATCH 063/244] Update AdGuardHome.yaml --- PATCH/R4S/files/etc/config/AdGuardHome.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/PATCH/R4S/files/etc/config/AdGuardHome.yaml b/PATCH/R4S/files/etc/config/AdGuardHome.yaml index 2bd020e83..17cfecd5f 100644 --- a/PATCH/R4S/files/etc/config/AdGuardHome.yaml +++ b/PATCH/R4S/files/etc/config/AdGuardHome.yaml @@ -42,8 +42,6 @@ dns: - id.server - hostname.bind cache_size: 4194304 - cache_ttl_min: 3600 - cache_ttl_max: 36000 bogus_nxdomain: [] aaaa_disabled: false enable_dnssec: false @@ -55,9 +53,6 @@ dns: parental_enabled: false safesearch_enabled: false safebrowsing_enabled: false - safebrowsing_cache_size: 1048576 - safesearch_cache_size: 1048576 - parental_cache_size: 1048576 cache_time: 30 rewrites: - domain: wifi.weixin.qq.com From a216cb549561f00c59f22e11646f47bc6b0b9594 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 6 May 2021 21:50:12 +0800 Subject: [PATCH 064/244] Update AdGuardHome.yaml --- PATCH/R2S/files/etc/config/AdGuardHome.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/PATCH/R2S/files/etc/config/AdGuardHome.yaml b/PATCH/R2S/files/etc/config/AdGuardHome.yaml index 2bd020e83..17cfecd5f 100644 --- a/PATCH/R2S/files/etc/config/AdGuardHome.yaml +++ b/PATCH/R2S/files/etc/config/AdGuardHome.yaml @@ -42,8 +42,6 @@ dns: - id.server - hostname.bind cache_size: 4194304 - cache_ttl_min: 3600 - cache_ttl_max: 36000 bogus_nxdomain: [] aaaa_disabled: false enable_dnssec: false @@ -55,9 +53,6 @@ dns: parental_enabled: false safesearch_enabled: false safebrowsing_enabled: false - safebrowsing_cache_size: 1048576 - safesearch_cache_size: 1048576 - parental_cache_size: 1048576 cache_time: 30 rewrites: - domain: wifi.weixin.qq.com From 5dfa56064666daf1afb137d7cba30a645bf810b3 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 6 May 2021 22:00:34 +0800 Subject: [PATCH 065/244] Update AdGuardHome.yaml --- PATCH/R2S/files/etc/config/AdGuardHome.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/PATCH/R2S/files/etc/config/AdGuardHome.yaml b/PATCH/R2S/files/etc/config/AdGuardHome.yaml index 17cfecd5f..14be8f1e4 100644 --- a/PATCH/R2S/files/etc/config/AdGuardHome.yaml +++ b/PATCH/R2S/files/etc/config/AdGuardHome.yaml @@ -41,7 +41,9 @@ dns: - version.bind - id.server - hostname.bind - cache_size: 4194304 + cache_size: 0 + cache_ttl_min: 0 + cache_ttl_max: 0 bogus_nxdomain: [] aaaa_disabled: false enable_dnssec: false From 1e15b8c99f7a71cded8fde69c324f256be7fb991 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 6 May 2021 22:01:40 +0800 Subject: [PATCH 066/244] Update smartdns --- PATCH/R2S/files/etc/config/smartdns | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PATCH/R2S/files/etc/config/smartdns b/PATCH/R2S/files/etc/config/smartdns index 06020c975..87e85b9c6 100644 --- a/PATCH/R2S/files/etc/config/smartdns +++ b/PATCH/R2S/files/etc/config/smartdns @@ -12,7 +12,7 @@ config smartdns option serve_expired '1' option tcp_server '1' option seconddns_no_cache '1' - option cache_size '4194304' + option cache_size '102400' option enabled '1' config server From 715ac8c3055e6925af5d93b7ab7268bee4583c63 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 6 May 2021 22:02:54 +0800 Subject: [PATCH 067/244] Update AdGuardHome.yaml --- PATCH/R4S/files/etc/config/AdGuardHome.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/PATCH/R4S/files/etc/config/AdGuardHome.yaml b/PATCH/R4S/files/etc/config/AdGuardHome.yaml index 17cfecd5f..14be8f1e4 100644 --- a/PATCH/R4S/files/etc/config/AdGuardHome.yaml +++ b/PATCH/R4S/files/etc/config/AdGuardHome.yaml @@ -41,7 +41,9 @@ dns: - version.bind - id.server - hostname.bind - cache_size: 4194304 + cache_size: 0 + cache_ttl_min: 0 + cache_ttl_max: 0 bogus_nxdomain: [] aaaa_disabled: false enable_dnssec: false From 86f29bba97f32c0e2fd6fa941b8aab38c4eaa7f9 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 6 May 2021 22:03:14 +0800 Subject: [PATCH 068/244] Update smartdns --- PATCH/R4S/files/etc/config/smartdns | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PATCH/R4S/files/etc/config/smartdns b/PATCH/R4S/files/etc/config/smartdns index 06020c975..87e85b9c6 100644 --- a/PATCH/R4S/files/etc/config/smartdns +++ b/PATCH/R4S/files/etc/config/smartdns @@ -12,7 +12,7 @@ config smartdns option serve_expired '1' option tcp_server '1' option seconddns_no_cache '1' - option cache_size '4194304' + option cache_size '102400' option enabled '1' config server From b45bfa04673dc9d1929a6f009369ed88b02a5bf1 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 6 May 2021 22:03:42 +0800 Subject: [PATCH 069/244] Update AdGuardHome.yaml --- PATCH/X86/files/etc/config/AdGuardHome.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/PATCH/X86/files/etc/config/AdGuardHome.yaml b/PATCH/X86/files/etc/config/AdGuardHome.yaml index 17cfecd5f..14be8f1e4 100644 --- a/PATCH/X86/files/etc/config/AdGuardHome.yaml +++ b/PATCH/X86/files/etc/config/AdGuardHome.yaml @@ -41,7 +41,9 @@ dns: - version.bind - id.server - hostname.bind - cache_size: 4194304 + cache_size: 0 + cache_ttl_min: 0 + cache_ttl_max: 0 bogus_nxdomain: [] aaaa_disabled: false enable_dnssec: false From 6e3fcdd841d137f7bcd69302eea461a9846aa9ec Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 6 May 2021 22:04:04 +0800 Subject: [PATCH 070/244] Update smartdns --- PATCH/X86/files/etc/config/smartdns | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PATCH/X86/files/etc/config/smartdns b/PATCH/X86/files/etc/config/smartdns index 06020c975..87e85b9c6 100644 --- a/PATCH/X86/files/etc/config/smartdns +++ b/PATCH/X86/files/etc/config/smartdns @@ -12,7 +12,7 @@ config smartdns option serve_expired '1' option tcp_server '1' option seconddns_no_cache '1' - option cache_size '4194304' + option cache_size '102400' option enabled '1' config server From 08ba8b6762a485a56eb6cab8e3137272fc18f314 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 7 May 2021 20:44:31 +0800 Subject: [PATCH 071/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 332da726c..83113bb09 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -256,7 +256,7 @@ svn co https://github.com/immortalwrt/packages/trunk/net/shadowsocks-rust packag svn co https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/lean/luci-app-ssr-plus rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans pushd package/lean -wget -qO - https://github.com/fw876/helloworld/pull/509.patch | patch -p1 +#wget -qO - https://github.com/fw876/helloworld/pull/509.patch | patch -p1 wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/c1674ad.patch | patch -p1 popd pushd package/lean/luci-app-ssr-plus From 9d8d9075e25af5a5d1187abf94a9f37dca425e9f Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sat, 8 May 2021 17:46:35 +0800 Subject: [PATCH 072/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 83113bb09..a2462894d 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -115,8 +115,7 @@ svn co https://github.com/QiuSimons/OpenWrt_luci-app/trunk/lean/luci-app-arpbind # 定时重启 svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-autoreboot package/lean/luci-app-autoreboot # Boost 通用即插即用 -svn co https://github.com/ryohuang/slim-wrt/trunk/slimapps/application/luci-app-boostupnp package/new/luci-app-boostupnp -sed -i 's,api.ipify.org,myip.ipip.net/s,g' ./package/new/luci-app-boostupnp/root/usr/sbin/boostupnp.sh +svn co https://github.com/QiuSimons/slim-wrt/branches/main/slimapps/application/luci-app-boostupnp package/new/luci-app-boostupnp rm -rf ./feeds/packages/net/miniupnpd svn co https://github.com/openwrt/packages/trunk/net/miniupnpd feeds/packages/net/miniupnpd # ChinaDNS From 3baf33337937978d6101af4c7858debcf14de318 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sat, 8 May 2021 18:31:05 +0800 Subject: [PATCH 073/244] Update zzz-default-settings --- PATCH/duplicate/addition-trans-zh/files/zzz-default-settings | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings b/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings index 10cf0f519..05b366e4f 100644 --- a/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings +++ b/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings @@ -65,6 +65,11 @@ uci commit dhcp sed -i '/log-facility/d' /etc/dnsmasq.conf echo "log-facility=/dev/null" >> /etc/dnsmasq.conf +#计划任务 +uci set system.@system[0].cronloglevel="9" +uci commit system +/etc/init.d/cron restart + #软链接 ln -sf /sbin/ip /usr/bin/ip ln -sf /usr/bin/wget /usr/bin/wget-ssl From dc205a98289354ebad7a356bff0aa754ca718a55 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 10 May 2021 14:54:51 +0800 Subject: [PATCH 074/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index a2462894d..b0650c6a1 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -235,7 +235,8 @@ rm -rf ./feeds/packages/net/kcptun rm -rf ./feeds/packages/net/proxychains-ng rm -rf ./feeds/packages/net/shadowsocks-libev rm -rf ./feeds/packages/net/xray-core -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/shadowsocksr-libev package/lean/shadowsocksr-libev +#svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/shadowsocksr-libev package/lean/shadowsocksr-libev +svn co https://github.com/fw876/helloworld/trunk/shadowsocksr-libev package/lean/shadowsocksr-libev svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/pdnsd-alt package/lean/pdnsd svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/kcptun package/lean/kcptun svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/srelay package/lean/srelay @@ -255,7 +256,7 @@ svn co https://github.com/immortalwrt/packages/trunk/net/shadowsocks-rust packag svn co https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/lean/luci-app-ssr-plus rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans pushd package/lean -#wget -qO - https://github.com/fw876/helloworld/pull/509.patch | patch -p1 +wget -qO - https://github.com/fw876/helloworld/pull/513.patch | patch -p1 wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/c1674ad.patch | patch -p1 popd pushd package/lean/luci-app-ssr-plus From 60c4e4568a04663d7bec4d28ad064260adcded7e Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 10 May 2021 15:30:00 +0800 Subject: [PATCH 075/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index b0650c6a1..5e5f55617 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -291,6 +291,8 @@ git clone -b master --depth 1 https://github.com/jerrykuku/lua-maxminddb.git pac sed -i 's,default n,default y,g' package/lean/luci-app-vssr/Makefile sed -i '/V2ray:v2ray/d' package/lean/luci-app-vssr/Makefile sed -i '/plugin:v2ray/d' package/lean/luci-app-vssr/Makefile +sed -i 's,+shadowsocksr-libev-alt ,,g' package/lean/luci-app-vssr/Makefile +sed -i '/Server:shadowsocksr-libev-server/d' package/lean/luci-app-vssr/Makefile sed -i '/result.encrypt_method/a\result.fast_open = "1"' package/lean/luci-app-vssr/root/usr/share/vssr/subscribe.lua sed -i 's,ispip.clang.cn/all_cn.txt,raw.sevencdn.com/QiuSimons/Chnroute/master/dist/chnroute/chnroute.txt,g' package/lean/luci-app-vssr/luasrc/controller/vssr.lua sed -i 's,ispip.clang.cn/all_cn.txt,raw.sevencdn.com/QiuSimons/Chnroute/master/dist/chnroute/chnroute.txt,g' package/lean/luci-app-vssr/root/usr/share/vssr/update.lua From ca53aea48036b1579f5b3d854f10b71ffe0e6d5b Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 10 May 2021 16:17:24 +0800 Subject: [PATCH 076/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 5e5f55617..bb004c135 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -20,6 +20,7 @@ wget -P include/ https://github.com/immortalwrt/immortalwrt/raw/master/include/d wget -P include/ https://github.com/immortalwrt/immortalwrt/raw/master/include/package-immortalwrt.mk sed -i '/unshift/d' scripts/download.pl sed -i '/mirror02/d' scripts/download.pl +echo "net.netfilter.nf_conntrack_helper = 1" >> ./package/kernel/linux/files/sysctl-nf-conntrack.conf #临时补丁 #wget -qO - https://github.com/openwrt/openwrt/commit/7fae64.patch | patch -p1 From 455ebd9b5a69acc0b6f2bb94db628b26fffd389a Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 10 May 2021 16:18:13 +0800 Subject: [PATCH 077/244] Update Makefile --- PATCH/duplicate/addition-trans-zh/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PATCH/duplicate/addition-trans-zh/Makefile b/PATCH/duplicate/addition-trans-zh/Makefile index 5e11c3d84..671cb55b5 100644 --- a/PATCH/duplicate/addition-trans-zh/Makefile +++ b/PATCH/duplicate/addition-trans-zh/Makefile @@ -21,7 +21,7 @@ define Package/addition-trans-zh CATEGORY:=LuCI TITLE:=LuCI support for Default Settings PKGARCH:=all - DEPENDS:=+luci-base +kmod-fast-classifier +kmod-ipt-nat6 +kmod-tun +luci-lib-ipkg +luci-compat +openssl-util +iptables-mod-fullconenat +iptables-mod-nat-extra +ip6tables-mod-nat +@LUCI_LANG_zh_Hans + DEPENDS:=+luci-base +kmod-fast-classifier +kmod-ipt-nat6 +kmod-tun +kmod-nf-nathelper-extra +luci-lib-ipkg +luci-compat +openssl-util +iptables-mod-fullconenat +iptables-mod-nat-extra +ip6tables-mod-nat +@LUCI_LANG_zh_Hans endef define Package/addition-trans-zh/description From d8f858a79f0c30f44d6b377710c754365e91736c Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 10 May 2021 16:30:07 +0800 Subject: [PATCH 078/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index bb004c135..96383527d 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -20,7 +20,7 @@ wget -P include/ https://github.com/immortalwrt/immortalwrt/raw/master/include/d wget -P include/ https://github.com/immortalwrt/immortalwrt/raw/master/include/package-immortalwrt.mk sed -i '/unshift/d' scripts/download.pl sed -i '/mirror02/d' scripts/download.pl -echo "net.netfilter.nf_conntrack_helper = 1" >> ./package/kernel/linux/files/sysctl-nf-conntrack.conf +#echo "net.netfilter.nf_conntrack_helper = 1" >> ./package/kernel/linux/files/sysctl-nf-conntrack.conf #临时补丁 #wget -qO - https://github.com/openwrt/openwrt/commit/7fae64.patch | patch -p1 From ac4587f59bbb6844293c70992efb8d37c3defbea Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 10 May 2021 21:29:52 +0800 Subject: [PATCH 079/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 96383527d..a8e2539eb 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -294,6 +294,7 @@ sed -i '/V2ray:v2ray/d' package/lean/luci-app-vssr/Makefile sed -i '/plugin:v2ray/d' package/lean/luci-app-vssr/Makefile sed -i 's,+shadowsocksr-libev-alt ,,g' package/lean/luci-app-vssr/Makefile sed -i '/Server:shadowsocksr-libev-server/d' package/lean/luci-app-vssr/Makefile +sed -i 's,xray\-plugin \\,xray\-plugin,g' package/lean/luci-app-vssr/Makefile sed -i '/result.encrypt_method/a\result.fast_open = "1"' package/lean/luci-app-vssr/root/usr/share/vssr/subscribe.lua sed -i 's,ispip.clang.cn/all_cn.txt,raw.sevencdn.com/QiuSimons/Chnroute/master/dist/chnroute/chnroute.txt,g' package/lean/luci-app-vssr/luasrc/controller/vssr.lua sed -i 's,ispip.clang.cn/all_cn.txt,raw.sevencdn.com/QiuSimons/Chnroute/master/dist/chnroute/chnroute.txt,g' package/lean/luci-app-vssr/root/usr/share/vssr/update.lua From 7fe0c9ceb385aea8b44085decd50b3a8b340b400 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 12 May 2021 11:41:23 +0800 Subject: [PATCH 080/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index a8e2539eb..86f2aa5c4 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -257,7 +257,7 @@ svn co https://github.com/immortalwrt/packages/trunk/net/shadowsocks-rust packag svn co https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/lean/luci-app-ssr-plus rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans pushd package/lean -wget -qO - https://github.com/fw876/helloworld/pull/513.patch | patch -p1 +#wget -qO - https://github.com/fw876/helloworld/pull/513.patch | patch -p1 wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/c1674ad.patch | patch -p1 popd pushd package/lean/luci-app-ssr-plus From c65e380a3e1cd6eb49d9b5b0afc9957dbccd4cb3 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 12 May 2021 15:18:50 +0800 Subject: [PATCH 081/244] Update config.seed --- SEED/R2S/config.seed | 1 + 1 file changed, 1 insertion(+) diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 502995045..176f5980d 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -16,6 +16,7 @@ CONFIG_TOOLCHAINOPTS=y CONFIG_GCC_USE_VERSION_9=y ### BASIC ### +CONFIG_PACKAGE_r8169-firmware=y CONFIG_PACKAGE_addition-trans-zh=y CONFIG_PACKAGE_arm-trusted-firmware-rockchip=y CONFIG_PACKAGE_autocore-arm=y From 2abbd50c6d84fd49913ad1e780a02e7abf302c09 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 12 May 2021 15:19:10 +0800 Subject: [PATCH 082/244] Update config.seed --- SEED/R4S/config.seed | 1 + 1 file changed, 1 insertion(+) diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index 887d0c11e..b87fac707 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -16,6 +16,7 @@ CONFIG_TOOLCHAINOPTS=y CONFIG_GCC_USE_VERSION_9=y ### BASIC ### +CONFIG_PACKAGE_r8169-firmware=y CONFIG_PACKAGE_addition-trans-zh=y CONFIG_PACKAGE_arm-trusted-firmware-rockchip=y CONFIG_PACKAGE_autocore-arm=y From 82f4ac73c3115cc54190dcc20612980fe854890a Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 12 May 2021 17:24:38 +0800 Subject: [PATCH 083/244] Revert "Update config.seed" This reverts commit 2abbd50c6d84fd49913ad1e780a02e7abf302c09. --- SEED/R4S/config.seed | 1 - 1 file changed, 1 deletion(-) diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index b87fac707..887d0c11e 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -16,7 +16,6 @@ CONFIG_TOOLCHAINOPTS=y CONFIG_GCC_USE_VERSION_9=y ### BASIC ### -CONFIG_PACKAGE_r8169-firmware=y CONFIG_PACKAGE_addition-trans-zh=y CONFIG_PACKAGE_arm-trusted-firmware-rockchip=y CONFIG_PACKAGE_autocore-arm=y From 72e7504463d739def1c4742c50e6c454f2591292 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 12 May 2021 17:24:41 +0800 Subject: [PATCH 084/244] Revert "Update config.seed" This reverts commit c65e380a3e1cd6eb49d9b5b0afc9957dbccd4cb3. --- SEED/R2S/config.seed | 1 - 1 file changed, 1 deletion(-) diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 176f5980d..502995045 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -16,7 +16,6 @@ CONFIG_TOOLCHAINOPTS=y CONFIG_GCC_USE_VERSION_9=y ### BASIC ### -CONFIG_PACKAGE_r8169-firmware=y CONFIG_PACKAGE_addition-trans-zh=y CONFIG_PACKAGE_arm-trusted-firmware-rockchip=y CONFIG_PACKAGE_autocore-arm=y From 4391281a5657f45914f8de8807ef9b03f2d3bb13 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 12 May 2021 17:46:11 +0800 Subject: [PATCH 085/244] Revert "Revert "Update config.seed"" This reverts commit 72e7504463d739def1c4742c50e6c454f2591292. --- SEED/R2S/config.seed | 1 + 1 file changed, 1 insertion(+) diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 502995045..176f5980d 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -16,6 +16,7 @@ CONFIG_TOOLCHAINOPTS=y CONFIG_GCC_USE_VERSION_9=y ### BASIC ### +CONFIG_PACKAGE_r8169-firmware=y CONFIG_PACKAGE_addition-trans-zh=y CONFIG_PACKAGE_arm-trusted-firmware-rockchip=y CONFIG_PACKAGE_autocore-arm=y From f85ee20267790fdd20115aadf2530dde2c18cb1e Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 12 May 2021 17:46:15 +0800 Subject: [PATCH 086/244] Revert "Revert "Update config.seed"" This reverts commit 82f4ac73c3115cc54190dcc20612980fe854890a. --- SEED/R4S/config.seed | 1 + 1 file changed, 1 insertion(+) diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index 887d0c11e..b87fac707 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -16,6 +16,7 @@ CONFIG_TOOLCHAINOPTS=y CONFIG_GCC_USE_VERSION_9=y ### BASIC ### +CONFIG_PACKAGE_r8169-firmware=y CONFIG_PACKAGE_addition-trans-zh=y CONFIG_PACKAGE_arm-trusted-firmware-rockchip=y CONFIG_PACKAGE_autocore-arm=y From 2f233c06a0dc69dd469ce5a8f4905e933d00501c Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 17 May 2021 13:58:42 +0800 Subject: [PATCH 087/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 86f2aa5c4..565d415f7 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -15,9 +15,9 @@ sed -i 's,-SNAPSHOT,,g' package/base-files/image-config.in # 维多利亚的秘密 rm -rf ./scripts/download.pl rm -rf ./include/download.mk -wget -P scripts/ https://github.com/immortalwrt/immortalwrt/raw/master/scripts/download.pl -wget -P include/ https://github.com/immortalwrt/immortalwrt/raw/master/include/download.mk -wget -P include/ https://github.com/immortalwrt/immortalwrt/raw/master/include/package-immortalwrt.mk +wget -P scripts/ https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/scripts/download.pl +wget -P include/ https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/include/download.mk +wget -P include/ https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/include/package-immortalwrt.mk sed -i '/unshift/d' scripts/download.pl sed -i '/mirror02/d' scripts/download.pl #echo "net.netfilter.nf_conntrack_helper = 1" >> ./package/kernel/linux/files/sysctl-nf-conntrack.conf From 0032daa2b59f4bee6dc05366cb4722d5a761e887 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 17 May 2021 21:52:31 +0800 Subject: [PATCH 088/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 565d415f7..393505928 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -306,7 +306,7 @@ git clone -b master --depth 1 https://github.com/brvphoenix/luci-app-wrtbwmon.gi # 迅雷快鸟宽带加速 git clone --depth 1 https://github.com/garypang13/luci-app-xlnetacc.git package/lean/luci-app-xlnetacc # Zerotier -svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/lean/luci-app-zerotier package/lean/luci-app-zerotier +svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-zerotier package/lean/luci-app-zerotier cp -f ../PATCH/new/script/move_2_services.sh ./package/lean/luci-app-zerotier/move_2_services.sh pushd package/lean/luci-app-zerotier bash move_2_services.sh From d1c8887ee9b1dca6158559099b6b01259e773b70 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 17 May 2021 21:55:23 +0800 Subject: [PATCH 089/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 393505928..4072c4dd6 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -62,7 +62,7 @@ cp -f ../PATCH/duplicate/shortcut-fe ./package/base-files/files/etc/init.d ### 获取额外的基础软件包 ### # AutoCore -svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/lean/autocore package/lean/autocore +svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/emortal/autocore package/lean/autocore #wget -qO - https://github.com/immortalwrt/immortalwrt/commit/13d6e338f1f7eba45e1aada749ac74fc391b9216.patch | patch -Rp1 rm -rf ./feeds/packages/utils/coremark svn co https://github.com/immortalwrt/packages/trunk/utils/coremark feeds/packages/utils/coremark From 148a989059fee762cc7405ae728c36b6a9e6e52f Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 17 May 2021 22:00:57 +0800 Subject: [PATCH 090/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 4072c4dd6..523cf570d 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -132,7 +132,7 @@ cp -rf ../NoTengoBattery/feeds/luci/applications/luci-app-compressed-memory ./pa sed -i 's,include ../..,include $(TOPDIR)/feeds/luci,g' ./package/new/luci-app-compressed-memory/Makefile cp -rf ../NoTengoBattery/package/system/compressed-memory ./package/system/compressed-memory # CPU 控制相关 -svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/lean/luci-app-cpufreq package/lean/luci-app-cpufreq +svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-cpufreq package/lean/luci-app-cpufreq cp -rf ../PATCH/duplicate/luci-app-cpulimit ./package/lean/luci-app-cpulimit svn co https://github.com/immortalwrt/packages/trunk/utils/cpulimit package/lean/cpulimit # 动态DNS From 6ffb4447171f5f3941271bce4d05c761cec88738 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 17 May 2021 22:21:44 +0800 Subject: [PATCH 091/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 38 +++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 523cf570d..277498545 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -63,7 +63,6 @@ cp -f ../PATCH/duplicate/shortcut-fe ./package/base-files/files/etc/init.d ### 获取额外的基础软件包 ### # AutoCore svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/emortal/autocore package/lean/autocore -#wget -qO - https://github.com/immortalwrt/immortalwrt/commit/13d6e338f1f7eba45e1aada749ac74fc391b9216.patch | patch -Rp1 rm -rf ./feeds/packages/utils/coremark svn co https://github.com/immortalwrt/packages/trunk/utils/coremark feeds/packages/utils/coremark # 更换 Nodejs 版本 @@ -132,9 +131,11 @@ cp -rf ../NoTengoBattery/feeds/luci/applications/luci-app-compressed-memory ./pa sed -i 's,include ../..,include $(TOPDIR)/feeds/luci,g' ./package/new/luci-app-compressed-memory/Makefile cp -rf ../NoTengoBattery/package/system/compressed-memory ./package/system/compressed-memory # CPU 控制相关 -svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-cpufreq package/lean/luci-app-cpufreq +svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-cpufreq feeds/luci/applications/luci-app-cpufreq +ln -sf ../../../feeds/luci/applications/luci-app-cpufreq ./package/feeds/luci/luci-app-cpufreq cp -rf ../PATCH/duplicate/luci-app-cpulimit ./package/lean/luci-app-cpulimit -svn co https://github.com/immortalwrt/packages/trunk/utils/cpulimit package/lean/cpulimit +svn co https://github.com/immortalwrt/packages/trunk/utils/cpulimit feeds/packages/utils/cpulimit +ln -sf ../../../feeds/packages/utils/cpulimit ./package/feeds/packages/cpulimit # 动态DNS #rm -rf ./feeds/packages/net/ddns-scripts #rm -rf ./feeds/luci/applications/luci-app-ddns @@ -198,7 +199,7 @@ svn co https://github.com/teasiu/dragino2/trunk/devices/common/diy/package/teasi svn co https://github.com/teasiu/dragino2/trunk/devices/common/diy/package/teasiu/phtunnel package/new/phtunnel svn co https://github.com/QiuSimons/dragino2-teasiu/trunk/package/teasiu/luci-app-oray package/new/luci-app-oray # Pandownload -svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/lean/pandownload-fake-server package/lean/pandownload-fake-server +#svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/lean/pandownload-fake-server package/lean/pandownload-fake-server # Passwall svn co https://github.com/xiaorouji/openwrt-passwall/trunk/luci-app-passwall package/new/luci-app-passwall sed -i 's,default n,default y,g' package/new/luci-app-passwall/Makefile @@ -221,7 +222,8 @@ svn co https://github.com/xiaorouji/openwrt-passwall/trunk/xray-plugin package/n # qBittorrent 下载 svn co https://github.com/garypang13/openwrt-static-qb/trunk/qBittorrent-Enhanced-Edition package/lean/qBittorrent-Enhanced-Edition sed -i 's/4.3.3.10/4.3.4.10/g' package/lean/qBittorrent-Enhanced-Edition/Makefile -svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/lean/luci-app-qbittorrent package/lean/luci-app-qbittorrent +svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-qbittorrent feeds/luci/applications/luci-app-qbittorrent +ln -sf ../../../feeds/luci/applications/luci-app-qbittorrent ./package/feeds/luci/luci-app-qbittorrent # 清理内存 svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-ramfree package/lean/luci-app-ramfree # ServerChan 微信推送 @@ -251,8 +253,8 @@ svn co https://github.com/coolsnowwolf/packages/trunk/net/shadowsocks-libev pack svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/trojan package/lean/trojan svn co https://github.com/fw876/helloworld/trunk/naiveproxy package/lean/naiveproxy svn co https://github.com/fw876/helloworld/trunk/v2ray-core package/lean/v2ray-core -svn co https://github.com/immortalwrt/packages/trunk/net/shadowsocks-rust package/lean/shadowsocks-rust -#svn co https://github.com/fw876/helloworld/trunk/shadowsocks-rust package/lean/shadowsocks-rust +svn co https://github.com/immortalwrt/packages/trunk/net/shadowsocks-rust feeds/packages/net/shadowsocks-rust +ln -sf ../../../feeds/packages/net/shadowsocks-rust ./package/feeds/packages/shadowsocks-rust # ShadowsocksR Plus+ svn co https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/lean/luci-app-ssr-plus rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans @@ -271,11 +273,16 @@ sed -i 's,YW5vbnltb3Vz/domain-list-community/release/gfwlist.txt,Loyalsoldier/v2 sed -i '/Clang.CN.CIDR/a\o:value("https://cdn.jsdelivr.net/gh/QiuSimons/Chnroute@master/dist/chnroute/chnroute.txt", translate("QiuSimons/Chnroute"))' luasrc/model/cbi/shadowsocksr/advanced.lua popd # 订阅转换 -svn co https://github.com/immortalwrt/packages/trunk/net/subconverter package/new/subconverter -svn co https://github.com/immortalwrt/packages/trunk/libs/jpcre2 package/new/jpcre2 -svn co https://github.com/immortalwrt/packages/trunk/libs/rapidjson package/new/rapidjson -svn co https://github.com/immortalwrt/packages/trunk/libs/libcron package/new/libcron -svn co https://github.com/immortalwrt/packages/trunk/libs/quickjspp package/new/quickjspp +svn co https://github.com/immortalwrt/packages/trunk/net/subconverter feeds/packages/net/subconverter +ln -sf ../../../feeds/packages/net/subconverter ./package/feeds/packages/subconverter +svn co https://github.com/immortalwrt/packages/trunk/libs/jpcre2 feeds/packages/libs/jpcre2 +ln -sf ../../../feeds/packages/libs/jpcre2 ./package/feeds/packages/jpcre2 +svn co https://github.com/immortalwrt/packages/trunk/libs/rapidjson feeds/packages/libs/rapidjson +ln -sf ../../../feeds/packages/libs/rapidjson ./package/feeds/packages/rapidjson +svn co https://github.com/immortalwrt/packages/trunk/libs/libcron feeds/packages/libs/libcron +ln -sf ../../../feeds/packages/libs/libcron ./package/feeds/packages/libcron +svn co https://github.com/immortalwrt/packages/trunk/libs/quickjspp feeds/packages/libs/quickjspp +ln -sf ../../../feeds/packages/libs/quickjspp ./package/feeds/packages/quickjspp # 网易云音乐解锁 git clone --depth 1 https://github.com/immortalwrt/luci-app-unblockneteasemusic.git package/new/UnblockNeteaseMusic # USB 打印机 @@ -306,11 +313,12 @@ git clone -b master --depth 1 https://github.com/brvphoenix/luci-app-wrtbwmon.gi # 迅雷快鸟宽带加速 git clone --depth 1 https://github.com/garypang13/luci-app-xlnetacc.git package/lean/luci-app-xlnetacc # Zerotier -svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-zerotier package/lean/luci-app-zerotier -cp -f ../PATCH/new/script/move_2_services.sh ./package/lean/luci-app-zerotier/move_2_services.sh -pushd package/lean/luci-app-zerotier +svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-zerotier feeds/luci/applications/luci-app-zerotier +cp -f ../PATCH/new/script/move_2_services.sh ./feeds/luci/applications/luci-app-zerotier/move_2_services.sh +pushd feeds/luci/applications/luci-app-zerotier bash move_2_services.sh popd +ln -sf ../../../feeds/luci/applications/luci-app-zerotier ./package/feeds/luci/luci-app-zerotier rm -rf ./feeds/packages/net/zerotier/files/etc/init.d/zerotier From f69d83557181bf7db151f06a3c36f285ada8227a Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 17 May 2021 22:25:21 +0800 Subject: [PATCH 092/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 277498545..854b71f35 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -299,9 +299,6 @@ git clone -b master --depth 1 https://github.com/jerrykuku/lua-maxminddb.git pac sed -i 's,default n,default y,g' package/lean/luci-app-vssr/Makefile sed -i '/V2ray:v2ray/d' package/lean/luci-app-vssr/Makefile sed -i '/plugin:v2ray/d' package/lean/luci-app-vssr/Makefile -sed -i 's,+shadowsocksr-libev-alt ,,g' package/lean/luci-app-vssr/Makefile -sed -i '/Server:shadowsocksr-libev-server/d' package/lean/luci-app-vssr/Makefile -sed -i 's,xray\-plugin \\,xray\-plugin,g' package/lean/luci-app-vssr/Makefile sed -i '/result.encrypt_method/a\result.fast_open = "1"' package/lean/luci-app-vssr/root/usr/share/vssr/subscribe.lua sed -i 's,ispip.clang.cn/all_cn.txt,raw.sevencdn.com/QiuSimons/Chnroute/master/dist/chnroute/chnroute.txt,g' package/lean/luci-app-vssr/luasrc/controller/vssr.lua sed -i 's,ispip.clang.cn/all_cn.txt,raw.sevencdn.com/QiuSimons/Chnroute/master/dist/chnroute/chnroute.txt,g' package/lean/luci-app-vssr/root/usr/share/vssr/update.lua From d7f91466b66755f4063b850e9a9ee5a90552f5f7 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 24 May 2021 15:36:44 +0800 Subject: [PATCH 093/244] Update AdGuardHome.yaml --- PATCH/R2S/files/etc/config/AdGuardHome.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PATCH/R2S/files/etc/config/AdGuardHome.yaml b/PATCH/R2S/files/etc/config/AdGuardHome.yaml index 14be8f1e4..f62f0d275 100644 --- a/PATCH/R2S/files/etc/config/AdGuardHome.yaml +++ b/PATCH/R2S/files/etc/config/AdGuardHome.yaml @@ -89,11 +89,11 @@ filters: name: Peter Lowe's List id: 1595502661 - enabled: true - url: https://raw.sevencdn.com/hoshsadiq/adblock-nocoin-list/master/nocoin.txt + url: https://cdn.jsdelivr.net/gh/hoshsadiq/adblock-nocoin-list@master/nocoin.txt name: NoCoin Filter List id: 1595502662 - enabled: true - url: https://gitee.com/xinggsf/Adblock-Rule/raw/master/rule.txt + url: https://cdn.jsdelivr.net/gh/xinggsf/Adblock-Plus-Rule@master/rule.txt name: 乘风 广告过滤规则 id: 1600600707 - enabled: true @@ -101,11 +101,11 @@ filters: name: 乘风 视频广告过滤规则 id: 1600600708 - enabled: true - url: https://raw.sevencdn.com/cjx82630/cjxlist/master/cjx-ublock.txt + url: https://cdn.jsdelivr.net/gh/cjx82630/cjxlist@master/cjx-ublock.txt name: CJX's uBlock list id: 1600600709 - enabled: true - url: https://raw.sevencdn.com/cjx82630/cjxlist/master/cjx-annoyance.txt + url: https://cdn.jsdelivr.net/gh/cjx82630/cjxlist@master/cjx-annoyance.txt name: CJX's Annoyance List id: 1600600710 - enabled: true From 5127e6d3acbcf3d7e3c1b9165adbd3458bd00fc7 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 24 May 2021 15:37:01 +0800 Subject: [PATCH 094/244] Update AdGuardHome.yaml --- PATCH/R4S/files/etc/config/AdGuardHome.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PATCH/R4S/files/etc/config/AdGuardHome.yaml b/PATCH/R4S/files/etc/config/AdGuardHome.yaml index 14be8f1e4..f62f0d275 100644 --- a/PATCH/R4S/files/etc/config/AdGuardHome.yaml +++ b/PATCH/R4S/files/etc/config/AdGuardHome.yaml @@ -89,11 +89,11 @@ filters: name: Peter Lowe's List id: 1595502661 - enabled: true - url: https://raw.sevencdn.com/hoshsadiq/adblock-nocoin-list/master/nocoin.txt + url: https://cdn.jsdelivr.net/gh/hoshsadiq/adblock-nocoin-list@master/nocoin.txt name: NoCoin Filter List id: 1595502662 - enabled: true - url: https://gitee.com/xinggsf/Adblock-Rule/raw/master/rule.txt + url: https://cdn.jsdelivr.net/gh/xinggsf/Adblock-Plus-Rule@master/rule.txt name: 乘风 广告过滤规则 id: 1600600707 - enabled: true @@ -101,11 +101,11 @@ filters: name: 乘风 视频广告过滤规则 id: 1600600708 - enabled: true - url: https://raw.sevencdn.com/cjx82630/cjxlist/master/cjx-ublock.txt + url: https://cdn.jsdelivr.net/gh/cjx82630/cjxlist@master/cjx-ublock.txt name: CJX's uBlock list id: 1600600709 - enabled: true - url: https://raw.sevencdn.com/cjx82630/cjxlist/master/cjx-annoyance.txt + url: https://cdn.jsdelivr.net/gh/cjx82630/cjxlist@master/cjx-annoyance.txt name: CJX's Annoyance List id: 1600600710 - enabled: true From b842da657e8decfa2c43f39499bb3e13611051c6 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 24 May 2021 15:37:16 +0800 Subject: [PATCH 095/244] Update AdGuardHome.yaml --- PATCH/X86/files/etc/config/AdGuardHome.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PATCH/X86/files/etc/config/AdGuardHome.yaml b/PATCH/X86/files/etc/config/AdGuardHome.yaml index 14be8f1e4..f62f0d275 100644 --- a/PATCH/X86/files/etc/config/AdGuardHome.yaml +++ b/PATCH/X86/files/etc/config/AdGuardHome.yaml @@ -89,11 +89,11 @@ filters: name: Peter Lowe's List id: 1595502661 - enabled: true - url: https://raw.sevencdn.com/hoshsadiq/adblock-nocoin-list/master/nocoin.txt + url: https://cdn.jsdelivr.net/gh/hoshsadiq/adblock-nocoin-list@master/nocoin.txt name: NoCoin Filter List id: 1595502662 - enabled: true - url: https://gitee.com/xinggsf/Adblock-Rule/raw/master/rule.txt + url: https://cdn.jsdelivr.net/gh/xinggsf/Adblock-Plus-Rule@master/rule.txt name: 乘风 广告过滤规则 id: 1600600707 - enabled: true @@ -101,11 +101,11 @@ filters: name: 乘风 视频广告过滤规则 id: 1600600708 - enabled: true - url: https://raw.sevencdn.com/cjx82630/cjxlist/master/cjx-ublock.txt + url: https://cdn.jsdelivr.net/gh/cjx82630/cjxlist@master/cjx-ublock.txt name: CJX's uBlock list id: 1600600709 - enabled: true - url: https://raw.sevencdn.com/cjx82630/cjxlist/master/cjx-annoyance.txt + url: https://cdn.jsdelivr.net/gh/cjx82630/cjxlist@master/cjx-annoyance.txt name: CJX's Annoyance List id: 1600600710 - enabled: true From a6d1545b0675b6f79cdc4e369a90508e6edb80bc Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 25 May 2021 01:22:11 +0800 Subject: [PATCH 096/244] Update cpufreq --- PATCH/R4S/files/etc/config/cpufreq | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/PATCH/R4S/files/etc/config/cpufreq b/PATCH/R4S/files/etc/config/cpufreq index 76ee64e3d..90c939999 100644 --- a/PATCH/R4S/files/etc/config/cpufreq +++ b/PATCH/R4S/files/etc/config/cpufreq @@ -1,8 +1,9 @@ config settings 'cpufreq' option governor0 'schedutil' - option minfreq0 '816000' - option maxfreq0 '1800000' option governor4 'schedutil' - option minfreq4 '816000' + option maxfreq0 '1800000' option maxfreq4 '2208000' + option minfreq4 '816000' + option minfreq0 '816000' + From 091dd2c4e720185c705cc3121504b448693164a7 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 25 May 2021 01:24:31 +0800 Subject: [PATCH 097/244] Update cpufreq --- PATCH/R4S/files/etc/config/cpufreq | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PATCH/R4S/files/etc/config/cpufreq b/PATCH/R4S/files/etc/config/cpufreq index 90c939999..60bc38de3 100644 --- a/PATCH/R4S/files/etc/config/cpufreq +++ b/PATCH/R4S/files/etc/config/cpufreq @@ -1,9 +1,9 @@ config settings 'cpufreq' option governor0 'schedutil' - option governor4 'schedutil' + option minfreq0 '816000' option maxfreq0 '1800000' - option maxfreq4 '2208000' + option governor4 'schedutil' option minfreq4 '816000' - option minfreq0 '816000' + option maxfreq4 '2208000' From 9f44d0ca4b1a758e4a06b98e30e33b9520f1a993 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 25 May 2021 01:26:28 +0800 Subject: [PATCH 098/244] Update cpufreq --- PATCH/R2S/files/etc/config/cpufreq | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/PATCH/R2S/files/etc/config/cpufreq b/PATCH/R2S/files/etc/config/cpufreq index d96f08c9b..13a5486d2 100644 --- a/PATCH/R2S/files/etc/config/cpufreq +++ b/PATCH/R2S/files/etc/config/cpufreq @@ -1,5 +1,6 @@ config settings 'cpufreq' option governor0 'schedutil' - option minfreq0 '1008000' + option minfreq0 '816000' option maxfreq0 '1608000' + From 90f24fb0cdd575ea5848d9353ddd35d32bcc7daa Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sun, 30 May 2021 18:42:42 +0800 Subject: [PATCH 099/244] Update 02_target_only.sh --- SCRIPTS/R4S/02_target_only.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index b72f9ae27..4e7bc4413 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -31,6 +31,9 @@ sed -i '/set_interface_core 20 "eth1"/a\ethtool -C eth0 rx-usecs 1000 rx-frames # 翻译及部分功能优化 cp -rf ../PATCH/duplicate/addition-trans-zh ./package/lean/lean-translate +sed -i "/commit luci/a\uci set cpufreq.cpufreq.maxfreq0='1800000'" ./package/lean/lean-translate/files/zzz-default-settings +sed -i "/commit luci/a\uci set cpufreq.cpufreq.maxfreq4='2208000'" ./package/lean/lean-translate/files/zzz-default-settings +sed -i "/commit luci/a\uci commit cpufreq" ./package/lean/lean-translate/files/zzz-default-settings # 添加 R4S GPU 驱动 rm -rf ./package/kernel/linux/modules/video.mk From 6291700a67ac82a6eef6ad64e8c1c1be7ec5f11b Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sun, 30 May 2021 18:44:28 +0800 Subject: [PATCH 100/244] Update 02_target_only.sh --- SCRIPTS/R2S/02_target_only.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index b39d3e643..2b2dd9370 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -44,6 +44,8 @@ COMMENT # 翻译及部分功能优化 cp -rf ../PATCH/duplicate/addition-trans-zh ./package/lean/lean-translate +sed -i "/commit luci/a\uci commit cpufreq" ./package/lean/lean-translate/files/zzz-default-settings +sed -i "/commit luci/a\uci set cpufreq.cpufreq.maxfreq0='1608000'" ./package/lean/lean-translate/files/zzz-default-settings # 添加 R2S GPU 驱动 rm -rf ./package/kernel/linux/modules/video.mk From aea2a7db2f13fb57693f8af3fa86b2942fff1347 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sun, 30 May 2021 18:45:03 +0800 Subject: [PATCH 101/244] Update 02_target_only.sh --- SCRIPTS/R4S/02_target_only.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index 4e7bc4413..1f7621640 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -31,9 +31,9 @@ sed -i '/set_interface_core 20 "eth1"/a\ethtool -C eth0 rx-usecs 1000 rx-frames # 翻译及部分功能优化 cp -rf ../PATCH/duplicate/addition-trans-zh ./package/lean/lean-translate -sed -i "/commit luci/a\uci set cpufreq.cpufreq.maxfreq0='1800000'" ./package/lean/lean-translate/files/zzz-default-settings -sed -i "/commit luci/a\uci set cpufreq.cpufreq.maxfreq4='2208000'" ./package/lean/lean-translate/files/zzz-default-settings sed -i "/commit luci/a\uci commit cpufreq" ./package/lean/lean-translate/files/zzz-default-settings +sed -i "/commit luci/a\uci set cpufreq.cpufreq.maxfreq4='2208000'" ./package/lean/lean-translate/files/zzz-default-settings +sed -i "/commit luci/a\uci set cpufreq.cpufreq.maxfreq0='1800000'" ./package/lean/lean-translate/files/zzz-default-settings # 添加 R4S GPU 驱动 rm -rf ./package/kernel/linux/modules/video.mk From f108e8e82913119141492dc115e7bb96fd8a6677 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sun, 30 May 2021 18:57:59 +0800 Subject: [PATCH 102/244] Delete cpufreq --- PATCH/R2S/files/etc/config/cpufreq | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 PATCH/R2S/files/etc/config/cpufreq diff --git a/PATCH/R2S/files/etc/config/cpufreq b/PATCH/R2S/files/etc/config/cpufreq deleted file mode 100644 index 13a5486d2..000000000 --- a/PATCH/R2S/files/etc/config/cpufreq +++ /dev/null @@ -1,6 +0,0 @@ - -config settings 'cpufreq' - option governor0 'schedutil' - option minfreq0 '816000' - option maxfreq0 '1608000' - From dfff49a8df63c8d85e71a48cde87db017420df32 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sun, 30 May 2021 18:58:13 +0800 Subject: [PATCH 103/244] Delete cpufreq --- PATCH/R4S/files/etc/config/cpufreq | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 PATCH/R4S/files/etc/config/cpufreq diff --git a/PATCH/R4S/files/etc/config/cpufreq b/PATCH/R4S/files/etc/config/cpufreq deleted file mode 100644 index 60bc38de3..000000000 --- a/PATCH/R4S/files/etc/config/cpufreq +++ /dev/null @@ -1,9 +0,0 @@ - -config settings 'cpufreq' - option governor0 'schedutil' - option minfreq0 '816000' - option maxfreq0 '1800000' - option governor4 'schedutil' - option minfreq4 '816000' - option maxfreq4 '2208000' - From 6e1c7a3ab6aa7ded042dc27029bc06f8225f72c4 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 31 May 2021 10:10:56 +0800 Subject: [PATCH 104/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 854b71f35..9d0791b65 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -133,6 +133,9 @@ cp -rf ../NoTengoBattery/package/system/compressed-memory ./package/system/compr # CPU 控制相关 svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-cpufreq feeds/luci/applications/luci-app-cpufreq ln -sf ../../../feeds/luci/applications/luci-app-cpufreq ./package/feeds/luci/luci-app-cpufreq +sed -i 's,1608,1800,g' feeds/luci/applications/luci-app-cpufreq/root/etc/uci-defaults/cpufreq +sed -i 's,2016,2208,g' feeds/luci/applications/luci-app-cpufreq/root/etc/uci-defaults/cpufreq +sed -i 's,1512,1608,g' feeds/luci/applications/luci-app-cpufreq/root/etc/uci-defaults/cpufreq cp -rf ../PATCH/duplicate/luci-app-cpulimit ./package/lean/luci-app-cpulimit svn co https://github.com/immortalwrt/packages/trunk/utils/cpulimit feeds/packages/utils/cpulimit ln -sf ../../../feeds/packages/utils/cpulimit ./package/feeds/packages/cpulimit From f36f7c0d237e44c0a242f527f84cc0e414043e56 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 31 May 2021 10:11:21 +0800 Subject: [PATCH 105/244] Update 02_target_only.sh --- SCRIPTS/R2S/02_target_only.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index 2b2dd9370..b39d3e643 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -44,8 +44,6 @@ COMMENT # 翻译及部分功能优化 cp -rf ../PATCH/duplicate/addition-trans-zh ./package/lean/lean-translate -sed -i "/commit luci/a\uci commit cpufreq" ./package/lean/lean-translate/files/zzz-default-settings -sed -i "/commit luci/a\uci set cpufreq.cpufreq.maxfreq0='1608000'" ./package/lean/lean-translate/files/zzz-default-settings # 添加 R2S GPU 驱动 rm -rf ./package/kernel/linux/modules/video.mk From f79f4a53dcc60c3be73d4905951d87aecc5f8583 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 31 May 2021 10:11:52 +0800 Subject: [PATCH 106/244] Update 02_target_only.sh --- SCRIPTS/R4S/02_target_only.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index 1f7621640..b72f9ae27 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -31,9 +31,6 @@ sed -i '/set_interface_core 20 "eth1"/a\ethtool -C eth0 rx-usecs 1000 rx-frames # 翻译及部分功能优化 cp -rf ../PATCH/duplicate/addition-trans-zh ./package/lean/lean-translate -sed -i "/commit luci/a\uci commit cpufreq" ./package/lean/lean-translate/files/zzz-default-settings -sed -i "/commit luci/a\uci set cpufreq.cpufreq.maxfreq4='2208000'" ./package/lean/lean-translate/files/zzz-default-settings -sed -i "/commit luci/a\uci set cpufreq.cpufreq.maxfreq0='1800000'" ./package/lean/lean-translate/files/zzz-default-settings # 添加 R4S GPU 驱动 rm -rf ./package/kernel/linux/modules/video.mk From 2da4bc092df3ea73536e0e6bb7459441387763ce Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 31 May 2021 12:37:41 +0800 Subject: [PATCH 107/244] Update R2S-OpenWrt.yml --- .github/workflows/R2S-OpenWrt.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/R2S-OpenWrt.yml b/.github/workflows/R2S-OpenWrt.yml index e8221499e..a1984f92b 100644 --- a/.github/workflows/R2S-OpenWrt.yml +++ b/.github/workflows/R2S-OpenWrt.yml @@ -136,9 +136,9 @@ jobs: id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-R2S-R4S-X86-21.02.0-RC1 + name: OpenWRT-R2S-R4S-X86-21.02.0-RC2 allowUpdates: true - tag: 21.02.0-rc1 + tag: 21.02.0-rc2 commit: master replacesArtifacts: true token: ${{ secrets.workflow_token }} From efd6453a74451114ed9f5cf9eef5469e0e94f112 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 31 May 2021 12:37:59 +0800 Subject: [PATCH 108/244] Update R4S-OpenWrt.yml --- .github/workflows/R4S-OpenWrt.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/R4S-OpenWrt.yml b/.github/workflows/R4S-OpenWrt.yml index ad124dafb..bc5347600 100644 --- a/.github/workflows/R4S-OpenWrt.yml +++ b/.github/workflows/R4S-OpenWrt.yml @@ -136,9 +136,9 @@ jobs: id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-R2S-R4S-X86-21.02.0-RC1 + name: OpenWRT-R2S-R4S-X86-21.02.0-RC2 allowUpdates: true - tag: 21.02.0-rc1 + tag: 21.02.0-rc2 commit: master replacesArtifacts: true token: ${{ secrets.workflow_token }} From 9458c40c73e72cf2c61b903a66bbc8e39cdbd98b Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 31 May 2021 12:38:17 +0800 Subject: [PATCH 109/244] Update X86-OpenWrt.yml --- .github/workflows/X86-OpenWrt.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/X86-OpenWrt.yml b/.github/workflows/X86-OpenWrt.yml index 61be22341..cb44aa15e 100644 --- a/.github/workflows/X86-OpenWrt.yml +++ b/.github/workflows/X86-OpenWrt.yml @@ -136,9 +136,9 @@ jobs: id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-R2S-R4S-X86-21.02.0-RC1 + name: OpenWRT-R2S-R4S-X86-21.02.0-RC2 allowUpdates: true - tag: 21.02.0-rc1 + tag: 21.02.0-rc2 commit: master replacesArtifacts: true token: ${{ secrets.workflow_token }} From c2e8e710969dbb71f87899e80a6aaff210c1d406 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 1 Jun 2021 15:30:46 +0800 Subject: [PATCH 110/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 9d0791b65..aedeb0da8 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -270,7 +270,7 @@ sed -i 's,default n,default y,g' Makefile sed -i 's,Xray:xray ,Xray:xray-core ,g' Makefile sed -i '/V2ray:v2ray/d' Makefile sed -i '/plugin:v2ray/d' Makefile -#sed -i '/result.encrypt_method/a\result.fast_open = "1"' root/usr/share/shadowsocksr/subscribe.lua +sed -i '/result.encrypt_method/a\result.fast_open = "1"' root/usr/share/shadowsocksr/subscribe.lua sed -i 's,ispip.clang.cn/all_cn,cdn.jsdelivr.net/gh/QiuSimons/Chnroute@master/dist/chnroute/chnroute,' root/etc/init.d/shadowsocksr sed -i 's,YW5vbnltb3Vz/domain-list-community/release/gfwlist.txt,Loyalsoldier/v2ray-rules-dat/release/gfw.txt,' root/etc/init.d/shadowsocksr luasrc/model/cbi/shadowsocksr/advanced.lua sed -i '/Clang.CN.CIDR/a\o:value("https://cdn.jsdelivr.net/gh/QiuSimons/Chnroute@master/dist/chnroute/chnroute.txt", translate("QiuSimons/Chnroute"))' luasrc/model/cbi/shadowsocksr/advanced.lua From 2fac88adfb637459d85c570b166d01b7b28a048d Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 4 Jun 2021 13:45:31 +0800 Subject: [PATCH 111/244] add support for pwm fan --- SCRIPTS/R2S/02_target_only.sh | 25 ++++--------------------- SCRIPTS/R4S/02_target_only.sh | 5 +++++ 2 files changed, 9 insertions(+), 21 deletions(-) diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index b39d3e643..b05407451 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -12,6 +12,10 @@ rm -rf ./package/boot/uboot-rockchip svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/boot/uboot-rockchip package/boot/uboot-rockchip svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/boot/arm-trusted-firmware-rk3328 package/boot/arm-trusted-firmware-rk3328 +#增加风扇调速(被动散热不香么? +wget -P target/linux/rockchip/armv8/base-files/etc/init.d https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3328/base-files/etc/init.d/fa-rk3328-pwmfan +wget -P target/linux/rockchip/armv8/base-files/usr/bin https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3328/base-files/usr/bin/start-rk3328-pwm-fan.sh + # 配置 IRQ 并默认关闭 eth0 offloading rx/rx sed -i '/set_interface_core 4 "eth1"/a\set_interface_core 8 "ff160000" "ff160000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity sed -i '/set_interface_core 4 "eth1"/a\set_interface_core 1 "ff150000" "ff150000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity @@ -21,27 +25,6 @@ sed -i '/;;/i\ethtool -K eth0 rx off tx off && logger -t disable-offloading "dis sed -i 's,"eth1" "eth0","eth0" "eth1",g' target/linux/rockchip/armv8/base-files/etc/board.d/02_network sed -i "s,'eth1' 'eth0','eth0' 'eth1',g" target/linux/rockchip/armv8/base-files/etc/board.d/02_network -<<'COMMENT' -# 解决 DDR 内存问题 -patch -p1 < ../PATCH/new/main/0001-dmc-rk3328.patch -wget -P target/linux/rockchip/patches-5.4 https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/rockchip/patches-5.4/803-PM-devfreq-rockchip-add-devfreq-driver-for-rk3328-dmc.patch -wget -P target/linux/rockchip/patches-5.4 https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/rockchip/patches-5.4/804-clk-rockchip-support-setting-ddr-clock-via-SIP-Version-2-.patch -wget -P target/linux/rockchip/patches-5.4 https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/rockchip/patches-5.4/805-PM-devfreq-rockchip-dfi-add-more-soc-support.patch -wget -P target/linux/rockchip/patches-5.4 https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/rockchip/patches-5.4/806-arm64-dts-rockchip-rk3328-add-dfi-node.patch -wget -P target/linux/rockchip/patches-5.4 https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/rockchip/patches-5.4/807-arm64-dts-nanopi-r2s-add-rk3328-dmc-relate-node.patch -svn co https://github.com/immortalwrt/immortalwrt/branches/master/target/linux/rockchip/files target/linux/rockchip/files -svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/boot/arm-trusted-firmware-rk3328 package/boot/arm-trusted-firmware-rk3328 - -# RK3328 加入 idle 模式 -wget -P target/linux/rockchip/patches-5.4 https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/rockchip/patches-5.4/007-arm64-dts-rockchip-Add-RK3328-idle-state.patch -# 修改内核 DMA 到 2MiB -wget -P target/linux/rockchip/patches-5.4 https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/rockchip/patches-5.4/911-kernel-dma-adjust-default-coherent_pool-to-2MiB.patch -# 超频到 1.6 GHz -wget -P target/linux/rockchip/patches-5.4 https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/rockchip/patches-5.4/991-arm64-dts-rockchip-add-more-cpu-operating-points-for.patch -# 开启 i2c0 -cp -f ../PATCH/new/main/998-rockchip-enable-i2c0-on-NanoPi-R2S.patch ./target/linux/rockchip/patches-5.4/998-rockchip-enable-i2c0-on-NanoPi-R2S.patch -COMMENT - # 翻译及部分功能优化 cp -rf ../PATCH/duplicate/addition-trans-zh ./package/lean/lean-translate diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index b72f9ae27..bef550061 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -17,6 +17,11 @@ cp -f ../PATCH/new/main/213-RK3399-set-critical-CPU-temperature-for-thermal-thro sed -i 's,-mcpu=generic,-march=armv8-a+crypto+crc -mabi=lp64,g' include/target.mk cp -f ../PATCH/new/package/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch ./package/libs/mbedtls/patches/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch sed -i 's,kmod-r8169,kmod-r8168,g' target/linux/rockchip/image/armv8.mk + +#增加风扇调速(被动散热不香么? +wget -P target/linux/rockchip/armv8/base-files/etc/init.d https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3399/base-files/etc/init.d/fa-rk3399-pwmfan +wget -P target/linux/rockchip/armv8/base-files/usr/bin https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3399/base-files/usr/bin/start-rk3399-pwm-fan.sh + # 测试性功能 sed -i '/CRYPTO_DEV_ROCKCHIP/d' ./target/linux/rockchip/armv8/config-5.4 sed -i '/HW_RANDOM_ROCKCHIP/d' ./target/linux/rockchip/armv8/config-5.4 From f2c4602b8b90157e65571780cf89f0b94bbcd8aa Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 4 Jun 2021 15:50:23 +0800 Subject: [PATCH 112/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index aedeb0da8..b35b3c644 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -171,7 +171,8 @@ svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/ipv6-helper packa git clone --depth 1 https://github.com/jerrykuku/node-request.git package/new/node-request svn co -r131 https://github.com/jerrykuku/luci-app-jd-dailybonus/trunk package/new/luci-app-jd-dailybonus pushd package/new/luci-app-jd-dailybonus -sed -i 's/wget-ssl/wget/g' root/usr/share/jd-dailybonus/newapp.sh luasrc/controller/jd-dailybonus.lua +sed -i 's,wget-ssl,wget,g' root/usr/share/jd-dailybonus/newapp.sh luasrc/controller/jd-dailybonus.lua +sed -i 's,* sh,*,g' root/usr/share/jd-dailybonus/newapp.sh popd rm -rf ./package/new/luci-app-jd-dailybonus/root/usr/share/jd-dailybonus/JD_DailyBonus.js wget -P package/new/luci-app-jd-dailybonus/root/usr/share/jd-dailybonus/ https://github.com/NobyDa/Script/raw/master/JD-DailyBonus/JD_DailyBonus.js From a1d1c80ff02ce879eb3216ff8f1e5574e61aef38 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 7 Jun 2021 22:22:41 +0800 Subject: [PATCH 113/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index b35b3c644..2d1d01ddd 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -111,7 +111,7 @@ wget -P ./package/new/luci-theme-argon/luasrc/view/themes/argon -N https://githu wget -P ./package/new/luci-theme-argon/luasrc/view/themes/argon -N https://github.com/jerrykuku/luci-theme-argon/raw/9fdcfc866ca80d8d094d554c6aedc18682661973/luasrc/view/themes/argon/header.htm git clone -b master --depth 1 https://github.com/jerrykuku/luci-app-argon-config.git package/new/luci-app-argon-config # MAC 地址与 IP 绑定 -svn co https://github.com/QiuSimons/OpenWrt_luci-app/trunk/lean/luci-app-arpbind package/lean/luci-app-arpbind +svn co https://github.com/QiuSimons/OpenWrt_luci-app/trunk/luci-app-arpbind package/lean/luci-app-arpbind # 定时重启 svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-autoreboot package/lean/luci-app-autoreboot # Boost 通用即插即用 From acb3f21fe659d5d109075444e03f524260efca18 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 14 Jun 2021 14:35:34 +0800 Subject: [PATCH 114/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 2d1d01ddd..27e01ac30 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -107,8 +107,8 @@ sed -i '/\t)/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DI sed -i '/init/d' feeds/packages/net/adguardhome/Makefile # Argon 主题 git clone -b master --depth 1 https://github.com/jerrykuku/luci-theme-argon.git package/new/luci-theme-argon -wget -P ./package/new/luci-theme-argon/luasrc/view/themes/argon -N https://github.com/jerrykuku/luci-theme-argon/raw/9fdcfc866ca80d8d094d554c6aedc18682661973/luasrc/view/themes/argon/footer.htm -wget -P ./package/new/luci-theme-argon/luasrc/view/themes/argon -N https://github.com/jerrykuku/luci-theme-argon/raw/9fdcfc866ca80d8d094d554c6aedc18682661973/luasrc/view/themes/argon/header.htm +#wget -P ./package/new/luci-theme-argon/luasrc/view/themes/argon -N https://github.com/jerrykuku/luci-theme-argon/raw/9fdcfc866ca80d8d094d554c6aedc18682661973/luasrc/view/themes/argon/footer.htm +#wget -P ./package/new/luci-theme-argon/luasrc/view/themes/argon -N https://github.com/jerrykuku/luci-theme-argon/raw/9fdcfc866ca80d8d094d554c6aedc18682661973/luasrc/view/themes/argon/header.htm git clone -b master --depth 1 https://github.com/jerrykuku/luci-app-argon-config.git package/new/luci-app-argon-config # MAC 地址与 IP 绑定 svn co https://github.com/QiuSimons/OpenWrt_luci-app/trunk/luci-app-arpbind package/lean/luci-app-arpbind From 6b62c44cfb18f2df3570ec63b3b1185e61527555 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 15 Jun 2021 10:34:11 +0800 Subject: [PATCH 115/244] Update R2S-OpenWrt.yml --- .github/workflows/R2S-OpenWrt.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/R2S-OpenWrt.yml b/.github/workflows/R2S-OpenWrt.yml index a1984f92b..1daa72210 100644 --- a/.github/workflows/R2S-OpenWrt.yml +++ b/.github/workflows/R2S-OpenWrt.yml @@ -136,9 +136,9 @@ jobs: id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-R2S-R4S-X86-21.02.0-RC2 + name: OpenWRT-R2S-R4S-X86-21.02.0-RC3 allowUpdates: true - tag: 21.02.0-rc2 + tag: 21.02.0-rc3 commit: master replacesArtifacts: true token: ${{ secrets.workflow_token }} From bcdb904aedeb49ea4ccb22481fa655f716a9f51a Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 15 Jun 2021 10:34:28 +0800 Subject: [PATCH 116/244] Update R4S-OpenWrt.yml --- .github/workflows/R4S-OpenWrt.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/R4S-OpenWrt.yml b/.github/workflows/R4S-OpenWrt.yml index bc5347600..ac00cd33a 100644 --- a/.github/workflows/R4S-OpenWrt.yml +++ b/.github/workflows/R4S-OpenWrt.yml @@ -136,9 +136,9 @@ jobs: id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-R2S-R4S-X86-21.02.0-RC2 + name: OpenWRT-R2S-R4S-X86-21.02.0-RC3 allowUpdates: true - tag: 21.02.0-rc2 + tag: 21.02.0-rc3 commit: master replacesArtifacts: true token: ${{ secrets.workflow_token }} From 725ce888052699eb98857bb49238a41d96ff0b7b Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 15 Jun 2021 10:34:46 +0800 Subject: [PATCH 117/244] Update X86-OpenWrt.yml --- .github/workflows/X86-OpenWrt.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/X86-OpenWrt.yml b/.github/workflows/X86-OpenWrt.yml index cb44aa15e..663d664c7 100644 --- a/.github/workflows/X86-OpenWrt.yml +++ b/.github/workflows/X86-OpenWrt.yml @@ -136,9 +136,9 @@ jobs: id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-R2S-R4S-X86-21.02.0-RC2 + name: OpenWRT-R2S-R4S-X86-21.02.0-RC3 allowUpdates: true - tag: 21.02.0-rc2 + tag: 21.02.0-rc3 commit: master replacesArtifacts: true token: ${{ secrets.workflow_token }} From 91dba83edffacf93b88900fdad061d67eb4d3780 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 16 Jun 2021 12:57:34 +0800 Subject: [PATCH 118/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 27e01ac30..37489e89f 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -38,7 +38,7 @@ cp -f ../PATCH/new/package/900-add-filter-aaaa-option.patch ./package/network/se ### Fullcone-NAT 部分 ### # Patch Kernel 以解决 FullCone 冲突 pushd target/linux/generic/hack-5.4 -wget https://github.com/coolsnowwolf/lede/raw/master/target/linux/generic/hack-5.4/952-net-conntrack-events-support-multiple-registrant.patch +wget https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/generic/hack-5.4/952-net-conntrack-events-support-multiple-registrant.patch popd # Patch FireWall 以增添 FullCone 功能 mkdir package/network/config/firewall/patches @@ -51,7 +51,7 @@ cp -rf ../openwrt-lienol/package/network/fullconenat ./package/network/fullconen ### Shortcut-FE 部分 ### # Patch Kernel 以支持 Shortcut-FE pushd target/linux/generic/hack-5.4 -wget https://github.com/coolsnowwolf/lede/raw/master/target/linux/generic/hack-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch +wget https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/generic/hack-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch popd # Patch LuCI 以增添 Shortcut-FE 开关 patch -p1 < ../PATCH/new/package/luci-app-firewall_add_sfe_switch.patch @@ -245,7 +245,7 @@ rm -rf ./feeds/packages/net/xray-core #svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/shadowsocksr-libev package/lean/shadowsocksr-libev svn co https://github.com/fw876/helloworld/trunk/shadowsocksr-libev package/lean/shadowsocksr-libev svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/pdnsd-alt package/lean/pdnsd -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/kcptun package/lean/kcptun +#svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/kcptun package/lean/kcptun svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/srelay package/lean/srelay svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/microsocks package/lean/microsocks svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/dns2socks package/lean/dns2socks @@ -259,6 +259,8 @@ svn co https://github.com/fw876/helloworld/trunk/naiveproxy package/lean/naivepr svn co https://github.com/fw876/helloworld/trunk/v2ray-core package/lean/v2ray-core svn co https://github.com/immortalwrt/packages/trunk/net/shadowsocks-rust feeds/packages/net/shadowsocks-rust ln -sf ../../../feeds/packages/net/shadowsocks-rust ./package/feeds/packages/shadowsocks-rust +svn co https://github.com/immortalwrt/packages/trunk/net/kcptun feeds/packages/net/kcptun +ln -sf ../../../feeds/packages/net/kcptun ./package/feeds/packages/kcptun # ShadowsocksR Plus+ svn co https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/lean/luci-app-ssr-plus rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans From 2989a05489b8f396afb3d8378f2e91a59a798fd2 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 17 Jun 2021 18:39:32 +0800 Subject: [PATCH 119/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 37489e89f..406558d3f 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -20,7 +20,7 @@ wget -P include/ https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/in wget -P include/ https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/include/package-immortalwrt.mk sed -i '/unshift/d' scripts/download.pl sed -i '/mirror02/d' scripts/download.pl -#echo "net.netfilter.nf_conntrack_helper = 1" >> ./package/kernel/linux/files/sysctl-nf-conntrack.conf +echo "net.netfilter.nf_conntrack_helper = 1" >> ./package/kernel/linux/files/sysctl-nf-conntrack.conf #临时补丁 #wget -qO - https://github.com/openwrt/openwrt/commit/7fae64.patch | patch -p1 From 417e4d3d63603f9878e16b4842be1a4b63b06bb7 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 21 Jun 2021 11:22:33 +0800 Subject: [PATCH 120/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 406558d3f..05811cb3f 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -84,7 +84,8 @@ rm -rf ./feeds/packages/lang/node-yarn svn co https://github.com/nxhack/openwrt-node-packages/trunk/node-yarn feeds/packages/lang/node-yarn ln -sf ../../../feeds/packages/lang/node-yarn ./package/feeds/packages/node-yarn # R8168驱动 -svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/kernel/r8168 package/new/r8168 +#svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/kernel/r8168 package/new/r8168 +git clone -b master --depth 1 https://github.com/BROBIRD/openwrt-r8168.git package/new/r8168 #patch -p1 < ../PATCH/new/main/r8168-fix_LAN_led-for_r4s-from_TL.patch # UPX 可执行软件压缩 sed -i '/patchelf pkgconf/i\tools-y += ucl upx' ./tools/Makefile From da280b2b43a289c70cf7d7fa8e9226caafd0182f Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 21 Jun 2021 11:28:55 +0800 Subject: [PATCH 121/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 05811cb3f..483cd9b6f 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -108,6 +108,7 @@ sed -i '/\t)/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DI sed -i '/init/d' feeds/packages/net/adguardhome/Makefile # Argon 主题 git clone -b master --depth 1 https://github.com/jerrykuku/luci-theme-argon.git package/new/luci-theme-argon +wget -P ./package/new/luci-theme-argon/htdocs/luci-static/argon/css -N https://github.com/msylgj/luci-theme-argon/raw/patch-1/htdocs/luci-static/argon/css/dark.css #wget -P ./package/new/luci-theme-argon/luasrc/view/themes/argon -N https://github.com/jerrykuku/luci-theme-argon/raw/9fdcfc866ca80d8d094d554c6aedc18682661973/luasrc/view/themes/argon/footer.htm #wget -P ./package/new/luci-theme-argon/luasrc/view/themes/argon -N https://github.com/jerrykuku/luci-theme-argon/raw/9fdcfc866ca80d8d094d554c6aedc18682661973/luasrc/view/themes/argon/header.htm git clone -b master --depth 1 https://github.com/jerrykuku/luci-app-argon-config.git package/new/luci-app-argon-config From 13a134a0e1ef2e1fd1326e140844f4b63c3945de Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 23 Jun 2021 14:38:21 +0800 Subject: [PATCH 122/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 483cd9b6f..c1bcd422e 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -277,7 +277,7 @@ sed -i '/V2ray:v2ray/d' Makefile sed -i '/plugin:v2ray/d' Makefile sed -i '/result.encrypt_method/a\result.fast_open = "1"' root/usr/share/shadowsocksr/subscribe.lua sed -i 's,ispip.clang.cn/all_cn,cdn.jsdelivr.net/gh/QiuSimons/Chnroute@master/dist/chnroute/chnroute,' root/etc/init.d/shadowsocksr -sed -i 's,YW5vbnltb3Vz/domain-list-community/release/gfwlist.txt,Loyalsoldier/v2ray-rules-dat/release/gfw.txt,' root/etc/init.d/shadowsocksr luasrc/model/cbi/shadowsocksr/advanced.lua +sed -i 's,YW5vbnltb3Vz/domain-list-community/release/gfwlist.txt,Loyalsoldier/v2ray-rules-dat/release/gfw.txt,' root/etc/init.d/shadowsocksr sed -i '/Clang.CN.CIDR/a\o:value("https://cdn.jsdelivr.net/gh/QiuSimons/Chnroute@master/dist/chnroute/chnroute.txt", translate("QiuSimons/Chnroute"))' luasrc/model/cbi/shadowsocksr/advanced.lua popd # 订阅转换 From 116a8429b4c4dfd8909d3ce9ca1ada002fee71a2 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 25 Jun 2021 15:10:36 +0800 Subject: [PATCH 123/244] do some cleanup --- PATCH/R4S/files/etc/config/AdGuardHome | 14 - PATCH/R4S/files/etc/config/AdGuardHome.yaml | 141 -- PATCH/R4S/files/etc/config/cpulimit | 6 - PATCH/R4S/files/etc/config/smartdns | 54 - PATCH/R4S/files/etc/ssrplus/black.list | 3 - PATCH/R4S/files/etc/ssrplus/white.list | 10 - PATCH/X86/files/etc/config/AdGuardHome | 14 - PATCH/X86/files/etc/config/AdGuardHome.yaml | 141 -- PATCH/X86/files/etc/config/cpulimit | 6 - PATCH/X86/files/etc/config/smartdns | 54 - PATCH/X86/files/etc/ssrplus/black.list | 3 - PATCH/X86/files/etc/ssrplus/white.list | 10 - .../900-add-filter-aaaa-option.patch | 0 .../dnsmasq-add-filter-aaaa-option.patch | 0 .../luci-add-filter-aaaa-option.patch | 0 PATCH/duplicate/addition-trans-zh/Makefile | 47 - .../files/zzz-default-settings | 100 -- .../addition-trans-zh/i18n/default.zh_Hans.po | 234 ---- .../addition-trans-zh/i18n/more.zh_Hans.po | 1211 ----------------- .../addition-trans-zh/status/status.lua | 250 ---- .../luci-app-control-weburl/Makefile | 18 - .../luasrc/controller/weburl.lua | 10 - .../luasrc/model/cbi/weburl.lua | 65 - .../po/zh-cn/weburl.po | 2 - .../root/etc/config/weburl | 27 - .../root/etc/init.d/weburl | 65 - .../etc/uci-defaults/luci-app-control-weburl | 11 - PATCH/duplicate/luci-app-cpulimit/Makefile | 14 - .../luasrc/controller/cpulimit.lua | 13 - .../luasrc/model/cbi/cpulimit.lua | 38 - .../luci-app-cpulimit/po/zh_Hans/cpulimit.po | 30 - .../root/etc/config/cpulimit | 6 - .../root/etc/init.d/cpulimit | 17 - .../root/etc/uci-defaults/luci-app-cpulimit | 13 - .../root/usr/bin/cpulimit.sh | 36 - .../share/rpcd/acl.d/luci-app-cpulimit.json | 11 - PATCH/duplicate/shortcut-fe | 52 - PATCH/{R2S => }/files/etc/config/AdGuardHome | 0 .../files/etc/config/AdGuardHome.yaml | 0 PATCH/{R2S => }/files/etc/config/cpulimit | 0 PATCH/{R2S => }/files/etc/config/smartdns | 0 PATCH/{R2S => }/files/etc/ssrplus/black.list | 0 PATCH/{R2S => }/files/etc/ssrplus/white.list | 0 .../luci-app-firewall_add_fullcone.patch | 0 .../luci-app-firewall_add_sfe_switch.patch | 0 .../use_json_object_new_int64.patch | 0 ...and-GCM-with-ARMv8-Crypto-Extensions.patch | 0 PATCH/new/main/0001-dmc-rk3328.patch | 88 -- ...isable-eth0-tcp-udp-offloading-tx-rx.patch | 25 - ...8-rockchip-enable-i2c0-on-NanoPi-R2S.patch | 15 - PATCH/new/script/chinadnslist | 13 - PATCH/new/script/fuck | 16 - PATCH/new/script/move_2_services.sh | 21 - .../r8168-fix_LAN_led-for_r4s-from_TL.patch | 0 ...U-temperature-for-thermal-throttling.patch | 0 ...overclock-to-2.2-1.8-GHz-for-NanoPi4.patch | 0 SCRIPTS/02_prepare_package.sh | 31 +- SCRIPTS/R2S/02_target_only.sh | 7 +- SCRIPTS/R4S/02_target_only.sh | 11 +- SCRIPTS/X86/02_target_only.sh | 5 +- 60 files changed, 23 insertions(+), 2935 deletions(-) delete mode 100644 PATCH/R4S/files/etc/config/AdGuardHome delete mode 100644 PATCH/R4S/files/etc/config/AdGuardHome.yaml delete mode 100644 PATCH/R4S/files/etc/config/cpulimit delete mode 100644 PATCH/R4S/files/etc/config/smartdns delete mode 100644 PATCH/R4S/files/etc/ssrplus/black.list delete mode 100644 PATCH/R4S/files/etc/ssrplus/white.list delete mode 100644 PATCH/X86/files/etc/config/AdGuardHome delete mode 100644 PATCH/X86/files/etc/config/AdGuardHome.yaml delete mode 100644 PATCH/X86/files/etc/config/cpulimit delete mode 100644 PATCH/X86/files/etc/config/smartdns delete mode 100644 PATCH/X86/files/etc/ssrplus/black.list delete mode 100644 PATCH/X86/files/etc/ssrplus/white.list rename PATCH/{new/package => dnsmasq}/900-add-filter-aaaa-option.patch (100%) rename PATCH/{new/package => dnsmasq}/dnsmasq-add-filter-aaaa-option.patch (100%) rename PATCH/{new/package => dnsmasq}/luci-add-filter-aaaa-option.patch (100%) delete mode 100644 PATCH/duplicate/addition-trans-zh/Makefile delete mode 100644 PATCH/duplicate/addition-trans-zh/files/zzz-default-settings delete mode 100644 PATCH/duplicate/addition-trans-zh/i18n/default.zh_Hans.po delete mode 100644 PATCH/duplicate/addition-trans-zh/i18n/more.zh_Hans.po delete mode 100644 PATCH/duplicate/addition-trans-zh/status/status.lua delete mode 100644 PATCH/duplicate/luci-app-control-weburl/Makefile delete mode 100644 PATCH/duplicate/luci-app-control-weburl/luasrc/controller/weburl.lua delete mode 100644 PATCH/duplicate/luci-app-control-weburl/luasrc/model/cbi/weburl.lua delete mode 100644 PATCH/duplicate/luci-app-control-weburl/po/zh-cn/weburl.po delete mode 100644 PATCH/duplicate/luci-app-control-weburl/root/etc/config/weburl delete mode 100644 PATCH/duplicate/luci-app-control-weburl/root/etc/init.d/weburl delete mode 100644 PATCH/duplicate/luci-app-control-weburl/root/etc/uci-defaults/luci-app-control-weburl delete mode 100644 PATCH/duplicate/luci-app-cpulimit/Makefile delete mode 100644 PATCH/duplicate/luci-app-cpulimit/luasrc/controller/cpulimit.lua delete mode 100644 PATCH/duplicate/luci-app-cpulimit/luasrc/model/cbi/cpulimit.lua delete mode 100644 PATCH/duplicate/luci-app-cpulimit/po/zh_Hans/cpulimit.po delete mode 100644 PATCH/duplicate/luci-app-cpulimit/root/etc/config/cpulimit delete mode 100644 PATCH/duplicate/luci-app-cpulimit/root/etc/init.d/cpulimit delete mode 100644 PATCH/duplicate/luci-app-cpulimit/root/etc/uci-defaults/luci-app-cpulimit delete mode 100644 PATCH/duplicate/luci-app-cpulimit/root/usr/bin/cpulimit.sh delete mode 100644 PATCH/duplicate/luci-app-cpulimit/root/usr/share/rpcd/acl.d/luci-app-cpulimit.json delete mode 100644 PATCH/duplicate/shortcut-fe rename PATCH/{R2S => }/files/etc/config/AdGuardHome (100%) rename PATCH/{R2S => }/files/etc/config/AdGuardHome.yaml (100%) rename PATCH/{R2S => }/files/etc/config/cpulimit (100%) rename PATCH/{R2S => }/files/etc/config/smartdns (100%) rename PATCH/{R2S => }/files/etc/ssrplus/black.list (100%) rename PATCH/{R2S => }/files/etc/ssrplus/white.list (100%) rename PATCH/{new/package => firewall}/luci-app-firewall_add_fullcone.patch (100%) rename PATCH/{new/package => firewall}/luci-app-firewall_add_sfe_switch.patch (100%) rename PATCH/{new/package => jsonc}/use_json_object_new_int64.patch (100%) rename PATCH/{new/package => mbedtls}/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch (100%) delete mode 100644 PATCH/new/main/0001-dmc-rk3328.patch delete mode 100644 PATCH/new/main/0002-IRQ-and-disable-eth0-tcp-udp-offloading-tx-rx.patch delete mode 100644 PATCH/new/main/998-rockchip-enable-i2c0-on-NanoPi-R2S.patch delete mode 100644 PATCH/new/script/chinadnslist delete mode 100644 PATCH/new/script/fuck delete mode 100644 PATCH/new/script/move_2_services.sh rename PATCH/{new/main => r8168}/r8168-fix_LAN_led-for_r4s-from_TL.patch (100%) rename PATCH/{new/main => target_r4s}/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch (100%) rename PATCH/{new/main => target_r4s}/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch (100%) diff --git a/PATCH/R4S/files/etc/config/AdGuardHome b/PATCH/R4S/files/etc/config/AdGuardHome deleted file mode 100644 index e20422ce9..000000000 --- a/PATCH/R4S/files/etc/config/AdGuardHome +++ /dev/null @@ -1,14 +0,0 @@ - -config AdGuardHome 'AdGuardHome' - option httpport '3000' - option configpath '/etc/config/AdGuardHome.yaml' - option logfile '/tmp/AdGuardHome.log' - option waitonboot '0' - option crontab 'cutquerylog cutruntimelog' - option redirect 'dnsmasq-upstream' - option backupfile 'filters' - option workdir '/etc/config/AdGuardHomeConfig' - option backupwdpath '/etc/config/AdGuardHomeConfig' - option binpath '/usr/bin/AdGuardHome' - option enabled '0' - option binmtime '0' diff --git a/PATCH/R4S/files/etc/config/AdGuardHome.yaml b/PATCH/R4S/files/etc/config/AdGuardHome.yaml deleted file mode 100644 index f62f0d275..000000000 --- a/PATCH/R4S/files/etc/config/AdGuardHome.yaml +++ /dev/null @@ -1,141 +0,0 @@ -bind_host: 0.0.0.0 -bind_port: 3000 -users: -- name: root - password: $2y$10$8GfLmnbQpS883RMTpGN66.TbyavsPmElcy2aR6vec7xL0YOG.gx52 -http_proxy: "" -language: "" -rlimit_nofile: 0 -debug_pprof: false -web_session_ttl: 720 -dns: - bind_host: 127.0.0.1 - port: 5335 - statistics_interval: 1 - querylog_enabled: false - querylog_file_enabled: true - querylog_interval: 1 - querylog_size_memory: 1000 - anonymize_client_ip: false - protection_enabled: true - blocking_mode: default - blocking_ipv4: "" - blocking_ipv6: "" - blocked_response_ttl: 10 - parental_block_host: family-block.dns.adguard.com - safebrowsing_block_host: standard-block.dns.adguard.com - ratelimit: 0 - ratelimit_whitelist: [] - refuse_any: true - upstream_dns: - - 127.0.0.1:6052 - - '[/awsglobalaccelerator.com/]127.0.0.1:6050' - upstream_dns_file: "" - bootstrap_dns: - - 127.0.0.1:6052 - all_servers: false - fastest_addr: true - allowed_clients: [] - disallowed_clients: [] - blocked_hosts: - - version.bind - - id.server - - hostname.bind - cache_size: 0 - cache_ttl_min: 0 - cache_ttl_max: 0 - bogus_nxdomain: [] - aaaa_disabled: false - enable_dnssec: false - edns_client_subnet: false - max_goroutines: 0 - ipset: [] - filtering_enabled: true - filters_update_interval: 24 - parental_enabled: false - safesearch_enabled: false - safebrowsing_enabled: false - cache_time: 30 - rewrites: - - domain: wifi.weixin.qq.com - answer: 127.0.0.1 - - domain: clock.redhat.com - answer: cn.ntp.org.cn - - domain: clock.cuhk.edu.hk - answer: cn.ntp.org.cn - - domain: https://www.meituan.com - answer: www.meituan.com - blocked_services: [] -tls: - enabled: false - server_name: "" - force_https: false - port_https: 443 - port_dns_over_tls: 853 - port_dns_over_quic: 784 - allow_unencrypted_doh: false - strict_sni_check: false - certificate_chain: "" - private_key: "" - certificate_path: "" - private_key_path: "" -filters: -- enabled: false - url: https://gitee.com/halflife/list/raw/master/ad.txt - name: HalfLife - id: 1595502658 -- enabled: false - url: https://pgl.yoyo.org/adservers/serverlist.php?hostformat=adblockplus&showintro=1&mimetype=plaintext - name: Peter Lowe's List - id: 1595502661 -- enabled: true - url: https://cdn.jsdelivr.net/gh/hoshsadiq/adblock-nocoin-list@master/nocoin.txt - name: NoCoin Filter List - id: 1595502662 -- enabled: true - url: https://cdn.jsdelivr.net/gh/xinggsf/Adblock-Plus-Rule@master/rule.txt - name: 乘风 广告过滤规则 - id: 1600600707 -- enabled: true - url: https://gitee.com/xinggsf/Adblock-Rule/raw/master/mv.txt - name: 乘风 视频广告过滤规则 - id: 1600600708 -- enabled: true - url: https://cdn.jsdelivr.net/gh/cjx82630/cjxlist@master/cjx-ublock.txt - name: CJX's uBlock list - id: 1600600709 -- enabled: true - url: https://cdn.jsdelivr.net/gh/cjx82630/cjxlist@master/cjx-annoyance.txt - name: CJX's Annoyance List - id: 1600600710 -- enabled: true - url: http://sub.adtchrome.com/adt-chinalist-easylist.txt - name: ChinaList and EasyList - id: 1600600711 -whitelist_filters: [] -user_rules: [] -dhcp: - enabled: false - interface_name: "" - dhcpv4: - gateway_ip: "" - subnet_mask: "" - range_start: "" - range_end: "" - lease_duration: 86400 - icmp_timeout_msec: 1000 - options: [] - dhcpv6: - range_start: "" - lease_duration: 86400 - ra_slaac_only: false - ra_allow_slaac: false -clients: [] -log_compress: false -log_localtime: false -log_max_backups: 0 -log_max_size: 100 -log_max_age: 3 -log_file: "" -verbose: false -schema_version: 7 diff --git a/PATCH/R4S/files/etc/config/cpulimit b/PATCH/R4S/files/etc/config/cpulimit deleted file mode 100644 index 939f8ac22..000000000 --- a/PATCH/R4S/files/etc/config/cpulimit +++ /dev/null @@ -1,6 +0,0 @@ - -config list - option exename '/sbin/rngd' - option limit '1' - option enabled '1' - diff --git a/PATCH/R4S/files/etc/config/smartdns b/PATCH/R4S/files/etc/config/smartdns deleted file mode 100644 index 87e85b9c6..000000000 --- a/PATCH/R4S/files/etc/config/smartdns +++ /dev/null @@ -1,54 +0,0 @@ - -config smartdns - option server_name 'smartdns' - option port '6051 -force-aaaa-soa -group oversea' - option server_group 'oversea' - option seconddns_port '6050' - option seconddns_tcp_server '1' - option seconddns_enabled '1' - option redirect 'none' - option seconddns_server_group 'mainland' - option prefetch_domain '1' - option serve_expired '1' - option tcp_server '1' - option seconddns_no_cache '1' - option cache_size '102400' - option enabled '1' - -config server - option type 'udp' - option name 'DNSPod' - option ip '119.29.29.29' - option server_group 'mainland' - option enabled '1' - option addition_arg '-exclude-default-group' - -config server - option type 'udp' - option name 'AliDNS' - option ip '223.5.5.5' - option server_group 'mainland' - option enabled '1' - option addition_arg '-exclude-default-group' - -config server - option type 'tls' - option server_group 'oversea' - option name 'Google TLS' - option enabled '1' - option ip '8.8.4.4' - -config server - option type 'tls' - option server_group 'oversea' - option ip '1.1.1.1' - option enabled '1' - option name 'Cloudflare TLS' - -config server - option enabled '1' - option server_group 'oversea' - option type 'udp' - option port '5353' - option name 'USTC' - option ip '202.141.162.123' diff --git a/PATCH/R4S/files/etc/ssrplus/black.list b/PATCH/R4S/files/etc/ssrplus/black.list deleted file mode 100644 index 5d064162a..000000000 --- a/PATCH/R4S/files/etc/ssrplus/black.list +++ /dev/null @@ -1,3 +0,0 @@ -dns.sb -doh.li -containerpi.com diff --git a/PATCH/R4S/files/etc/ssrplus/white.list b/PATCH/R4S/files/etc/ssrplus/white.list deleted file mode 100644 index 0f7abfd0e..000000000 --- a/PATCH/R4S/files/etc/ssrplus/white.list +++ /dev/null @@ -1,10 +0,0 @@ -checkip.synology.com -checkipv6.synology.com -checkport.synology.com -ddns.synology.com -account.synology.com -whatismyip.akamai.com -checkip.dyndns.org -teamviewer.com -bing.com -api.ipify.org diff --git a/PATCH/X86/files/etc/config/AdGuardHome b/PATCH/X86/files/etc/config/AdGuardHome deleted file mode 100644 index e20422ce9..000000000 --- a/PATCH/X86/files/etc/config/AdGuardHome +++ /dev/null @@ -1,14 +0,0 @@ - -config AdGuardHome 'AdGuardHome' - option httpport '3000' - option configpath '/etc/config/AdGuardHome.yaml' - option logfile '/tmp/AdGuardHome.log' - option waitonboot '0' - option crontab 'cutquerylog cutruntimelog' - option redirect 'dnsmasq-upstream' - option backupfile 'filters' - option workdir '/etc/config/AdGuardHomeConfig' - option backupwdpath '/etc/config/AdGuardHomeConfig' - option binpath '/usr/bin/AdGuardHome' - option enabled '0' - option binmtime '0' diff --git a/PATCH/X86/files/etc/config/AdGuardHome.yaml b/PATCH/X86/files/etc/config/AdGuardHome.yaml deleted file mode 100644 index f62f0d275..000000000 --- a/PATCH/X86/files/etc/config/AdGuardHome.yaml +++ /dev/null @@ -1,141 +0,0 @@ -bind_host: 0.0.0.0 -bind_port: 3000 -users: -- name: root - password: $2y$10$8GfLmnbQpS883RMTpGN66.TbyavsPmElcy2aR6vec7xL0YOG.gx52 -http_proxy: "" -language: "" -rlimit_nofile: 0 -debug_pprof: false -web_session_ttl: 720 -dns: - bind_host: 127.0.0.1 - port: 5335 - statistics_interval: 1 - querylog_enabled: false - querylog_file_enabled: true - querylog_interval: 1 - querylog_size_memory: 1000 - anonymize_client_ip: false - protection_enabled: true - blocking_mode: default - blocking_ipv4: "" - blocking_ipv6: "" - blocked_response_ttl: 10 - parental_block_host: family-block.dns.adguard.com - safebrowsing_block_host: standard-block.dns.adguard.com - ratelimit: 0 - ratelimit_whitelist: [] - refuse_any: true - upstream_dns: - - 127.0.0.1:6052 - - '[/awsglobalaccelerator.com/]127.0.0.1:6050' - upstream_dns_file: "" - bootstrap_dns: - - 127.0.0.1:6052 - all_servers: false - fastest_addr: true - allowed_clients: [] - disallowed_clients: [] - blocked_hosts: - - version.bind - - id.server - - hostname.bind - cache_size: 0 - cache_ttl_min: 0 - cache_ttl_max: 0 - bogus_nxdomain: [] - aaaa_disabled: false - enable_dnssec: false - edns_client_subnet: false - max_goroutines: 0 - ipset: [] - filtering_enabled: true - filters_update_interval: 24 - parental_enabled: false - safesearch_enabled: false - safebrowsing_enabled: false - cache_time: 30 - rewrites: - - domain: wifi.weixin.qq.com - answer: 127.0.0.1 - - domain: clock.redhat.com - answer: cn.ntp.org.cn - - domain: clock.cuhk.edu.hk - answer: cn.ntp.org.cn - - domain: https://www.meituan.com - answer: www.meituan.com - blocked_services: [] -tls: - enabled: false - server_name: "" - force_https: false - port_https: 443 - port_dns_over_tls: 853 - port_dns_over_quic: 784 - allow_unencrypted_doh: false - strict_sni_check: false - certificate_chain: "" - private_key: "" - certificate_path: "" - private_key_path: "" -filters: -- enabled: false - url: https://gitee.com/halflife/list/raw/master/ad.txt - name: HalfLife - id: 1595502658 -- enabled: false - url: https://pgl.yoyo.org/adservers/serverlist.php?hostformat=adblockplus&showintro=1&mimetype=plaintext - name: Peter Lowe's List - id: 1595502661 -- enabled: true - url: https://cdn.jsdelivr.net/gh/hoshsadiq/adblock-nocoin-list@master/nocoin.txt - name: NoCoin Filter List - id: 1595502662 -- enabled: true - url: https://cdn.jsdelivr.net/gh/xinggsf/Adblock-Plus-Rule@master/rule.txt - name: 乘风 广告过滤规则 - id: 1600600707 -- enabled: true - url: https://gitee.com/xinggsf/Adblock-Rule/raw/master/mv.txt - name: 乘风 视频广告过滤规则 - id: 1600600708 -- enabled: true - url: https://cdn.jsdelivr.net/gh/cjx82630/cjxlist@master/cjx-ublock.txt - name: CJX's uBlock list - id: 1600600709 -- enabled: true - url: https://cdn.jsdelivr.net/gh/cjx82630/cjxlist@master/cjx-annoyance.txt - name: CJX's Annoyance List - id: 1600600710 -- enabled: true - url: http://sub.adtchrome.com/adt-chinalist-easylist.txt - name: ChinaList and EasyList - id: 1600600711 -whitelist_filters: [] -user_rules: [] -dhcp: - enabled: false - interface_name: "" - dhcpv4: - gateway_ip: "" - subnet_mask: "" - range_start: "" - range_end: "" - lease_duration: 86400 - icmp_timeout_msec: 1000 - options: [] - dhcpv6: - range_start: "" - lease_duration: 86400 - ra_slaac_only: false - ra_allow_slaac: false -clients: [] -log_compress: false -log_localtime: false -log_max_backups: 0 -log_max_size: 100 -log_max_age: 3 -log_file: "" -verbose: false -schema_version: 7 diff --git a/PATCH/X86/files/etc/config/cpulimit b/PATCH/X86/files/etc/config/cpulimit deleted file mode 100644 index 939f8ac22..000000000 --- a/PATCH/X86/files/etc/config/cpulimit +++ /dev/null @@ -1,6 +0,0 @@ - -config list - option exename '/sbin/rngd' - option limit '1' - option enabled '1' - diff --git a/PATCH/X86/files/etc/config/smartdns b/PATCH/X86/files/etc/config/smartdns deleted file mode 100644 index 87e85b9c6..000000000 --- a/PATCH/X86/files/etc/config/smartdns +++ /dev/null @@ -1,54 +0,0 @@ - -config smartdns - option server_name 'smartdns' - option port '6051 -force-aaaa-soa -group oversea' - option server_group 'oversea' - option seconddns_port '6050' - option seconddns_tcp_server '1' - option seconddns_enabled '1' - option redirect 'none' - option seconddns_server_group 'mainland' - option prefetch_domain '1' - option serve_expired '1' - option tcp_server '1' - option seconddns_no_cache '1' - option cache_size '102400' - option enabled '1' - -config server - option type 'udp' - option name 'DNSPod' - option ip '119.29.29.29' - option server_group 'mainland' - option enabled '1' - option addition_arg '-exclude-default-group' - -config server - option type 'udp' - option name 'AliDNS' - option ip '223.5.5.5' - option server_group 'mainland' - option enabled '1' - option addition_arg '-exclude-default-group' - -config server - option type 'tls' - option server_group 'oversea' - option name 'Google TLS' - option enabled '1' - option ip '8.8.4.4' - -config server - option type 'tls' - option server_group 'oversea' - option ip '1.1.1.1' - option enabled '1' - option name 'Cloudflare TLS' - -config server - option enabled '1' - option server_group 'oversea' - option type 'udp' - option port '5353' - option name 'USTC' - option ip '202.141.162.123' diff --git a/PATCH/X86/files/etc/ssrplus/black.list b/PATCH/X86/files/etc/ssrplus/black.list deleted file mode 100644 index 5d064162a..000000000 --- a/PATCH/X86/files/etc/ssrplus/black.list +++ /dev/null @@ -1,3 +0,0 @@ -dns.sb -doh.li -containerpi.com diff --git a/PATCH/X86/files/etc/ssrplus/white.list b/PATCH/X86/files/etc/ssrplus/white.list deleted file mode 100644 index 0f7abfd0e..000000000 --- a/PATCH/X86/files/etc/ssrplus/white.list +++ /dev/null @@ -1,10 +0,0 @@ -checkip.synology.com -checkipv6.synology.com -checkport.synology.com -ddns.synology.com -account.synology.com -whatismyip.akamai.com -checkip.dyndns.org -teamviewer.com -bing.com -api.ipify.org diff --git a/PATCH/new/package/900-add-filter-aaaa-option.patch b/PATCH/dnsmasq/900-add-filter-aaaa-option.patch similarity index 100% rename from PATCH/new/package/900-add-filter-aaaa-option.patch rename to PATCH/dnsmasq/900-add-filter-aaaa-option.patch diff --git a/PATCH/new/package/dnsmasq-add-filter-aaaa-option.patch b/PATCH/dnsmasq/dnsmasq-add-filter-aaaa-option.patch similarity index 100% rename from PATCH/new/package/dnsmasq-add-filter-aaaa-option.patch rename to PATCH/dnsmasq/dnsmasq-add-filter-aaaa-option.patch diff --git a/PATCH/new/package/luci-add-filter-aaaa-option.patch b/PATCH/dnsmasq/luci-add-filter-aaaa-option.patch similarity index 100% rename from PATCH/new/package/luci-add-filter-aaaa-option.patch rename to PATCH/dnsmasq/luci-add-filter-aaaa-option.patch diff --git a/PATCH/duplicate/addition-trans-zh/Makefile b/PATCH/duplicate/addition-trans-zh/Makefile deleted file mode 100644 index 671cb55b5..000000000 --- a/PATCH/duplicate/addition-trans-zh/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -# -# Copyright (C) 2016-2017 GitHub -# -# This is free software, licensed under the GNU General Public License v3. -# See /LICENSE for more information. - -include $(TOPDIR)/rules.mk - -PKG_NAME:=addition-trans-zh -PKG_VERSION:=1.1 -PKG_RELEASE:=52 -PKG_LICENSE:=GPLv3 -PKG_LICENSE_FILES:=LICENSE - -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(INCLUDE_DIR)/package.mk - -define Package/addition-trans-zh - SECTION:=luci - CATEGORY:=LuCI - TITLE:=LuCI support for Default Settings - PKGARCH:=all - DEPENDS:=+luci-base +kmod-fast-classifier +kmod-ipt-nat6 +kmod-tun +kmod-nf-nathelper-extra +luci-lib-ipkg +luci-compat +openssl-util +iptables-mod-fullconenat +iptables-mod-nat-extra +ip6tables-mod-nat +@LUCI_LANG_zh_Hans -endef - -define Package/addition-trans-zh/description - Language Support Packages. -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/addition-trans-zh/install - $(INSTALL_DIR) $(1)/etc/uci-defaults - $(INSTALL_BIN) ./files/zzz-default-settings $(1)/etc/uci-defaults/99-default-settings - $(INSTALL_DIR) $(1)/usr/lib/lua/luci/i18n - po2lmo ./i18n/default.zh_Hans.po $(1)/usr/lib/lua/luci/i18n/default.zh-cn.lmo - po2lmo ./i18n/more.zh_Hans.po $(1)/usr/lib/lua/luci/i18n/more.zh-cn.lmo - $(INSTALL_DIR) $(1)/usr/lib/lua/luci/tools - $(INSTALL_DATA) ./status/status.lua $(1)/usr/lib/lua/luci/tools/status.lua -endef - -$(eval $(call BuildPackage,addition-trans-zh)) diff --git a/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings b/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings deleted file mode 100644 index 05b366e4f..000000000 --- a/PATCH/duplicate/addition-trans-zh/files/zzz-default-settings +++ /dev/null @@ -1,100 +0,0 @@ -#!/bin/sh - -#Argon 主题 -uci set luci.main.mediaurlbase='/luci-static/argon' -uci commit luci - -#时区设置 -uci set system.@system[0].timezone=CST-8 -uci set system.@system[0].zonename=Asia/Shanghai -uci commit system - -#SSRP -uci set shadowsocksr.@global[0].gfwlist_url='https://cdn.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/gfw.txt' -uci set shadowsocksr.@global[0].chnroute_url='https://cdn.jsdelivr.net/gh/QiuSimons/Chnroute@master/dist/chnroute/chnroute.txt' -uci commit shadowsocksr - -#Feeds 更换镜像源 -#sed -i 's,21.02,21.02-SNAPSHOT,g' /etc/opkg/distfeeds.conf -sed -i 's,downloads.openwrt.org,mirror.sjtu.edu.cn/openwrt,g' /etc/opkg/distfeeds.conf - -#uhttpd 设置 -uci set uhttpd.main.rfc1918_filter=0 -uci set uhttpd.main.redirect_https=0 -uci commit uhttpd -/etc/init.d/uhttpd restart - -#在防火墙默认开启全锥形 NAT 以及 Flow Offloading -uci set firewall.@defaults[0].fullcone='1' -#uci set firewall.@defaults[0].flow_offloading='1' -uci commit firewall - -#默认开启 Packet Steering -uci set network.globals.packet_steering='1' -uci commit network - -#通用即插即用 -uci set upnpd.config.igdv1='1' -uci set upnpd.config.enabled='1' -uci del upnpd.config.enable_upnp -uci del upnpd.config.enable_natpmp -uci set upnpd.config.external_iface='wan' -uci commit upnpd - -#网易云音乐 -#echo "59.111.239.62 httpdns.n.netease.com" >> /etc/hosts && cat /etc/hosts | sort | uniq > /tmp/tmp_hosts && cat /tmp/tmp_hosts > /etc/hosts -echo "10 2 * * * cd /usr/share/unblockneteasemusic/core/ && openssl req -new -x509 -key server.key -out server.crt -days 3650 -subj "/CN=*.music.163.com" && cd" >> /etc/crontabs/root && cat /etc/crontabs/root | sort | uniq > /tmp/tmp_cron_root && cat /tmp/tmp_cron_root > /etc/crontabs/root - -#OpenClash 设置 -echo "/etc/openclash/" >> /etc/sysupgrade.conf && cat /etc/sysupgrade.conf | sort | uniq > /tmp/tmp_sysupgrade_conf && cat /tmp/tmp_sysupgrade_conf > /etc/sysupgrade.conf - -#Dockerman 设置 -#sed -i 's,/opt,/overlay,g' /etc/config/dockerman - -#qBittorrent 设置 -#echo "nobody:x:65534:" >> /etc/group - -#dnsmasq 设置以及开启 IPv6 -uci set dhcp.lan.ra='hybrid' -uci set dhcp.lan.ndp='hybrid' -uci set dhcp.lan.dhcpv6='hybrid' -uci set dhcp.lan.ra_management='1' -uci del dhcp.@dnsmasq[0].rebind_protection -uci del dhcp.@dnsmasq[0].filteraaaa -uci commit dhcp -sed -i '/log-facility/d' /etc/dnsmasq.conf -echo "log-facility=/dev/null" >> /etc/dnsmasq.conf - -#计划任务 -uci set system.@system[0].cronloglevel="9" -uci commit system -/etc/init.d/cron restart - -#软链接 -ln -sf /sbin/ip /usr/bin/ip -ln -sf /usr/bin/wget /usr/bin/wget-ssl - -#Flag packages -opkg flag hold luci-app-firewall -opkg flag hold firewall -opkg flag hold dnsmasq-full - -#清理内存缓存 -#sync; echo 3 > /proc/sys/vm/drop_caches - -#默认关闭 Shortcut-FE -#service shortcut-fe stop -#rm -rf /etc/rc.d/S90shortcut-fe - -#自用 -[ -f '/rom/etc/rpcd_10_system.js' ] && rm -f /etc/rpcd_10_system.js -[ -f '/rom/etc/rpcd_10_system.js' ] && rm -f /www/luci-static/resources/view/status/include/10_system.js -[ -f '/rom/etc/rpcd_10_system.js' ] && cp -f /rom/etc/rpcd_10_system.js /www/luci-static/resources/view/status/include/10_system.js -[ -f '/etc/fucked' ] && sed -i '/Source Code/d' /www/luci-static/resources/view/status/include/10_system.js -[ -f '/rom/etc/rpcd_10_system.js' ] && touch /etc/fucked - -#清除 LuCI 残留缓存 -rm -rf /tmp/luci-modulecache -rm -f /tmp/luci-indexcache - -exit 0 diff --git a/PATCH/duplicate/addition-trans-zh/i18n/default.zh_Hans.po b/PATCH/duplicate/addition-trans-zh/i18n/default.zh_Hans.po deleted file mode 100644 index 3218014b3..000000000 --- a/PATCH/duplicate/addition-trans-zh/i18n/default.zh_Hans.po +++ /dev/null @@ -1,234 +0,0 @@ -msgid "Processor" -msgstr "处理器" - -msgid "Architecture" -msgstr "架构" - -msgid "CPU Temperature" -msgstr "CPU 温度" - -msgid "CPU Info" -msgstr "CPU 信息" - -msgid "CPU Model" -msgstr "处理器型号" - -msgid "CPU frequency" -msgstr "CPU 频率" - -msgid "RAM frequency" -msgstr "RAM 频率" - -msgid "Flash Size" -msgstr "闪存大小" - -msgid "Free Memory" -msgstr "释放内存" - -msgid "RUNNING" -msgstr "运行中" - -msgid "NOT RUNNING" -msgstr "未运行" - -msgid "ZRam Settings" -msgstr "ZRam 设置" - -msgid "ZRam Compression Algorithm" -msgstr "ZRam 压缩算法" - -msgid "ZRam Compression Streams" -msgstr "ZRam 压缩数据流线程数" - -msgid "ZRam Size" -msgstr "ZRam 大小" - -msgid "Size of the ZRam device in megabytes" -msgstr "划分给 ZRam 分区的内存大小(MB),推荐留空由系统自动管理" - -msgid "Number of parallel threads used for compression" -msgstr "用于压缩内存数据的 CPU 并发线程数" - -msgid "Swap" -msgstr "虚拟内存" - -msgid "Force 40MHz mode" -msgstr "强制 40MHz 频宽" - -msgid "" -"Always use 40MHz channels even if the secondary channel overlaps. Using this " -"option does not comply with IEEE 802.11n-2009!" -msgstr "强制启用 40MHz 频宽并忽略辅助信道重叠。此选项可能不兼容某些无线硬件导致无法启用!" - -msgid "Disassociate On Low Acknowledgement" -msgstr "弱信号剔除" - -msgid "Allow AP mode to disconnect STAs based on low ACK condition" -msgstr "允许 AP 模式基于低 ACK 条件判断剔除弱信号的客户端" - -msgid "Base Setting" -msgstr "基本设置" - -msgid "Log" -msgstr "日志" - -msgid "Ethernet Information" -msgstr "网口信息" - -msgid "Ethernet Name" -msgstr "网口名" - -msgid "Link Status" -msgstr "连接状态" - -msgid "Speed" -msgstr "速率" - -msgid "Duplex" -msgstr "双工模式" - -msgid "Link Up" -msgstr "已连接" - -msgid "Link Down" -msgstr "已断开" - -msgid "Full Duplex" -msgstr "全双工" - -msgid "Half Duplex" -msgstr "半双工" - -msgid "10 seconds" -msgstr "10 秒" - -msgid "2 seconds" -msgstr "2 秒" - -msgid "30 seconds" -msgstr "30 秒" - -msgid "5 seconds" -msgstr "5 秒" - -msgid "Auto update every:" -msgstr "自动刷新:" - -msgid "Clients" -msgstr "客户端" - -msgid "Collecting data..." -msgstr "收集数据中..." - -msgid "Configuration" -msgstr "配置" - -msgid "Database Path" -msgstr "数据路径" - -msgid "Details" -msgstr "流量信息" - -msgid "Disabled" -msgstr "禁用" - -msgid "Download" -msgstr "下载" - -msgid "Each line must have the following format:" -msgstr "每行需要满足以下格式:" - -msgid "Enabled" -msgstr "启用" - -msgid "Error! Bandwidth reset!!!" -msgstr "错误!重置带宽!!!" - -msgid "First Seen" -msgstr "初次记录" - -msgid "General settings" -msgstr "通用设置" - -msgid "Last Seen" -msgstr "最后记录" - -msgid "Last updated at %s." -msgstr "最后更新于 %s。" - -msgid "Reset Database" -msgstr "重置" - -msgid "Save" -msgstr "保存" - -msgid "Show More:" -msgstr "显示更多:" - -msgid "Show Zeros:" -msgstr "显示 0 流量:" - -msgid "TOTAL" -msgstr "总共" - -msgid "" -"This box is used to select the Database path, which is /tmp/usage.db by " -"default." -msgstr "该选项用于选择数据存储路径,默认路径为 /tmp/usage.db。" - -msgid "This will delete the database file. Are you sure?" -msgstr "该操作将删除数据统计文件,确定执行该操作?" - -msgid "This will revert the changes. Are you sure?" -msgstr "更改将会重置,确定吗?" - -msgid "Total" -msgstr "总计" - -msgid "Total Down" -msgstr "总下载" - -msgid "Total Up" -msgstr "总上传" - -msgid "Traffic Status" -msgstr "流量监控" - -msgid "Unable to load the customized hostname file:" -msgstr "不能载入自定义用户名文件:" - -msgid "Updating again in %s seconds." -msgstr "下次更新将于 %s 秒之后。" - -msgid "Upload" -msgstr "上传" - -msgid "Usage - Configuration" -msgstr "文件设置" - -msgid "Usage - Custom User File" -msgstr "用户文件配置" - -msgid "Usage - Details" -msgstr "流量详情" - -msgid "User file" -msgstr "用户文件" - -msgid "bandwidth:" -msgstr "带宽:" - -msgid "downflow:" -msgstr "下行:" - -msgid "protocol:" -msgstr "协议:" - -msgid "seconds." -msgstr "秒。" - -msgid "upflow:" -msgstr "上传:" - -msgid "There is no password set on this router. Please configure a root password to protect the web interface and enable SSH." -msgstr "尚未设置密码。请为 root 用户设置密码以保护主机并启用 SSH 。" diff --git a/PATCH/duplicate/addition-trans-zh/i18n/more.zh_Hans.po b/PATCH/duplicate/addition-trans-zh/i18n/more.zh_Hans.po deleted file mode 100644 index 0ffe4c1e6..000000000 --- a/PATCH/duplicate/addition-trans-zh/i18n/more.zh_Hans.po +++ /dev/null @@ -1,1211 +0,0 @@ -msgid "" -msgstr "" -"Content-Type: text/plain; charset=UTF-8\n" -"Last-Translator: dingpengyu \n" -"Project-Id-Version: \n" -"POT-Creation-Date: \n" -"PO-Revision-Date: \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: zh_CN\n" -"X-Generator: Poedit 2.3.1\n" - -msgid "%d hour" -msgstr "%d 小时" - -msgid "%d minute" -msgstr "%d 分钟" - -msgid "%d minutes" -msgstr "%d 分钟" - -msgid "%d second" -msgstr "%d 秒" - -msgid "%d seconds" -msgstr "%d 秒" - -msgid "" -"Acceptable values: 1-100. This many Tracking IP addresses must respond for " -"the link to be deemed up" -msgstr "" -"取值范围: 1-100。这个设置项指定了当多少个 IP 地址能够连通时接口会被认为在线" - -msgid "Acceptable values: 1-1000. Defaults to 1 if not set" -msgstr "取值范围: 1-100。如果不填写,默认值为 1" - -msgid "Advanced" -msgstr "高级" - -msgid "Check IP rules" -msgstr "检查 IP 规则" - -msgid "Check routing table" -msgstr "检查路由表" - -msgid "Collecting data..." -msgstr "正在收集数据..." - -msgid "Configuration" -msgstr "配置" - -msgid "Currently Configured Interfaces" -msgstr "当前配置的接口" - -msgid "Currently Configured Members" -msgstr "当前配置的成员" - -msgid "Currently Configured Policies" -msgstr "当前配置的策略" - -msgid "Destination address" -msgstr "目标地址" - -msgid "Destination port" -msgstr "目标端口" - -msgid "Detailed Status" -msgstr "详细状态" - -msgid "Diagnostic Results" -msgstr "诊断结果" - -msgid "Diagnostics" -msgstr "诊断" - -msgid "Disabled" -msgstr "禁用" - -msgid "" -"Downed interface will be deemed up after this many successful ping tests" -msgstr "当 Ping 成功次数达到这个数值后,已经被认为离线的接口将会重新上线" - -msgid "Enabled" -msgstr "启用" - -msgid "Error collecting troubleshooting information" -msgstr "收集故障排除信息时出错" - -msgid "Errors" -msgstr "错误" - -msgid "Failure interval" -msgstr "故障检测间隔" - -msgid "Flush conntrack table" -msgstr "刷新连接跟踪表" - -msgid "Flush global firewall conntrack table on interface events" -msgstr "在接口事件触发时刷新全局防火墙连接跟踪表" - -msgid "Hotplug Script" -msgstr "Hotplug 脚本" - -msgid "Hotplug ifdown" -msgstr "Hotplug ifdown" - -msgid "Hotplug ifup" -msgstr "Hotplug ifup" - -msgid "IPset" -msgstr "IPset" - -msgid "IPv4" -msgstr "IPv4" - -msgid "IPv6" -msgstr "IPv6" - -msgid "Interface" -msgstr "接口" - -msgid "Interface Status" -msgstr "接口状态" - -msgid "Interface down" -msgstr "接口离线" - -msgid "Interface up" -msgstr "接口上线" - -msgid "Interface will be deemed down after this many failed ping tests" -msgstr "当 Ping 失败次数达到这个数值后接口会被认为离线" - -msgid "Interfaces" -msgstr "接口" - -msgid "Internet Protocol" -msgstr "互联网协议" - -msgid "Last 50 MWAN systemlog entries. Newest entries sorted at the top :" -msgstr "最近 50 条 MWAN 系统日志,最新条目排在顶部:" - -msgid "Last resort" -msgstr "备用成员" - -msgid "Load Balancing" -msgstr "负载均衡" - -msgid "Loading" -msgstr "载入中" - -msgid "MWAN Config" -msgstr "MWAN 配置文件" - -msgid "MWAN Detailed Status" -msgstr "MWAN 详细状态" - -msgid "MWAN Interface Configuration" -msgstr "MWAN 接口配置" - -msgid "MWAN Interface Configuration - %s" -msgstr "MWAN 接口配置 - %s" - -msgid "MWAN Interface Diagnostics" -msgstr "MWAN 接口诊断" - -msgid "MWAN Interface Live Status" -msgstr "MWAN 接口实时状态" - -msgid "MWAN Interface Systemlog" -msgstr "MWAN 接口系统日志" - -msgid "MWAN Member Configuration" -msgstr "MWAN 成员配置" - -msgid "MWAN Member Configuration - %s" -msgstr "MWAN 成员配置 - %s" - -msgid "MWAN Policy Configuration" -msgstr "MWAN 策略配置" - -msgid "MWAN Policy Configuration - %s" -msgstr "MWAN 策略配置 - %s" - -msgid "MWAN Rule Configuration" -msgstr "MWAN 规则配置" - -msgid "MWAN Rule Configuration - %s" -msgstr "MWAN 规则配置 - %s" - -msgid "MWAN Service Control" -msgstr "MWAN 服务控制" - -msgid "" -"MWAN supports up to 250 physical and/or logical interfaces
MWAN " -"requires that all interfaces have a unique metric configured in /etc/config/" -"network
Names must match the interface name found in /etc/config/" -"network (see advanced tab)
Names may contain characters A-Z, a-z, 0-9, " -"_ and no spaces
Interfaces may not share the same name as configured " -"members, policies or rules" -msgstr "" -"MWAN 支持最多 250 个物理或逻辑接口。
MWAN 要求所有接口必须在 /etc/" -"config/network 中设定唯一的网关跃点。
名称必须与 /etc/config/network 中" -"的接口名称匹配。(可查看“高级”选项卡)
名称允许包括A-Z、a-z、0-9、_ 但是" -"不能有空格。
接口不应该与成员、策略、规则中的任意一个设置项使用相同的名" -"称" - -msgid "" -"May be entered as a single or multiple port(s) (eg \"22\" or \"80,443\") or " -"as a portrange (eg \"1024:2048\") without quotes" -msgstr "" -"可以输入一个或多个端口(例如 \"22\" 或者 \"80,443\")或者是一个端口范围(例" -"如 \"1024:2048\")不含引号" - -msgid "Member" -msgstr "成员" - -msgid "Member used" -msgstr "使用的成员" - -msgid "Members" -msgstr "成员" - -msgid "" -"Members are profiles attaching a metric and weight to an MWAN interface
Names may contain characters A-Z, a-z, 0-9, _ and no spaces
Members " -"may not share the same name as configured interfaces, policies or rules" -msgstr "" -"“成员”用来设置每一个 MWAN 接口的跃点数(即接口优先级)和所占比重。
名称" -"允许包括 A-Z、 a-、0-9、_ 但是不能有空格。
成员不应该与接口、策略、规则" -"中的任意一个设置项使用相同的名称" - -msgid "Members assigned" -msgstr "分配的成员" - -msgid "Metric" -msgstr "跃点数" - -msgid "" -"Name of IPset rule. Requires IPset rule in /etc/dnsmasq.conf (eg \"ipset=/" -"youtube.com/youtube\")" -msgstr "" -"匹配 IPset 规则列表名称。需要先配置 /etc/dnsmasq.conf 中的 IPset 规则 (例如: " -"\"ipset=/youtube.com/youtube\")" - -msgid "Network Config" -msgstr "网络配置文件" - -msgid "No" -msgstr "否" - -msgid "No MWAN interfaces found" -msgstr "没有找到 MWAN 接口" - -msgid "No MWAN systemlog history found" -msgstr "没有在系统日志中找到 MWAN 历史信息" - -msgid "No detailed status information available" -msgstr "没有状态详细信息可用" - -msgid "No diagnostic results returned" -msgstr "没有返回诊断结果" - -msgid "No protocol specified" -msgstr "未指定协议" - -msgid "Offline" -msgstr "离线" - -msgid "Online (tracking active)" -msgstr "在线(追踪启用中)" - -msgid "Online (tracking off)" -msgstr "在线(追踪已关闭)" - -msgid "Overview" -msgstr "概况" - -msgid "Ping count" -msgstr "Ping 计数" - -msgid "Ping default gateway" -msgstr "Ping 默认网关" - -msgid "Ping interval" -msgstr "Ping 间隔" - -msgid "Ping interval during failure detection" -msgstr "故障检测期间的 Ping 间隔" - -msgid "Ping interval during failure recovering" -msgstr "故障恢复期间的 Ping 间隔" - -msgid "Ping size" -msgstr "Ping 大小" - -msgid "Ping timeout" -msgstr "Ping 超时" - -msgid "Ping tracking IP" -msgstr "Ping 跟踪 IP" - -msgid "Policies" -msgstr "策略" - -msgid "" -"Policies are profiles grouping one or more members controlling how MWAN " -"distributes traffic
Member interfaces with lower metrics are used " -"first. Interfaces with the same metric load-balance
Load-balanced " -"member interfaces distribute more traffic out those with higher weights
Names may contain characters A-Z, a-z, 0-9, _ and no spaces. Names must be " -"15 characters or less
Policies may not share the same name as " -"configured interfaces, members or rules" -msgstr "" -"“策略”把成员进行分组,告诉 MWAN 如何分配“规则”中使用这一策略的流量
拥有" -"较低跃点数的成员将会被优先使用。拥有相同跃点数的成员把流量进行负载均衡。
进行负载均衡的成员之间拥有较高比重的成员将会被分配到更多流量。
名称允许" -"包括A-Z、a-z、0-9、_ 但是不能有空格。名称应该在 15 个字符以内
策略不应该" -"与接口、成员、规则中的任意一个设置项使用相同的名称" - -msgid "Policy" -msgstr "策略" - -msgid "Policy assigned" -msgstr "分配的策略" - -msgid "Protocol" -msgstr "协议" - -msgid "Recovery interval" -msgstr "故障恢复间隔" - -msgid "Restart MWAN" -msgstr "重启 MWAN" - -msgid "Restore default hotplug script" -msgstr "恢复默认的 hotplug 脚本" - -msgid "Restore..." -msgstr "恢复..." - -msgid "Rule" -msgstr "规则" - -msgid "Rules" -msgstr "规则" - -msgid "" -"Rules specify which traffic will use a particular MWAN policy based on IP " -"address, port or protocol
Rules are matched from top to bottom. Rules " -"below a matching rule are ignored. Traffic not matching any rule is routed " -"using the main routing table
Traffic destined for known (other than " -"default) networks is handled by the main routing table. Traffic matching a " -"rule, but all WAN interfaces for that policy are down will be blackholed
Names may contain characters A-Z, a-z, 0-9, _ and no spaces
Rules may " -"not share the same name as configured interfaces, members or policies" -msgstr "" -"“规则”基于 IP 地址、协议、端口把流量划分到指定的“策略”中。
规则按照从上" -"到下的顺序进行匹配。除了第一条能够匹配一次通信的规则以外,其它规则将被忽略。" -"不匹配任何规则的通信将会由系统默认路由表进行。
来自已知的网络的转发流量" -"由系统默认路由表接手,然后 MWAN 从中匹配出相应的流量并转移到 MWAN 自己的路由" -"表。但是所有被划分到一个无法使用的策略的流量将会无法正常进行路由。
名称" -"允许包括A-Z、a-z、0-9、_ 但是不能有空格。
规则不应该与接口、成员、策略中" -"的任意一个设置项使用相同的名称" - -msgid "Seconds. Acceptable values: 1-1000000. Defaults to 600 if not set" -msgstr "单位为秒。接受的值: 1-1000000。留空则使用默认值 600 秒" - -msgid "Source address" -msgstr "源地址" - -msgid "Source port" -msgstr "源端口" - -msgid "Start MWAN" -msgstr "启动 MWAN" - -msgid "Sticky" -msgstr "粘滞模式" - -msgid "Sticky timeout" -msgstr "粘滞超时" - -msgid "Stop MWAN" -msgstr "停止 MWAN" - -msgid "Supports CIDR notation (eg \"192.168.100.0/24\") without quotes" -msgstr "支持 CIDR 记法(例如: \"192.168.100.0/24\")不含引号" - -msgid "There are currently %d of 250 supported interfaces configured" -msgstr "当前已配置 %d 个接口,最大支持 250 个" - -msgid "" -"This displays the metric assigned to this interface in /etc/config/network" -msgstr "这里显示了这个接口在 /etc/config/network 中配置的跃点数" - -msgid "" -"This hostname or IP address will be pinged to determine if the link is up or " -"down. Leave blank to assume interface is always online" -msgstr "通过 ping 此主机或 IP 地址来确定链路是否在线。留空则认为接口始终在线" - -msgid "This section allows you to modify the contents of /etc/config/mwan3" -msgstr "这里允许你修改 /etc/config/mwan3 的内容" - -msgid "This section allows you to modify the contents of /etc/config/network" -msgstr "这里允许你修改 /etc/config/network 的内容" - -msgid "This section allows you to modify the contents of /etc/config/wireless" -msgstr "这里允许你修改 /etc/config/wireless 的内容" - -msgid "" -"This section allows you to modify the contents of /etc/hotplug.d/iface/16-" -"mwancustom
This is useful for running system commands and/or scripts " -"based on interface ifup or ifdown hotplug events

Notes:
The " -"first line of the script must be "#!/bin/sh" without quotes
Lines beginning with # are comments and are not executed

Available variables:
$ACTION is the hotplug event (ifup, ifdown)
" -"$INTERFACE is the interface name (wan1, wan2, etc.)
$DEVICE is the " -"device name attached to the interface (eth0.1, eth1, etc.)" -msgstr "" -"这里允许你修改 /etc/hotplug.d/iface/16-mwancustom 的内容
这可以在接口 " -"ifup 或 ifdown Hotplug 事件时运行系统命令或脚本

注意:
脚本的" -"第一行必须是 "#!/bin/sh" 不含引号
以#开头的行是注释,不会执行" -"

可用变量:
$ACTION 是 Hotplug 事件(ifup, ifdown)
" -"$INTERFACE 是接口名称(wan1、wan2 等)
$DEVICE 是连接到接口的设备名称 " -"(eth0.1、eth1 等)" - -msgid "Tracking IP" -msgstr "追踪的 IP" - -msgid "Tracking hostname or IP address" -msgstr "追踪的主机或 IP 地址" - -msgid "Tracking reliability" -msgstr "追踪可靠性" - -msgid "Traffic Rules" -msgstr "流量规则" - -msgid "" -"Traffic from the same source IP address that previously matched this rule " -"within the sticky timeout period will use the same WAN interface" -msgstr "" -"来自相同源 IP 的流量,如果已经匹配过此规则并且在粘滞超时时间内,将会使用相同" -"的 WAN 接口" - -msgid "Troubleshooting" -msgstr "故障排除" - -msgid "Troubleshooting Data" -msgstr "故障排除数据" - -msgid "View the contents of /etc/protocols for protocol descriptions" -msgstr "请查看 /etc/protocols 获取可选协议详情" - -msgid "WARNING: %d interfaces are configured exceeding the maximum of 250!" -msgstr "警告: 已配置 %d 个接口,超过最大值 250!" - -msgid "" -"WARNING: Some policies have names exceeding the maximum of 15 characters!" -msgstr "警告: 某些策略的名称超过了 15 个字符!" - -msgid "" -"WARNING: some interfaces are configured incorrectly or not at all in /etc/" -"config/network!" -msgstr "警告: 某些接口配置不正确或未配置到 /etc/config/network!" - -msgid "" -"WARNING: some interfaces have a higher reliability requirement than there " -"are tracking IP addresses!" -msgstr "警告: 某些接口的追踪可靠性要求大于了追踪 IP 地址总数!" - -msgid "" -"WARNING: some interfaces have duplicate metrics configured in /etc/config/" -"network!" -msgstr "警告: 某些接口在 /etc/config/network 中配置了相同的跃点数!" - -msgid "" -"WARNING: some interfaces have no default route in the main routing table!" -msgstr "警告: 某些接口在主路由表中没有默认路由!" - -msgid "" -"WARNING: some interfaces have no metric configured in /etc/config/network!" -msgstr "警告: 某些接口没有在 /etc/config/network 中配置跃点数!" - -msgid "" -"WARNING: some rules have a port configured with no or improper protocol " -"specified! Please configure a specific protocol!" -msgstr "" -"警告: 某些规则指定了端口却没有配置或配置了不正确的协议,请重新指定协议!" - -msgid "" -"WARNING: this and other interfaces have duplicate metrics configured in /etc/" -"config/network!" -msgstr "警告: 此接口和其他接口在 /etc/config/network 中配置了相同的跃点数!" - -msgid "" -"WARNING: this interface has a higher reliability requirement than there are " -"tracking IP addresses!" -msgstr "警告: 此接口的追踪可靠性要求大于了追踪 IP 地址总数!" - -msgid "WARNING: this interface has no default route in the main routing table!" -msgstr "警告: 此接口在主路由表中没有默认路由!" - -msgid "" -"WARNING: this interface has no metric configured in /etc/config/network!" -msgstr "警告: 此接口没有在 /etc/config/network 中配置跃点数!" - -msgid "" -"WARNING: this interface is configured incorrectly or not at all in /etc/" -"config/network!" -msgstr "警告: 此接口配置不正确或未配置到 /etc/config/network!" - -msgid "" -"WARNING: this policy's name is %d characters exceeding the maximum of 15!" -msgstr "警告: 此策略的名称具有 %d 个字符,超过了 15 个字符!" - -msgid "" -"WARNING: this rule is incorrectly configured with no or improper protocol " -"specified! Please configure a specific protocol!" -msgstr "警告: 此规则没有配置或配置了不正确的协议,请重新指定协议!" - -msgid "Waiting for MWAN to %s..." -msgstr "等待 MWAN %s..." - -msgid "Waiting for diagnostic results..." -msgstr "等待诊断结果..." - -msgid "Weight" -msgstr "比重" - -msgid "" -"When all policy members are offline use this behavior for matched traffic" -msgstr "当所有策略成员都无法使用的时候,对使用该策略的流量使用这个操作" - -msgid "Wireless Config" -msgstr "无线配置" - -msgid "Yes" -msgstr "是" - -msgid "always" -msgstr "总是" - -msgid "blackhole (drop)" -msgstr "黑洞(丢弃)" - -msgid "default (use main routing table)" -msgstr "默认(使用主路由表)" - -msgid "ifdown" -msgstr "ifdown" - -msgid "ifup" -msgstr "ifup" - -msgid "never" -msgstr "从不" - -msgid "restart" -msgstr "重启" - -msgid "start" -msgstr "启动" - -msgid "stop" -msgstr "关闭" - -msgid "unreachable (reject)" -msgstr "不可达(拒绝)" - -msgid "%d IPv4-only hosts" -msgstr "%d 个主机仅支持 IPv4" - -msgid "%d IPv6-only hosts" -msgstr "%d 个主机仅支持 IPv6" - -msgid "%d dual-stack hosts" -msgstr "%d 个双协议栈主机" - -msgid "%s and %s" -msgstr "%s 和 %s" - -msgid "%s, %s and %s" -msgstr "%s, %s 和 %s" - -msgid "-1 - Restart every last day of month" -msgstr "-1 - 每月的最后一天重新开始" - -msgid "-7 - Restart a week before end of month" -msgstr "-7 - 每月底前一周重新开始" - -msgid "1 - Restart every 1st of month" -msgstr "1 - 每月的第一天重新开始" - -msgid "10m - frequent commits at the expense of flash wear" -msgstr "10m - 频繁提交,闪存损耗的开销也增大" - -msgid "12h - compromise between risk of data loss and flash wear" -msgstr "12h - 平衡统计数据丢失的风险以及闪存使用寿命" - -msgid "24h - least flash wear at the expense of data loss risk" -msgstr "24h - 以数据丢失风险的代价换取最小的闪存损耗" - -msgid "30s - refresh twice per minute for reasonably current stats" -msgstr "30s - 每分钟刷新二次以获得较准确的当前统计值" - -msgid "5m - rarely refresh to avoid frequently clearing conntrack counters" -msgstr "5m - 较少刷新以避免频繁清除连接跟踪计数器" - -msgid "60s - commit minutely, useful for non-flash storage" -msgstr "60s - 每分钟提交,适用于非闪存类型存储" - -msgid "0 connections" -msgstr "连接:0" - -msgid "0 hosts" -msgstr "主机:0" - -msgid "0% IPv6 support rate among hosts" -msgstr "支持 IPv6 的主机比例:0%" - -msgid "0B total IPv6 download" -msgstr "IPv6 总下载量:0B" - -msgid "0% of the total traffic is IPv6" -msgstr "IPv6 流量比例:0%" - -msgid "0B total IPv6 upload" -msgstr "IPv6 总上传量:0B" - -msgid "0 cause the most connections" -msgstr "0 是连接数最多的协议" - -msgid "0 cause the most download" -msgstr "0 是下载量最大的协议" - -msgid "0 cause the most upload" -msgstr "0 是上传量最大的协议" - -msgid "0 different application protocols" -msgstr "0 种不同的应用层协议" - -msgid "0 download" -msgstr "下载:0" - -msgid "0 upload" -msgstr "上传:0" - -msgid "Accounting period" -msgstr "统计周期" - -msgid "Advanced Settings" -msgstr "高级设置" - -msgid "Application" -msgstr "应用层协议" - -msgid "Application Protocols" -msgstr "应用层协议" - -msgid "Backup" -msgstr "备份" - -msgid "Bandwidth Monitor" -msgstr "带宽监控" - -msgid "CSV, grouped by IP" -msgstr "CSV,按 IP 分组" - -msgid "CSV, grouped by MAC" -msgstr "CSV,按 MAC 分组" - -msgid "CSV, grouped by protocol" -msgstr "CSV,按协议分组" - -msgid "" -"Changing the accounting interval type will invalidate existing databases!" -"
Download backup." -msgstr "" -"更改统计周期类型会使现有数据库无效!
下载备份." - -msgid "" -"Choose \"Day of month\" to restart the accounting period monthly on a " -"specific date, e.g. every 3rd. Choose \"Fixed interval\" to restart the " -"accounting period exactly every N days, beginning at a given date." -msgstr "" -"选择“每月的某一天”来设置统计周期的重启时间,例如:每个月的第 3 天。选择“固定" -"周期”来设置从给定日期开始每 N 天重启统计周期。" - -msgid "Commit interval" -msgstr "提交间隔" - -msgid "Compress database" -msgstr "压缩数据库" - -msgid "Conn." -msgstr "连接。" - -msgid "Connections" -msgstr "连接" - -msgid "Connections / Host" -msgstr "连接 / 主机" - -msgid "Database directory" -msgstr "数据库目录" - -msgid "" -"Database storage directory. One file per accounting period will be placed " -"into this directory." -msgstr "数据库存储目录。每个“统计周期”的文件将被放到这个目录中。" - -msgid "Day of month" -msgstr "每月的某一天" - -msgid "" -"Day of month to restart the accounting period. Use negative values to count " -"towards the end of month, e.g. \"-5\" to specify the 27th of July or the " -"24th of Februrary." -msgstr "" -"每个月重启统计周期的日期。使用负数表示从月底开始计算,例如:\"-5\" 可以表示 " -"7 月份的 27 号或者 2 月份的 24 号。" - -msgid "Display" -msgstr "显示" - -msgid "Down. (Bytes / Pkts.)" -msgstr "下载(字节 / 数据包)" - -msgid "Download (Bytes / Packets)" -msgstr "下载(字节 / 数据包)" - -msgid "Download / Application" -msgstr "下载 / 应用层协议" - -msgid "Download Database Backup" -msgstr "下载数据库备份" - -msgid "Dualstack enabled hosts" -msgstr "双协议栈主机" - -msgid "Due date" -msgstr "重置日期" - -msgid "Export" -msgstr "导出" - -msgid "Family" -msgstr "协议类型" - -msgid "Fixed interval" -msgstr "固定周期" - -msgid "Force reload…" -msgstr "强制重新加载..…" - -msgid "General Settings" -msgstr "基本设置" - -msgid "Generate Backup" -msgstr "生成备份" - -msgid "Host" -msgstr "主机" - -msgid "Hostname: example.org" -msgstr "主机名:example.org" - -msgid "IPv4 vs. IPv6" -msgstr "IPv4 与 IPv6" - -msgid "Interval" -msgstr "周期" - -msgid "" -"Interval at which the temporary in-memory database is committed to the " -"persistent database directory." -msgstr "将内存中的临时数据库提交到持久性数据库目录的间隔时间。" - -msgid "" -"Interval at which traffic counters of still established connections are " -"refreshed from netlink information." -msgstr "从 netlink 信息中刷新“已建立连接”的流量计数器的间隔时间。" - -msgid "Invalid or empty backup archive" -msgstr "备份存档无效或为空" - -msgid "JSON dump" -msgstr "JSON 输出" - -msgid "Length of accounting interval in days." -msgstr "统计周期(天)。" - -msgid "Local interfaces" -msgstr "本地接口" - -msgid "Local subnets" -msgstr "本地子网" - -msgid "MAC" -msgstr "MAC" - -msgid "Maximum entries" -msgstr "最大条目" - -msgid "" -"Maximum number of accounting periods to keep, use zero to keep databases " -"forever." -msgstr "保留的统计周期数据库的最大数量,设置 0 表示不限制。" - -msgid "Netlink Bandwidth Monitor" -msgstr "网络带宽监视器" - -msgid "Netlink Bandwidth Monitor - Backup / Restore" -msgstr "网络带宽监视器 - 备份 / 恢复" - -msgid "Netlink Bandwidth Monitor - Configuration" -msgstr "网络带宽监视器 - 配置" - -msgid "No data recorded yet." -msgstr "暂无数据记录。" - -msgid "Only conntrack streams from or to any of these networks are counted." -msgstr "仅统计来自或目标为这些网络接口的连接流量。" - -msgid "Only conntrack streams from or to any of these subnets are counted." -msgstr "仅统计来自或目标为这些子网的连接流量。" - -msgid "Preallocate database" -msgstr "预分配数据库" - -msgid "Protocol Mapping" -msgstr "协议映射" - -msgid "" -"Protocol mappings to distinguish traffic types per host, one mapping per " -"line. The first value specifies the IP protocol, the second value the port " -"number and the third column is the name of the mapped protocol." -msgstr "" -"协议映射用于区分流量类型,每行一条。第一个值指定 IP 协议类型,第二个值是端口" -"号,第三个值是映射的协议名称。" - -msgid "Refresh interval" -msgstr "刷新间隔" - -msgid "Restore" -msgstr "恢复" - -msgid "Restore Database Backup" -msgstr "恢复数据库备份" - -msgid "Select accounting period:" -msgstr "选择统计周期:" - -msgid "Source IP" -msgstr "源 IP" - -msgid "Start date" -msgstr "起始日期" - -msgid "Start date of the first accounting period, e.g. begin of ISP contract." -msgstr "第一个统计周期的起始日期,例如:ISP 合约的起始日期。" - -msgid "Stored periods" -msgstr "储存周期" - -msgid "" -"The Netlink Bandwidth Monitor (nlbwmon) is a lightweight, efficient traffic " -"accounting program keeping track of bandwidth usage per host and protocol." -msgstr "" -"网络带宽监视器(nlbwmon)是一个轻量、高效的流量统计程序,可以统计每个主机和协" -"议的带宽使用情况。" - -msgid "The following database files have been restored: %s" -msgstr "以下数据库文件已恢复:%s" - -msgid "" -"The maximum amount of entries that should be put into the database, setting " -"the limit to 0 will allow databases to grow indefinitely." -msgstr "数据库中的最大条目数量, 设置为 0 将允许数据库无限增长。" - -msgid "Traffic / Host" -msgstr "流量 / 主机" - -msgid "Traffic Distribution" -msgstr "流量分布" - -msgid "Up. (Bytes / Pkts.)" -msgstr "上传(字节 / 数据包)" - -msgid "Upload (Bytes / Packets)" -msgstr "上传(字节 / 数据包)" - -msgid "Upload / Application" -msgstr "上传 / 应用层协议" - -msgid "Vendor: Example Corp." -msgstr "供应商: Example Corp." - -msgid "Warning" -msgstr "警告" - -msgid "" -"Whether to gzip compress archive databases. Compressing the database files " -"makes accessing old data slightly slower but helps to reduce storage " -"requirements." -msgstr "" -"是否使用 gzip 压缩数据库存档。压缩数据库文件会使访问旧数据稍微慢一些, 但有助" -"于减少存储占用空间。" - -msgid "" -"Whether to preallocate the maximum possible database size in memory. This is " -"mainly useful for memory constrained systems which might not be able to " -"satisfy memory allocation after longer uptime periods." -msgstr "" -"是否预先分配数据库最大可能占用的内存大小。这主要适用于内存较小系统,这些系统" -"在长时间运行之后可能无法满足数据库的内存需求。" - -msgid "no traffic" -msgstr "无流量数据" - -msgid "other" -msgstr "其他" - -msgid "" -"Enable IGMP " -"snooping" -msgstr "" -"开启 IGMP snooping" - -msgid "Enables IGMP snooping on this bridge" -msgstr "在此桥接上启用 IGMP snooping 组播(多播)" - -msgid "Action" -msgstr "动作" - -msgid "Advanced Reboot" -msgstr "双分区启动切换" - -msgid "Alternative" -msgstr "备选" - -msgid "Cancel" -msgstr "取消" - -msgid "Confirm" -msgstr "确定" - -msgid "Current" -msgstr "当前" - -msgid "Firmware/OS (Kernel)" -msgstr "固件/系统 (内核)" - -msgid "Partition" -msgstr "分区" - -msgid "Partitions" -msgstr "分区" - -msgid "Perform power off..." -msgstr "点击关机..." - -msgid "Power Off Device" -msgstr "关闭设备" - -msgid "Proceed" -msgstr "处理" - -msgid "Reboot Device to an Alternative Partition" -msgstr "重启设备到备选分区" - -msgid "Reboot to alternative partition..." -msgstr "重启到备选分区。" - -msgid "Reboot to current partition" -msgstr "重启到当前分区" - -msgid "Rebooting..." -msgstr "正在重启..." - -msgid "Shutting down..." -msgstr "正在关闭..." - -msgid "Status" -msgstr "状态" - -msgid "" -"The system is rebooting now.
DO NOT POWER OFF THE DEVICE!
Wait a " -"few minutes before you try to reconnect. It might be necessary to renew the " -"address of your computer to reach the device again, depending on your " -"settings." -msgstr "" -"系统正在重启。
请勿关闭设备电源!
请等待几分钟,然后再尝试重新连" -"接。根据您的设置,可能需要更新计算机的地址才能再次访问该设备。" - -msgid "" -"The system is rebooting to an alternative partition now.
DO NOT POWER " -"OFF THE DEVICE!
Wait a few minutes before you try to reconnect. It " -"might be necessary to renew the address of your computer to reach the device " -"again, depending on your settings." -msgstr "" -"系统正在重新引导到备用分区。
请勿关闭设备电源!
请等待几分钟,然" -"后再尝试重新连接。根据您的设置,可能需要更新计算机的地址才能再次访问该设备。" - -msgid "" -"The system is shutting down now.
DO NOT POWER OFF THE DEVICE!
It " -"might be necessary to renew the address of your computer to reach the device " -"again, depending on your settings." -msgstr "" -"系统正在关闭。
请勿关闭设备电源!
根据您的设置,可能需要更新计算" -"机的地址才能再次访问该设备。" - -msgid "" -"WARNING: An alternative partition might have its own settings and completely " -"different firmware.

As your network configuration and WiFi SSID/" -"password on alternative partition might be different, you might have to " -"adjust your computer settings to be able to access your device once it " -"reboots.

Please also be aware that alternative partition " -"firmware might not provide an easy way to switch active partition and boot " -"back to the currently active partition.

Click \"Proceed\" below " -"to reboot device to an alternative partition." -msgstr "" -"警告:备用分区可能具有自己的设置和完全不同的固件。

由于备用分区上" -"的网络配置和 WiFi SSID / 密码可能有所不同,因此您可能必须调整计算机设置才能在" -"设备重启后访问设备。

另请注意,备用分区固件可能无法提供切换活动分" -"区并引导回当前活动分区的简便方法。

点击 \"继续\" 下面将设备重新" -"引导到备用分区。" - -msgid "" -"WARNING: Power off might result in a reboot on a device which doesn't " -"support power off.

Click \"Proceed\" below to power off your " -"device." -msgstr "" -"警告: 关闭电源可能会导致不支持关闭电源的设备重新启动。

单击下面的" -"\"继续\"以关闭设备电源。" - -msgid "Warning: There are unsaved changes that will get lost on reboot!" -msgstr "警告:某些设置没有保存,重启将导致丢失这些配置!" - -msgid "Warning: This system does not have two partitions!" -msgstr "警告:当前系统没有包括两个分区!" - -msgid "Warning: This system does not support powering off!" -msgstr "警告:本系统不支持软关机!" - -msgid "Filter IPv6 Records" -msgstr "过滤 IPv6 记录" - -msgid "Filter IPv6(AAAA) Records during DNS resolution" -msgstr "在域名解析时,过滤 IPv6(AAAA) 记录" - -msgid "SFE flow offloading" -msgstr "SFE 流量分载" - -msgid "SFE based offloading for Routing/NAT. Restart recommended." -msgstr "基于 SFE 的 Routing/NAT 分载(开/关后建议重启设备)" - -msgid "DNS Settings" -msgstr "DNS 设置" - -msgid "Packet Steering" -msgstr "数据包引导" - -msgid "" -"Enable packet steering across all CPUs. May help or hinder network speed." -msgstr "启用所有 CPU 的数据包控制。 可能有助于或阻碍网络速度。" - -msgid "Compressed memory" -msgstr "内存压缩" - -msgid "Compressed memory subsystem" -msgstr "内存压缩系统" - -msgid "Configure the compressed memory subsystem, which allows data in memory to be compressed to enhance resource usage." -msgstr "配置内存压缩系统,允许压缩内存中的数据以提高资源利用率。" - -msgid "Compressed RAM disk properties" -msgstr "RamDisk 压缩设置" - -msgid "Configure the compressed RAM disk properties. This RAM disk will be used as a swap device." -msgstr "对 RamDisk 压缩参数进行设置。这个 RamDisk 将会作为 Swap 设备。" - -msgid "Enable swap on zram" -msgstr "在 zRam 上启用 Swap" - -msgid "Enable usage of the compressed RAM disk (zram)." -msgstr "启用 RamDisk 压缩(zRam)" - -msgid "Compression algorithm" -msgstr "压缩算法" - -msgid "Select the compression algorithm. The one with higher compression ratio is the first and the one with the lower is the last." -msgstr "选择压缩算法,压缩比按列表中的顺序,由高到低排列。启用最好的压缩算法可以节省更多的内存,但会增加 CPU 占用。" - -msgid "Base memory pool" -msgstr "基础内存池" - -msgid "This is the maximum percentage of the main memory to use as the compressed disk assuming that the data is compressible." -msgstr "压缩内存可使用的最大内存百分比。" - -msgid "Backing storage device" -msgstr "后备存储池" - -msgid "This file or device will be used when the data is hard to compress which offer no gain to keep it in memory. Note that the file or device must have the appropiate size, for example, the size of the RAM disk." -msgstr "这个文件或存储位置将在数据难以被压缩时使用。请注意,该文件或存储位置的剩余空间需大于 RamDisk。" - -msgid "Show advanced setup" -msgstr "高级设置" - -msgid "Absolute memory pool limit" -msgstr "内存池限制" - -msgid "Compressed swap cache properties" -msgstr "Swap Cache压缩设置" - -msgid "Configure the compressed swap cache. This cache will try to avoid I/O to slow disks or to use the more expensive compressor of zram." -msgstr "对 Swap Cache 压缩参数进行设置。这个 Cache 将会减少硬盘 IO。" - -msgid "Enable zswap cache" -msgstr "启用 zSwap Cache" - -msgid "Enable the usage of the compressed swap cache (zswap)." -msgstr "启用 zSwap Cache 压缩(zSwap)" - -msgid "Select the compression algorithm, they are not ordered by speed. There is no gain in choosing a slower algorithm, since the zpool limits the maximum compression ratio. Because of this, the default is the best option." -msgstr "选择压缩算法,建议使用默认的。" - -msgid "Maximum memory pool" -msgstr "最大内存池" - -msgid "This is the maximum percentage of the main memory to use as the compressed cache for swap when zram is not available." -msgstr "这个值是当 zRam 不可用时候,zSwap Cache 可使用的最大内存百分比。" - -msgid "Memory allocator" -msgstr "内存分配器" - -msgid "Select the compressed memory allocator (zpool). The zpool can store, at most, this quantity of pages in the space that uses one." -msgstr "选择内存分配器,这间影响单个页面对应的最大压缩比。" - -msgid "System swappiness" -msgstr "系统交换空间策略" - -msgid "The tendency of the system to swap unused pages instead of dropping file system cache. If your file system is compressed, such as SQUASHFS, UBI or zfs, use a slightly higher swappiness.'" -msgstr "数值越大,代表越积极的使用 Swap 空间而不是 Ram ,建议在 SQUASHFS 之类的文件系统上使用一个相对更大的值。" - -msgid "Compressor for zram" -msgstr "zRam 压缩算法" - -msgid "Select the compression algorithm for zram when zswap is enabled. The one with higher compression ratio is the first and the one with the lower is the last. Enabling the best compression enables greater memory savings." -msgstr "选择 zRam 的压缩算法,压缩比按列表中的顺序,由高到低排列。启用最好的压缩算法可以节省更多的内存,但会增加 CPU 占用。" - -msgid "Scale factor" -msgstr "比例因子" - -msgid "This is the percentage that will use the zswap pool when zram is enabled. This represents the uncompressed data size as a percentage of the zram\'s pool maximum size." -msgstr "这是 zRam 启用后,zSwap 占用的内存百分比。这也表示未压缩数据占 zRam 池的最大占比。" - -msgid "Enable FullCone NAT" -msgstr "启用 FullCone-NAT" - -msgid "Compressed swap disk and cache" -msgstr "压缩交换缓存" - -msgid "Configure the compressed memory subsystem, which allows data in memory to be compressed to enhance resource usage." -msgstr "配置内存压缩系统,允许压缩内存中的数据以提高内存资源利用率(可能会消耗更多的处理器资源)。" - -msgid "Configure the compressed RAM disk properties. This section will configure the zram "compressed" block device, which will be used by the kernel as a physical swap disk. If your CPU and RAM are fast or your device does not have external storage, zram is the best alternative to free unused or rarely used memory." -msgstr "对 RamDisk 压缩参数进行设置。在内存中划分一块空间,作为 Swap 空间。 在处理器和内存性能足够的情况下,zRam 是获额外内存空间的最佳方式。" - -msgid "Enable a zram disk as a swap area" -msgstr "将 zRam 作为 Swap 空间" - -msgid "Compressed swap cache [zswap]" -msgstr "zSwap" - -msgid "Compressed RAM disk [zram]" -msgstr "zRam" - -msgid "Configure the compressed swap cache. When used as a cache to a swap device or file, it will reduce the I/O requests to the device or filesystem, allowing faster access to swapped memory areas by keeping them in memory.
When used as a cache to zram, it will avoid using the more efficient, yet more expensive, zram block compressor.
Note that while zram is a compressed block device, this is a compact-page LRU cache, and while zram can work as a stand-alone swap device, zswap always needs a backing swap device, which can be any swap area, including zram." -msgstr "对 Swap Cache 压缩参数进行设置。这个 Cache 将会减少硬盘 IO。" - -msgid "Compressor for zram when using zswap" -msgstr "zSwap 压缩算法" - -msgid "Enable a zswap cache for swap devices" -msgstr "启用 zSwap Cache" - -msgid "MiniUPnP extra settings" -msgstr "MiniUPnP 补充设置" - -msgid "Settings for router behined DMZ" -msgstr "二级路由设置" - -msgid "External Network Interface" -msgstr "外部网络接口" - -msgid "Internal Network Interface" -msgstr "内部网络接口" - -msgid "usually is wan" -msgstr "通常为 wan" - -msgid "usually is lan" -msgstr "通常为 lan" - -msgid "Source Code" -msgstr "源代码" diff --git a/PATCH/duplicate/addition-trans-zh/status/status.lua b/PATCH/duplicate/addition-trans-zh/status/status.lua deleted file mode 100644 index 864b3ef6b..000000000 --- a/PATCH/duplicate/addition-trans-zh/status/status.lua +++ /dev/null @@ -1,250 +0,0 @@ --- Copyright 2011 Jo-Philipp Wich --- Licensed to the public under the Apache License 2.0. - -module("luci.tools.status", package.seeall) - -local uci = require "luci.model.uci".cursor() -local ipc = require "luci.ip" - -local function dhcp_leases_common(family) - local rv = { } - local nfs = require "nixio.fs" - local sys = require "luci.sys" - local leasefile = "/tmp/dhcp.leases" - - uci:foreach("dhcp", "dnsmasq", - function(s) - if s.leasefile and nfs.access(s.leasefile) then - leasefile = s.leasefile - return false - end - end) - - local fd = io.open(leasefile, "r") - if fd then - while true do - local ln = fd:read("*l") - if not ln then - break - else - local ts, mac, ip, name, duid = ln:match("^(%d+) (%S+) (%S+) (%S+) (%S+)") - local expire = tonumber(ts) or 0 - if ts and mac and ip and name and duid then - if family == 4 and not ip:match(":") then - rv[#rv+1] = { - expires = (expire ~= 0) and os.difftime(expire, os.time()), - macaddr = ipc.checkmac(mac) or "00:00:00:00:00:00", - ipaddr = ip, - hostname = (name ~= "*") and name - } - elseif family == 6 and ip:match(":") then - rv[#rv+1] = { - expires = (expire ~= 0) and os.difftime(expire, os.time()), - ip6addr = ip, - duid = (duid ~= "*") and duid, - hostname = (name ~= "*") and name - } - end - end - end - end - fd:close() - end - - local lease6file = "/tmp/hosts/odhcpd" - uci:foreach("dhcp", "odhcpd", - function(t) - if t.leasefile and nfs.access(t.leasefile) then - lease6file = t.leasefile - return false - end - end) - local fd = io.open(lease6file, "r") - if fd then - while true do - local ln = fd:read("*l") - if not ln then - break - else - local iface, duid, iaid, name, ts, id, length, ip = ln:match("^# (%S+) (%S+) (%S+) (%S+) (-?%d+) (%S+) (%S+) (.*)") - local expire = tonumber(ts) or 0 - if ip and iaid ~= "ipv4" and family == 6 then - rv[#rv+1] = { - expires = (expire >= 0) and os.difftime(expire, os.time()), - duid = duid, - ip6addr = ip, - hostname = (name ~= "-") and name - } - elseif ip and iaid == "ipv4" and family == 4 then - rv[#rv+1] = { - expires = (expire >= 0) and os.difftime(expire, os.time()), - macaddr = sys.net.duid_to_mac(duid) or "00:00:00:00:00:00", - ipaddr = ip, - hostname = (name ~= "-") and name - } - end - end - end - fd:close() - end - - if family == 6 then - local _, lease - local hosts = sys.net.host_hints() - for _, lease in ipairs(rv) do - local mac = sys.net.duid_to_mac(lease.duid) - local host = mac and hosts[mac] - if host then - if not lease.name then - lease.host_hint = host.name or host.ipv4 or host.ipv6 - elseif host.name and lease.hostname ~= host.name then - lease.host_hint = host.name - end - end - end - end - - return rv -end - -function dhcp_leases() - return dhcp_leases_common(4) -end - -function dhcp6_leases() - return dhcp_leases_common(6) -end - -function wifi_networks() - local rv = { } - local ntm = require "luci.model.network".init() - - local dev - for _, dev in ipairs(ntm:get_wifidevs()) do - local rd = { - up = dev:is_up(), - device = dev:name(), - name = dev:get_i18n(), - networks = { } - } - - local net - for _, net in ipairs(dev:get_wifinets()) do - local a, an = nil, 0 - for _, a in pairs(net:assoclist() or {}) do - an = an + 1 - end - - rd.networks[#rd.networks+1] = { - name = net:shortname(), - link = net:adminlink(), - up = net:is_up(), - mode = net:active_mode(), - ssid = net:active_ssid(), - bssid = net:active_bssid(), - encryption = net:active_encryption(), - frequency = net:frequency(), - channel = net:channel(), - signal = net:signal(), - quality = net:signal_percent(), - noise = net:noise(), - bitrate = net:bitrate(), - ifname = net:ifname(), - country = net:country(), - txpower = net:txpower(), - txpoweroff = net:txpower_offset(), - num_assoc = an, - disabled = (dev:get("disabled") == "1" or - net:get("disabled") == "1") - } - end - - rv[#rv+1] = rd - end - - return rv -end - -function wifi_network(id) - local ntm = require "luci.model.network".init() - local net = ntm:get_wifinet(id) - if net then - local dev = net:get_device() - if dev then - return { - id = id, - name = net:shortname(), - link = net:adminlink(), - up = net:is_up(), - mode = net:active_mode(), - ssid = net:active_ssid(), - bssid = net:active_bssid(), - encryption = net:active_encryption(), - frequency = net:frequency(), - channel = net:channel(), - signal = net:signal(), - quality = net:signal_percent(), - noise = net:noise(), - bitrate = net:bitrate(), - ifname = net:ifname(), - country = net:country(), - txpower = net:txpower(), - txpoweroff = net:txpower_offset(), - disabled = (dev:get("disabled") == "1" or - net:get("disabled") == "1"), - device = { - up = dev:is_up(), - device = dev:name(), - name = dev:get_i18n() - } - } - end - end - return { } -end - -function wifi_assoclist() - local sys = require "luci.sys" - local ntm = require "luci.model.network".init() - local hosts = sys.net.host_hints() - - local assoc = {} - local _, dev, net, bss - - for _, dev in ipairs(ntm:get_wifidevs()) do - local radioname = dev:get_i18n() - - for _, net in ipairs(dev:get_wifinets()) do - local netname = net:shortname() - local netlink = net:adminlink() - local ifname = net:ifname() - - for _, bss in pairs(net:assoclist() or {}) do - local host = hosts[_] - - bss.bssid = _ - bss.ifname = ifname - bss.radio = radioname - bss.name = netname - bss.link = netlink - - bss.host_name = (host) and (host.name or host.ipv4 or host.ipv6) - bss.host_hint = (host and host.name and (host.ipv4 or host.ipv6)) and (host.ipv4 or host.ipv6) - - assoc[#assoc+1] = bss - end - end - end - - table.sort(assoc, function(a, b) - if a.radio ~= b.radio then - return a.radio < b.radio - elseif a.ifname ~= b.ifname then - return a.ifname < b.ifname - else - return a.bssid < b.bssid - end - end) - - return assoc -end \ No newline at end of file diff --git a/PATCH/duplicate/luci-app-control-weburl/Makefile b/PATCH/duplicate/luci-app-control-weburl/Makefile deleted file mode 100644 index b0df327f8..000000000 --- a/PATCH/duplicate/luci-app-control-weburl/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (C) 2016 Openwrt.org -# -# This is free software, licensed under the Apache License, Version 2.0 . -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=LuCI support for Weburl From Koolshare -LUCI_DEPENDS:=+iptables-mod-filter +kmod-ipt-filter -LUCI_PKGARCH:=all -PKG_VERSION:=1.5 -PKG_RELEASE:=20200923 - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature - - diff --git a/PATCH/duplicate/luci-app-control-weburl/luasrc/controller/weburl.lua b/PATCH/duplicate/luci-app-control-weburl/luasrc/controller/weburl.lua deleted file mode 100644 index 539e4f988..000000000 --- a/PATCH/duplicate/luci-app-control-weburl/luasrc/controller/weburl.lua +++ /dev/null @@ -1,10 +0,0 @@ -module("luci.controller.weburl", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/weburl") then return end - - entry({"admin", "control"}, firstchild(), "Control", 50).dependent = false - entry({"admin", "control", "weburl"}, cbi("weburl"), _("过滤军刀"), 12).dependent = - true -end - diff --git a/PATCH/duplicate/luci-app-control-weburl/luasrc/model/cbi/weburl.lua b/PATCH/duplicate/luci-app-control-weburl/luasrc/model/cbi/weburl.lua deleted file mode 100644 index c40766079..000000000 --- a/PATCH/duplicate/luci-app-control-weburl/luasrc/model/cbi/weburl.lua +++ /dev/null @@ -1,65 +0,0 @@ -local o = require "luci.sys" -local a, t, e -local button = "" -local state_msg = "" -local running=(luci.sys.call("iptables -L FORWARD|grep WEBURL >/dev/null") == 0) -local button = "" -local state_msg = "" -if running then - state_msg = "" .. translate("正在运行") .. "" -else - state_msg = "" .. translate("没有运行") .. "" -end -a = Map("weburl", translate("网址过滤/关键字过滤/MAC黑名单/时间控制/端口控制"), translate("利用iptables来单独或组合使用多种条件过滤。条件除特别说明外都可以留空不使用。
* 如指定“关键词/URL”(MAC黑名单、时间、星期可选)则为关键字过滤,关键字可以是字符串或网址。
* 如指定“MAC黑名单”而“关键词/URL”留空则为纯MAC黑名单模式(如已改变默认时间或星期则成为时间控制)。
* 如指定端口(MAC黑名单、时间、星期可选)则禁止通过此端口联网。端口可以是端口范围如5000:5100或多端口5100,5110。" .. button .. "

" .. translate("运行状态").. " : " .. state_msg .. "
")) -t = a:section(TypedSection, "basic", translate(""), translate("")) -t.anonymous = true -e = t:option(Flag, "enabled", translate("开启功能")) -e.rmempty = false -e = t:option(ListValue, "algos", translate("过滤力度")) -e:value("bm", "一般过滤") -e:value("kmp", "强效过滤") -e.default = "kmp" -t = a:section(TypedSection, "macbind", translate("")) -t.template = "cbi/tblsection" -t.anonymous = true -t.addremove = true -e = t:option(Flag, "enable", translate("开启")) -e.rmempty = false -e.default = '1' -e = t:option(Value, "macaddr", translate("黑名单MAC(留空则过滤全部客户端)")) -e.rmempty = true -o.net.mac_hints(function(t, a) e:value(t, "%s (%s)" % {t, a}) end) -e = t:option(Value, "keyword", translate("关键词/URL(可留空)")) -e.rmempty = true -e = t:option(ListValue, "proto", translate("端口协议")) -e.rmempty = false -e.default = 'tcp' -e:value("tcp", translate("TCP")) -e:value("udp", translate("UDP")) -e = t:option(Value, "sport", translate("源端口")) -e.rmempty = true -e = t:option(Value, "dport", translate("目的端口")) -e.rmempty = true -e = t:option(Value, "timeon", translate("起控时间")) -e.placeholder = "00:00" -e.default = '00:00' -e.rmempty = true -e = t:option(Value, "timeoff", translate("停控时间")) -e.placeholder = "00:00" -e.default = '00:00' -e.rmempty = true -e = t:option(MultiValue, "daysofweek", translate("星期(至少选一天,某天不选则该天不进行控制)")) -e.optional = false -e.rmempty = false -e.default = 'Monday Tuesday Wednesday Thursday Friday Saturday Sunday' -e:value("Monday", translate("一")) -e:value("Tuesday", translate("二")) -e:value("Wednesday", translate("三")) -e:value("Thursday", translate("四")) -e:value("Friday", translate("五")) -e:value("Saturday", translate("六")) -e:value("Sunday", translate("日")) -return a - - - diff --git a/PATCH/duplicate/luci-app-control-weburl/po/zh-cn/weburl.po b/PATCH/duplicate/luci-app-control-weburl/po/zh-cn/weburl.po deleted file mode 100644 index a883cf73a..000000000 --- a/PATCH/duplicate/luci-app-control-weburl/po/zh-cn/weburl.po +++ /dev/null @@ -1,2 +0,0 @@ -msgid "Control" -msgstr "管控" diff --git a/PATCH/duplicate/luci-app-control-weburl/root/etc/config/weburl b/PATCH/duplicate/luci-app-control-weburl/root/etc/config/weburl deleted file mode 100644 index 331fc492b..000000000 --- a/PATCH/duplicate/luci-app-control-weburl/root/etc/config/weburl +++ /dev/null @@ -1,27 +0,0 @@ - -config basic - option algos 'kmp' - option enabled '0' - -config macbind - option timeoff '00:00' - option timeon '00:00' - option daysofweek 'Monday Tuesday Wednesday Thursday Friday Saturday Sunday' - option keyword 'qq.com' - option enable '0' - -config macbind - option timeoff '00:00' - option timeon '00:00' - option daysofweek 'Monday Tuesday Wednesday Thursday Friday Saturday Sunday' - option enable '0' - option keyword 'www' - -config macbind - option timeoff '00:00' - option timeon '00:00' - option daysofweek 'Monday Tuesday Wednesday Thursday Friday Saturday Sunday' - option enable '0' - option keyword 'cmd.exe' - - diff --git a/PATCH/duplicate/luci-app-control-weburl/root/etc/init.d/weburl b/PATCH/duplicate/luci-app-control-weburl/root/etc/init.d/weburl deleted file mode 100644 index c34d5f1e8..000000000 --- a/PATCH/duplicate/luci-app-control-weburl/root/etc/init.d/weburl +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/sh /etc/rc.common -# -# Copyright (C) 2015 OpenWrt-dist -# Copyright (C) 2016 fw867 -# -# This is free software, licensed under the GNU General Public License v3. -# See /LICENSE for more information. -# wulishui mod. at 20200923 , - -START=98 - -add_rules() { -rulessum=$(grep -c 'macbind' /etc/config/weburl) -for i in $(seq 0 $((rulessum-1))) -do -enable=$(uci get weburl.@macbind[$i].enable 2>/dev/null) -if [ "$enable" == 1 ]; then - macaddr=$(uci get weburl.@macbind[$i].macaddr 2>/dev/null) && MAC="-m mac --mac-source $macaddr" || MAC="" - keyword=$(uci get weburl.@macbind[$i].keyword 2>/dev/null) && STG="-m string --string ${keyword} --algo ${algos}" || STG="" - proto=$(uci get weburl.@macbind[$i].proto 2>/dev/null) || proto="tcp" - sport=$(uci get weburl.@macbind[$i].sport 2>/dev/null) && SPT="--sport ${sport}" || SPT="" - dport=$(uci get weburl.@macbind[$i].dport 2>/dev/null) && DPT="--dport ${dport}" || DPT="" - havesMPT=`echo "$sport"|grep ","` && sMPT="-m multiport" || sMPT="" - havedMPT=`echo "$dport"|grep ","` && dMPT="-m multiport" || dMPT="" - [ -z "$sport" -a -z "$dport" ] && PTS="" || PTS="-p ${proto} ${sMPT} ${SPT} ${dMPT} ${DPT}" - timestart=$(uci get weburl.@macbind[$i].timeon 2>/dev/null) || timestart="00:00" - timestop=$(uci get weburl.@macbind[$i].timeoff 2>/dev/null) || timestop="00:00" - week_days=$(uci get weburl.@macbind[$i].daysofweek |sed 's/ /,/g' 2>/dev/null) - [ "$timestart" = "$timestop" ] && TIME="" || TIME="--timestart ${timestart} --timestop ${timestop}" - [ -z "$week_days" -o "$week_days" = "Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday" ] && WEEK="" || WEEK="--weekdays ${week_days}" - [ -n "$TIME" -o -n "$WEEK" ] && TME="-m time --kerneltz ${TIME} ${WEEK}" || TME="" - if [ -n "$keyword" -o -n "$MAC" -o -n "$sport" -o -n "$dport" ]; then - iptables -A WEBURL ${MAC} ${PTS} ${TME} ${STG} -j REJECT 2>/dev/null - ip6tables -A WEBURL ${MAC} ${PTS} ${TME} ${STG} -j REJECT 2>/dev/null - fi -fi -done -} - -start(){ -enabled=`uci get weburl.@basic[0].enabled 2>/dev/null` -if [ "$enabled" == 1 ]; then - ENsum=`grep -c 'enable .1.' /etc/config/weburl` - if [ "$ENsum" -gt 0 ]; then - algos=`uci get weburl.@basic[0].algos 2>/dev/null` - iptables -N WEBURL 2>/dev/null || iptables -F WEBURL 2>/dev/null - ip6tables -N WEBURL 2>/dev/null || ip6tables -F WEBURL 2>/dev/null - iptables -C FORWARD -j WEBURL 2>/dev/null || iptables -I FORWARD -j WEBURL - ip6tables -C FORWARD -j WEBURL 2>/dev/null || ip6tables -I FORWARD -j WEBURL - add_rules - grep 'weburl' /etc/firewall.user || echo "/etc/init.d/weburl restart" >> /etc/firewall.user - fi -fi -} - -stop(){ - sed -i '/weburl/d' /etc/firewall.user 2>/dev/null - iptables -D FORWARD -j WEBURL 2>/dev/null - ip6tables -D FORWARD -j WEBURL 2>/dev/null - iptables -F WEBURL 2>/dev/null - ip6tables -F WEBURL 2>/dev/null - iptables - X WEBURL 2>/dev/null - ip6tables -X WEBURL 2>/dev/null -} - diff --git a/PATCH/duplicate/luci-app-control-weburl/root/etc/uci-defaults/luci-app-control-weburl b/PATCH/duplicate/luci-app-control-weburl/root/etc/uci-defaults/luci-app-control-weburl deleted file mode 100644 index fed829197..000000000 --- a/PATCH/duplicate/luci-app-control-weburl/root/etc/uci-defaults/luci-app-control-weburl +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@weburl[-1] - add ucitrack weburl - set ucitrack.@weburl[-1].init=weburl - commit ucitrack -EOF - -rm -f /tmp/luci-indexcache -exit 0 diff --git a/PATCH/duplicate/luci-app-cpulimit/Makefile b/PATCH/duplicate/luci-app-cpulimit/Makefile deleted file mode 100644 index bf0eced0c..000000000 --- a/PATCH/duplicate/luci-app-cpulimit/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# -# Copyright (C) 2008-2014 The LuCI Team -# -# This is free software, licensed under the Apache License, Version 2.0 . -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=cpulimit configuration module -LUCI_DEPENDS:=+cpulimit - -include $(TOPDIR)/feeds/luci/luci.mk - -# call BuildPackage - OpenWrt buildroot signature \ No newline at end of file diff --git a/PATCH/duplicate/luci-app-cpulimit/luasrc/controller/cpulimit.lua b/PATCH/duplicate/luci-app-cpulimit/luasrc/controller/cpulimit.lua deleted file mode 100644 index 2ff63233d..000000000 --- a/PATCH/duplicate/luci-app-cpulimit/luasrc/controller/cpulimit.lua +++ /dev/null @@ -1,13 +0,0 @@ - -module("luci.controller.cpulimit", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/cpulimit") then - return - end - - local page = entry({"admin", "system", "cpulimit"}, cbi("cpulimit"), luci.i18n.translate("cpulimit"), 65) - page.i18n = "cpulimit" - page.dependent = true - -end diff --git a/PATCH/duplicate/luci-app-cpulimit/luasrc/model/cbi/cpulimit.lua b/PATCH/duplicate/luci-app-cpulimit/luasrc/model/cbi/cpulimit.lua deleted file mode 100644 index af00b452e..000000000 --- a/PATCH/duplicate/luci-app-cpulimit/luasrc/model/cbi/cpulimit.lua +++ /dev/null @@ -1,38 +0,0 @@ - -m = Map("cpulimit", translate("cpulimit"),translate("cpulimit ")) -s = m:section(TypedSection, "list", translate("Settings")) -s.template = "cbi/tblsection" -s.anonymous = true -s.addremove = true - -enable = s:option(Flag, "enabled", translate("enable", "enable")) -enable.optional = false -enable.rmempty = false - -exename = s:option(Value, "exename", translate("exename"), translate("name of the executable program file or path name")) -exename.optional = false -exename.rmempty = false -exename.default = "/usr/bin/transmission-daemon" -exename:value("transmission","/usr/bin/transmission-daemon") -exename:value("samba","/usr/sbin/smbd") -exename:value("mount.ntfs-3g","mount.ntfs-3g") -exename:value("vsftpd","/usr/sbin/vsftpd") -exename:value("pure-ftpd","/usr/sbin/pure-ftpd") - -limit = s:option(Value, "limit", translate("limit")) -limit.optional = false -limit.rmempty = false -limit.default = "50" -limit:value("100","100%") -limit:value("90","90%") -limit:value("80","80%") -limit:value("70","70%") -limit:value("60","60%") -limit:value("50","50%") -limit:value("40","40%") -limit:value("30","30%") -limit:value("20","20%") -limit:value("10","10%") - - -return m diff --git a/PATCH/duplicate/luci-app-cpulimit/po/zh_Hans/cpulimit.po b/PATCH/duplicate/luci-app-cpulimit/po/zh_Hans/cpulimit.po deleted file mode 100644 index 46e3a5799..000000000 --- a/PATCH/duplicate/luci-app-cpulimit/po/zh_Hans/cpulimit.po +++ /dev/null @@ -1,30 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-06-28\n" -"PO-Revision-Date: 2014-06-28\n" -"Last-Translator: Syrone Wong \n" -"Language: zh_Hans\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -msgid "cpulimit" -msgstr "CPU占用率限制" - -msgid "Use cpulimit to restrict app's cpu usage." -msgstr "利用cpulimit限制应用程序的CPU使用率" - -msgid "Usage restrictions" -msgstr "使用率限制" - -msgid "exename" -msgstr "进程名称" - -msgid "name of the executable program file or path name" -msgstr "可执行文件名称,或包含路径的应用程序" - -msgid "limit" -msgstr "占用率限制(自定义时使用不含'%'的整数)" diff --git a/PATCH/duplicate/luci-app-cpulimit/root/etc/config/cpulimit b/PATCH/duplicate/luci-app-cpulimit/root/etc/config/cpulimit deleted file mode 100644 index df66e8fec..000000000 --- a/PATCH/duplicate/luci-app-cpulimit/root/etc/config/cpulimit +++ /dev/null @@ -1,6 +0,0 @@ - -config 'list' - option 'exename' '/usr/bin/transmission-daemon' - option 'limit' '50' - option 'enabled' '0' - diff --git a/PATCH/duplicate/luci-app-cpulimit/root/etc/init.d/cpulimit b/PATCH/duplicate/luci-app-cpulimit/root/etc/init.d/cpulimit deleted file mode 100644 index e68580062..000000000 --- a/PATCH/duplicate/luci-app-cpulimit/root/etc/init.d/cpulimit +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh /etc/rc.common -# Copyright (C) 2006-2011 OpenWrt.org -. /lib/functions.sh - -START=50 - -DEFAULT=/etc/default/cpulimit - - -start() { - /usr/bin/cpulimit.sh start & -} - -stop() { - killall -9 cpulimit -} - diff --git a/PATCH/duplicate/luci-app-cpulimit/root/etc/uci-defaults/luci-app-cpulimit b/PATCH/duplicate/luci-app-cpulimit/root/etc/uci-defaults/luci-app-cpulimit deleted file mode 100644 index 7e6637487..000000000 --- a/PATCH/duplicate/luci-app-cpulimit/root/etc/uci-defaults/luci-app-cpulimit +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@cpulimit[-1] - add ucitrack cpulimit - set ucitrack.@cpulimit[-1].init=cpulimit - commit ucitrack -EOF - -/etc/init.d/cpulimit enable - -rm -f /tmp/luci-indexcache -exit 0 diff --git a/PATCH/duplicate/luci-app-cpulimit/root/usr/bin/cpulimit.sh b/PATCH/duplicate/luci-app-cpulimit/root/usr/bin/cpulimit.sh deleted file mode 100644 index 76c88df34..000000000 --- a/PATCH/duplicate/luci-app-cpulimit/root/usr/bin/cpulimit.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh - -. /lib/functions.sh - -cpulimit_get(){ - echo cpulimit_get - config_get enabled $1 enabled - [ $enabled -gt 0 ] || return 1 - config_get limit $1 limit - config_get exename $1 exename - eval exepid=$(pgrep $exename) - cpulimit -l $limit -p $exepid & - echo cpulimit -l $limit -p $exepid -} - - - -stop() { -killall -9 cpulimit -# ps -a|grep cpulimit|while read line -# do -# killall cpulimit>/dev/null 2>&1 -# done -} - -case "$1" in - "start") - echo start - killall -9 cpulimit - config_load cpulimit - config_foreach cpulimit_get list - echo end - exit 0 -;; - "stop")echo stop; killall -9 cpulimit;; -esac diff --git a/PATCH/duplicate/luci-app-cpulimit/root/usr/share/rpcd/acl.d/luci-app-cpulimit.json b/PATCH/duplicate/luci-app-cpulimit/root/usr/share/rpcd/acl.d/luci-app-cpulimit.json deleted file mode 100644 index 84fa30435..000000000 --- a/PATCH/duplicate/luci-app-cpulimit/root/usr/share/rpcd/acl.d/luci-app-cpulimit.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "luci-app-cpulimit": { - "description": "Grant UCI access for luci-app-cpulimit", - "read": { - "uci": [ "cpulimit" ] - }, - "write": { - "uci": [ "cpulimit" ] - } - } -} diff --git a/PATCH/duplicate/shortcut-fe b/PATCH/duplicate/shortcut-fe deleted file mode 100644 index 83f628bc5..000000000 --- a/PATCH/duplicate/shortcut-fe +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/sh /etc/rc.common -# -# Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. -# Permission to use, copy, modify, and/or distribute this software for -# any purpose with or without fee is hereby granted, provided that the -# above copyright notice and this permission notice appear in all copies. -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# - -#SFE connection manager has a lower priority, it should be started after other connection manager -#to detect the existence of connection manager with higher priority -START=90 - -have_cm() { - [ -d "/sys/kernel/debug/ecm" ] && echo 1 && return - - echo 0 -} - -#load shortcut-fe connection manager -load_sfe_cm() { - local kernel_version=$(uname -r) - - #shortcut-fe-drv.ko is not needed because other connection manager is not enabled - [ -d "/sys/module/shortcut_fe_drv" ] && rmmod shortcut_fe_drv - - [ -e "/lib/modules/$kernel_version/fast-classifier.ko" ] && { - [ -d /sys/module/fast_classifier ] || insmod /lib/modules/$kernel_version/fast-classifier.ko && return - } - - [ -e "/lib/modules/$kernel_version/shortcut-fe-cm.ko" ] && { - [ -d /sys/module/shortcut_fe_cm ] || insmod /lib/modules/$kernel_version/shortcut-fe-cm.ko && return - } -} - -start() { - [ "$(have_cm)" = "1" ] || load_sfe_cm - echo 1 > /sys/fast_classifier/skip_to_bridge_ingress - sfe_ipv6=$(cat /sys/sfe_ipv6/debug_dev) - [ ! -f /dev/sfe_ipv6 ] && mknod /dev/sfe_ipv6 c $sfe_ipv6 0 -} - -stop() { - [ -d /sys/module/shortcut_fe_cm ] && rmmod shortcut_fe_cm - [ -d /sys/module/fast_classifier ] && rmmod fast_classifier -} diff --git a/PATCH/R2S/files/etc/config/AdGuardHome b/PATCH/files/etc/config/AdGuardHome similarity index 100% rename from PATCH/R2S/files/etc/config/AdGuardHome rename to PATCH/files/etc/config/AdGuardHome diff --git a/PATCH/R2S/files/etc/config/AdGuardHome.yaml b/PATCH/files/etc/config/AdGuardHome.yaml similarity index 100% rename from PATCH/R2S/files/etc/config/AdGuardHome.yaml rename to PATCH/files/etc/config/AdGuardHome.yaml diff --git a/PATCH/R2S/files/etc/config/cpulimit b/PATCH/files/etc/config/cpulimit similarity index 100% rename from PATCH/R2S/files/etc/config/cpulimit rename to PATCH/files/etc/config/cpulimit diff --git a/PATCH/R2S/files/etc/config/smartdns b/PATCH/files/etc/config/smartdns similarity index 100% rename from PATCH/R2S/files/etc/config/smartdns rename to PATCH/files/etc/config/smartdns diff --git a/PATCH/R2S/files/etc/ssrplus/black.list b/PATCH/files/etc/ssrplus/black.list similarity index 100% rename from PATCH/R2S/files/etc/ssrplus/black.list rename to PATCH/files/etc/ssrplus/black.list diff --git a/PATCH/R2S/files/etc/ssrplus/white.list b/PATCH/files/etc/ssrplus/white.list similarity index 100% rename from PATCH/R2S/files/etc/ssrplus/white.list rename to PATCH/files/etc/ssrplus/white.list diff --git a/PATCH/new/package/luci-app-firewall_add_fullcone.patch b/PATCH/firewall/luci-app-firewall_add_fullcone.patch similarity index 100% rename from PATCH/new/package/luci-app-firewall_add_fullcone.patch rename to PATCH/firewall/luci-app-firewall_add_fullcone.patch diff --git a/PATCH/new/package/luci-app-firewall_add_sfe_switch.patch b/PATCH/firewall/luci-app-firewall_add_sfe_switch.patch similarity index 100% rename from PATCH/new/package/luci-app-firewall_add_sfe_switch.patch rename to PATCH/firewall/luci-app-firewall_add_sfe_switch.patch diff --git a/PATCH/new/package/use_json_object_new_int64.patch b/PATCH/jsonc/use_json_object_new_int64.patch similarity index 100% rename from PATCH/new/package/use_json_object_new_int64.patch rename to PATCH/jsonc/use_json_object_new_int64.patch diff --git a/PATCH/new/package/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch b/PATCH/mbedtls/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch similarity index 100% rename from PATCH/new/package/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch rename to PATCH/mbedtls/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch diff --git a/PATCH/new/main/0001-dmc-rk3328.patch b/PATCH/new/main/0001-dmc-rk3328.patch deleted file mode 100644 index b678f655f..000000000 --- a/PATCH/new/main/0001-dmc-rk3328.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 7a811c035ed752cad2a6705fe2391a7312bc8834 Mon Sep 17 00:00:00 2001 -This is free software, licensed under the GNU General Public License v3 -From: Immortalwrt -Repatch From: Nicholas Sun -Date: Sun, 14 Mar 2021 04:34:10 +1100 -Subject: [PATCH] DMC for Nanopi R2S - ---- - package/boot/uboot-rockchip/Makefile | 14 +- - target/linux/rockchip/image/Makefile | 14 + - target/linux/rockchip/image/armv8.mk | 2 +- - 3 files changed, 30 insertions(+), 4 deletions(-) - -diff --git a/package/boot/uboot-rockchip/Makefile b/package/boot/uboot-rockchip/Makefile -index 393e8c3..cbd9d7d 100644 ---- a/package/boot/uboot-rockchip/Makefile -+++ b/package/boot/uboot-rockchip/Makefile -@@ -29,9 +29,10 @@ define U-Boot/nanopi-r2s-rk3328 - NAME:=NanoPi R2S - BUILD_DEVICES:= \ - friendlyarm_nanopi-r2s -- DEPENDS:=+PACKAGE_u-boot-nanopi-r2s-rk3328:arm-trusted-firmware-rockchip -- PKG_BUILD_DEPENDS:=arm-trusted-firmware-rockchip -- ATF:=rk3328_bl31.elf -+ DEPENDS:=+PACKAGE_u-boot-nanopi-r2s-rk3328:arm-trusted-firmware-rk3328 -+ PKG_BUILD_DEPENDS:=arm-trusted-firmware-rk3328 -+ ATF:=rk322xh_bl31_v1.44.elf -+ USE_RKBIN:=1 - OF_PLATDATA:=$(1) - endef - -@@ -85,8 +86,15 @@ endef - - define Build/InstallDev - $(INSTALL_DIR) $(STAGING_DIR_IMAGE) -+ifneq ($(USE_RKBIN),) -+ $(STAGING_DIR_IMAGE)/loaderimage --pack --uboot $(PKG_BUILD_DIR)/u-boot-dtb.bin $(PKG_BUILD_DIR)/uboot.img 0x200000 -+ $(CP) $(PKG_BUILD_DIR)/uboot.img $(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-uboot.img -+ $(CP) $(STAGING_DIR_IMAGE)/idbloader.bin $(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-idbloader.bin -+ $(CP) $(STAGING_DIR_IMAGE)/trust.bin $(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-trust.bin -+else - $(CP) $(PKG_BUILD_DIR)/idbloader.img $(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-idbloader.img - $(CP) $(PKG_BUILD_DIR)/u-boot.itb $(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-u-boot.itb -+endif - endef - - define Package/u-boot/install/default -diff --git a/target/linux/rockchip/image/Makefile b/target/linux/rockchip/image/Makefile -index f5fdff6..3741bee 100644 ---- a/target/linux/rockchip/image/Makefile -+++ b/target/linux/rockchip/image/Makefile -@@ -45,6 +45,20 @@ define Build/pine64-img - dd if="$(STAGING_DIR_IMAGE)"/$(UBOOT_DEVICE_NAME)-u-boot.itb of="$@" seek=16384 conv=notrunc - endef - -+define Build/pine64-bin -+ # This is a copy of pine64-img, but uses rockchip ddrloader -+ -+ $(SCRIPT_DIR)/gen_image_generic.sh \ -+ $@ \ -+ $(CONFIG_TARGET_KERNEL_PARTSIZE) $@.boot \ -+ $(CONFIG_TARGET_ROOTFS_PARTSIZE) $(IMAGE_ROOTFS) \ -+ 32768 -+ -+ dd if="$(STAGING_DIR_IMAGE)"/$(UBOOT_DEVICE_NAME)-idbloader.bin of="$@" seek=64 conv=notrunc -+ dd if="$(STAGING_DIR_IMAGE)"/$(UBOOT_DEVICE_NAME)-uboot.img of="$@" seek=16384 conv=notrunc -+ dd if="$(STAGING_DIR_IMAGE)"/$(UBOOT_DEVICE_NAME)-trust.bin of="$@" seek=24576 conv=notrunc -+endef -+ - ### Devices ### - define Device/Default - PROFILES := Default -diff --git a/target/linux/rockchip/image/armv8.mk b/target/linux/rockchip/image/armv8.mk -index 24b1c38..04a9aa8 100644 ---- a/target/linux/rockchip/image/armv8.mk -+++ b/target/linux/rockchip/image/armv8.mk -@@ -7,7 +7,7 @@ define Device/friendlyarm_nanopi-r2s - DEVICE_MODEL := NanoPi R2S - SOC := rk3328 - UBOOT_DEVICE_NAME := nanopi-r2s-rk3328 -- IMAGE/sysupgrade.img.gz := boot-common | boot-script nanopi-r2s | pine64-img | gzip | append-metadata -+ IMAGE/sysupgrade.img.gz := boot-common | boot-script nanopi-r2s | pine64-bin | gzip | append-metadata - DEVICE_PACKAGES := kmod-usb-net-rtl8152 - endef - TARGET_DEVICES += friendlyarm_nanopi-r2s --- -2.30.1 - diff --git a/PATCH/new/main/0002-IRQ-and-disable-eth0-tcp-udp-offloading-tx-rx.patch b/PATCH/new/main/0002-IRQ-and-disable-eth0-tcp-udp-offloading-tx-rx.patch deleted file mode 100644 index b0e320cc0..000000000 --- a/PATCH/new/main/0002-IRQ-and-disable-eth0-tcp-udp-offloading-tx-rx.patch +++ /dev/null @@ -1,25 +0,0 @@ -From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> -Repatch From: Nicholas Sun -Date: Sun, 7 Mar 2021 21:06:48 +1100 -Subject: [PATCH] IRQ and disable eth0 tcp/udp offloading tx/rx - ---- - .../armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity b/target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity -index d8e513f..eea0979 100644 ---- a/target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity -+++ b/target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity -@@ -26,6 +26,9 @@ friendlyarm,nanopi-r2s|\ - xunlong,orangepi-r1-plus) - set_interface_core 2 "eth0" - set_interface_core 4 "eth1" "xhci-hcd:usb3" -+ set_interface_core 1 "ff150000" "ff150000.i2c" -+ set_interface_core 8 "ff160000" "ff160000.i2c" -+ ethtool -K eth0 rx off tx off && logger -t disable-offloading "disabed rk3328 ethernet tcp/udp offloading tx/rx" - ;; - friendlyarm,nanopi-r4s) - set_interface_core 10 "eth0" --- -2.30.1 diff --git a/PATCH/new/main/998-rockchip-enable-i2c0-on-NanoPi-R2S.patch b/PATCH/new/main/998-rockchip-enable-i2c0-on-NanoPi-R2S.patch deleted file mode 100644 index 606d73dd9..000000000 --- a/PATCH/new/main/998-rockchip-enable-i2c0-on-NanoPi-R2S.patch +++ /dev/null @@ -1,15 +0,0 @@ -From: QiuSimons -diff --git a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts ---- a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts -+++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts -@@ -226,6 +226,10 @@ - }; - }; - -+&i2c0 { -+ status = "okay"; -+}; -+ - &io_domains { - status = "okay"; - diff --git a/PATCH/new/script/chinadnslist b/PATCH/new/script/chinadnslist deleted file mode 100644 index 2d255feab..000000000 --- a/PATCH/new/script/chinadnslist +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -e -set -o pipefail -rm -rf /tmp/chinadns-ng -mkdir /tmp/chinadns-ng -wget https://raw.githubusercontent.com/pexcn/daily/gh-pages/chnroute/chnroute.txt -nv -O /tmp/chinadns-ng/chnroute.txt -wget https://raw.githubusercontent.com/pexcn/daily/gh-pages/chnroute/chnroute-v6.txt -nv -O /tmp/chinadns-ng/chnroute6.txt -wget https://raw.githubusercontent.com/pexcn/daily/gh-pages/gfwlist/gfwlist.txt -nv -O /tmp/chinadns-ng/gfwlist.txt -wget https://raw.githubusercontent.com/pexcn/daily/gh-pages/chinalist/chinalist.txt -nv -O /tmp/chinadns-ng/chinalist.txt -find /tmp/chinadns-ng/ -size -20k -exec rm {} \; -chmod -R 755 /tmp/chinadns-ng -cp -rf /tmp/chinadns-ng/** /etc/chinadns-ng -#wget -P /tmp "https://raw.githubusercontent.com/QiuSimons/Others/master/blacklist-ip.conf" && cat /tmp/blacklist-ip.conf >> "/etc/smartdns/blacklist-ip.conf" && cat "/etc/smartdns/blacklist-ip.conf" | sort | uniq > /tmp/tmp_blacklist-ip.conf && cat /tmp/tmp_blacklist-ip.conf > "/etc/smartdns/blacklist-ip.conf" -exit 0 diff --git a/PATCH/new/script/fuck b/PATCH/new/script/fuck deleted file mode 100644 index 75ee5aeb7..000000000 --- a/PATCH/new/script/fuck +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh -# From QiuSimons - -cd /overlay -rm -rf `ls | egrep -v '(upper|.fs_state)'` -cd /overlay/upper -rm -rf `ls | egrep -v '(etc|usr)'` -cd /overlay/upper/usr -rm -rf `ls | egrep -v '(share)'` -cd /overlay/upper/usr/share -rm -rf `ls | egrep -v '(unblockneteasemusic|passwall)'` -cd /overlay/upper/etc -rm -rf `ls | egrep -v '(config|smartdns|ssrplus|bench.log|shadow|openclash|fucked)'` -cd /overlay/upper/etc/config -rm -rf `ls | egrep -v '(arpbind|autoreboot|ddns|firewall|jd-dailybonus|network|oled|openclash|passwall|serverchan|shadowsocksr|sqm|unblockneteasemusic|weburl|zerotier|vssr|zero|dhcp)'` -sleep 5 && touch /etc/banner && reboot diff --git a/PATCH/new/script/move_2_services.sh b/PATCH/new/script/move_2_services.sh deleted file mode 100644 index a6ca37752..000000000 --- a/PATCH/new/script/move_2_services.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -# From: QiuSimons - -lua_file="$({ find |grep "\.lua"; } 2>"/dev/null")" -for a in ${lua_file} -do - [ -n "$(grep '"vpn"' "$a")" ] && sed -i 's,"vpn","services",g' "$a" - [ -n "$(grep '"VPN"' "$a")" ] && sed -i 's,"VPN","services",g' "$a" - [ -n "$(grep '\[\[vpn\]\]' "$a")" ] && sed -i 's,\[\[vpn\]\],\[\[services\]\],g' "$a" - [ -n "$(grep 'admin/vpn' "$a")" ] && sed -i 's,admin/vpn,admin/services,g' "$a" -done - -htm_file="$({ find |grep "\.htm"; } 2>"/dev/null")" -for b in ${htm_file} -do - [ -n "$(grep '"vpn"' "$b")" ] && sed -i 's,"vpn","services",g' "$b" - [ -n "$(grep '"VPN"' "$b")" ] && sed -i 's,"VPN","services",g' "$b" - [ -n "$(grep '\[\[vpn\]\]' "$b")" ] && sed -i 's,\[\[vpn\]\],\[\[services\]\],g' "$b" - [ -n "$(grep 'admin/vpn' "$b")" ] && sed -i 's,admin/vpn,admin/services,g' "$b" -done - diff --git a/PATCH/new/main/r8168-fix_LAN_led-for_r4s-from_TL.patch b/PATCH/r8168/r8168-fix_LAN_led-for_r4s-from_TL.patch similarity index 100% rename from PATCH/new/main/r8168-fix_LAN_led-for_r4s-from_TL.patch rename to PATCH/r8168/r8168-fix_LAN_led-for_r4s-from_TL.patch diff --git a/PATCH/new/main/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch b/PATCH/target_r4s/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch similarity index 100% rename from PATCH/new/main/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch rename to PATCH/target_r4s/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch diff --git a/PATCH/new/main/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch b/PATCH/target_r4s/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch similarity index 100% rename from PATCH/new/main/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch rename to PATCH/target_r4s/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index c1bcd422e..36a3d51c1 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -29,11 +29,11 @@ echo "net.netfilter.nf_conntrack_helper = 1" >> ./package/kernel/linux/files/sys # Patch arm64 型号名称 wget -P target/linux/generic/pending-5.4 https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/generic/hack-5.4/312-arm64-cpuinfo-Add-model-name-in-proc-cpuinfo-for-64bit-ta.patch # Patch jsonc -patch -p1 < ../PATCH/new/package/use_json_object_new_int64.patch +patch -p1 < ../PATCH/jsonc/use_json_object_new_int64.patch # Patch dnsmasq -patch -p1 < ../PATCH/new/package/dnsmasq-add-filter-aaaa-option.patch -patch -p1 < ../PATCH/new/package/luci-add-filter-aaaa-option.patch -cp -f ../PATCH/new/package/900-add-filter-aaaa-option.patch ./package/network/services/dnsmasq/patches/900-add-filter-aaaa-option.patch +patch -p1 < ../PATCH/dnsmasq/dnsmasq-add-filter-aaaa-option.patch +patch -p1 < ../PATCH/dnsmasq/luci-add-filter-aaaa-option.patch +cp -f ../PATCH/dnsmasq/900-add-filter-aaaa-option.patch ./package/network/services/dnsmasq/patches/900-add-filter-aaaa-option.patch ### Fullcone-NAT 部分 ### # Patch Kernel 以解决 FullCone 冲突 @@ -44,7 +44,7 @@ popd mkdir package/network/config/firewall/patches wget -P package/network/config/firewall/patches/ https://github.com/immortalwrt/immortalwrt/raw/master/package/network/config/firewall/patches/fullconenat.patch # Patch LuCI 以增添 FullCone 开关 -patch -p1 < ../PATCH/new/package/luci-app-firewall_add_fullcone.patch +patch -p1 < ../PATCH/firewall/luci-app-firewall_add_fullcone.patch # FullCone 相关组件 cp -rf ../openwrt-lienol/package/network/fullconenat ./package/network/fullconenat @@ -54,11 +54,11 @@ pushd target/linux/generic/hack-5.4 wget https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/generic/hack-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch popd # Patch LuCI 以增添 Shortcut-FE 开关 -patch -p1 < ../PATCH/new/package/luci-app-firewall_add_sfe_switch.patch +patch -p1 < ../PATCH/firewall/luci-app-firewall_add_sfe_switch.patch # Shortcut-FE 相关组件 svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/shortcut-fe package/lean/shortcut-fe svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/fast-classifier package/lean/fast-classifier -cp -f ../PATCH/duplicate/shortcut-fe ./package/base-files/files/etc/init.d +wget -P package/base-files/files/etc/init.d/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/shortcut-fe ### 获取额外的基础软件包 ### # AutoCore @@ -86,7 +86,7 @@ ln -sf ../../../feeds/packages/lang/node-yarn ./package/feeds/packages/node-yarn # R8168驱动 #svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/kernel/r8168 package/new/r8168 git clone -b master --depth 1 https://github.com/BROBIRD/openwrt-r8168.git package/new/r8168 -#patch -p1 < ../PATCH/new/main/r8168-fix_LAN_led-for_r4s-from_TL.patch +patch -p1 < ../PATCH/r8168/r8168-fix_LAN_led-for_r4s-from_TL.patch # UPX 可执行软件压缩 sed -i '/patchelf pkgconf/i\tools-y += ucl upx' ./tools/Makefile sed -i '\/autoconf\/compile :=/i\$(curdir)/upx/compile := $(curdir)/ucl/compile' ./tools/Makefile @@ -96,7 +96,7 @@ svn co https://github.com/immortalwrt/immortalwrt/branches/master/tools/ucl tool ### 获取额外的 LuCI 应用、主题和依赖 ### # 访问控制 svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-accesscontrol package/lean/luci-app-accesscontrol -cp -rf ../PATCH/duplicate/luci-app-control-weburl ./package/new/luci-app-control-weburl +svn co https://github.com/QiuSimons/OpenWrt-Add/tree/master/luci-app-control-weburl package/new/luci-app-control-weburl # 广告过滤 Adbyby svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-adbyby-plus package/lean/luci-app-adbyby-plus svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/adbyby package/lean/adbyby @@ -138,7 +138,7 @@ ln -sf ../../../feeds/luci/applications/luci-app-cpufreq ./package/feeds/luci/lu sed -i 's,1608,1800,g' feeds/luci/applications/luci-app-cpufreq/root/etc/uci-defaults/cpufreq sed -i 's,2016,2208,g' feeds/luci/applications/luci-app-cpufreq/root/etc/uci-defaults/cpufreq sed -i 's,1512,1608,g' feeds/luci/applications/luci-app-cpufreq/root/etc/uci-defaults/cpufreq -cp -rf ../PATCH/duplicate/luci-app-cpulimit ./package/lean/luci-app-cpulimit +svn co https://github.com/QiuSimons/OpenWrt-Add/tree/master/luci-app-cpulimit package/lean/luci-app-cpulimit svn co https://github.com/immortalwrt/packages/trunk/utils/cpulimit feeds/packages/utils/cpulimit ln -sf ../../../feeds/packages/utils/cpulimit ./package/feeds/packages/cpulimit # 动态DNS @@ -211,7 +211,7 @@ svn co https://github.com/xiaorouji/openwrt-passwall/trunk/luci-app-passwall pac sed -i 's,default n,default y,g' package/new/luci-app-passwall/Makefile sed -i '/V2ray:v2ray/d' package/new/luci-app-passwall/Makefile sed -i '/plugin:v2ray/d' package/new/luci-app-passwall/Makefile -cp -f ../PATCH/new/script/move_2_services.sh ./package/new/luci-app-passwall/move_2_services.sh +wget -P package/new/luci-app-passwall https://github.com/QiuSimons/OpenWrt-Add/raw/master/move_2_services.sh pushd package/new/luci-app-passwall bash move_2_services.sh popd @@ -319,19 +319,20 @@ git clone -b master --depth 1 https://github.com/brvphoenix/luci-app-wrtbwmon.gi git clone --depth 1 https://github.com/garypang13/luci-app-xlnetacc.git package/lean/luci-app-xlnetacc # Zerotier svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-zerotier feeds/luci/applications/luci-app-zerotier -cp -f ../PATCH/new/script/move_2_services.sh ./feeds/luci/applications/luci-app-zerotier/move_2_services.sh +wget -P feeds/luci/applications/luci-app-zerotier https://github.com/QiuSimons/OpenWrt-Add/raw/master/move_2_services.sh pushd feeds/luci/applications/luci-app-zerotier bash move_2_services.sh popd ln -sf ../../../feeds/luci/applications/luci-app-zerotier ./package/feeds/luci/luci-app-zerotier rm -rf ./feeds/packages/net/zerotier/files/etc/init.d/zerotier - +# 翻译及部分功能优化 +svn co https://github.com/QiuSimons/OpenWrt-Add/tree/master/addition-trans-zh package/lean/lean-translate ### 最后的收尾工作 ### # Lets Fuck mkdir package/base-files/files/usr/bin -cp -f ../PATCH/new/script/fuck package/base-files/files/usr/bin/fuck -cp -f ../PATCH/new/script/chinadnslist package/base-files/files/usr/bin/chinadnslist +wget -P package/base-files/files/usr/bin https://github.com/QiuSimons/OpenWrt-Add/raw/master/fuck +wget -P package/base-files/files/usr/bin https://github.com/QiuSimons/OpenWrt-Add/raw/master/chinadnslist # 最大连接数 sed -i 's/16384/65535/g' package/kernel/linux/files/sysctl-nf-conntrack.conf # 生成默认配置及缓存 diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index b05407451..f007561f2 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -3,7 +3,7 @@ clear # 使用专属优化 sed -i 's,-mcpu=generic,-march=armv8-a+crypto+crc -mabi=lp64,g' include/target.mk -cp -f ../PATCH/new/package/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch ./package/libs/mbedtls/patches/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch +cp -f ../PATCH/mbedtls/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch ./package/libs/mbedtls/patches/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch # R2S_TL rm -rf ./target/linux/rockchip @@ -25,9 +25,6 @@ sed -i '/;;/i\ethtool -K eth0 rx off tx off && logger -t disable-offloading "dis sed -i 's,"eth1" "eth0","eth0" "eth1",g' target/linux/rockchip/armv8/base-files/etc/board.d/02_network sed -i "s,'eth1' 'eth0','eth0' 'eth1',g" target/linux/rockchip/armv8/base-files/etc/board.d/02_network -# 翻译及部分功能优化 -cp -rf ../PATCH/duplicate/addition-trans-zh ./package/lean/lean-translate - # 添加 R2S GPU 驱动 rm -rf ./package/kernel/linux/modules/video.mk wget -P package/kernel/linux/modules/ https://github.com/immortalwrt/immortalwrt/raw/master/package/kernel/linux/modules/video.mk @@ -66,7 +63,7 @@ CONFIG_CRYPTO_SM4_ARM64_CE=y ' >> ./target/linux/rockchip/armv8/config-5.4 # 预配置一些插件 -cp -rf ../PATCH/R2S/files ./files +cp -rf ../PATCH/files ./files chmod -R 755 ./ find ./ -name *.orig | xargs rm -f diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index bef550061..d6da58c74 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -10,12 +10,12 @@ svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/boot/a # 超频到 2.2/1.8 GHz rm -rf ./target/linux/rockchip/patches-5.4/992-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch -cp -f ../PATCH/new/main/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch ./target/linux/rockchip/patches-5.4/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch -cp -f ../PATCH/new/main/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch ./target/linux/rockchip/patches-5.4/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch +cp -f ../PATCH/target_r4s/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch ./target/linux/rockchip/patches-5.4/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch +cp -f ../PATCH/target_r4s/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch ./target/linux/rockchip/patches-5.4/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch # 使用特定的优化 sed -i 's,-mcpu=generic,-march=armv8-a+crypto+crc -mabi=lp64,g' include/target.mk -cp -f ../PATCH/new/package/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch ./package/libs/mbedtls/patches/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch +cp -f ../PATCH/mbedtls/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch ./package/libs/mbedtls/patches/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch sed -i 's,kmod-r8169,kmod-r8168,g' target/linux/rockchip/image/armv8.mk #增加风扇调速(被动散热不香么? @@ -34,9 +34,6 @@ CONFIG_HW_RANDOM_ROCKCHIP=y sed -i '/set_interface_core 20 "eth1"/a\set_interface_core 8 "ff3c0000" "ff3c0000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity sed -i '/set_interface_core 20 "eth1"/a\ethtool -C eth0 rx-usecs 1000 rx-frames 25 tx-usecs 100 tx-frames 25' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity -# 翻译及部分功能优化 -cp -rf ../PATCH/duplicate/addition-trans-zh ./package/lean/lean-translate - # 添加 R4S GPU 驱动 rm -rf ./package/kernel/linux/modules/video.mk wget -P package/kernel/linux/modules/ https://github.com/immortalwrt/immortalwrt/raw/master/package/kernel/linux/modules/video.mk @@ -72,7 +69,7 @@ zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' > .v sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic/' include/kernel-defaults.mk # 预配置一些插件 -cp -rf ../PATCH/R4S/files ./files +cp -rf ../PATCH/files ./files chmod -R 755 ./ find ./ -name *.orig | xargs rm -f diff --git a/SCRIPTS/X86/02_target_only.sh b/SCRIPTS/X86/02_target_only.sh index 77fbc80d7..b721cf3f8 100644 --- a/SCRIPTS/X86/02_target_only.sh +++ b/SCRIPTS/X86/02_target_only.sh @@ -3,9 +3,6 @@ # 使用 O2 级别的优化 sed -i 's/O3/O2/g' include/target.mk -# 翻译及部分功能优化 -cp -rf ../PATCH/duplicate/addition-trans-zh ./package/lean/lean-translate - # 在 X86 架构下移除 Shadowsocks-rust sed -i '/Rust:/d' package/lean/luci-app-ssr-plus/Makefile sed -i '/Rust:/d' package/new/luci-app-passwall/Makefile @@ -18,7 +15,7 @@ zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' > .v sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic/' include/kernel-defaults.mk # 预配置一些插件 -cp -rf ../PATCH/X86/files ./files +cp -rf ../PATCH/files ./files chmod -R 755 ./ find ./ -name *.orig | xargs rm -f From b86d8e964c61321cf3c0850e2f2b5154c848fe09 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 25 Jun 2021 18:11:07 +0800 Subject: [PATCH 124/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 36a3d51c1..e957968ff 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -269,6 +269,7 @@ rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans pushd package/lean #wget -qO - https://github.com/fw876/helloworld/pull/513.patch | patch -p1 wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/c1674ad.patch | patch -p1 +wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/5bbf6e7.patch | patch -p1 popd pushd package/lean/luci-app-ssr-plus sed -i 's,default n,default y,g' Makefile From b738caa9f77b06e95c0ed2ecee7207c58ab6b9ba Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 25 Jun 2021 23:35:49 +0800 Subject: [PATCH 125/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index e957968ff..916cadc81 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -332,8 +332,8 @@ svn co https://github.com/QiuSimons/OpenWrt-Add/tree/master/addition-trans-zh pa ### 最后的收尾工作 ### # Lets Fuck mkdir package/base-files/files/usr/bin -wget -P package/base-files/files/usr/bin https://github.com/QiuSimons/OpenWrt-Add/raw/master/fuck -wget -P package/base-files/files/usr/bin https://github.com/QiuSimons/OpenWrt-Add/raw/master/chinadnslist +wget -P package/base-files/files/usr/bin/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/fuck +wget -P package/base-files/files/usr/bin/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/chinadnslist # 最大连接数 sed -i 's/16384/65535/g' package/kernel/linux/files/sysctl-nf-conntrack.conf # 生成默认配置及缓存 From 5f1536f9bafb92e5499c595b4eea7887acf2b3ed Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 25 Jun 2021 23:44:04 +0800 Subject: [PATCH 126/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 916cadc81..a157dcd89 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -27,7 +27,7 @@ echo "net.netfilter.nf_conntrack_helper = 1" >> ./package/kernel/linux/files/sys ### 必要的 Patches ### # Patch arm64 型号名称 -wget -P target/linux/generic/pending-5.4 https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/generic/hack-5.4/312-arm64-cpuinfo-Add-model-name-in-proc-cpuinfo-for-64bit-ta.patch +wget -P target/linux/generic/pending-5.4/ https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/generic/hack-5.4/312-arm64-cpuinfo-Add-model-name-in-proc-cpuinfo-for-64bit-ta.patch # Patch jsonc patch -p1 < ../PATCH/jsonc/use_json_object_new_int64.patch # Patch dnsmasq @@ -108,7 +108,7 @@ sed -i '/\t)/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DI sed -i '/init/d' feeds/packages/net/adguardhome/Makefile # Argon 主题 git clone -b master --depth 1 https://github.com/jerrykuku/luci-theme-argon.git package/new/luci-theme-argon -wget -P ./package/new/luci-theme-argon/htdocs/luci-static/argon/css -N https://github.com/msylgj/luci-theme-argon/raw/patch-1/htdocs/luci-static/argon/css/dark.css +wget -P ./package/new/luci-theme-argon/htdocs/luci-static/argon/css/ -N https://github.com/msylgj/luci-theme-argon/raw/patch-1/htdocs/luci-static/argon/css/dark.css #wget -P ./package/new/luci-theme-argon/luasrc/view/themes/argon -N https://github.com/jerrykuku/luci-theme-argon/raw/9fdcfc866ca80d8d094d554c6aedc18682661973/luasrc/view/themes/argon/footer.htm #wget -P ./package/new/luci-theme-argon/luasrc/view/themes/argon -N https://github.com/jerrykuku/luci-theme-argon/raw/9fdcfc866ca80d8d094d554c6aedc18682661973/luasrc/view/themes/argon/header.htm git clone -b master --depth 1 https://github.com/jerrykuku/luci-app-argon-config.git package/new/luci-app-argon-config @@ -211,7 +211,7 @@ svn co https://github.com/xiaorouji/openwrt-passwall/trunk/luci-app-passwall pac sed -i 's,default n,default y,g' package/new/luci-app-passwall/Makefile sed -i '/V2ray:v2ray/d' package/new/luci-app-passwall/Makefile sed -i '/plugin:v2ray/d' package/new/luci-app-passwall/Makefile -wget -P package/new/luci-app-passwall https://github.com/QiuSimons/OpenWrt-Add/raw/master/move_2_services.sh +wget -P package/new/luci-app-passwall/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/move_2_services.sh pushd package/new/luci-app-passwall bash move_2_services.sh popd @@ -320,7 +320,7 @@ git clone -b master --depth 1 https://github.com/brvphoenix/luci-app-wrtbwmon.gi git clone --depth 1 https://github.com/garypang13/luci-app-xlnetacc.git package/lean/luci-app-xlnetacc # Zerotier svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-zerotier feeds/luci/applications/luci-app-zerotier -wget -P feeds/luci/applications/luci-app-zerotier https://github.com/QiuSimons/OpenWrt-Add/raw/master/move_2_services.sh +wget -P feeds/luci/applications/luci-app-zerotier/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/move_2_services.sh pushd feeds/luci/applications/luci-app-zerotier bash move_2_services.sh popd From fc4c34c29a40c40f648bd97e62e2c05808713e5f Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 25 Jun 2021 23:45:01 +0800 Subject: [PATCH 127/244] Update 02_target_only.sh --- SCRIPTS/R2S/02_target_only.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index f007561f2..161f7672c 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -13,8 +13,8 @@ svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/boot/u svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/boot/arm-trusted-firmware-rk3328 package/boot/arm-trusted-firmware-rk3328 #增加风扇调速(被动散热不香么? -wget -P target/linux/rockchip/armv8/base-files/etc/init.d https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3328/base-files/etc/init.d/fa-rk3328-pwmfan -wget -P target/linux/rockchip/armv8/base-files/usr/bin https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3328/base-files/usr/bin/start-rk3328-pwm-fan.sh +wget -P target/linux/rockchip/armv8/base-files/etc/init.d/ https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3328/base-files/etc/init.d/fa-rk3328-pwmfan +wget -P target/linux/rockchip/armv8/base-files/usr/bin/ https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3328/base-files/usr/bin/start-rk3328-pwm-fan.sh # 配置 IRQ 并默认关闭 eth0 offloading rx/rx sed -i '/set_interface_core 4 "eth1"/a\set_interface_core 8 "ff160000" "ff160000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity From b7de85dbb2455be9ab29108685aeaa91bebfd3b4 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 25 Jun 2021 23:45:52 +0800 Subject: [PATCH 128/244] Update 02_target_only.sh --- SCRIPTS/R4S/02_target_only.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index d6da58c74..ca2aaa4be 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -19,8 +19,8 @@ cp -f ../PATCH/mbedtls/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.p sed -i 's,kmod-r8169,kmod-r8168,g' target/linux/rockchip/image/armv8.mk #增加风扇调速(被动散热不香么? -wget -P target/linux/rockchip/armv8/base-files/etc/init.d https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3399/base-files/etc/init.d/fa-rk3399-pwmfan -wget -P target/linux/rockchip/armv8/base-files/usr/bin https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3399/base-files/usr/bin/start-rk3399-pwm-fan.sh +wget -P target/linux/rockchip/armv8/base-files/etc/init.d/ https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3399/base-files/etc/init.d/fa-rk3399-pwmfan +wget -P target/linux/rockchip/armv8/base-files/usr/bin/ https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3399/base-files/usr/bin/start-rk3399-pwm-fan.sh # 测试性功能 sed -i '/CRYPTO_DEV_ROCKCHIP/d' ./target/linux/rockchip/armv8/config-5.4 From 1e996c90314f2104ee299f68162e0aeefbfeede9 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 25 Jun 2021 23:58:43 +0800 Subject: [PATCH 129/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index a157dcd89..ad54bd1ee 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -96,7 +96,7 @@ svn co https://github.com/immortalwrt/immortalwrt/branches/master/tools/ucl tool ### 获取额外的 LuCI 应用、主题和依赖 ### # 访问控制 svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-accesscontrol package/lean/luci-app-accesscontrol -svn co https://github.com/QiuSimons/OpenWrt-Add/tree/master/luci-app-control-weburl package/new/luci-app-control-weburl +svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/luci-app-control-weburl package/new/luci-app-control-weburl # 广告过滤 Adbyby svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-adbyby-plus package/lean/luci-app-adbyby-plus svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/adbyby package/lean/adbyby @@ -138,7 +138,7 @@ ln -sf ../../../feeds/luci/applications/luci-app-cpufreq ./package/feeds/luci/lu sed -i 's,1608,1800,g' feeds/luci/applications/luci-app-cpufreq/root/etc/uci-defaults/cpufreq sed -i 's,2016,2208,g' feeds/luci/applications/luci-app-cpufreq/root/etc/uci-defaults/cpufreq sed -i 's,1512,1608,g' feeds/luci/applications/luci-app-cpufreq/root/etc/uci-defaults/cpufreq -svn co https://github.com/QiuSimons/OpenWrt-Add/tree/master/luci-app-cpulimit package/lean/luci-app-cpulimit +svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/luci-app-cpulimit package/lean/luci-app-cpulimit svn co https://github.com/immortalwrt/packages/trunk/utils/cpulimit feeds/packages/utils/cpulimit ln -sf ../../../feeds/packages/utils/cpulimit ./package/feeds/packages/cpulimit # 动态DNS @@ -327,7 +327,7 @@ popd ln -sf ../../../feeds/luci/applications/luci-app-zerotier ./package/feeds/luci/luci-app-zerotier rm -rf ./feeds/packages/net/zerotier/files/etc/init.d/zerotier # 翻译及部分功能优化 -svn co https://github.com/QiuSimons/OpenWrt-Add/tree/master/addition-trans-zh package/lean/lean-translate +svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/addition-trans-zh package/lean/lean-translate ### 最后的收尾工作 ### # Lets Fuck From a2af39661d4c272ed2cf6c5039af955085ef07ba Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sat, 26 Jun 2021 00:01:07 +0800 Subject: [PATCH 130/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index ad54bd1ee..e49e48b0c 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -339,4 +339,4 @@ sed -i 's/16384/65535/g' package/kernel/linux/files/sysctl-nf-conntrack.conf # 生成默认配置及缓存 rm -rf .config -exit 0 +#exit 0 From 5144e34acb959d28da54f1b97546a6ab12840eb2 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sat, 26 Jun 2021 00:01:32 +0800 Subject: [PATCH 131/244] Update 02_target_only.sh --- SCRIPTS/R2S/02_target_only.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index 161f7672c..d6becb049 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -69,4 +69,4 @@ chmod -R 755 ./ find ./ -name *.orig | xargs rm -f find ./ -name *.rej | xargs rm -f -exit 0 +#exit 0 From 9111b30a68c0b572fb43816f82bec364f0057f9d Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sat, 26 Jun 2021 00:01:55 +0800 Subject: [PATCH 132/244] Update 02_target_only.sh --- SCRIPTS/R4S/02_target_only.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index ca2aaa4be..8a64bd1b2 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -75,4 +75,4 @@ chmod -R 755 ./ find ./ -name *.orig | xargs rm -f find ./ -name *.rej | xargs rm -f -exit 0 +#exit 0 From 0e4adb085ba57f537e7d3b4dff54641ea62afa9c Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sat, 26 Jun 2021 00:17:33 +0800 Subject: [PATCH 133/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index e49e48b0c..e1535894e 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -108,7 +108,7 @@ sed -i '/\t)/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DI sed -i '/init/d' feeds/packages/net/adguardhome/Makefile # Argon 主题 git clone -b master --depth 1 https://github.com/jerrykuku/luci-theme-argon.git package/new/luci-theme-argon -wget -P ./package/new/luci-theme-argon/htdocs/luci-static/argon/css/ -N https://github.com/msylgj/luci-theme-argon/raw/patch-1/htdocs/luci-static/argon/css/dark.css +#wget -P ./package/new/luci-theme-argon/htdocs/luci-static/argon/css/ -N https://github.com/msylgj/luci-theme-argon/raw/patch-1/htdocs/luci-static/argon/css/dark.css #wget -P ./package/new/luci-theme-argon/luasrc/view/themes/argon -N https://github.com/jerrykuku/luci-theme-argon/raw/9fdcfc866ca80d8d094d554c6aedc18682661973/luasrc/view/themes/argon/footer.htm #wget -P ./package/new/luci-theme-argon/luasrc/view/themes/argon -N https://github.com/jerrykuku/luci-theme-argon/raw/9fdcfc866ca80d8d094d554c6aedc18682661973/luasrc/view/themes/argon/header.htm git clone -b master --depth 1 https://github.com/jerrykuku/luci-app-argon-config.git package/new/luci-app-argon-config From 811e32002250a80c1872f0c725b486529f1fed75 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sat, 26 Jun 2021 00:22:43 +0800 Subject: [PATCH 134/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index e1535894e..32248d9c7 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -212,6 +212,7 @@ sed -i 's,default n,default y,g' package/new/luci-app-passwall/Makefile sed -i '/V2ray:v2ray/d' package/new/luci-app-passwall/Makefile sed -i '/plugin:v2ray/d' package/new/luci-app-passwall/Makefile wget -P package/new/luci-app-passwall/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/move_2_services.sh +chmod -R 755 ./package/new/luci-app-passwall/move_2_services.sh pushd package/new/luci-app-passwall bash move_2_services.sh popd @@ -321,6 +322,7 @@ git clone --depth 1 https://github.com/garypang13/luci-app-xlnetacc.git package/ # Zerotier svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-zerotier feeds/luci/applications/luci-app-zerotier wget -P feeds/luci/applications/luci-app-zerotier/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/move_2_services.sh +chmod -R 755 ./feeds/luci/applications/luci-app-zerotier/move_2_services.sh pushd feeds/luci/applications/luci-app-zerotier bash move_2_services.sh popd From 868309512b0d3b87b64dab7e8b6b68c102e8776c Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 28 Jun 2021 14:35:19 +0800 Subject: [PATCH 135/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 32248d9c7..19137ca85 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -155,6 +155,11 @@ svn co https://github.com/kenzok8/openwrt-packages/trunk/luci-app-aliddns feeds/ ln -sf ../../../feeds/luci/applications/luci-app-aliddns ./package/feeds/luci/luci-app-aliddns # Docker 容器(会导致 OpenWrt 出现 UDP 转发问题,慎用) sed -i 's/+docker/+docker \\\n\t+dockerd/g' ./feeds/luci/applications/luci-app-dockerman/Makefile +# Dnsfilter +git clone -b master --depth 1 https://github.com/garypang13/luci-app-dnsfilter.git package/new/luci-app-dnsfilter +# Dnsproxy +svn co https://github.com/immortalwrt/packages/trunk/net/dnsproxy feeds/packages/net/dnsproxy +ln -sf ../../../feeds/packages/net/dnsproxy ./package/feeds/packages/dnsproxy # Edge 主题 git clone -b master --depth 1 https://github.com/garypang13/luci-theme-edge.git package/new/luci-theme-edge # FRP 内网穿透 From 222d075f804d58e9aa4df49ece6c3d9d45a396b2 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 28 Jun 2021 18:02:06 +0800 Subject: [PATCH 136/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 19137ca85..c8a278093 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -160,6 +160,7 @@ git clone -b master --depth 1 https://github.com/garypang13/luci-app-dnsfilter.g # Dnsproxy svn co https://github.com/immortalwrt/packages/trunk/net/dnsproxy feeds/packages/net/dnsproxy ln -sf ../../../feeds/packages/net/dnsproxy ./package/feeds/packages/dnsproxy +wget -P package/base-files/files/etc/init.d/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/dnsproxy # Edge 主题 git clone -b master --depth 1 https://github.com/garypang13/luci-theme-edge.git package/new/luci-theme-edge # FRP 内网穿透 From 64a06ed7ee7bb6abab1f26bd2d4c38431b6740d4 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 28 Jun 2021 18:04:28 +0800 Subject: [PATCH 137/244] Update config.seed --- SEED/R4S/config.seed | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index b87fac707..68eeb1ea3 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -84,8 +84,8 @@ CONFIG_PACKAGE_luci-proto-ipv6=y CONFIG_PACKAGE_luci-proto-ppp=y ### APPLICATION ### -CONFIG_PACKAGE_luci-app-adguardhome=y -CONFIG_PACKAGE_adguardhome=y +#CONFIG_PACKAGE_luci-app-adguardhome=y +#CONFIG_PACKAGE_adguardhome=y CONFIG_PACKAGE_luci-app-argon-config=y CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y @@ -102,13 +102,13 @@ CONFIG_PACKAGE_frpc=y CONFIG_PACKAGE_luci-app-frps=y CONFIG_PACKAGE_frps=y CONFIG_PACKAGE_luci-app-jd-dailybonus=y -CONFIG_PACKAGE_luci-app-mosdns=y +#CONFIG_PACKAGE_luci-app-mosdns=y CONFIG_PACKAGE_luci-app-openclash=y CONFIG_PACKAGE_luci-app-opkg=y #CONFIG_PACKAGE_luci-app-qbittorrent=y CONFIG_PACKAGE_luci-app-ramfree=y CONFIG_PACKAGE_luci-app-serverchan=y -CONFIG_PACKAGE_luci-app-smartdns=y +#CONFIG_PACKAGE_luci-app-smartdns=y CONFIG_PACKAGE_luci-app-sqm=y CONFIG_PACKAGE_luci-app-vlmcsd=y CONFIG_PACKAGE_luci-app-vssr=y @@ -125,6 +125,8 @@ CONFIG_PACKAGE_zerotier=y CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y +CONFIG_PACKAGE_dnsproxy=y +CONFIG_PACKAGE_luci-app-dnsfilter=y ### THEME ### CONFIG_PACKAGE_luci-theme-argon=y From 0d45f213f82aeeb9e72657233e20b7a86a002783 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 28 Jun 2021 18:05:31 +0800 Subject: [PATCH 138/244] Update config.seed --- SEED/R2S/config.seed | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 176f5980d..5af5b7435 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -83,8 +83,8 @@ CONFIG_PACKAGE_luci-proto-ipv6=y CONFIG_PACKAGE_luci-proto-ppp=y ### APPLICATION ### -CONFIG_PACKAGE_luci-app-adguardhome=y -CONFIG_PACKAGE_adguardhome=y +#CONFIG_PACKAGE_luci-app-adguardhome=y +#CONFIG_PACKAGE_adguardhome=y CONFIG_PACKAGE_luci-app-argon-config=y CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y @@ -101,14 +101,14 @@ CONFIG_PACKAGE_frpc=y CONFIG_PACKAGE_luci-app-frps=y CONFIG_PACKAGE_frps=y CONFIG_PACKAGE_luci-app-jd-dailybonus=y -CONFIG_PACKAGE_luci-app-mosdns=y +#CONFIG_PACKAGE_luci-app-mosdns=y CONFIG_PACKAGE_luci-app-oled=y CONFIG_PACKAGE_luci-app-openclash=y CONFIG_PACKAGE_luci-app-opkg=y #CONFIG_PACKAGE_luci-app-qbittorrent=y CONFIG_PACKAGE_luci-app-ramfree=y CONFIG_PACKAGE_luci-app-serverchan=y -CONFIG_PACKAGE_luci-app-smartdns=y +#CONFIG_PACKAGE_luci-app-smartdns=y CONFIG_PACKAGE_luci-app-sqm=y CONFIG_PACKAGE_luci-app-vlmcsd=y CONFIG_PACKAGE_luci-app-vssr=y @@ -125,6 +125,8 @@ CONFIG_PACKAGE_zerotier=y CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y +CONFIG_PACKAGE_dnsproxy=y +CONFIG_PACKAGE_luci-app-dnsfilter=y ### ZRAM ### CONFIG_PACKAGE_luci-app-compressed-memory=y From 444e1cc965eff4e27eee10267c53658abe7d3733 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 28 Jun 2021 18:07:43 +0800 Subject: [PATCH 139/244] Update config.seed --- SEED/X86/config.seed | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index 08b56caf1..1591b59a6 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -84,8 +84,8 @@ CONFIG_PACKAGE_luci-proto-ipv6=y CONFIG_PACKAGE_luci-proto-ppp=y ### APPLICATION ### -CONFIG_PACKAGE_luci-app-adguardhome=y -CONFIG_PACKAGE_adguardhome=y +#CONFIG_PACKAGE_luci-app-adguardhome=y +#CONFIG_PACKAGE_adguardhome=y CONFIG_PACKAGE_luci-app-argon-config=y CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y @@ -102,13 +102,13 @@ CONFIG_PACKAGE_frpc=y CONFIG_PACKAGE_luci-app-frps=y CONFIG_PACKAGE_frps=y CONFIG_PACKAGE_luci-app-jd-dailybonus=y -CONFIG_PACKAGE_luci-app-mosdns=y +#CONFIG_PACKAGE_luci-app-mosdns=y CONFIG_PACKAGE_luci-app-openclash=y CONFIG_PACKAGE_luci-app-opkg=y #CONFIG_PACKAGE_luci-app-qbittorrent=y CONFIG_PACKAGE_luci-app-ramfree=y CONFIG_PACKAGE_luci-app-serverchan=y -CONFIG_PACKAGE_luci-app-smartdns=y +#CONFIG_PACKAGE_luci-app-smartdns=y CONFIG_PACKAGE_luci-app-sqm=y CONFIG_PACKAGE_luci-app-vlmcsd=y CONFIG_PACKAGE_luci-app-vssr=y @@ -125,6 +125,8 @@ CONFIG_PACKAGE_zerotier=y CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y +CONFIG_PACKAGE_dnsproxy=y +CONFIG_PACKAGE_luci-app-dnsfilter=y ### THEME ### CONFIG_PACKAGE_luci-theme-argon=y From fe1448a0e72b1494dfe295a845902687d7ada1ba Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 29 Jun 2021 00:19:32 +0800 Subject: [PATCH 140/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index c8a278093..44e3d5a78 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -156,7 +156,7 @@ ln -sf ../../../feeds/luci/applications/luci-app-aliddns ./package/feeds/luci/lu # Docker 容器(会导致 OpenWrt 出现 UDP 转发问题,慎用) sed -i 's/+docker/+docker \\\n\t+dockerd/g' ./feeds/luci/applications/luci-app-dockerman/Makefile # Dnsfilter -git clone -b master --depth 1 https://github.com/garypang13/luci-app-dnsfilter.git package/new/luci-app-dnsfilter +git clone -b master --depth 1 https://github.com/garypang13/luci-app-dnsfilter.git package/luci-app-dnsfilter # Dnsproxy svn co https://github.com/immortalwrt/packages/trunk/net/dnsproxy feeds/packages/net/dnsproxy ln -sf ../../../feeds/packages/net/dnsproxy ./package/feeds/packages/dnsproxy From b71e59b9c96aee16b61bb82ceb96218cf59a14be Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 29 Jun 2021 00:23:29 +0800 Subject: [PATCH 141/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 44e3d5a78..0f64c2ca3 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -156,7 +156,7 @@ ln -sf ../../../feeds/luci/applications/luci-app-aliddns ./package/feeds/luci/lu # Docker 容器(会导致 OpenWrt 出现 UDP 转发问题,慎用) sed -i 's/+docker/+docker \\\n\t+dockerd/g' ./feeds/luci/applications/luci-app-dockerman/Makefile # Dnsfilter -git clone -b master --depth 1 https://github.com/garypang13/luci-app-dnsfilter.git package/luci-app-dnsfilter +git clone --depth 1 https://github.com/garypang13/luci-app-dnsfilter.git package/new/luci-app-dnsfilter # Dnsproxy svn co https://github.com/immortalwrt/packages/trunk/net/dnsproxy feeds/packages/net/dnsproxy ln -sf ../../../feeds/packages/net/dnsproxy ./package/feeds/packages/dnsproxy From 67f0d3cbddb264f276b9943a84c0005d896551cb Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 29 Jun 2021 09:57:49 +0800 Subject: [PATCH 142/244] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5c555d08d..d399f66b4 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ - 基于原生 OpenWrt 21.02 编译,默认管理地址192.168.1.1 - 同时支持 SFE/Software Offload (选则其一开启,默认开启SFE) - 内置升级功能可用,物理 Reset 按键可用 -- 预配置了部分插件(包括但不限于 DNS 套娃,使用时先将 SSRP 的 DNS 上游提前选成本机5335端口,然后再 ADG 中勾上启用就好*“管理账户root,密码admin”,如果要作用于路由器本身,可以把lan和wan的dns都配置成127.0.0.1,dhcp高级里设置下发dns 6,192.168.1.1。注:这里取决于你设定的路由的ip地址) +- 预配置了部分插件(包括但不限于 DNS 套娃,使用时先将 SSRP 的 DNS 上游提前选成本机5335端口,然后再 ADG 中勾上启用就好*“管理账户root,密码admin”,如果要作用于路由器本身,可以把lan和wan的dns都配置成127.0.0.1,dhcp高级里设置下发dns 6,192.168.1.1。注:这里取决于你设定的路由的ip地址)(注意,6月28日开始取消了dns套娃,使用dnsproxy作为dns分留措施,海外端口5335,国内端口6050,无GUI,自行琢磨使用) - 正式 Release 版本将具有可无脑 opkg kmod 的特性 - R2S核心频率1.6(交换了LAN WAN),R4S核心频率2.2/1.8(建议使用5v4a电源,死机大多数情况下,都是因为你用的电源过于垃圾,另外,你也可以选择使用自带的app限制最大频率,茄子🍆) - O3 编译 From 9b08cde5ac35fa7c2d1528ffa7444fc4051fe645 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 29 Jun 2021 10:11:57 +0800 Subject: [PATCH 143/244] Add files via upload --- PATCH/files/etc/config/dnsfilter | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 PATCH/files/etc/config/dnsfilter diff --git a/PATCH/files/etc/config/dnsfilter b/PATCH/files/etc/config/dnsfilter new file mode 100644 index 000000000..0998cdd46 --- /dev/null +++ b/PATCH/files/etc/config/dnsfilter @@ -0,0 +1,10 @@ + +config dnsfilter + option cron_mode '1' + option time_update '6' + option flash '0' + option enable '1' + list url 'https://cdn.jsdelivr.net/gh/AdguardTeam/FiltersRegistry@master/filters/filter_2_English/filter.txt' + list url 'https://cdn.jsdelivr.net/gh/AdguardTeam/FiltersRegistry@master/filters/filter_224_Chinese/filter.txt' + list url 'https://cdn.jsdelivr.net/gh/AdguardTeam/FiltersRegistry@master/filters/filter_14_Annoyances/filter.txt' + From 9cf3b87a19d47abeb362e381efcb53155b2fd30e Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 29 Jun 2021 10:29:28 +0800 Subject: [PATCH 144/244] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d399f66b4..1a827ad71 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ - 基于原生 OpenWrt 21.02 编译,默认管理地址192.168.1.1 - 同时支持 SFE/Software Offload (选则其一开启,默认开启SFE) - 内置升级功能可用,物理 Reset 按键可用 -- 预配置了部分插件(包括但不限于 DNS 套娃,使用时先将 SSRP 的 DNS 上游提前选成本机5335端口,然后再 ADG 中勾上启用就好*“管理账户root,密码admin”,如果要作用于路由器本身,可以把lan和wan的dns都配置成127.0.0.1,dhcp高级里设置下发dns 6,192.168.1.1。注:这里取决于你设定的路由的ip地址)(注意,6月28日开始取消了dns套娃,使用dnsproxy作为dns分留措施,海外端口5335,国内端口6050,无GUI,自行琢磨使用) +- 预配置了部分插件(包括但不限于 DNS 套娃,使用时先将 SSRP 的 DNS 上游提前选成本机5335端口,然后再 ADG 中勾上启用就好*“管理账户root,密码admin”,如果要作用于路由器本身,可以把lan和wan的dns都配置成127.0.0.1,dhcp高级里设置下发dns 6,192.168.1.1。注:这里取决于你设定的路由的ip地址)(注意,6月28日开始取消了dns套娃,使用dnsproxy作为dns分流措施,海外端口5335,国内端口6050,无GUI,自行琢磨使用) - 正式 Release 版本将具有可无脑 opkg kmod 的特性 - R2S核心频率1.6(交换了LAN WAN),R4S核心频率2.2/1.8(建议使用5v4a电源,死机大多数情况下,都是因为你用的电源过于垃圾,另外,你也可以选择使用自带的app限制最大频率,茄子🍆) - O3 编译 From 1e652273a9b8590ed01779a505a0df653b5227f2 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 29 Jun 2021 13:08:01 +0800 Subject: [PATCH 145/244] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1a827ad71..44d1de563 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ - 基于原生 OpenWrt 21.02 编译,默认管理地址192.168.1.1 - 同时支持 SFE/Software Offload (选则其一开启,默认开启SFE) - 内置升级功能可用,物理 Reset 按键可用 -- 预配置了部分插件(包括但不限于 DNS 套娃,使用时先将 SSRP 的 DNS 上游提前选成本机5335端口,然后再 ADG 中勾上启用就好*“管理账户root,密码admin”,如果要作用于路由器本身,可以把lan和wan的dns都配置成127.0.0.1,dhcp高级里设置下发dns 6,192.168.1.1。注:这里取决于你设定的路由的ip地址)(注意,6月28日开始取消了dns套娃,使用dnsproxy作为dns分流措施,海外端口5335,国内端口6050,无GUI,自行琢磨使用) +- 预配置了部分插件(包括但不限于 DNS 套娃,使用时先将 SSRP 的 DNS 上游提前选成本机5335端口,然后再 ADG 中勾上启用就好*“管理账户root,密码admin”,如果要作用于路由器本身,可以把lan和wan的dns都配置成127.0.0.1,dhcp高级里设置下发dns 6,192.168.1.1。注:这里取决于你设定的路由的ip地址)(注意,6月28日开始取消了dns套娃,使用dnsfilter作为广告过滤手段,使用dnsproxy作为dns分流措施,海外端口5335,国内端口6050,无GUI,自行琢磨使用) - 正式 Release 版本将具有可无脑 opkg kmod 的特性 - R2S核心频率1.6(交换了LAN WAN),R4S核心频率2.2/1.8(建议使用5v4a电源,死机大多数情况下,都是因为你用的电源过于垃圾,另外,你也可以选择使用自带的app限制最大频率,茄子🍆) - O3 编译 From ce68ec535d9913cead28b80caa458fe3e47cf10f Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 29 Jun 2021 14:42:18 +0800 Subject: [PATCH 146/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 0f64c2ca3..b6e86c4b5 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -342,6 +342,7 @@ svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/addition-trans-zh package/ mkdir package/base-files/files/usr/bin wget -P package/base-files/files/usr/bin/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/fuck wget -P package/base-files/files/usr/bin/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/chinadnslist +wget -P package/base-files/files/usr/bin/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/setdns # 最大连接数 sed -i 's/16384/65535/g' package/kernel/linux/files/sysctl-nf-conntrack.conf # 生成默认配置及缓存 From 0daa34f0e45ea4ec84ce9e041de60213ac2ce9cc Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 29 Jun 2021 14:49:46 +0800 Subject: [PATCH 147/244] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 44d1de563..414d0f4e3 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ - 基于原生 OpenWrt 21.02 编译,默认管理地址192.168.1.1 - 同时支持 SFE/Software Offload (选则其一开启,默认开启SFE) - 内置升级功能可用,物理 Reset 按键可用 -- 预配置了部分插件(包括但不限于 DNS 套娃,使用时先将 SSRP 的 DNS 上游提前选成本机5335端口,然后再 ADG 中勾上启用就好*“管理账户root,密码admin”,如果要作用于路由器本身,可以把lan和wan的dns都配置成127.0.0.1,dhcp高级里设置下发dns 6,192.168.1.1。注:这里取决于你设定的路由的ip地址)(注意,6月28日开始取消了dns套娃,使用dnsfilter作为广告过滤手段,使用dnsproxy作为dns分流措施,海外端口5335,国内端口6050,无GUI,自行琢磨使用) +- 预配置了部分插件(包括但不限于 DNS 套娃,使用时先将 SSRP 的 DNS 上游提前选成本机5335端口,然后再 ADG 中勾上启用就好*“管理账户root,密码admin”,如果要作用于路由器本身,可以把lan和wan的dns都配置成127.0.0.1,dhcp高级里设置下发dns 6,192.168.1.1。注:这里取决于你设定的路由的ip地址)(注意,6月29日开始取消了dns套娃,使用dnsfilter作为广告过滤手段,使用dnsproxy作为dns分流措施,海外端口5335,国内端口6050,无GUI,自行琢磨使用。或可尝试ssh进入后台,输入setdns后回车,使用预设的dns方案) - 正式 Release 版本将具有可无脑 opkg kmod 的特性 - R2S核心频率1.6(交换了LAN WAN),R4S核心频率2.2/1.8(建议使用5v4a电源,死机大多数情况下,都是因为你用的电源过于垃圾,另外,你也可以选择使用自带的app限制最大频率,茄子🍆) - O3 编译 From 3cbb78f12187bebaa7ca47aead038633cbe9f55e Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 30 Jun 2021 17:19:10 +0800 Subject: [PATCH 148/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index b6e86c4b5..1eb34edac 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -277,6 +277,7 @@ pushd package/lean #wget -qO - https://github.com/fw876/helloworld/pull/513.patch | patch -p1 wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/c1674ad.patch | patch -p1 wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/5bbf6e7.patch | patch -p1 +wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/4fd0616.patch | patch -p1 popd pushd package/lean/luci-app-ssr-plus sed -i 's,default n,default y,g' Makefile From 9b6e76e9660e2e79d1d11eb5e20699ac1f608220 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 30 Jun 2021 22:19:02 +0800 Subject: [PATCH 149/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 1eb34edac..e99bc2978 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -277,7 +277,7 @@ pushd package/lean #wget -qO - https://github.com/fw876/helloworld/pull/513.patch | patch -p1 wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/c1674ad.patch | patch -p1 wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/5bbf6e7.patch | patch -p1 -wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/4fd0616.patch | patch -p1 +wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/323fbf0.patch | patch -p1 popd pushd package/lean/luci-app-ssr-plus sed -i 's,default n,default y,g' Makefile From bee4580740c2acd8285a918f7ea9203d78c0a47a Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 2 Jul 2021 16:40:02 +0800 Subject: [PATCH 150/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index e99bc2978..e10fe37f9 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -106,6 +106,8 @@ rm -rf ./feeds/packages/net/adguardhome svn co https://github.com/openwrt/packages/trunk/net/adguardhome feeds/packages/net/adguardhome sed -i '/\t)/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/AdGuardHome' ./feeds/packages/net/adguardhome/Makefile sed -i '/init/d' feeds/packages/net/adguardhome/Makefile +# ADBP +git clone --depth 1 https://github.com/small-5/luci-app-adblock-plus.git package/new/luci-app-adblock-plus # Argon 主题 git clone -b master --depth 1 https://github.com/jerrykuku/luci-theme-argon.git package/new/luci-theme-argon #wget -P ./package/new/luci-theme-argon/htdocs/luci-static/argon/css/ -N https://github.com/msylgj/luci-theme-argon/raw/patch-1/htdocs/luci-static/argon/css/dark.css @@ -156,7 +158,7 @@ ln -sf ../../../feeds/luci/applications/luci-app-aliddns ./package/feeds/luci/lu # Docker 容器(会导致 OpenWrt 出现 UDP 转发问题,慎用) sed -i 's/+docker/+docker \\\n\t+dockerd/g' ./feeds/luci/applications/luci-app-dockerman/Makefile # Dnsfilter -git clone --depth 1 https://github.com/garypang13/luci-app-dnsfilter.git package/new/luci-app-dnsfilter +#git clone --depth 1 https://github.com/garypang13/luci-app-dnsfilter.git package/new/luci-app-dnsfilter # Dnsproxy svn co https://github.com/immortalwrt/packages/trunk/net/dnsproxy feeds/packages/net/dnsproxy ln -sf ../../../feeds/packages/net/dnsproxy ./package/feeds/packages/dnsproxy From 9e43db77cbb748d597f5a98e0f10240f67fcbb87 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 2 Jul 2021 16:43:24 +0800 Subject: [PATCH 151/244] Update config.seed --- SEED/R4S/config.seed | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index 68eeb1ea3..80110f241 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -126,7 +126,7 @@ CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y CONFIG_PACKAGE_dnsproxy=y -CONFIG_PACKAGE_luci-app-dnsfilter=y +CONFIG_PACKAGE_luci-app-adblock-plus=y ### THEME ### CONFIG_PACKAGE_luci-theme-argon=y From 627710761bd2b0d77301a6bc30bfc4760e0a56f2 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 2 Jul 2021 16:43:48 +0800 Subject: [PATCH 152/244] Update config.seed --- SEED/R2S/config.seed | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 5af5b7435..664b1b077 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -126,7 +126,7 @@ CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y CONFIG_PACKAGE_dnsproxy=y -CONFIG_PACKAGE_luci-app-dnsfilter=y +CONFIG_PACKAGE_luci-app-adblock-plus=y ### ZRAM ### CONFIG_PACKAGE_luci-app-compressed-memory=y From 5659ed3b6b99a0bf95e3aba2dd9c7cd64bb01459 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 2 Jul 2021 16:44:05 +0800 Subject: [PATCH 153/244] Update config.seed --- SEED/X86/config.seed | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index 1591b59a6..6767c8009 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -126,7 +126,7 @@ CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y CONFIG_PACKAGE_dnsproxy=y -CONFIG_PACKAGE_luci-app-dnsfilter=y +CONFIG_PACKAGE_luci-app-adblock-plus=y ### THEME ### CONFIG_PACKAGE_luci-theme-argon=y From 7eec4606f58c3b3bb17005911e46416e004c577b Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 2 Jul 2021 16:44:38 +0800 Subject: [PATCH 154/244] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 414d0f4e3..dd0a13d9a 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ - 基于原生 OpenWrt 21.02 编译,默认管理地址192.168.1.1 - 同时支持 SFE/Software Offload (选则其一开启,默认开启SFE) - 内置升级功能可用,物理 Reset 按键可用 -- 预配置了部分插件(包括但不限于 DNS 套娃,使用时先将 SSRP 的 DNS 上游提前选成本机5335端口,然后再 ADG 中勾上启用就好*“管理账户root,密码admin”,如果要作用于路由器本身,可以把lan和wan的dns都配置成127.0.0.1,dhcp高级里设置下发dns 6,192.168.1.1。注:这里取决于你设定的路由的ip地址)(注意,6月29日开始取消了dns套娃,使用dnsfilter作为广告过滤手段,使用dnsproxy作为dns分流措施,海外端口5335,国内端口6050,无GUI,自行琢磨使用。或可尝试ssh进入后台,输入setdns后回车,使用预设的dns方案) +- 预配置了部分插件(包括但不限于 DNS 套娃,使用时先将 SSRP 的 DNS 上游提前选成本机5335端口,然后再 ADG 中勾上启用就好*“管理账户root,密码admin”,如果要作用于路由器本身,可以把lan和wan的dns都配置成127.0.0.1,dhcp高级里设置下发dns 6,192.168.1.1。注:这里取决于你设定的路由的ip地址)(注意,6月29日开始取消了dns套娃,使用ADBP作为广告过滤手段,使用dnsproxy作为dns分流措施,海外端口5335,国内端口6050,无GUI,自行琢磨使用。或可尝试ssh进入后台,输入setdns后回车,使用预设的dns方案) - 正式 Release 版本将具有可无脑 opkg kmod 的特性 - R2S核心频率1.6(交换了LAN WAN),R4S核心频率2.2/1.8(建议使用5v4a电源,死机大多数情况下,都是因为你用的电源过于垃圾,另外,你也可以选择使用自带的app限制最大频率,茄子🍆) - O3 编译 From d0cdbc2142cdb736159b382dbc96ae6a7376b194 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 2 Jul 2021 16:46:58 +0800 Subject: [PATCH 155/244] Update and rename dnsfilter to adblock --- PATCH/files/etc/config/{dnsfilter => adblock} | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) rename PATCH/files/etc/config/{dnsfilter => adblock} (87%) diff --git a/PATCH/files/etc/config/dnsfilter b/PATCH/files/etc/config/adblock similarity index 87% rename from PATCH/files/etc/config/dnsfilter rename to PATCH/files/etc/config/adblock index 0998cdd46..007f100c4 100644 --- a/PATCH/files/etc/config/dnsfilter +++ b/PATCH/files/etc/config/adblock @@ -1,8 +1,10 @@ -config dnsfilter +config adblock option cron_mode '1' option time_update '6' option flash '0' + option block_cnshort '0' + option block_ios '0' option enable '1' list url 'https://cdn.jsdelivr.net/gh/AdguardTeam/FiltersRegistry@master/filters/filter_2_English/filter.txt' list url 'https://cdn.jsdelivr.net/gh/AdguardTeam/FiltersRegistry@master/filters/filter_224_Chinese/filter.txt' From 1edc6a9216f06ce10729d2bae8078524781ec248 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 2 Jul 2021 21:59:29 +0800 Subject: [PATCH 156/244] Update adblock --- PATCH/files/etc/config/adblock | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/PATCH/files/etc/config/adblock b/PATCH/files/etc/config/adblock index 007f100c4..2890de852 100644 --- a/PATCH/files/etc/config/adblock +++ b/PATCH/files/etc/config/adblock @@ -3,10 +3,6 @@ config adblock option cron_mode '1' option time_update '6' option flash '0' - option block_cnshort '0' - option block_ios '0' option enable '1' - list url 'https://cdn.jsdelivr.net/gh/AdguardTeam/FiltersRegistry@master/filters/filter_2_English/filter.txt' - list url 'https://cdn.jsdelivr.net/gh/AdguardTeam/FiltersRegistry@master/filters/filter_224_Chinese/filter.txt' - list url 'https://cdn.jsdelivr.net/gh/AdguardTeam/FiltersRegistry@master/filters/filter_14_Annoyances/filter.txt' + list url 'https://cdn.jsdelivr.net/gh/small-5/ad-rules/adguard' From 0247f5988e3b8c7b896cc0577e16020664914639 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 2 Jul 2021 16:40:02 +0800 Subject: [PATCH 157/244] Update 02_prepare_package.sh Update config.seed Update config.seed Update config.seed Update README.md Update and rename dnsfilter to adblock Update adblock --- PATCH/files/etc/config/adblock | 8 ++++++++ PATCH/files/etc/config/dnsfilter | 10 ---------- README.md | 2 +- SCRIPTS/02_prepare_package.sh | 4 +++- SEED/R2S/config.seed | 2 +- SEED/R4S/config.seed | 2 +- SEED/X86/config.seed | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) create mode 100644 PATCH/files/etc/config/adblock delete mode 100644 PATCH/files/etc/config/dnsfilter diff --git a/PATCH/files/etc/config/adblock b/PATCH/files/etc/config/adblock new file mode 100644 index 000000000..2890de852 --- /dev/null +++ b/PATCH/files/etc/config/adblock @@ -0,0 +1,8 @@ + +config adblock + option cron_mode '1' + option time_update '6' + option flash '0' + option enable '1' + list url 'https://cdn.jsdelivr.net/gh/small-5/ad-rules/adguard' + diff --git a/PATCH/files/etc/config/dnsfilter b/PATCH/files/etc/config/dnsfilter deleted file mode 100644 index 0998cdd46..000000000 --- a/PATCH/files/etc/config/dnsfilter +++ /dev/null @@ -1,10 +0,0 @@ - -config dnsfilter - option cron_mode '1' - option time_update '6' - option flash '0' - option enable '1' - list url 'https://cdn.jsdelivr.net/gh/AdguardTeam/FiltersRegistry@master/filters/filter_2_English/filter.txt' - list url 'https://cdn.jsdelivr.net/gh/AdguardTeam/FiltersRegistry@master/filters/filter_224_Chinese/filter.txt' - list url 'https://cdn.jsdelivr.net/gh/AdguardTeam/FiltersRegistry@master/filters/filter_14_Annoyances/filter.txt' - diff --git a/README.md b/README.md index 414d0f4e3..dd0a13d9a 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ - 基于原生 OpenWrt 21.02 编译,默认管理地址192.168.1.1 - 同时支持 SFE/Software Offload (选则其一开启,默认开启SFE) - 内置升级功能可用,物理 Reset 按键可用 -- 预配置了部分插件(包括但不限于 DNS 套娃,使用时先将 SSRP 的 DNS 上游提前选成本机5335端口,然后再 ADG 中勾上启用就好*“管理账户root,密码admin”,如果要作用于路由器本身,可以把lan和wan的dns都配置成127.0.0.1,dhcp高级里设置下发dns 6,192.168.1.1。注:这里取决于你设定的路由的ip地址)(注意,6月29日开始取消了dns套娃,使用dnsfilter作为广告过滤手段,使用dnsproxy作为dns分流措施,海外端口5335,国内端口6050,无GUI,自行琢磨使用。或可尝试ssh进入后台,输入setdns后回车,使用预设的dns方案) +- 预配置了部分插件(包括但不限于 DNS 套娃,使用时先将 SSRP 的 DNS 上游提前选成本机5335端口,然后再 ADG 中勾上启用就好*“管理账户root,密码admin”,如果要作用于路由器本身,可以把lan和wan的dns都配置成127.0.0.1,dhcp高级里设置下发dns 6,192.168.1.1。注:这里取决于你设定的路由的ip地址)(注意,6月29日开始取消了dns套娃,使用ADBP作为广告过滤手段,使用dnsproxy作为dns分流措施,海外端口5335,国内端口6050,无GUI,自行琢磨使用。或可尝试ssh进入后台,输入setdns后回车,使用预设的dns方案) - 正式 Release 版本将具有可无脑 opkg kmod 的特性 - R2S核心频率1.6(交换了LAN WAN),R4S核心频率2.2/1.8(建议使用5v4a电源,死机大多数情况下,都是因为你用的电源过于垃圾,另外,你也可以选择使用自带的app限制最大频率,茄子🍆) - O3 编译 diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index e99bc2978..e10fe37f9 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -106,6 +106,8 @@ rm -rf ./feeds/packages/net/adguardhome svn co https://github.com/openwrt/packages/trunk/net/adguardhome feeds/packages/net/adguardhome sed -i '/\t)/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/AdGuardHome' ./feeds/packages/net/adguardhome/Makefile sed -i '/init/d' feeds/packages/net/adguardhome/Makefile +# ADBP +git clone --depth 1 https://github.com/small-5/luci-app-adblock-plus.git package/new/luci-app-adblock-plus # Argon 主题 git clone -b master --depth 1 https://github.com/jerrykuku/luci-theme-argon.git package/new/luci-theme-argon #wget -P ./package/new/luci-theme-argon/htdocs/luci-static/argon/css/ -N https://github.com/msylgj/luci-theme-argon/raw/patch-1/htdocs/luci-static/argon/css/dark.css @@ -156,7 +158,7 @@ ln -sf ../../../feeds/luci/applications/luci-app-aliddns ./package/feeds/luci/lu # Docker 容器(会导致 OpenWrt 出现 UDP 转发问题,慎用) sed -i 's/+docker/+docker \\\n\t+dockerd/g' ./feeds/luci/applications/luci-app-dockerman/Makefile # Dnsfilter -git clone --depth 1 https://github.com/garypang13/luci-app-dnsfilter.git package/new/luci-app-dnsfilter +#git clone --depth 1 https://github.com/garypang13/luci-app-dnsfilter.git package/new/luci-app-dnsfilter # Dnsproxy svn co https://github.com/immortalwrt/packages/trunk/net/dnsproxy feeds/packages/net/dnsproxy ln -sf ../../../feeds/packages/net/dnsproxy ./package/feeds/packages/dnsproxy diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 5af5b7435..664b1b077 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -126,7 +126,7 @@ CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y CONFIG_PACKAGE_dnsproxy=y -CONFIG_PACKAGE_luci-app-dnsfilter=y +CONFIG_PACKAGE_luci-app-adblock-plus=y ### ZRAM ### CONFIG_PACKAGE_luci-app-compressed-memory=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index 68eeb1ea3..80110f241 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -126,7 +126,7 @@ CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y CONFIG_PACKAGE_dnsproxy=y -CONFIG_PACKAGE_luci-app-dnsfilter=y +CONFIG_PACKAGE_luci-app-adblock-plus=y ### THEME ### CONFIG_PACKAGE_luci-theme-argon=y diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index 1591b59a6..6767c8009 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -126,7 +126,7 @@ CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y CONFIG_PACKAGE_dnsproxy=y -CONFIG_PACKAGE_luci-app-dnsfilter=y +CONFIG_PACKAGE_luci-app-adblock-plus=y ### THEME ### CONFIG_PACKAGE_luci-theme-argon=y From 260853ea66f40f1b5ced856d0fcbcd54add04603 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 7 Jul 2021 12:35:54 +0800 Subject: [PATCH 158/244] Revert "Update 02_prepare_package.sh" This reverts commit 0247f5988e3b8c7b896cc0577e16020664914639. --- PATCH/files/etc/config/adblock | 8 -------- PATCH/files/etc/config/dnsfilter | 10 ++++++++++ README.md | 2 +- SCRIPTS/02_prepare_package.sh | 4 +--- SEED/R2S/config.seed | 2 +- SEED/R4S/config.seed | 2 +- SEED/X86/config.seed | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) delete mode 100644 PATCH/files/etc/config/adblock create mode 100644 PATCH/files/etc/config/dnsfilter diff --git a/PATCH/files/etc/config/adblock b/PATCH/files/etc/config/adblock deleted file mode 100644 index 2890de852..000000000 --- a/PATCH/files/etc/config/adblock +++ /dev/null @@ -1,8 +0,0 @@ - -config adblock - option cron_mode '1' - option time_update '6' - option flash '0' - option enable '1' - list url 'https://cdn.jsdelivr.net/gh/small-5/ad-rules/adguard' - diff --git a/PATCH/files/etc/config/dnsfilter b/PATCH/files/etc/config/dnsfilter new file mode 100644 index 000000000..0998cdd46 --- /dev/null +++ b/PATCH/files/etc/config/dnsfilter @@ -0,0 +1,10 @@ + +config dnsfilter + option cron_mode '1' + option time_update '6' + option flash '0' + option enable '1' + list url 'https://cdn.jsdelivr.net/gh/AdguardTeam/FiltersRegistry@master/filters/filter_2_English/filter.txt' + list url 'https://cdn.jsdelivr.net/gh/AdguardTeam/FiltersRegistry@master/filters/filter_224_Chinese/filter.txt' + list url 'https://cdn.jsdelivr.net/gh/AdguardTeam/FiltersRegistry@master/filters/filter_14_Annoyances/filter.txt' + diff --git a/README.md b/README.md index dd0a13d9a..414d0f4e3 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ - 基于原生 OpenWrt 21.02 编译,默认管理地址192.168.1.1 - 同时支持 SFE/Software Offload (选则其一开启,默认开启SFE) - 内置升级功能可用,物理 Reset 按键可用 -- 预配置了部分插件(包括但不限于 DNS 套娃,使用时先将 SSRP 的 DNS 上游提前选成本机5335端口,然后再 ADG 中勾上启用就好*“管理账户root,密码admin”,如果要作用于路由器本身,可以把lan和wan的dns都配置成127.0.0.1,dhcp高级里设置下发dns 6,192.168.1.1。注:这里取决于你设定的路由的ip地址)(注意,6月29日开始取消了dns套娃,使用ADBP作为广告过滤手段,使用dnsproxy作为dns分流措施,海外端口5335,国内端口6050,无GUI,自行琢磨使用。或可尝试ssh进入后台,输入setdns后回车,使用预设的dns方案) +- 预配置了部分插件(包括但不限于 DNS 套娃,使用时先将 SSRP 的 DNS 上游提前选成本机5335端口,然后再 ADG 中勾上启用就好*“管理账户root,密码admin”,如果要作用于路由器本身,可以把lan和wan的dns都配置成127.0.0.1,dhcp高级里设置下发dns 6,192.168.1.1。注:这里取决于你设定的路由的ip地址)(注意,6月29日开始取消了dns套娃,使用dnsfilter作为广告过滤手段,使用dnsproxy作为dns分流措施,海外端口5335,国内端口6050,无GUI,自行琢磨使用。或可尝试ssh进入后台,输入setdns后回车,使用预设的dns方案) - 正式 Release 版本将具有可无脑 opkg kmod 的特性 - R2S核心频率1.6(交换了LAN WAN),R4S核心频率2.2/1.8(建议使用5v4a电源,死机大多数情况下,都是因为你用的电源过于垃圾,另外,你也可以选择使用自带的app限制最大频率,茄子🍆) - O3 编译 diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index e10fe37f9..e99bc2978 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -106,8 +106,6 @@ rm -rf ./feeds/packages/net/adguardhome svn co https://github.com/openwrt/packages/trunk/net/adguardhome feeds/packages/net/adguardhome sed -i '/\t)/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/AdGuardHome' ./feeds/packages/net/adguardhome/Makefile sed -i '/init/d' feeds/packages/net/adguardhome/Makefile -# ADBP -git clone --depth 1 https://github.com/small-5/luci-app-adblock-plus.git package/new/luci-app-adblock-plus # Argon 主题 git clone -b master --depth 1 https://github.com/jerrykuku/luci-theme-argon.git package/new/luci-theme-argon #wget -P ./package/new/luci-theme-argon/htdocs/luci-static/argon/css/ -N https://github.com/msylgj/luci-theme-argon/raw/patch-1/htdocs/luci-static/argon/css/dark.css @@ -158,7 +156,7 @@ ln -sf ../../../feeds/luci/applications/luci-app-aliddns ./package/feeds/luci/lu # Docker 容器(会导致 OpenWrt 出现 UDP 转发问题,慎用) sed -i 's/+docker/+docker \\\n\t+dockerd/g' ./feeds/luci/applications/luci-app-dockerman/Makefile # Dnsfilter -#git clone --depth 1 https://github.com/garypang13/luci-app-dnsfilter.git package/new/luci-app-dnsfilter +git clone --depth 1 https://github.com/garypang13/luci-app-dnsfilter.git package/new/luci-app-dnsfilter # Dnsproxy svn co https://github.com/immortalwrt/packages/trunk/net/dnsproxy feeds/packages/net/dnsproxy ln -sf ../../../feeds/packages/net/dnsproxy ./package/feeds/packages/dnsproxy diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 664b1b077..5af5b7435 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -126,7 +126,7 @@ CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y CONFIG_PACKAGE_dnsproxy=y -CONFIG_PACKAGE_luci-app-adblock-plus=y +CONFIG_PACKAGE_luci-app-dnsfilter=y ### ZRAM ### CONFIG_PACKAGE_luci-app-compressed-memory=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index 80110f241..68eeb1ea3 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -126,7 +126,7 @@ CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y CONFIG_PACKAGE_dnsproxy=y -CONFIG_PACKAGE_luci-app-adblock-plus=y +CONFIG_PACKAGE_luci-app-dnsfilter=y ### THEME ### CONFIG_PACKAGE_luci-theme-argon=y diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index 6767c8009..1591b59a6 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -126,7 +126,7 @@ CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y CONFIG_PACKAGE_dnsproxy=y -CONFIG_PACKAGE_luci-app-adblock-plus=y +CONFIG_PACKAGE_luci-app-dnsfilter=y ### THEME ### CONFIG_PACKAGE_luci-theme-argon=y From 9da2c7cccd98b9da2072394e1c378d18d8c4e921 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 7 Jul 2021 12:37:04 +0800 Subject: [PATCH 159/244] Revert "Merge branch 'master' of https://github.com/QiuSimons/R2S-R4S-X86-OpenWrt" This reverts commit 48a48a1636acb28e4c37e8b484ba1f8d51c6dcc3, reversing changes made to 260853ea66f40f1b5ced856d0fcbcd54add04603. --- PATCH/files/etc/config/adblock | 8 -------- PATCH/files/etc/config/dnsfilter | 10 ++++++++++ README.md | 2 +- SCRIPTS/02_prepare_package.sh | 4 +--- SEED/R2S/config.seed | 2 +- SEED/R4S/config.seed | 2 +- SEED/X86/config.seed | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) delete mode 100644 PATCH/files/etc/config/adblock create mode 100644 PATCH/files/etc/config/dnsfilter diff --git a/PATCH/files/etc/config/adblock b/PATCH/files/etc/config/adblock deleted file mode 100644 index 2890de852..000000000 --- a/PATCH/files/etc/config/adblock +++ /dev/null @@ -1,8 +0,0 @@ - -config adblock - option cron_mode '1' - option time_update '6' - option flash '0' - option enable '1' - list url 'https://cdn.jsdelivr.net/gh/small-5/ad-rules/adguard' - diff --git a/PATCH/files/etc/config/dnsfilter b/PATCH/files/etc/config/dnsfilter new file mode 100644 index 000000000..0998cdd46 --- /dev/null +++ b/PATCH/files/etc/config/dnsfilter @@ -0,0 +1,10 @@ + +config dnsfilter + option cron_mode '1' + option time_update '6' + option flash '0' + option enable '1' + list url 'https://cdn.jsdelivr.net/gh/AdguardTeam/FiltersRegistry@master/filters/filter_2_English/filter.txt' + list url 'https://cdn.jsdelivr.net/gh/AdguardTeam/FiltersRegistry@master/filters/filter_224_Chinese/filter.txt' + list url 'https://cdn.jsdelivr.net/gh/AdguardTeam/FiltersRegistry@master/filters/filter_14_Annoyances/filter.txt' + diff --git a/README.md b/README.md index dd0a13d9a..414d0f4e3 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ - 基于原生 OpenWrt 21.02 编译,默认管理地址192.168.1.1 - 同时支持 SFE/Software Offload (选则其一开启,默认开启SFE) - 内置升级功能可用,物理 Reset 按键可用 -- 预配置了部分插件(包括但不限于 DNS 套娃,使用时先将 SSRP 的 DNS 上游提前选成本机5335端口,然后再 ADG 中勾上启用就好*“管理账户root,密码admin”,如果要作用于路由器本身,可以把lan和wan的dns都配置成127.0.0.1,dhcp高级里设置下发dns 6,192.168.1.1。注:这里取决于你设定的路由的ip地址)(注意,6月29日开始取消了dns套娃,使用ADBP作为广告过滤手段,使用dnsproxy作为dns分流措施,海外端口5335,国内端口6050,无GUI,自行琢磨使用。或可尝试ssh进入后台,输入setdns后回车,使用预设的dns方案) +- 预配置了部分插件(包括但不限于 DNS 套娃,使用时先将 SSRP 的 DNS 上游提前选成本机5335端口,然后再 ADG 中勾上启用就好*“管理账户root,密码admin”,如果要作用于路由器本身,可以把lan和wan的dns都配置成127.0.0.1,dhcp高级里设置下发dns 6,192.168.1.1。注:这里取决于你设定的路由的ip地址)(注意,6月29日开始取消了dns套娃,使用dnsfilter作为广告过滤手段,使用dnsproxy作为dns分流措施,海外端口5335,国内端口6050,无GUI,自行琢磨使用。或可尝试ssh进入后台,输入setdns后回车,使用预设的dns方案) - 正式 Release 版本将具有可无脑 opkg kmod 的特性 - R2S核心频率1.6(交换了LAN WAN),R4S核心频率2.2/1.8(建议使用5v4a电源,死机大多数情况下,都是因为你用的电源过于垃圾,另外,你也可以选择使用自带的app限制最大频率,茄子🍆) - O3 编译 diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index e10fe37f9..e99bc2978 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -106,8 +106,6 @@ rm -rf ./feeds/packages/net/adguardhome svn co https://github.com/openwrt/packages/trunk/net/adguardhome feeds/packages/net/adguardhome sed -i '/\t)/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/AdGuardHome' ./feeds/packages/net/adguardhome/Makefile sed -i '/init/d' feeds/packages/net/adguardhome/Makefile -# ADBP -git clone --depth 1 https://github.com/small-5/luci-app-adblock-plus.git package/new/luci-app-adblock-plus # Argon 主题 git clone -b master --depth 1 https://github.com/jerrykuku/luci-theme-argon.git package/new/luci-theme-argon #wget -P ./package/new/luci-theme-argon/htdocs/luci-static/argon/css/ -N https://github.com/msylgj/luci-theme-argon/raw/patch-1/htdocs/luci-static/argon/css/dark.css @@ -158,7 +156,7 @@ ln -sf ../../../feeds/luci/applications/luci-app-aliddns ./package/feeds/luci/lu # Docker 容器(会导致 OpenWrt 出现 UDP 转发问题,慎用) sed -i 's/+docker/+docker \\\n\t+dockerd/g' ./feeds/luci/applications/luci-app-dockerman/Makefile # Dnsfilter -#git clone --depth 1 https://github.com/garypang13/luci-app-dnsfilter.git package/new/luci-app-dnsfilter +git clone --depth 1 https://github.com/garypang13/luci-app-dnsfilter.git package/new/luci-app-dnsfilter # Dnsproxy svn co https://github.com/immortalwrt/packages/trunk/net/dnsproxy feeds/packages/net/dnsproxy ln -sf ../../../feeds/packages/net/dnsproxy ./package/feeds/packages/dnsproxy diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 664b1b077..5af5b7435 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -126,7 +126,7 @@ CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y CONFIG_PACKAGE_dnsproxy=y -CONFIG_PACKAGE_luci-app-adblock-plus=y +CONFIG_PACKAGE_luci-app-dnsfilter=y ### ZRAM ### CONFIG_PACKAGE_luci-app-compressed-memory=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index 80110f241..68eeb1ea3 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -126,7 +126,7 @@ CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y CONFIG_PACKAGE_dnsproxy=y -CONFIG_PACKAGE_luci-app-adblock-plus=y +CONFIG_PACKAGE_luci-app-dnsfilter=y ### THEME ### CONFIG_PACKAGE_luci-theme-argon=y diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index 6767c8009..1591b59a6 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -126,7 +126,7 @@ CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y CONFIG_PACKAGE_dnsproxy=y -CONFIG_PACKAGE_luci-app-adblock-plus=y +CONFIG_PACKAGE_luci-app-dnsfilter=y ### THEME ### CONFIG_PACKAGE_luci-theme-argon=y From b6a9bf67f0c0d353d58af75fda7e9df8a70a283c Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sat, 10 Jul 2021 11:56:24 +0800 Subject: [PATCH 160/244] TWEAK Update 02_target_only.sh --- README.md | 2 +- SCRIPTS/02_prepare_package.sh | 11 +++++++++-- SCRIPTS/X86/02_target_only.sh | 16 +++++++++++++++- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 414d0f4e3..4f9051c71 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ - 基于原生 OpenWrt 21.02 编译,默认管理地址192.168.1.1 - 同时支持 SFE/Software Offload (选则其一开启,默认开启SFE) - 内置升级功能可用,物理 Reset 按键可用 -- 预配置了部分插件(包括但不限于 DNS 套娃,使用时先将 SSRP 的 DNS 上游提前选成本机5335端口,然后再 ADG 中勾上启用就好*“管理账户root,密码admin”,如果要作用于路由器本身,可以把lan和wan的dns都配置成127.0.0.1,dhcp高级里设置下发dns 6,192.168.1.1。注:这里取决于你设定的路由的ip地址)(注意,6月29日开始取消了dns套娃,使用dnsfilter作为广告过滤手段,使用dnsproxy作为dns分流措施,海外端口5335,国内端口6050,无GUI,自行琢磨使用。或可尝试ssh进入后台,输入setdns后回车,使用预设的dns方案) +- 预配置了部分插件(包括但不限于 DNS 套娃,(注意,6月29日开始取消了dns套娃,使用dnsfilter作为广告过滤手段,使用dnsproxy作为dns分流措施,海外端口5335,国内端口6050,无GUI,自行琢磨使用。或可尝试ssh进入后台,输入setdns后回车,使用预设的dns方案,升级固件或fuck后,请重新setdns) - 正式 Release 版本将具有可无脑 opkg kmod 的特性 - R2S核心频率1.6(交换了LAN WAN),R4S核心频率2.2/1.8(建议使用5v4a电源,死机大多数情况下,都是因为你用的电源过于垃圾,另外,你也可以选择使用自带的app限制最大频率,茄子🍆) - O3 编译 diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index e99bc2978..5309684d9 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -113,7 +113,8 @@ git clone -b master --depth 1 https://github.com/jerrykuku/luci-theme-argon.git #wget -P ./package/new/luci-theme-argon/luasrc/view/themes/argon -N https://github.com/jerrykuku/luci-theme-argon/raw/9fdcfc866ca80d8d094d554c6aedc18682661973/luasrc/view/themes/argon/header.htm git clone -b master --depth 1 https://github.com/jerrykuku/luci-app-argon-config.git package/new/luci-app-argon-config # MAC 地址与 IP 绑定 -svn co https://github.com/QiuSimons/OpenWrt_luci-app/trunk/luci-app-arpbind package/lean/luci-app-arpbind +svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-arpbind feeds/luci/applications/luci-app-arpbind +ln -sf ../../../feeds/luci/applications/luci-app-arpbind ./package/feeds/luci/luci-app-arpbind # 定时重启 svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-autoreboot package/lean/luci-app-autoreboot # Boost 通用即插即用 @@ -217,6 +218,7 @@ svn co https://github.com/xiaorouji/openwrt-passwall/trunk/luci-app-passwall pac sed -i 's,default n,default y,g' package/new/luci-app-passwall/Makefile sed -i '/V2ray:v2ray/d' package/new/luci-app-passwall/Makefile sed -i '/plugin:v2ray/d' package/new/luci-app-passwall/Makefile +sed -i '/Proxy:naive/d' package/new/luci-app-passwall/Makefile wget -P package/new/luci-app-passwall/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/move_2_services.sh chmod -R 755 ./package/new/luci-app-passwall/move_2_services.sh pushd package/new/luci-app-passwall @@ -275,7 +277,7 @@ svn co https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/lean/ rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans pushd package/lean #wget -qO - https://github.com/fw876/helloworld/pull/513.patch | patch -p1 -wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/c1674ad.patch | patch -p1 +#wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/c1674ad.patch | patch -p1 wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/5bbf6e7.patch | patch -p1 wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/323fbf0.patch | patch -p1 popd @@ -284,10 +286,15 @@ sed -i 's,default n,default y,g' Makefile sed -i 's,Xray:xray ,Xray:xray-core ,g' Makefile sed -i '/V2ray:v2ray/d' Makefile sed -i '/plugin:v2ray/d' Makefile +sed -i '/Proxy:naive/d' Makefile sed -i '/result.encrypt_method/a\result.fast_open = "1"' root/usr/share/shadowsocksr/subscribe.lua sed -i 's,ispip.clang.cn/all_cn,cdn.jsdelivr.net/gh/QiuSimons/Chnroute@master/dist/chnroute/chnroute,' root/etc/init.d/shadowsocksr sed -i 's,YW5vbnltb3Vz/domain-list-community/release/gfwlist.txt,Loyalsoldier/v2ray-rules-dat/release/gfw.txt,' root/etc/init.d/shadowsocksr sed -i '/Clang.CN.CIDR/a\o:value("https://cdn.jsdelivr.net/gh/QiuSimons/Chnroute@master/dist/chnroute/chnroute.txt", translate("QiuSimons/Chnroute"))' luasrc/model/cbi/shadowsocksr/advanced.lua + +sed -i 's/443 -j RETURN/443 -j DROP/' root/usr/bin/ssr-rules +sed -i 's/80 -j RETURN/80 -j DROP/' root/usr/bin/ssr-rules + popd # 订阅转换 svn co https://github.com/immortalwrt/packages/trunk/net/subconverter feeds/packages/net/subconverter diff --git a/SCRIPTS/X86/02_target_only.sh b/SCRIPTS/X86/02_target_only.sh index b721cf3f8..90f46fee1 100644 --- a/SCRIPTS/X86/02_target_only.sh +++ b/SCRIPTS/X86/02_target_only.sh @@ -8,6 +8,20 @@ sed -i '/Rust:/d' package/lean/luci-app-ssr-plus/Makefile sed -i '/Rust:/d' package/new/luci-app-passwall/Makefile sed -i '/Rust:/d' package/lean/luci-app-vssr/Makefile +# 内核加解密组件 +echo ' +CONFIG_CRYPTO_AES_NI_INTEL=y +' >> ./target/linux/x86/64/config-5.4 + +# MPTCP +echo ' +CONFIG_MPTCP=y +CONFIG_MPTCP_PM_ADVANCED=y +CONFIG_MPTCP_FULLMESH=y +CONFIG_DEFAULT_FULLMESH=y +CONFIG_DEFAULT_MPTCP_PM="fullmesh" +' >> ./target/linux/x86/64/config-5.4 + #Vermagic latest_version="$(curl -s https://github.com/openwrt/openwrt/releases |grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" |sed -n '/21/p' |sed -n 1p |sed 's/v//g' |sed 's/.tar.gz//g')" wget https://downloads.openwrt.org/releases/${latest_version}/targets/x86/64/packages/Packages.gz @@ -21,4 +35,4 @@ chmod -R 755 ./ find ./ -name *.orig | xargs rm -f find ./ -name *.rej | xargs rm -f -exit 0 +exit 0 \ No newline at end of file From 45c8ad421a1bb996dbe074b458167bfe6bd8d6d5 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 14 Jul 2021 12:21:24 +0800 Subject: [PATCH 161/244] MPTCP --- SCRIPTS/02_prepare_package.sh | 13 ++++++++++-- SCRIPTS/R2S/02_target_only.sh | 37 ++++++++++++++--------------------- SCRIPTS/R4S/02_target_only.sh | 34 ++++++++++++++------------------ 3 files changed, 41 insertions(+), 43 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 5309684d9..e3a5ae6e1 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -22,12 +22,16 @@ sed -i '/unshift/d' scripts/download.pl sed -i '/mirror02/d' scripts/download.pl echo "net.netfilter.nf_conntrack_helper = 1" >> ./package/kernel/linux/files/sysctl-nf-conntrack.conf -#临时补丁 +# 临时补丁 #wget -qO - https://github.com/openwrt/openwrt/commit/7fae64.patch | patch -p1 +# MPTCP +wget -P target/linux/generic/hack-5.4/ https://github.com/Ysurac/openmptcprouter/raw/develop/root/target/linux/generic/hack-5.4/690-mptcp_trunk.patch +wget -P target/linux/generic/hack-5.4/ https://github.com/Ysurac/openmptcprouter/raw/develop/root/target/linux/generic/hack-5.4/998-ndpi-netfilter.patch + ### 必要的 Patches ### # Patch arm64 型号名称 -wget -P target/linux/generic/pending-5.4/ https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/generic/hack-5.4/312-arm64-cpuinfo-Add-model-name-in-proc-cpuinfo-for-64bit-ta.patch +wget -P target/linux/generic/hack-5.4/ https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/generic/hack-5.4/312-arm64-cpuinfo-Add-model-name-in-proc-cpuinfo-for-64bit-ta.patch # Patch jsonc patch -p1 < ../PATCH/jsonc/use_json_object_new_int64.patch # Patch dnsmasq @@ -345,6 +349,11 @@ rm -rf ./feeds/packages/net/zerotier/files/etc/init.d/zerotier # 翻译及部分功能优化 svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/addition-trans-zh package/lean/lean-translate +# MPTCP +echo ' +CONFIG_CRYPTO_SHA256=y +' >> ./target/linux/generic/config-5.4 + ### 最后的收尾工作 ### # Lets Fuck mkdir package/base-files/files/usr/bin diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index d6becb049..72ddf9ead 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -37,29 +37,22 @@ sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic # 内核加解密组件 echo ' +CONFIG_CRYPTO_HW=y CONFIG_ARM64_CRYPTO=y -CONFIG_ARM_PSCI_CPUIDLE_DOMAIN=y -CONFIG_ARM_PSCI_FW=y -CONFIG_ARM_RK3328_DMC_DEVFREQ=y -CONFIG_CRYPTO_AES_ARM64=y -CONFIG_CRYPTO_AES_ARM64_BS=y -CONFIG_CRYPTO_AES_ARM64_CE=y -CONFIG_CRYPTO_AES_ARM64_CE_BLK=y -CONFIG_CRYPTO_AES_ARM64_CE_CCM=y -CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y -CONFIG_CRYPTO_CHACHA20_NEON=y -# CONFIG_CRYPTO_CRCT10DIF_ARM64_CE is not set -CONFIG_CRYPTO_GHASH_ARM64_CE=y -CONFIG_CRYPTO_NHPOLY1305_NEON=y -CONFIG_CRYPTO_POLY1305_NEON=y -CONFIG_CRYPTO_SHA1_ARM64_CE=y -CONFIG_CRYPTO_SHA2_ARM64_CE=y -CONFIG_CRYPTO_SHA256_ARM64=y -CONFIG_CRYPTO_SHA3_ARM64=y -CONFIG_CRYPTO_SHA512_ARM64=y -# CONFIG_CRYPTO_SHA512_ARM64_CE is not set -CONFIG_CRYPTO_SM3_ARM64_CE=y -CONFIG_CRYPTO_SM4_ARM64_CE=y +CONFIG_CRYPTO_SHA1_ARM_CE=y +CONFIG_CRYPTO_SHA2_ARM_CE=y +CONFIG_CRYPTO_GHASH_ARM_CE=y +CONFIG_CRYPTO_AES_ARM=y +CONFIG_CRYPTO_AES_ARM_CE=y +' >> ./target/linux/rockchip/armv8/config-5.4 + +# MPTCP +echo ' +CONFIG_MPTCP=y +CONFIG_MPTCP_PM_ADVANCED=y +CONFIG_MPTCP_FULLMESH=y +CONFIG_DEFAULT_FULLMESH=y +CONFIG_DEFAULT_MPTCP_PM="fullmesh" ' >> ./target/linux/rockchip/armv8/config-5.4 # 预配置一些插件 diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index 8a64bd1b2..c5cda811b 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -40,26 +40,22 @@ wget -P package/kernel/linux/modules/ https://github.com/immortalwrt/immortalwrt # 内核加解密模块 echo ' +CONFIG_CRYPTO_HW=y CONFIG_ARM64_CRYPTO=y -CONFIG_CRYPTO_SHA256_ARM64=y -CONFIG_CRYPTO_SHA512_ARM64=y -CONFIG_CRYPTO_SHA1_ARM64_CE=y -CONFIG_CRYPTO_SHA2_ARM64_CE=y -# CONFIG_CRYPTO_SHA512_ARM64_CE is not set -CONFIG_CRYPTO_SHA3_ARM64=y -CONFIG_CRYPTO_SM3_ARM64_CE=y -CONFIG_CRYPTO_SM4_ARM64_CE=y -CONFIG_CRYPTO_GHASH_ARM64_CE=y -# CONFIG_CRYPTO_CRCT10DIF_ARM64_CE is not set -CONFIG_CRYPTO_AES_ARM64=y -CONFIG_CRYPTO_AES_ARM64_CE=y -CONFIG_CRYPTO_AES_ARM64_CE_CCM=y -CONFIG_CRYPTO_AES_ARM64_CE_BLK=y -CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y -CONFIG_CRYPTO_CHACHA20_NEON=y -CONFIG_CRYPTO_POLY1305_NEON=y -CONFIG_CRYPTO_NHPOLY1305_NEON=y -CONFIG_CRYPTO_AES_ARM64_BS=y +CONFIG_CRYPTO_SHA1_ARM_CE=y +CONFIG_CRYPTO_SHA2_ARM_CE=y +CONFIG_CRYPTO_GHASH_ARM_CE=y +CONFIG_CRYPTO_AES_ARM=y +CONFIG_CRYPTO_AES_ARM_CE=y +' >> ./target/linux/rockchip/armv8/config-5.4 + +# MPTCP +echo ' +CONFIG_MPTCP=y +CONFIG_MPTCP_PM_ADVANCED=y +CONFIG_MPTCP_FULLMESH=y +CONFIG_DEFAULT_FULLMESH=y +CONFIG_DEFAULT_MPTCP_PM="fullmesh" ' >> ./target/linux/rockchip/armv8/config-5.4 #Vermagic From d14b2d31b85b0d17c66f124a2c92cd12adfe1339 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 14 Jul 2021 14:09:28 +0800 Subject: [PATCH 162/244] BBRv2 --- SCRIPTS/02_prepare_package.sh | 7 +++++++ SCRIPTS/R2S/02_target_only.sh | 7 ------- SCRIPTS/R4S/02_target_only.sh | 7 ------- SEED/R2S/config.seed | 35 +++++++++-------------------------- SEED/R4S/config.seed | 35 +++++++++-------------------------- SEED/X86/config.seed | 4 ++++ 6 files changed, 29 insertions(+), 66 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index e3a5ae6e1..bace81beb 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -29,6 +29,13 @@ echo "net.netfilter.nf_conntrack_helper = 1" >> ./package/kernel/linux/files/sys wget -P target/linux/generic/hack-5.4/ https://github.com/Ysurac/openmptcprouter/raw/develop/root/target/linux/generic/hack-5.4/690-mptcp_trunk.patch wget -P target/linux/generic/hack-5.4/ https://github.com/Ysurac/openmptcprouter/raw/develop/root/target/linux/generic/hack-5.4/998-ndpi-netfilter.patch +# BBRv2 +wget -P target/linux/generic/hack-5.4/ https://github.com/Ysurac/openmptcprouter/raw/develop/root/target/linux/generic/hack-5.4/692-tcp_nanqinlang.patch +wget -P target/linux/generic/hack-5.4/ https://github.com/Ysurac/openmptcprouter/raw/develop/root/target/linux/generic/hack-5.4/693-tcp_bbr2.patch +wget https://github.com/google/bbr/commit/3d76056.patch -O target/linux/generic/hack-5.4/694-tcp_bbr2.patch +wget -qO - https://github.com/Ysurac/openmptcprouter/raw/develop/patches/nanqinlang.patch | patch -p1 +wget -qO - https://github.com/Ysurac/openmptcprouter/raw/develop/patches/bbr2.patch | patch -p1 + ### 必要的 Patches ### # Patch arm64 型号名称 wget -P target/linux/generic/hack-5.4/ https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/generic/hack-5.4/312-arm64-cpuinfo-Add-model-name-in-proc-cpuinfo-for-64bit-ta.patch diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index 72ddf9ead..ff6e8846c 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -37,13 +37,6 @@ sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic # 内核加解密组件 echo ' -CONFIG_CRYPTO_HW=y -CONFIG_ARM64_CRYPTO=y -CONFIG_CRYPTO_SHA1_ARM_CE=y -CONFIG_CRYPTO_SHA2_ARM_CE=y -CONFIG_CRYPTO_GHASH_ARM_CE=y -CONFIG_CRYPTO_AES_ARM=y -CONFIG_CRYPTO_AES_ARM_CE=y ' >> ./target/linux/rockchip/armv8/config-5.4 # MPTCP diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index c5cda811b..a8565f747 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -40,13 +40,6 @@ wget -P package/kernel/linux/modules/ https://github.com/immortalwrt/immortalwrt # 内核加解密模块 echo ' -CONFIG_CRYPTO_HW=y -CONFIG_ARM64_CRYPTO=y -CONFIG_CRYPTO_SHA1_ARM_CE=y -CONFIG_CRYPTO_SHA2_ARM_CE=y -CONFIG_CRYPTO_GHASH_ARM_CE=y -CONFIG_CRYPTO_AES_ARM=y -CONFIG_CRYPTO_AES_ARM_CE=y ' >> ./target/linux/rockchip/armv8/config-5.4 # MPTCP diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 5af5b7435..5fa9a4142 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -147,32 +147,15 @@ CONFIG_PACKAGE_kmod-usb-net-rndis=y CONFIG_PACKAGE_kmod-usb-net-ipheth=y ### CRYPTO ### -CONFIG_PACKAGE_kmod-crypto-acompress=y -CONFIG_PACKAGE_kmod-crypto-aead=y -CONFIG_PACKAGE_kmod-crypto-authenc=y -CONFIG_PACKAGE_kmod-crypto-cbc=y -CONFIG_PACKAGE_kmod-crypto-crc32c=y -CONFIG_PACKAGE_kmod-crypto-ctr=y -CONFIG_PACKAGE_kmod-crypto-deflate=y -CONFIG_PACKAGE_kmod-crypto-des=y -CONFIG_PACKAGE_kmod-crypto-ecb=y -CONFIG_PACKAGE_kmod-crypto-echainiv=y -CONFIG_PACKAGE_kmod-crypto-gcm=y -CONFIG_PACKAGE_kmod-crypto-gf128=y -CONFIG_PACKAGE_kmod-crypto-ghash=y -CONFIG_PACKAGE_kmod-crypto-hash=y -CONFIG_PACKAGE_kmod-crypto-hmac=y -CONFIG_PACKAGE_kmod-crypto-iv=y -CONFIG_PACKAGE_kmod-crypto-manager=y -CONFIG_PACKAGE_kmod-crypto-md5=y -CONFIG_PACKAGE_kmod-crypto-null=y -CONFIG_PACKAGE_kmod-crypto-pcompress=y -CONFIG_PACKAGE_kmod-crypto-rng=y -CONFIG_PACKAGE_kmod-crypto-seqiv=y -CONFIG_PACKAGE_kmod-crypto-sha1=y -CONFIG_PACKAGE_kmod-crypto-sha256=y -CONFIG_PACKAGE_kmod-crypto-wq=y -CONFIG_PACKAGE_kmod-cryptodev=y +CONFIG_KERNEL_ARM_MODULE_PLTS=y +CONFIG_KERNEL_TCP_CONG_BBR2=y +CONFIG_CRYPTO_HW=y +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM_CE=y +CONFIG_CRYPTO_SHA2_ARM_CE=y +CONFIG_CRYPTO_GHASH_ARM_CE=y +CONFIG_CRYPTO_AES_ARM=y +CONFIG_CRYPTO_AES_ARM_CE=y ### OPENSSL ### CONFIG_OPENSSL_ENGINE=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index 68eeb1ea3..6674683b4 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -141,32 +141,15 @@ CONFIG_PACKAGE_kmod-usb-net-rndis=y CONFIG_PACKAGE_kmod-usb-net-ipheth=y ### CRYPTO ### -CONFIG_PACKAGE_kmod-crypto-acompress=y -CONFIG_PACKAGE_kmod-crypto-aead=y -CONFIG_PACKAGE_kmod-crypto-authenc=y -CONFIG_PACKAGE_kmod-crypto-cbc=y -CONFIG_PACKAGE_kmod-crypto-crc32c=y -CONFIG_PACKAGE_kmod-crypto-ctr=y -CONFIG_PACKAGE_kmod-crypto-deflate=y -CONFIG_PACKAGE_kmod-crypto-des=y -CONFIG_PACKAGE_kmod-crypto-ecb=y -CONFIG_PACKAGE_kmod-crypto-echainiv=y -CONFIG_PACKAGE_kmod-crypto-gcm=y -CONFIG_PACKAGE_kmod-crypto-gf128=y -CONFIG_PACKAGE_kmod-crypto-ghash=y -CONFIG_PACKAGE_kmod-crypto-hash=y -CONFIG_PACKAGE_kmod-crypto-hmac=y -CONFIG_PACKAGE_kmod-crypto-iv=y -CONFIG_PACKAGE_kmod-crypto-manager=y -CONFIG_PACKAGE_kmod-crypto-md5=y -CONFIG_PACKAGE_kmod-crypto-null=y -CONFIG_PACKAGE_kmod-crypto-pcompress=y -CONFIG_PACKAGE_kmod-crypto-rng=y -CONFIG_PACKAGE_kmod-crypto-seqiv=y -CONFIG_PACKAGE_kmod-crypto-sha1=y -CONFIG_PACKAGE_kmod-crypto-sha256=y -CONFIG_PACKAGE_kmod-crypto-wq=y -CONFIG_PACKAGE_kmod-cryptodev=y +CONFIG_KERNEL_ARM_MODULE_PLTS=y +CONFIG_KERNEL_TCP_CONG_BBR2=y +CONFIG_CRYPTO_HW=y +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM_CE=y +CONFIG_CRYPTO_SHA2_ARM_CE=y +CONFIG_CRYPTO_GHASH_ARM_CE=y +CONFIG_CRYPTO_AES_ARM=y +CONFIG_CRYPTO_AES_ARM_CE=y ### OPENSSL ### CONFIG_OPENSSL_ENGINE=y diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index 1591b59a6..ac92824ad 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -7,6 +7,7 @@ CONFIG_TARGET_x86_64_Generic=y CONFIG_TARGET_ROOTFS_PARTSIZE=960 CONFIG_GRUB_TIMEOUT="0" # CONFIG_COLLECT_KERNEL_DEBUG is not set +CONFIG_CRYPTO_AES_NI_INTEL=y ### AGGRESSIVE ### CONFIG_PACKAGE_node=y @@ -137,6 +138,9 @@ CONFIG_PACKAGE_usbmuxd=y CONFIG_PACKAGE_kmod-usb-net-rndis=y CONFIG_PACKAGE_kmod-usb-net-ipheth=y +### BBRv2 ### +CONFIG_PACKAGE_kmod-tcp-bbr2=y + ### OPENSSL ### CONFIG_OPENSSL_ENGINE=y CONFIG_OPENSSL_OPTIMIZE_SPEED=y From ddbc3c02a5b8de9a5cc6450254aae49ba79962d6 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 15 Jul 2021 15:14:25 +0800 Subject: [PATCH 163/244] GCC11 --- SCRIPTS/02_prepare_package.sh | 29 +++++++++++++++++------------ SEED/R2S/config.seed | 17 ++++------------- SEED/R4S/config.seed | 17 ++++------------- SEED/X86/config.seed | 5 ++--- 4 files changed, 27 insertions(+), 41 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index bace81beb..d5fc67d2e 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -22,12 +22,22 @@ sed -i '/unshift/d' scripts/download.pl sed -i '/mirror02/d' scripts/download.pl echo "net.netfilter.nf_conntrack_helper = 1" >> ./package/kernel/linux/files/sysctl-nf-conntrack.conf -# 临时补丁 -#wget -qO - https://github.com/openwrt/openwrt/commit/7fae64.patch | patch -p1 +# GCC11 +rm -rf ./toolchain/gcc +svn co https://github.com/openwrt/openwrt/trunk/toolchain/gcc toolchain/gcc +rm -rf ./package/network/utils/bpftools +svn co https://github.com/openwrt/openwrt/trunk/package/network/utils/bpftools package/network/utils/bpftools +rm -rf ./package/libs/elfutils +svn co https://github.com/neheb/openwrt/branches/elf/package/libs/elfutils package/libs/elfutils +rm -rf ./feeds/packages/libs/dtc +svn co https://github.com/openwrt/packages/trunk/libs/dtc feeds/packages/libs/dtc # MPTCP wget -P target/linux/generic/hack-5.4/ https://github.com/Ysurac/openmptcprouter/raw/develop/root/target/linux/generic/hack-5.4/690-mptcp_trunk.patch wget -P target/linux/generic/hack-5.4/ https://github.com/Ysurac/openmptcprouter/raw/develop/root/target/linux/generic/hack-5.4/998-ndpi-netfilter.patch +echo ' +CONFIG_CRYPTO_SHA256=y +' >> ./target/linux/generic/config-5.4 # BBRv2 wget -P target/linux/generic/hack-5.4/ https://github.com/Ysurac/openmptcprouter/raw/develop/root/target/linux/generic/hack-5.4/692-tcp_nanqinlang.patch @@ -36,6 +46,9 @@ wget https://github.com/google/bbr/commit/3d76056.patch -O target/linux/generic/ wget -qO - https://github.com/Ysurac/openmptcprouter/raw/develop/patches/nanqinlang.patch | patch -p1 wget -qO - https://github.com/Ysurac/openmptcprouter/raw/develop/patches/bbr2.patch | patch -p1 +# OPENSSL +wget -qO - https://github.com/mj22226/openwrt/commit/5e1063.patch | patch -p1 + ### 必要的 Patches ### # Patch arm64 型号名称 wget -P target/linux/generic/hack-5.4/ https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/generic/hack-5.4/312-arm64-cpuinfo-Add-model-name-in-proc-cpuinfo-for-64bit-ta.patch @@ -229,7 +242,7 @@ svn co https://github.com/xiaorouji/openwrt-passwall/trunk/luci-app-passwall pac sed -i 's,default n,default y,g' package/new/luci-app-passwall/Makefile sed -i '/V2ray:v2ray/d' package/new/luci-app-passwall/Makefile sed -i '/plugin:v2ray/d' package/new/luci-app-passwall/Makefile -sed -i '/Proxy:naive/d' package/new/luci-app-passwall/Makefile +#sed -i '/Proxy:naive/d' package/new/luci-app-passwall/Makefile wget -P package/new/luci-app-passwall/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/move_2_services.sh chmod -R 755 ./package/new/luci-app-passwall/move_2_services.sh pushd package/new/luci-app-passwall @@ -297,15 +310,12 @@ sed -i 's,default n,default y,g' Makefile sed -i 's,Xray:xray ,Xray:xray-core ,g' Makefile sed -i '/V2ray:v2ray/d' Makefile sed -i '/plugin:v2ray/d' Makefile -sed -i '/Proxy:naive/d' Makefile +#sed -i '/Proxy:naive/d' Makefile sed -i '/result.encrypt_method/a\result.fast_open = "1"' root/usr/share/shadowsocksr/subscribe.lua sed -i 's,ispip.clang.cn/all_cn,cdn.jsdelivr.net/gh/QiuSimons/Chnroute@master/dist/chnroute/chnroute,' root/etc/init.d/shadowsocksr sed -i 's,YW5vbnltb3Vz/domain-list-community/release/gfwlist.txt,Loyalsoldier/v2ray-rules-dat/release/gfw.txt,' root/etc/init.d/shadowsocksr sed -i '/Clang.CN.CIDR/a\o:value("https://cdn.jsdelivr.net/gh/QiuSimons/Chnroute@master/dist/chnroute/chnroute.txt", translate("QiuSimons/Chnroute"))' luasrc/model/cbi/shadowsocksr/advanced.lua -sed -i 's/443 -j RETURN/443 -j DROP/' root/usr/bin/ssr-rules -sed -i 's/80 -j RETURN/80 -j DROP/' root/usr/bin/ssr-rules - popd # 订阅转换 svn co https://github.com/immortalwrt/packages/trunk/net/subconverter feeds/packages/net/subconverter @@ -356,11 +366,6 @@ rm -rf ./feeds/packages/net/zerotier/files/etc/init.d/zerotier # 翻译及部分功能优化 svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/addition-trans-zh package/lean/lean-translate -# MPTCP -echo ' -CONFIG_CRYPTO_SHA256=y -' >> ./target/linux/generic/config-5.4 - ### 最后的收尾工作 ### # Lets Fuck mkdir package/base-files/files/usr/bin diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 5fa9a4142..0aeecbdaa 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -13,7 +13,7 @@ CONFIG_NODEJS_14=y CONFIG_NODEJS_ICU_NONE=y CONFIG_DEVEL=y CONFIG_TOOLCHAINOPTS=y -CONFIG_GCC_USE_VERSION_9=y +CONFIG_GCC_USE_VERSION_11=y ### BASIC ### CONFIG_PACKAGE_r8169-firmware=y @@ -124,7 +124,7 @@ CONFIG_PACKAGE_luci-app-zerotier=y CONFIG_PACKAGE_zerotier=y CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y -CONFIG_PACKAGE_subconverter=y +#CONFIG_PACKAGE_subconverter=y CONFIG_PACKAGE_dnsproxy=y CONFIG_PACKAGE_luci-app-dnsfilter=y @@ -146,21 +146,12 @@ CONFIG_PACKAGE_usbmuxd=y CONFIG_PACKAGE_kmod-usb-net-rndis=y CONFIG_PACKAGE_kmod-usb-net-ipheth=y -### CRYPTO ### -CONFIG_KERNEL_ARM_MODULE_PLTS=y -CONFIG_KERNEL_TCP_CONG_BBR2=y -CONFIG_CRYPTO_HW=y -CONFIG_ARM64_CRYPTO=y -CONFIG_CRYPTO_SHA1_ARM_CE=y -CONFIG_CRYPTO_SHA2_ARM_CE=y -CONFIG_CRYPTO_GHASH_ARM_CE=y -CONFIG_CRYPTO_AES_ARM=y -CONFIG_CRYPTO_AES_ARM_CE=y +### BBRv2 ### +CONFIG_PACKAGE_kmod-tcp-bbr2=y ### OPENSSL ### CONFIG_OPENSSL_ENGINE=y CONFIG_OPENSSL_OPTIMIZE_SPEED=y -CONFIG_OPENSSL_PREFER_CHACHA_OVER_GCM=y CONFIG_OPENSSL_WITH_ASM=y # CONFIG_OPENSSL_WITH_ERROR_MESSAGES is not set CONFIG_PACKAGE_libopenssl-devcrypto=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index 6674683b4..2e295b86a 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -13,7 +13,7 @@ CONFIG_NODEJS_14=y CONFIG_NODEJS_ICU_NONE=y CONFIG_DEVEL=y CONFIG_TOOLCHAINOPTS=y -CONFIG_GCC_USE_VERSION_9=y +CONFIG_GCC_USE_VERSION_11=y ### BASIC ### CONFIG_PACKAGE_r8169-firmware=y @@ -124,7 +124,7 @@ CONFIG_PACKAGE_luci-app-zerotier=y CONFIG_PACKAGE_zerotier=y CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y -CONFIG_PACKAGE_subconverter=y +#CONFIG_PACKAGE_subconverter=y CONFIG_PACKAGE_dnsproxy=y CONFIG_PACKAGE_luci-app-dnsfilter=y @@ -140,21 +140,12 @@ CONFIG_PACKAGE_usbmuxd=y CONFIG_PACKAGE_kmod-usb-net-rndis=y CONFIG_PACKAGE_kmod-usb-net-ipheth=y -### CRYPTO ### -CONFIG_KERNEL_ARM_MODULE_PLTS=y -CONFIG_KERNEL_TCP_CONG_BBR2=y -CONFIG_CRYPTO_HW=y -CONFIG_ARM64_CRYPTO=y -CONFIG_CRYPTO_SHA1_ARM_CE=y -CONFIG_CRYPTO_SHA2_ARM_CE=y -CONFIG_CRYPTO_GHASH_ARM_CE=y -CONFIG_CRYPTO_AES_ARM=y -CONFIG_CRYPTO_AES_ARM_CE=y +### BBRv2 ### +CONFIG_PACKAGE_kmod-tcp-bbr2=y ### OPENSSL ### CONFIG_OPENSSL_ENGINE=y CONFIG_OPENSSL_OPTIMIZE_SPEED=y -CONFIG_OPENSSL_PREFER_CHACHA_OVER_GCM=y CONFIG_OPENSSL_WITH_ASM=y # CONFIG_OPENSSL_WITH_ERROR_MESSAGES is not set CONFIG_PACKAGE_libopenssl-devcrypto=y diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index ac92824ad..a5492f327 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -7,7 +7,6 @@ CONFIG_TARGET_x86_64_Generic=y CONFIG_TARGET_ROOTFS_PARTSIZE=960 CONFIG_GRUB_TIMEOUT="0" # CONFIG_COLLECT_KERNEL_DEBUG is not set -CONFIG_CRYPTO_AES_NI_INTEL=y ### AGGRESSIVE ### CONFIG_PACKAGE_node=y @@ -15,7 +14,7 @@ CONFIG_NODEJS_14=y CONFIG_NODEJS_ICU_NONE=y CONFIG_DEVEL=y CONFIG_TOOLCHAINOPTS=y -CONFIG_GCC_USE_VERSION_9=y +CONFIG_GCC_USE_VERSION_11=y ### BASIC ### CONFIG_PACKAGE_addition-trans-zh=y @@ -125,7 +124,7 @@ CONFIG_PACKAGE_luci-app-zerotier=y CONFIG_PACKAGE_zerotier=y CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y -CONFIG_PACKAGE_subconverter=y +#CONFIG_PACKAGE_subconverter=y CONFIG_PACKAGE_dnsproxy=y CONFIG_PACKAGE_luci-app-dnsfilter=y From b69f2bacf067986ac2fbcafab79ab5983989bff4 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 21 Jul 2021 17:22:36 +0800 Subject: [PATCH 164/244] Update 02_prepare_package.sh Update 02_prepare_package.sh Update config.seed Update config.seed Update config.seed Update README.md --- README.md | 2 +- SCRIPTS/02_prepare_package.sh | 4 ++-- SEED/R2S/config.seed | 2 +- SEED/R4S/config.seed | 2 +- SEED/X86/config.seed | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 4f9051c71..200d40975 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ - 基于原生 OpenWrt 21.02 编译,默认管理地址192.168.1.1 - 同时支持 SFE/Software Offload (选则其一开启,默认开启SFE) - 内置升级功能可用,物理 Reset 按键可用 -- 预配置了部分插件(包括但不限于 DNS 套娃,(注意,6月29日开始取消了dns套娃,使用dnsfilter作为广告过滤手段,使用dnsproxy作为dns分流措施,海外端口5335,国内端口6050,无GUI,自行琢磨使用。或可尝试ssh进入后台,输入setdns后回车,使用预设的dns方案,升级固件或fuck后,请重新setdns) +- 预配置了部分插件(包括但不限于 DNS 套娃,(注意,6月29日开始取消了dns套娃,使用dnsfilter作为广告过滤手段,使用dnsproxy作为dns分流措施,海外端口5335,国内端口6050。) - 正式 Release 版本将具有可无脑 opkg kmod 的特性 - R2S核心频率1.6(交换了LAN WAN),R4S核心频率2.2/1.8(建议使用5v4a电源,死机大多数情况下,都是因为你用的电源过于垃圾,另外,你也可以选择使用自带的app限制最大频率,茄子🍆) - O3 编译 diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index d5fc67d2e..09f6a5dc2 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -185,7 +185,7 @@ git clone --depth 1 https://github.com/garypang13/luci-app-dnsfilter.git package # Dnsproxy svn co https://github.com/immortalwrt/packages/trunk/net/dnsproxy feeds/packages/net/dnsproxy ln -sf ../../../feeds/packages/net/dnsproxy ./package/feeds/packages/dnsproxy -wget -P package/base-files/files/etc/init.d/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/dnsproxy +svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/luci-app-dnsproxy package/new/luci-app-dnsproxy # Edge 主题 git clone -b master --depth 1 https://github.com/garypang13/luci-theme-edge.git package/new/luci-theme-edge # FRP 内网穿透 @@ -371,7 +371,7 @@ svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/addition-trans-zh package/ mkdir package/base-files/files/usr/bin wget -P package/base-files/files/usr/bin/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/fuck wget -P package/base-files/files/usr/bin/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/chinadnslist -wget -P package/base-files/files/usr/bin/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/setdns +#wget -P package/base-files/files/usr/bin/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/setdns # 最大连接数 sed -i 's/16384/65535/g' package/kernel/linux/files/sysctl-nf-conntrack.conf # 生成默认配置及缓存 diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 0aeecbdaa..09e712054 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -101,7 +101,7 @@ CONFIG_PACKAGE_frpc=y CONFIG_PACKAGE_luci-app-frps=y CONFIG_PACKAGE_frps=y CONFIG_PACKAGE_luci-app-jd-dailybonus=y -#CONFIG_PACKAGE_luci-app-mosdns=y +CONFIG_PACKAGE_luci-app-dnsproxy=y CONFIG_PACKAGE_luci-app-oled=y CONFIG_PACKAGE_luci-app-openclash=y CONFIG_PACKAGE_luci-app-opkg=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index 2e295b86a..b3c26e343 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -102,7 +102,7 @@ CONFIG_PACKAGE_frpc=y CONFIG_PACKAGE_luci-app-frps=y CONFIG_PACKAGE_frps=y CONFIG_PACKAGE_luci-app-jd-dailybonus=y -#CONFIG_PACKAGE_luci-app-mosdns=y +CONFIG_PACKAGE_luci-app-dnsproxy=y CONFIG_PACKAGE_luci-app-openclash=y CONFIG_PACKAGE_luci-app-opkg=y #CONFIG_PACKAGE_luci-app-qbittorrent=y diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index a5492f327..4115050a4 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -102,7 +102,7 @@ CONFIG_PACKAGE_frpc=y CONFIG_PACKAGE_luci-app-frps=y CONFIG_PACKAGE_frps=y CONFIG_PACKAGE_luci-app-jd-dailybonus=y -#CONFIG_PACKAGE_luci-app-mosdns=y +CONFIG_PACKAGE_luci-app-dnsproxy=y CONFIG_PACKAGE_luci-app-openclash=y CONFIG_PACKAGE_luci-app-opkg=y #CONFIG_PACKAGE_luci-app-qbittorrent=y From b05eb7af4b330d60e96d4e0036b3eb97957410cd Mon Sep 17 00:00:00 2001 From: Topsy Chen <62056970+thomaswcy@users.noreply.github.com> Date: Thu, 22 Jul 2021 15:04:12 +0800 Subject: [PATCH 165/244] Add USB3.0 Support for R2S MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 我用中文来说吧。众所周知,r2s的一个网口是usb3转接的,而大多数固件只打了usb2的驱动。 --- SEED/R2S/config.seed | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 09e712054..828ca2495 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -42,6 +42,9 @@ CONFIG_PACKAGE_kmod-ipt-nat6=y CONFIG_PACKAGE_kmod-tun=y CONFIG_PACKAGE_kmod-shortcut-fe=y CONFIG_PACKAGE_kmod-fast-classifier=y +CONFIG_PACKAGE_kmod-usb2=y +CONFIG_PACKAGE_kmod-usb2-pci=y +CONFIG_PACKAGE_kmod-usb3=y # CONFIG_PACKAGE_kmod-shortcut-fe-cm is not set CONFIG_PACKAGE_libiwinfo=y CONFIG_PACKAGE_libiwinfo-lua=y From 0574b39a75659b6a94158609b2b786b84de63e66 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 23 Jul 2021 14:54:35 +0800 Subject: [PATCH 166/244] Revert MPTCP --- SCRIPTS/02_prepare_package.sh | 10 +++++----- SCRIPTS/R2S/02_target_only.sh | 14 +++++++------- SCRIPTS/R4S/02_target_only.sh | 14 +++++++------- SCRIPTS/X86/02_target_only.sh | 16 ++++++++-------- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 09f6a5dc2..0935fdc34 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -33,11 +33,11 @@ rm -rf ./feeds/packages/libs/dtc svn co https://github.com/openwrt/packages/trunk/libs/dtc feeds/packages/libs/dtc # MPTCP -wget -P target/linux/generic/hack-5.4/ https://github.com/Ysurac/openmptcprouter/raw/develop/root/target/linux/generic/hack-5.4/690-mptcp_trunk.patch -wget -P target/linux/generic/hack-5.4/ https://github.com/Ysurac/openmptcprouter/raw/develop/root/target/linux/generic/hack-5.4/998-ndpi-netfilter.patch -echo ' -CONFIG_CRYPTO_SHA256=y -' >> ./target/linux/generic/config-5.4 +#wget -P target/linux/generic/hack-5.4/ https://github.com/Ysurac/openmptcprouter/raw/develop/root/target/linux/generic/hack-5.4/690-mptcp_trunk.patch +#wget -P target/linux/generic/hack-5.4/ https://github.com/Ysurac/openmptcprouter/raw/develop/root/target/linux/generic/hack-5.4/998-ndpi-netfilter.patch +#echo ' +#CONFIG_CRYPTO_SHA256=y +#' >> ./target/linux/generic/config-5.4 # BBRv2 wget -P target/linux/generic/hack-5.4/ https://github.com/Ysurac/openmptcprouter/raw/develop/root/target/linux/generic/hack-5.4/692-tcp_nanqinlang.patch diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index ff6e8846c..ef617e961 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -40,13 +40,13 @@ echo ' ' >> ./target/linux/rockchip/armv8/config-5.4 # MPTCP -echo ' -CONFIG_MPTCP=y -CONFIG_MPTCP_PM_ADVANCED=y -CONFIG_MPTCP_FULLMESH=y -CONFIG_DEFAULT_FULLMESH=y -CONFIG_DEFAULT_MPTCP_PM="fullmesh" -' >> ./target/linux/rockchip/armv8/config-5.4 +#echo ' +#CONFIG_MPTCP=y +#CONFIG_MPTCP_PM_ADVANCED=y +#CONFIG_MPTCP_FULLMESH=y +#CONFIG_DEFAULT_FULLMESH=y +#CONFIG_DEFAULT_MPTCP_PM="fullmesh" +#' >> ./target/linux/rockchip/armv8/config-5.4 # 预配置一些插件 cp -rf ../PATCH/files ./files diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index a8565f747..8f3f7edd9 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -43,13 +43,13 @@ echo ' ' >> ./target/linux/rockchip/armv8/config-5.4 # MPTCP -echo ' -CONFIG_MPTCP=y -CONFIG_MPTCP_PM_ADVANCED=y -CONFIG_MPTCP_FULLMESH=y -CONFIG_DEFAULT_FULLMESH=y -CONFIG_DEFAULT_MPTCP_PM="fullmesh" -' >> ./target/linux/rockchip/armv8/config-5.4 +#echo ' +#CONFIG_MPTCP=y +#CONFIG_MPTCP_PM_ADVANCED=y +#CONFIG_MPTCP_FULLMESH=y +#CONFIG_DEFAULT_FULLMESH=y +#CONFIG_DEFAULT_MPTCP_PM="fullmesh" +#' >> ./target/linux/rockchip/armv8/config-5.4 #Vermagic latest_version="$(curl -s https://github.com/openwrt/openwrt/releases |grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" |sed -n '/21/p' |sed -n 1p |sed 's/v//g' |sed 's/.tar.gz//g')" diff --git a/SCRIPTS/X86/02_target_only.sh b/SCRIPTS/X86/02_target_only.sh index 90f46fee1..8695203f3 100644 --- a/SCRIPTS/X86/02_target_only.sh +++ b/SCRIPTS/X86/02_target_only.sh @@ -14,13 +14,13 @@ CONFIG_CRYPTO_AES_NI_INTEL=y ' >> ./target/linux/x86/64/config-5.4 # MPTCP -echo ' -CONFIG_MPTCP=y -CONFIG_MPTCP_PM_ADVANCED=y -CONFIG_MPTCP_FULLMESH=y -CONFIG_DEFAULT_FULLMESH=y -CONFIG_DEFAULT_MPTCP_PM="fullmesh" -' >> ./target/linux/x86/64/config-5.4 +#echo ' +#CONFIG_MPTCP=y +#CONFIG_MPTCP_PM_ADVANCED=y +#CONFIG_MPTCP_FULLMESH=y +#CONFIG_DEFAULT_FULLMESH=y +#CONFIG_DEFAULT_MPTCP_PM="fullmesh" +#' >> ./target/linux/x86/64/config-5.4 #Vermagic latest_version="$(curl -s https://github.com/openwrt/openwrt/releases |grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" |sed -n '/21/p' |sed -n 1p |sed 's/v//g' |sed 's/.tar.gz//g')" @@ -35,4 +35,4 @@ chmod -R 755 ./ find ./ -name *.orig | xargs rm -f find ./ -name *.rej | xargs rm -f -exit 0 \ No newline at end of file +exit 0 From acdf82ed356bb7a9ccc4a3eac6c22d78bb47d4b2 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 23 Jul 2021 17:04:30 +0800 Subject: [PATCH 167/244] BBRv2 --- PATCH/BBRv2/693-tcp_bbr2.patch | 3319 +++++++++++++++++++++++++++ PATCH/BBRv2/openwrt-kmod-bbr2.patch | 37 + SCRIPTS/02_prepare_package.sh | 7 +- 3 files changed, 3358 insertions(+), 5 deletions(-) create mode 100644 PATCH/BBRv2/693-tcp_bbr2.patch create mode 100644 PATCH/BBRv2/openwrt-kmod-bbr2.patch diff --git a/PATCH/BBRv2/693-tcp_bbr2.patch b/PATCH/BBRv2/693-tcp_bbr2.patch new file mode 100644 index 000000000..dc7a9d1b9 --- /dev/null +++ b/PATCH/BBRv2/693-tcp_bbr2.patch @@ -0,0 +1,3319 @@ +From 3d76056b85feab3aade8007eb560c3451e7d3433 Mon Sep 17 00:00:00 2001 +From: Adithya Abraham Philip +Date: Fri, 11 Jun 2021 21:56:10 +0000 +Subject: [PATCH] net-tcp_bbr: v2: Fix missing ECT markings on retransmits for BBRv2 + +Adds a new flag TCP_ECN_ECT_PERMANENT that is used by CCAs to +indicate that retransmitted packets and pure ACKs must have the +ECT bit set. This is a necessary fix for BBRv2, which when using +ECN expects ECT to be set even on retransmitted packets and ACKs. +Currently CCAs like BBRv2 which can use ECN but don't "need" it +do not have a way to indicate that ECT should be set on +retransmissions/ACKs. + +Signed-off-by: Adithya Abraham Philip +Signed-off-by: Neal Cardwell +--- +diff --git a/include/linux/tcp.h b/include/linux/tcp.h +index ca6f01531e64..145b15f5d07e 100644 +--- a/include/linux/tcp.h ++++ b/include/linux/tcp.h +@@ -218,6 +218,7 @@ + u8 compressed_ack; + u8 tlp_retrans:1, /* TLP is a retransmission */ + unused_1:7; ++ u8 fast_ack_mode:2; /* which fast ack mode ? */ + u32 chrono_start; /* Start time in jiffies of a TCP chrono */ + u32 chrono_stat[3]; /* Time in jiffies for chrono_stat stats */ + u8 chrono_type:2, /* current chronograph type */ +diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h +index 895546058a20..1038f192cd09 100644 +--- a/include/net/inet_connection_sock.h ++++ b/include/net/inet_connection_sock.h +@@ -138,8 +138,9 @@ + u32 icsk_probes_tstamp; + u32 icsk_user_timeout; + +- u64 icsk_ca_priv[104 / sizeof(u64)]; +-#define ICSK_CA_PRIV_SIZE (13 * sizeof(u64)) ++/* XXX inflated by temporary internal debugging info */ ++#define ICSK_CA_PRIV_SIZE (216) ++ u64 icsk_ca_priv[ICSK_CA_PRIV_SIZE / sizeof(u64)]; + }; + + #define ICSK_TIME_RETRANS 1 /* Retransmit timer */ +diff --git a/include/net/tcp.h b/include/net/tcp.h +index 36f195fb576a..c28000be002a 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -362,6 +362,7 @@ + #define TCP_ECN_QUEUE_CWR 2 + #define TCP_ECN_DEMAND_CWR 4 + #define TCP_ECN_SEEN 8 ++#define TCP_ECN_ECT_PERMANENT 16 + + enum tcp_tw_status { + TCP_TW_SUCCESS = 0, +@@ -782,6 +783,11 @@ + return max_t(s64, t1 - t0, 0); + } + ++static inline u32 tcp_stamp32_us_delta(u32 t1, u32 t0) ++{ ++ return max_t(s32, t1 - t0, 0); ++} ++ + static inline u32 tcp_skb_timestamp(const struct sk_buff *skb) + { + return div_u64(skb->skb_mstamp_ns, NSEC_PER_SEC / TCP_TS_HZ); +@@ -849,16 +855,22 @@ + __u32 ack_seq; /* Sequence number ACK'd */ + union { + struct { ++#define TCPCB_DELIVERED_CE_MASK ((1U<<20) - 1) + /* There is space for up to 24 bytes */ +- __u32 in_flight:30,/* Bytes in flight at transmit */ +- is_app_limited:1, /* cwnd not fully used? */ +- unused:1; ++ __u32 is_app_limited:1, /* cwnd not fully used? */ ++ delivered_ce:20, ++ unused:11; + /* pkts S/ACKed so far upon tx of skb, incl retrans: */ + __u32 delivered; + /* start of send pipeline phase */ +- u64 first_tx_mstamp; ++ u32 first_tx_mstamp; + /* when we reached the "delivered" count */ +- u64 delivered_mstamp; ++ u32 delivered_mstamp; ++#define TCPCB_IN_FLIGHT_BITS 20 ++#define TCPCB_IN_FLIGHT_MAX ((1U << TCPCB_IN_FLIGHT_BITS) - 1) ++ u32 in_flight:20, /* packets in flight at transmit */ ++ unused2:12; ++ u32 lost; /* packets lost so far upon tx of skb */ + } tx; /* only used for outgoing skbs */ + union { + struct inet_skb_parm h4; +@@ -1002,6 +1014,8 @@ + #define TCP_CONG_NON_RESTRICTED 0x1 + /* Requires ECN/ECT set on all packets */ + #define TCP_CONG_NEEDS_ECN 0x2 ++/* Wants notification of CE events (CA_EVENT_ECN_IS_CE, CA_EVENT_ECN_NO_CE). */ ++#define TCP_CONG_WANTS_CE_EVENTS 0x100000 + + union tcp_cc_info; + +@@ -1021,8 +1035,13 @@ + */ + struct rate_sample { + u64 prior_mstamp; /* starting timestamp for interval */ ++ u32 prior_lost; /* tp->lost at "prior_mstamp" */ + u32 prior_delivered; /* tp->delivered at "prior_mstamp" */ ++ u32 prior_delivered_ce;/* tp->delivered_ce at "prior_mstamp" */ ++ u32 tx_in_flight; /* packets in flight at starting timestamp */ ++ s32 lost; /* number of packets lost over interval */ + s32 delivered; /* number of packets delivered over interval */ ++ s32 delivered_ce; /* packets delivered w/ CE mark over interval */ + long interval_us; /* time for tp->delivered to incr "delivered" */ + u32 snd_interval_us; /* snd interval for delivered packets */ + u32 rcv_interval_us; /* rcv interval for delivered packets */ +@@ -1033,6 +1052,7 @@ + bool is_app_limited; /* is sample from packet with bubble in pipe? */ + bool is_retrans; /* is sample from retransmission? */ + bool is_ack_delayed; /* is this (likely) a delayed ACK? */ ++ bool is_ece; /* did this ACK have ECN marked? */ + }; + + struct tcp_congestion_ops { +@@ -1059,10 +1079,12 @@ + u32 (*undo_cwnd)(struct sock *sk); + /* hook for packet ack accounting (optional) */ + void (*pkts_acked)(struct sock *sk, const struct ack_sample *sample); +- /* override sysctl_tcp_min_tso_segs */ +- u32 (*min_tso_segs)(struct sock *sk); ++ /* pick target number of segments per TSO/GSO skb (optional): */ ++ u32 (*tso_segs)(struct sock *sk, unsigned int mss_now); + /* returns the multiplier used in tcp_sndbuf_expand (optional) */ + u32 (*sndbuf_expand)(struct sock *sk); ++ /* react to a specific lost skb (optional) */ ++ void (*skb_marked_lost)(struct sock *sk, const struct sk_buff *skb); + /* call when packets are delivered to update cwnd and pacing rate, + * after all the ca_state processing. (optional) + */ +@@ -1107,6 +1129,14 @@ + } + #endif + ++static inline bool tcp_ca_wants_ce_events(const struct sock *sk) ++{ ++ const struct inet_connection_sock *icsk = inet_csk(sk); ++ ++ return icsk->icsk_ca_ops->flags & (TCP_CONG_NEEDS_ECN | ++ TCP_CONG_WANTS_CE_EVENTS); ++} ++ + static inline bool tcp_ca_needs_ecn(const struct sock *sk) + { + const struct inet_connection_sock *icsk = inet_csk(sk); +@@ -1132,6 +1162,7 @@ + } + + /* From tcp_rate.c */ ++void tcp_set_tx_in_flight(struct sock *sk, struct sk_buff *skb); + void tcp_rate_skb_sent(struct sock *sk, struct sk_buff *skb); + void tcp_rate_skb_delivered(struct sock *sk, struct sk_buff *skb, + struct rate_sample *rs); +diff --git a/include/uapi/linux/inet_diag.h b/include/uapi/linux/inet_diag.h +index a1ff345b3f33..ffc88b01868d 100644 +--- a/include/uapi/linux/inet_diag.h ++++ b/include/uapi/linux/inet_diag.h +@@ -206,9 +206,42 @@ + __u32 bbr_cwnd_gain; /* cwnd gain shifted left 8 bits */ + }; + ++/* Phase as reported in netlink/ss stats. */ ++enum tcp_bbr2_phase { ++ BBR2_PHASE_INVALID = 0, ++ BBR2_PHASE_STARTUP = 1, ++ BBR2_PHASE_DRAIN = 2, ++ BBR2_PHASE_PROBE_RTT = 3, ++ BBR2_PHASE_PROBE_BW_UP = 4, ++ BBR2_PHASE_PROBE_BW_DOWN = 5, ++ BBR2_PHASE_PROBE_BW_CRUISE = 6, ++ BBR2_PHASE_PROBE_BW_REFILL = 7 ++}; ++ ++struct tcp_bbr2_info { ++ /* u64 bw: bandwidth (app throughput) estimate in Byte per sec: */ ++ __u32 bbr_bw_lsb; /* lower 32 bits of bw */ ++ __u32 bbr_bw_msb; /* upper 32 bits of bw */ ++ __u32 bbr_min_rtt; /* min-filtered RTT in uSec */ ++ __u32 bbr_pacing_gain; /* pacing gain shifted left 8 bits */ ++ __u32 bbr_cwnd_gain; /* cwnd gain shifted left 8 bits */ ++ __u32 bbr_bw_hi_lsb; /* lower 32 bits of bw_hi */ ++ __u32 bbr_bw_hi_msb; /* upper 32 bits of bw_hi */ ++ __u32 bbr_bw_lo_lsb; /* lower 32 bits of bw_lo */ ++ __u32 bbr_bw_lo_msb; /* upper 32 bits of bw_lo */ ++ __u8 bbr_mode; /* current bbr_mode in state machine */ ++ __u8 bbr_phase; /* current state machine phase */ ++ __u8 unused1; /* alignment padding; not used yet */ ++ __u8 bbr_version; /* MUST be at this offset in struct */ ++ __u32 bbr_inflight_lo; /* lower/short-term data volume bound */ ++ __u32 bbr_inflight_hi; /* higher/long-term data volume bound */ ++ __u32 bbr_extra_acked; /* max excess packets ACKed in epoch */ ++}; ++ + union tcp_cc_info { + struct tcpvegas_info vegas; + struct tcp_dctcp_info dctcp; + struct tcp_bbr_info bbr; ++ struct tcp_bbr2_info bbr2; + }; + #endif /* _UAPI_INET_DIAG_H_ */ +diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig +index 03381f3e12ba..a638dee76e8b 100644 +--- a/net/ipv4/Kconfig ++++ b/net/ipv4/Kconfig +@@ -655,6 +655,24 @@ + bufferbloat, policers, or AQM schemes that do not provide a delay + signal. It requires the fq ("Fair Queue") pacing packet scheduler. + ++config TCP_CONG_BBR2 ++ tristate "BBR2 TCP" ++ default n ++ ---help--- ++ ++ BBR2 TCP congestion control is a model-based congestion control ++ algorithm that aims to maximize network utilization, keep queues and ++ retransmit rates low, and to be able to coexist with Reno/CUBIC in ++ common scenarios. It builds an explicit model of the network path. It ++ tolerates a targeted degree of random packet loss and delay that are ++ unrelated to congestion. It can operate over LAN, WAN, cellular, wifi, ++ or cable modem links, and can use DCTCP-L4S-style ECN signals. It can ++ coexist with flows that use loss-based congestion control, and can ++ operate with shallow buffers, deep buffers, bufferbloat, policers, or ++ AQM schemes that do not provide a delay signal. It requires pacing, ++ using either TCP internal pacing or the fq ("Fair Queue") pacing packet ++ scheduler. ++ + choice + prompt "Default TCP congestion control" + default DEFAULT_CUBIC +@@ -692,6 +710,9 @@ + config DEFAULT_BBR + bool "BBR" if TCP_CONG_BBR=y + ++ config DEFAULT_BBR2 ++ bool "BBR2" if TCP_CONG_BBR2=y ++ + config DEFAULT_RENO + bool "Reno" + endchoice +@@ -716,6 +737,7 @@ + default "dctcp" if DEFAULT_DCTCP + default "cdg" if DEFAULT_CDG + default "bbr" if DEFAULT_BBR ++ default "bbr2" if DEFAULT_BBR2 + default "cubic" + + config TCP_MD5SIG +diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile +index d57ecfaf89d4..7f187a52156c 100644 +--- a/net/ipv4/Makefile ++++ b/net/ipv4/Makefile +@@ -45,6 +45,7 @@ + obj-$(CONFIG_INET_UDP_DIAG) += udp_diag.o + obj-$(CONFIG_INET_RAW_DIAG) += raw_diag.o + obj-$(CONFIG_TCP_CONG_BBR) += tcp_bbr.o ++obj-$(CONFIG_TCP_CONG_BBR2) += tcp_bbr2.o + obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o + obj-$(CONFIG_TCP_CONG_CDG) += tcp_cdg.o + obj-$(CONFIG_TCP_CONG_CUBIC) += tcp_cubic.o +diff --git a/net/ipv4/tcp_bbr2.c b/net/ipv4/tcp_bbr2.c +new file mode 100644 +index 000000000000..875ebfef5a03 +--- /dev/null ++++ b/net/ipv4/tcp_bbr2.c +@@ -0,0 +1,2674 @@ ++/* BBR (Bottleneck Bandwidth and RTT) congestion control, v2 ++ * ++ * BBRv2 is a model-based congestion control algorithm that aims for low ++ * queues, low loss, and (bounded) Reno/CUBIC coexistence. To maintain a model ++ * of the network path, it uses measurements of bandwidth and RTT, as well as ++ * (if they occur) packet loss and/or DCTCP/L4S-style ECN signals. Note that ++ * although it can use ECN or loss signals explicitly, it does not require ++ * either; it can bound its in-flight data based on its estimate of the BDP. ++ * ++ * The model has both higher and lower bounds for the operating range: ++ * lo: bw_lo, inflight_lo: conservative short-term lower bound ++ * hi: bw_hi, inflight_hi: robust long-term upper bound ++ * The bandwidth-probing time scale is (a) extended dynamically based on ++ * estimated BDP to improve coexistence with Reno/CUBIC; (b) bounded by ++ * an interactive wall-clock time-scale to be more scalable and responsive ++ * than Reno and CUBIC. ++ * ++ * Here is a state transition diagram for BBR: ++ * ++ * | ++ * V ++ * +---> STARTUP ----+ ++ * | | | ++ * | V | ++ * | DRAIN ----+ ++ * | | | ++ * | V | ++ * +---> PROBE_BW ----+ ++ * | ^ | | ++ * | | | | ++ * | +----+ | ++ * | | ++ * +---- PROBE_RTT <--+ ++ * ++ * A BBR flow starts in STARTUP, and ramps up its sending rate quickly. ++ * When it estimates the pipe is full, it enters DRAIN to drain the queue. ++ * In steady state a BBR flow only uses PROBE_BW and PROBE_RTT. ++ * A long-lived BBR flow spends the vast majority of its time remaining ++ * (repeatedly) in PROBE_BW, fully probing and utilizing the pipe's bandwidth ++ * in a fair manner, with a small, bounded queue. *If* a flow has been ++ * continuously sending for the entire min_rtt window, and hasn't seen an RTT ++ * sample that matches or decreases its min_rtt estimate for 10 seconds, then ++ * it briefly enters PROBE_RTT to cut inflight to a minimum value to re-probe ++ * the path's two-way propagation delay (min_rtt). When exiting PROBE_RTT, if ++ * we estimated that we reached the full bw of the pipe then we enter PROBE_BW; ++ * otherwise we enter STARTUP to try to fill the pipe. ++ * ++ * BBR is described in detail in: ++ * "BBR: Congestion-Based Congestion Control", ++ * Neal Cardwell, Yuchung Cheng, C. Stephen Gunn, Soheil Hassas Yeganeh, ++ * Van Jacobson. ACM Queue, Vol. 14 No. 5, September-October 2016. ++ * ++ * There is a public e-mail list for discussing BBR development and testing: ++ * https://groups.google.com/forum/#!forum/bbr-dev ++ * ++ * NOTE: BBR might be used with the fq qdisc ("man tc-fq") with pacing enabled, ++ * otherwise TCP stack falls back to an internal pacing using one high ++ * resolution timer per TCP socket and may use more resources. ++ */ ++#include ++#include ++#include ++#include ++#include ++ ++#include "tcp_dctcp.h" ++ ++/* Scale factor for rate in pkt/uSec unit to avoid truncation in bandwidth ++ * estimation. The rate unit ~= (1500 bytes / 1 usec / 2^24) ~= 715 bps. ++ * This handles bandwidths from 0.06pps (715bps) to 256Mpps (3Tbps) in a u32. ++ * Since the minimum window is >=4 packets, the lower bound isn't ++ * an issue. The upper bound isn't an issue with existing technologies. ++ */ ++#define BW_SCALE 24 ++#define BW_UNIT (1 << BW_SCALE) ++ ++#define BBR_SCALE 8 /* scaling factor for fractions in BBR (e.g. gains) */ ++#define BBR_UNIT (1 << BBR_SCALE) ++ ++#define FLAG_DEBUG_VERBOSE 0x1 /* Verbose debugging messages */ ++#define FLAG_DEBUG_LOOPBACK 0x2 /* Do NOT skip loopback addr */ ++ ++#define CYCLE_LEN 8 /* number of phases in a pacing gain cycle */ ++ ++/* BBR has the following modes for deciding how fast to send: */ ++enum bbr_mode { ++ BBR_STARTUP, /* ramp up sending rate rapidly to fill pipe */ ++ BBR_DRAIN, /* drain any queue created during startup */ ++ BBR_PROBE_BW, /* discover, share bw: pace around estimated bw */ ++ BBR_PROBE_RTT, /* cut inflight to min to probe min_rtt */ ++}; ++ ++/* How does the incoming ACK stream relate to our bandwidth probing? */ ++enum bbr_ack_phase { ++ BBR_ACKS_INIT, /* not probing; not getting probe feedback */ ++ BBR_ACKS_REFILLING, /* sending at est. bw to fill pipe */ ++ BBR_ACKS_PROBE_STARTING, /* inflight rising to probe bw */ ++ BBR_ACKS_PROBE_FEEDBACK, /* getting feedback from bw probing */ ++ BBR_ACKS_PROBE_STOPPING, /* stopped probing; still getting feedback */ ++}; ++ ++/* BBR congestion control block */ ++struct bbr { ++ u32 min_rtt_us; /* min RTT in min_rtt_win_sec window */ ++ u32 min_rtt_stamp; /* timestamp of min_rtt_us */ ++ u32 probe_rtt_done_stamp; /* end time for BBR_PROBE_RTT mode */ ++ u32 probe_rtt_min_us; /* min RTT in bbr_probe_rtt_win_ms window */ ++ u32 probe_rtt_min_stamp; /* timestamp of probe_rtt_min_us*/ ++ u32 next_rtt_delivered; /* scb->tx.delivered at end of round */ ++ u32 prior_rcv_nxt; /* tp->rcv_nxt when CE state last changed */ ++ u64 cycle_mstamp; /* time of this cycle phase start */ ++ u32 mode:3, /* current bbr_mode in state machine */ ++ prev_ca_state:3, /* CA state on previous ACK */ ++ packet_conservation:1, /* use packet conservation? */ ++ round_start:1, /* start of packet-timed tx->ack round? */ ++ ce_state:1, /* If most recent data has CE bit set */ ++ bw_probe_up_rounds:5, /* cwnd-limited rounds in PROBE_UP */ ++ try_fast_path:1, /* can we take fast path? */ ++ unused2:11, ++ idle_restart:1, /* restarting after idle? */ ++ probe_rtt_round_done:1, /* a BBR_PROBE_RTT round at 4 pkts? */ ++ cycle_idx:3, /* current index in pacing_gain cycle array */ ++ has_seen_rtt:1; /* have we seen an RTT sample yet? */ ++ u32 pacing_gain:11, /* current gain for setting pacing rate */ ++ cwnd_gain:11, /* current gain for setting cwnd */ ++ full_bw_reached:1, /* reached full bw in Startup? */ ++ full_bw_cnt:2, /* number of rounds without large bw gains */ ++ init_cwnd:7; /* initial cwnd */ ++ u32 prior_cwnd; /* prior cwnd upon entering loss recovery */ ++ u32 full_bw; /* recent bw, to estimate if pipe is full */ ++ ++ /* For tracking ACK aggregation: */ ++ u64 ack_epoch_mstamp; /* start of ACK sampling epoch */ ++ u16 extra_acked[2]; /* max excess data ACKed in epoch */ ++ u32 ack_epoch_acked:20, /* packets (S)ACKed in sampling epoch */ ++ extra_acked_win_rtts:5, /* age of extra_acked, in round trips */ ++ extra_acked_win_idx:1, /* current index in extra_acked array */ ++ /* BBR v2 state: */ ++ unused1:2, ++ startup_ecn_rounds:2, /* consecutive hi ECN STARTUP rounds */ ++ loss_in_cycle:1, /* packet loss in this cycle? */ ++ ecn_in_cycle:1; /* ECN in this cycle? */ ++ u32 loss_round_delivered; /* scb->tx.delivered ending loss round */ ++ u32 undo_bw_lo; /* bw_lo before latest losses */ ++ u32 undo_inflight_lo; /* inflight_lo before latest losses */ ++ u32 undo_inflight_hi; /* inflight_hi before latest losses */ ++ u32 bw_latest; /* max delivered bw in last round trip */ ++ u32 bw_lo; /* lower bound on sending bandwidth */ ++ u32 bw_hi[2]; /* upper bound of sending bandwidth range*/ ++ u32 inflight_latest; /* max delivered data in last round trip */ ++ u32 inflight_lo; /* lower bound of inflight data range */ ++ u32 inflight_hi; /* upper bound of inflight data range */ ++ u32 bw_probe_up_cnt; /* packets delivered per inflight_hi incr */ ++ u32 bw_probe_up_acks; /* packets (S)ACKed since inflight_hi incr */ ++ u32 probe_wait_us; /* PROBE_DOWN until next clock-driven probe */ ++ u32 ecn_eligible:1, /* sender can use ECN (RTT, handshake)? */ ++ ecn_alpha:9, /* EWMA delivered_ce/delivered; 0..256 */ ++ bw_probe_samples:1, /* rate samples reflect bw probing? */ ++ prev_probe_too_high:1, /* did last PROBE_UP go too high? */ ++ stopped_risky_probe:1, /* last PROBE_UP stopped due to risk? */ ++ rounds_since_probe:8, /* packet-timed rounds since probed bw */ ++ loss_round_start:1, /* loss_round_delivered round trip? */ ++ loss_in_round:1, /* loss marked in this round trip? */ ++ ecn_in_round:1, /* ECN marked in this round trip? */ ++ ack_phase:3, /* bbr_ack_phase: meaning of ACKs */ ++ loss_events_in_round:4,/* losses in STARTUP round */ ++ initialized:1; /* has bbr_init() been called? */ ++ u32 alpha_last_delivered; /* tp->delivered at alpha update */ ++ u32 alpha_last_delivered_ce; /* tp->delivered_ce at alpha update */ ++ ++ /* Params configurable using setsockopt. Refer to correspoding ++ * module param for detailed description of params. ++ */ ++ struct bbr_params { ++ u32 high_gain:11, /* max allowed value: 2047 */ ++ drain_gain:10, /* max allowed value: 1023 */ ++ cwnd_gain:11; /* max allowed value: 2047 */ ++ u32 cwnd_min_target:4, /* max allowed value: 15 */ ++ min_rtt_win_sec:5, /* max allowed value: 31 */ ++ probe_rtt_mode_ms:9, /* max allowed value: 511 */ ++ full_bw_cnt:3, /* max allowed value: 7 */ ++ cwnd_tso_budget:1, /* allowed values: {0, 1} */ ++ unused3:6, ++ drain_to_target:1, /* boolean */ ++ precise_ece_ack:1, /* boolean */ ++ extra_acked_in_startup:1, /* allowed values: {0, 1} */ ++ fast_path:1; /* boolean */ ++ u32 full_bw_thresh:10, /* max allowed value: 1023 */ ++ startup_cwnd_gain:11, /* max allowed value: 2047 */ ++ bw_probe_pif_gain:9, /* max allowed value: 511 */ ++ usage_based_cwnd:1, /* boolean */ ++ unused2:1; ++ u16 probe_rtt_win_ms:14, /* max allowed value: 16383 */ ++ refill_add_inc:2; /* max allowed value: 3 */ ++ u16 extra_acked_gain:11, /* max allowed value: 2047 */ ++ extra_acked_win_rtts:5; /* max allowed value: 31*/ ++ u16 pacing_gain[CYCLE_LEN]; /* max allowed value: 1023 */ ++ /* Mostly BBR v2 parameters below here: */ ++ u32 ecn_alpha_gain:8, /* max allowed value: 255 */ ++ ecn_factor:8, /* max allowed value: 255 */ ++ ecn_thresh:8, /* max allowed value: 255 */ ++ beta:8; /* max allowed value: 255 */ ++ u32 ecn_max_rtt_us:19, /* max allowed value: 524287 */ ++ bw_probe_reno_gain:9, /* max allowed value: 511 */ ++ full_loss_cnt:4; /* max allowed value: 15 */ ++ u32 probe_rtt_cwnd_gain:8, /* max allowed value: 255 */ ++ inflight_headroom:8, /* max allowed value: 255 */ ++ loss_thresh:8, /* max allowed value: 255 */ ++ bw_probe_max_rounds:8; /* max allowed value: 255 */ ++ u32 bw_probe_rand_rounds:4, /* max allowed value: 15 */ ++ bw_probe_base_us:26, /* usecs: 0..2^26-1 (67 secs) */ ++ full_ecn_cnt:2; /* max allowed value: 3 */ ++ u32 bw_probe_rand_us:26, /* usecs: 0..2^26-1 (67 secs) */ ++ undo:1, /* boolean */ ++ tso_rtt_shift:4, /* max allowed value: 15 */ ++ unused5:1; ++ u32 ecn_reprobe_gain:9, /* max allowed value: 511 */ ++ unused1:14, ++ ecn_alpha_init:9; /* max allowed value: 256 */ ++ } params; ++ ++ struct { ++ u32 snd_isn; /* Initial sequence number */ ++ u32 rs_bw; /* last valid rate sample bw */ ++ u32 target_cwnd; /* target cwnd, based on BDP */ ++ u8 undo:1, /* Undo even happened but not yet logged */ ++ unused:7; ++ char event; /* single-letter event debug codes */ ++ u16 unused2; ++ } debug; ++}; ++ ++struct bbr_context { ++ u32 sample_bw; ++ u32 target_cwnd; ++ u32 log:1; ++}; ++ ++/* Window length of min_rtt filter (in sec). Max allowed value is 31 (0x1F) */ ++static u32 bbr_min_rtt_win_sec = 10; ++/* Minimum time (in ms) spent at bbr_cwnd_min_target in BBR_PROBE_RTT mode. ++ * Max allowed value is 511 (0x1FF). ++ */ ++static u32 bbr_probe_rtt_mode_ms = 200; ++/* Window length of probe_rtt_min_us filter (in ms), and consequently the ++ * typical interval between PROBE_RTT mode entries. ++ * Note that bbr_probe_rtt_win_ms must be <= bbr_min_rtt_win_sec * MSEC_PER_SEC ++ */ ++static u32 bbr_probe_rtt_win_ms = 5000; ++/* Skip TSO below the following bandwidth (bits/sec): */ ++static int bbr_min_tso_rate = 1200000; ++ ++/* Use min_rtt to help adapt TSO burst size, with smaller min_rtt resulting ++ * in bigger TSO bursts. By default we cut the RTT-based allowance in half ++ * for every 2^9 usec (aka 512 us) of RTT, so that the RTT-based allowance ++ * is below 1500 bytes after 6 * ~500 usec = 3ms. ++ */ ++static u32 bbr_tso_rtt_shift = 9; /* halve allowance per 2^9 usecs, 512us */ ++ ++/* Select cwnd TSO budget approach: ++ * 0: padding ++ * 1: flooring ++ */ ++static uint bbr_cwnd_tso_budget = 1; ++ ++/* Pace at ~1% below estimated bw, on average, to reduce queue at bottleneck. ++ * In order to help drive the network toward lower queues and low latency while ++ * maintaining high utilization, the average pacing rate aims to be slightly ++ * lower than the estimated bandwidth. This is an important aspect of the ++ * design. ++ */ ++static const int bbr_pacing_margin_percent = 1; ++ ++/* We use a high_gain value of 2/ln(2) because it's the smallest pacing gain ++ * that will allow a smoothly increasing pacing rate that will double each RTT ++ * and send the same number of packets per RTT that an un-paced, slow-starting ++ * Reno or CUBIC flow would. Max allowed value is 2047 (0x7FF). ++ */ ++static int bbr_high_gain = BBR_UNIT * 2885 / 1000 + 1; ++/* The gain for deriving startup cwnd. Max allowed value is 2047 (0x7FF). */ ++static int bbr_startup_cwnd_gain = BBR_UNIT * 2885 / 1000 + 1; ++/* The pacing gain of 1/high_gain in BBR_DRAIN is calculated to typically drain ++ * the queue created in BBR_STARTUP in a single round. Max allowed value ++ * is 1023 (0x3FF). ++ */ ++static int bbr_drain_gain = BBR_UNIT * 1000 / 2885; ++/* The gain for deriving steady-state cwnd tolerates delayed/stretched ACKs. ++ * Max allowed value is 2047 (0x7FF). ++ */ ++static int bbr_cwnd_gain = BBR_UNIT * 2; ++/* The pacing_gain values for the PROBE_BW gain cycle, to discover/share bw. ++ * Max allowed value for each element is 1023 (0x3FF). ++ */ ++enum bbr_pacing_gain_phase { ++ BBR_BW_PROBE_UP = 0, /* push up inflight to probe for bw/vol */ ++ BBR_BW_PROBE_DOWN = 1, /* drain excess inflight from the queue */ ++ BBR_BW_PROBE_CRUISE = 2, /* use pipe, w/ headroom in queue/pipe */ ++ BBR_BW_PROBE_REFILL = 3, /* v2: refill the pipe again to 100% */ ++}; ++static int bbr_pacing_gain[] = { ++ BBR_UNIT * 5 / 4, /* probe for more available bw */ ++ BBR_UNIT * 3 / 4, /* drain queue and/or yield bw to other flows */ ++ BBR_UNIT, BBR_UNIT, BBR_UNIT, /* cruise at 1.0*bw to utilize pipe, */ ++ BBR_UNIT, BBR_UNIT, BBR_UNIT /* without creating excess queue... */ ++}; ++ ++/* Try to keep at least this many packets in flight, if things go smoothly. For ++ * smooth functioning, a sliding window protocol ACKing every other packet ++ * needs at least 4 packets in flight. Max allowed value is 15 (0xF). ++ */ ++static u32 bbr_cwnd_min_target = 4; ++ ++/* Cwnd to BDP proportion in PROBE_RTT mode scaled by BBR_UNIT. Default: 50%. ++ * Use 0 to disable. Max allowed value is 255. ++ */ ++static u32 bbr_probe_rtt_cwnd_gain = BBR_UNIT * 1 / 2; ++ ++/* To estimate if BBR_STARTUP mode (i.e. high_gain) has filled pipe... */ ++/* If bw has increased significantly (1.25x), there may be more bw available. ++ * Max allowed value is 1023 (0x3FF). ++ */ ++static u32 bbr_full_bw_thresh = BBR_UNIT * 5 / 4; ++/* But after 3 rounds w/o significant bw growth, estimate pipe is full. ++ * Max allowed value is 7 (0x7). ++ */ ++static u32 bbr_full_bw_cnt = 3; ++ ++static u32 bbr_flags; /* Debugging related stuff */ ++ ++/* Whether to debug using printk. ++ */ ++static bool bbr_debug_with_printk; ++ ++/* Whether to debug using ftrace event tcp:tcp_bbr_event. ++ * Ignored when bbr_debug_with_printk is set. ++ */ ++static bool bbr_debug_ftrace; ++ ++/* Experiment: each cycle, try to hold sub-unity gain until inflight <= BDP. */ ++static bool bbr_drain_to_target = true; /* default: enabled */ ++ ++/* Experiment: Flags to control BBR with ECN behavior. ++ */ ++static bool bbr_precise_ece_ack = true; /* default: enabled */ ++ ++/* The max rwin scaling shift factor is 14 (RFC 1323), so the max sane rwin is ++ * (2^(16+14) B)/(1024 B/packet) = 1M packets. ++ */ ++static u32 bbr_cwnd_warn_val = 1U << 20; ++ ++static u16 bbr_debug_port_mask; ++ ++/* BBR module parameters. These are module parameters only in Google prod. ++ * Upstream these are intentionally not module parameters. ++ */ ++static int bbr_pacing_gain_size = CYCLE_LEN; ++ ++/* Gain factor for adding extra_acked to target cwnd: */ ++static int bbr_extra_acked_gain = 256; ++ ++/* Window length of extra_acked window. Max allowed val is 31. */ ++static u32 bbr_extra_acked_win_rtts = 5; ++ ++/* Max allowed val for ack_epoch_acked, after which sampling epoch is reset */ ++static u32 bbr_ack_epoch_acked_reset_thresh = 1U << 20; ++ ++/* Time period for clamping cwnd increment due to ack aggregation */ ++static u32 bbr_extra_acked_max_us = 100 * 1000; ++ ++/* Use extra acked in startup ? ++ * 0: disabled ++ * 1: use latest extra_acked value from 1-2 rtt in startup ++ */ ++static int bbr_extra_acked_in_startup = 1; /* default: enabled */ ++ ++/* Experiment: don't grow cwnd beyond twice of what we just probed. */ ++static bool bbr_usage_based_cwnd; /* default: disabled */ ++ ++/* For lab testing, researchers can enable BBRv2 ECN support with this flag, ++ * when they know that any ECN marks that the connections experience will be ++ * DCTCP/L4S-style ECN marks, rather than RFC3168 ECN marks. ++ * TODO(ncardwell): Production use of the BBRv2 ECN functionality depends on ++ * negotiation or configuration that is outside the scope of the BBRv2 ++ * alpha release. ++ */ ++static bool bbr_ecn_enable = false; ++ ++module_param_named(min_tso_rate, bbr_min_tso_rate, int, 0644); ++module_param_named(tso_rtt_shift, bbr_tso_rtt_shift, int, 0644); ++module_param_named(high_gain, bbr_high_gain, int, 0644); ++module_param_named(drain_gain, bbr_drain_gain, int, 0644); ++module_param_named(startup_cwnd_gain, bbr_startup_cwnd_gain, int, 0644); ++module_param_named(cwnd_gain, bbr_cwnd_gain, int, 0644); ++module_param_array_named(pacing_gain, bbr_pacing_gain, int, ++ &bbr_pacing_gain_size, 0644); ++module_param_named(cwnd_min_target, bbr_cwnd_min_target, uint, 0644); ++module_param_named(probe_rtt_cwnd_gain, ++ bbr_probe_rtt_cwnd_gain, uint, 0664); ++module_param_named(cwnd_warn_val, bbr_cwnd_warn_val, uint, 0664); ++module_param_named(debug_port_mask, bbr_debug_port_mask, ushort, 0644); ++module_param_named(flags, bbr_flags, uint, 0644); ++module_param_named(debug_ftrace, bbr_debug_ftrace, bool, 0644); ++module_param_named(debug_with_printk, bbr_debug_with_printk, bool, 0644); ++module_param_named(min_rtt_win_sec, bbr_min_rtt_win_sec, uint, 0644); ++module_param_named(probe_rtt_mode_ms, bbr_probe_rtt_mode_ms, uint, 0644); ++module_param_named(probe_rtt_win_ms, bbr_probe_rtt_win_ms, uint, 0644); ++module_param_named(full_bw_thresh, bbr_full_bw_thresh, uint, 0644); ++module_param_named(full_bw_cnt, bbr_full_bw_cnt, uint, 0644); ++module_param_named(cwnd_tso_bduget, bbr_cwnd_tso_budget, uint, 0664); ++module_param_named(extra_acked_gain, bbr_extra_acked_gain, int, 0664); ++module_param_named(extra_acked_win_rtts, ++ bbr_extra_acked_win_rtts, uint, 0664); ++module_param_named(extra_acked_max_us, ++ bbr_extra_acked_max_us, uint, 0664); ++module_param_named(ack_epoch_acked_reset_thresh, ++ bbr_ack_epoch_acked_reset_thresh, uint, 0664); ++module_param_named(drain_to_target, bbr_drain_to_target, bool, 0664); ++module_param_named(precise_ece_ack, bbr_precise_ece_ack, bool, 0664); ++module_param_named(extra_acked_in_startup, ++ bbr_extra_acked_in_startup, int, 0664); ++module_param_named(usage_based_cwnd, bbr_usage_based_cwnd, bool, 0664); ++module_param_named(ecn_enable, bbr_ecn_enable, bool, 0664); ++ ++static void bbr2_exit_probe_rtt(struct sock *sk); ++static void bbr2_reset_congestion_signals(struct sock *sk); ++ ++static void bbr_check_probe_rtt_done(struct sock *sk); ++ ++/* Do we estimate that STARTUP filled the pipe? */ ++static bool bbr_full_bw_reached(const struct sock *sk) ++{ ++ const struct bbr *bbr = inet_csk_ca(sk); ++ ++ return bbr->full_bw_reached; ++} ++ ++/* Return the windowed max recent bandwidth sample, in pkts/uS << BW_SCALE. */ ++static u32 bbr_max_bw(const struct sock *sk) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ return max(bbr->bw_hi[0], bbr->bw_hi[1]); ++} ++ ++/* Return the estimated bandwidth of the path, in pkts/uS << BW_SCALE. */ ++static u32 bbr_bw(const struct sock *sk) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ return min(bbr_max_bw(sk), bbr->bw_lo); ++} ++ ++/* Return maximum extra acked in past k-2k round trips, ++ * where k = bbr_extra_acked_win_rtts. ++ */ ++static u16 bbr_extra_acked(const struct sock *sk) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ return max(bbr->extra_acked[0], bbr->extra_acked[1]); ++} ++ ++/* Return rate in bytes per second, optionally with a gain. ++ * The order here is chosen carefully to avoid overflow of u64. This should ++ * work for input rates of up to 2.9Tbit/sec and gain of 2.89x. ++ */ ++static u64 bbr_rate_bytes_per_sec(struct sock *sk, u64 rate, int gain, ++ int margin) ++{ ++ unsigned int mss = tcp_sk(sk)->mss_cache; ++ ++ rate *= mss; ++ rate *= gain; ++ rate >>= BBR_SCALE; ++ rate *= USEC_PER_SEC / 100 * (100 - margin); ++ rate >>= BW_SCALE; ++ rate = max(rate, 1ULL); ++ return rate; ++} ++ ++static u64 bbr_bw_bytes_per_sec(struct sock *sk, u64 rate) ++{ ++ return bbr_rate_bytes_per_sec(sk, rate, BBR_UNIT, 0); ++} ++ ++static u64 bbr_rate_kbps(struct sock *sk, u64 rate) ++{ ++ rate = bbr_bw_bytes_per_sec(sk, rate); ++ rate *= 8; ++ do_div(rate, 1000); ++ return rate; ++} ++ ++static u32 bbr_tso_segs_goal(struct sock *sk); ++static void bbr_debug(struct sock *sk, u32 acked, ++ const struct rate_sample *rs, struct bbr_context *ctx) ++{ ++ static const char ca_states[] = { ++ [TCP_CA_Open] = 'O', ++ [TCP_CA_Disorder] = 'D', ++ [TCP_CA_CWR] = 'C', ++ [TCP_CA_Recovery] = 'R', ++ [TCP_CA_Loss] = 'L', ++ }; ++ static const char mode[] = { ++ 'G', /* Growing - BBR_STARTUP */ ++ 'D', /* Drain - BBR_DRAIN */ ++ 'W', /* Window - BBR_PROBE_BW */ ++ 'M', /* Min RTT - BBR_PROBE_RTT */ ++ }; ++ static const char ack_phase[] = { /* bbr_ack_phase strings */ ++ 'I', /* BBR_ACKS_INIT - 'Init' */ ++ 'R', /* BBR_ACKS_REFILLING - 'Refilling' */ ++ 'B', /* BBR_ACKS_PROBE_STARTING - 'Before' */ ++ 'F', /* BBR_ACKS_PROBE_FEEDBACK - 'Feedback' */ ++ 'A', /* BBR_ACKS_PROBE_STOPPING - 'After' */ ++ }; ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ const u32 una = tp->snd_una - bbr->debug.snd_isn; ++ const u32 fack = tcp_highest_sack_seq(tp); ++ const u16 dport = ntohs(inet_sk(sk)->inet_dport); ++ bool is_port_match = (bbr_debug_port_mask && ++ ((dport & bbr_debug_port_mask) == 0)); ++ char debugmsg[320]; ++ ++ if (sk->sk_state == TCP_SYN_SENT) ++ return; /* no bbr_init() yet if SYN retransmit -> CA_Loss */ ++ ++ if (!tp->snd_cwnd || tp->snd_cwnd > bbr_cwnd_warn_val) { ++ char addr[INET6_ADDRSTRLEN + 10] = { 0 }; ++ ++ if (sk->sk_family == AF_INET) ++ snprintf(addr, sizeof(addr), "%pI4:%u", ++ &inet_sk(sk)->inet_daddr, dport); ++ else if (sk->sk_family == AF_INET6) ++ snprintf(addr, sizeof(addr), "%pI6:%u", ++ &sk->sk_v6_daddr, dport); ++ ++ WARN_ONCE(1, ++ "BBR %s cwnd alert: %u " ++ "snd_una: %u ca: %d pacing_gain: %u cwnd_gain: %u " ++ "bw: %u rtt: %u min_rtt: %u " ++ "acked: %u tso_segs: %u " ++ "bw: %d %ld %d pif: %u\n", ++ addr, tp->snd_cwnd, ++ una, inet_csk(sk)->icsk_ca_state, ++ bbr->pacing_gain, bbr->cwnd_gain, ++ bbr_max_bw(sk), (tp->srtt_us >> 3), bbr->min_rtt_us, ++ acked, bbr_tso_segs_goal(sk), ++ rs->delivered, rs->interval_us, rs->is_retrans, ++ tcp_packets_in_flight(tp)); ++ } ++ ++ if (likely(!bbr_debug_with_printk && !bbr_debug_ftrace)) ++ return; ++ ++ if (!sock_flag(sk, SOCK_DBG) && !is_port_match) ++ return; ++ ++ if (!ctx->log && !tp->app_limited && !(bbr_flags & FLAG_DEBUG_VERBOSE)) ++ return; ++ ++ if (ipv4_is_loopback(inet_sk(sk)->inet_daddr) && ++ !(bbr_flags & FLAG_DEBUG_LOOPBACK)) ++ return; ++ ++ snprintf(debugmsg, sizeof(debugmsg) - 1, ++ "BBR %pI4:%-5u %5u,%03u:%-7u %c " ++ "%c %2u br %2u cr %2d rtt %5ld d %2d i %5ld mrtt %d %cbw %llu " ++ "bw %llu lb %llu ib %llu qb %llu " ++ "a %u if %2u %c %c dl %u l %u al %u # %u t %u %c %c " ++ "lr %d er %d ea %d bwl %lld il %d ih %d c %d " ++ "v %d %c %u %c %s\n", ++ &inet_sk(sk)->inet_daddr, dport, ++ una / 1000, una % 1000, fack - tp->snd_una, ++ ca_states[inet_csk(sk)->icsk_ca_state], ++ bbr->debug.undo ? '@' : mode[bbr->mode], ++ tp->snd_cwnd, ++ bbr_extra_acked(sk), /* br (legacy): extra_acked */ ++ rs->tx_in_flight, /* cr (legacy): tx_inflight */ ++ rs->rtt_us, ++ rs->delivered, ++ rs->interval_us, ++ bbr->min_rtt_us, ++ rs->is_app_limited ? '_' : 'l', ++ bbr_rate_kbps(sk, ctx->sample_bw), /* lbw: latest sample bw */ ++ bbr_rate_kbps(sk, bbr_max_bw(sk)), /* bw: max bw */ ++ 0ULL, /* lb: [obsolete] */ ++ 0ULL, /* ib: [obsolete] */ ++ (u64)sk->sk_pacing_rate * 8 / 1000, ++ acked, ++ tcp_packets_in_flight(tp), ++ rs->is_ack_delayed ? 'd' : '.', ++ bbr->round_start ? '*' : '.', ++ tp->delivered, tp->lost, ++ tp->app_limited, ++ 0, /* #: [obsolete] */ ++ ctx->target_cwnd, ++ tp->reord_seen ? 'r' : '.', /* r: reordering seen? */ ++ ca_states[bbr->prev_ca_state], ++ (rs->lost + rs->delivered) > 0 ? ++ (1000 * rs->lost / ++ (rs->lost + rs->delivered)) : 0, /* lr: loss rate x1000 */ ++ (rs->delivered) > 0 ? ++ (1000 * rs->delivered_ce / ++ (rs->delivered)) : 0, /* er: ECN rate x1000 */ ++ 1000 * bbr->ecn_alpha >> BBR_SCALE, /* ea: ECN alpha x1000 */ ++ bbr->bw_lo == ~0U ? ++ -1 : (s64)bbr_rate_kbps(sk, bbr->bw_lo), /* bwl */ ++ bbr->inflight_lo, /* il */ ++ bbr->inflight_hi, /* ih */ ++ bbr->bw_probe_up_cnt, /* c */ ++ 2, /* v: version */ ++ bbr->debug.event, ++ bbr->cycle_idx, ++ ack_phase[bbr->ack_phase], ++ bbr->bw_probe_samples ? "Y" : "N"); ++ debugmsg[sizeof(debugmsg) - 1] = 0; ++ ++ /* printk takes a higher precedence. */ ++ if (bbr_debug_with_printk) ++ printk(KERN_DEBUG "%s", debugmsg); ++ ++ if (unlikely(bbr->debug.undo)) ++ bbr->debug.undo = 0; ++} ++ ++/* Convert a BBR bw and gain factor to a pacing rate in bytes per second. */ ++static unsigned long bbr_bw_to_pacing_rate(struct sock *sk, u32 bw, int gain) ++{ ++ u64 rate = bw; ++ ++ rate = bbr_rate_bytes_per_sec(sk, rate, gain, ++ bbr_pacing_margin_percent); ++ rate = min_t(u64, rate, sk->sk_max_pacing_rate); ++ return rate; ++} ++ ++/* Initialize pacing rate to: high_gain * init_cwnd / RTT. */ ++static void bbr_init_pacing_rate_from_rtt(struct sock *sk) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ u64 bw; ++ u32 rtt_us; ++ ++ if (tp->srtt_us) { /* any RTT sample yet? */ ++ rtt_us = max(tp->srtt_us >> 3, 1U); ++ bbr->has_seen_rtt = 1; ++ } else { /* no RTT sample yet */ ++ rtt_us = USEC_PER_MSEC; /* use nominal default RTT */ ++ } ++ bw = (u64)tp->snd_cwnd * BW_UNIT; ++ do_div(bw, rtt_us); ++ sk->sk_pacing_rate = bbr_bw_to_pacing_rate(sk, bw, bbr->params.high_gain); ++} ++ ++/* Pace using current bw estimate and a gain factor. */ ++static void bbr_set_pacing_rate(struct sock *sk, u32 bw, int gain) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ unsigned long rate = bbr_bw_to_pacing_rate(sk, bw, gain); ++ ++ if (unlikely(!bbr->has_seen_rtt && tp->srtt_us)) ++ bbr_init_pacing_rate_from_rtt(sk); ++ if (bbr_full_bw_reached(sk) || rate > sk->sk_pacing_rate) ++ sk->sk_pacing_rate = rate; ++} ++ ++static u32 bbr_min_tso_segs(struct sock *sk) ++{ ++ return sk->sk_pacing_rate < (bbr_min_tso_rate >> 3) ? 1 : 2; ++} ++ ++/* Return the number of segments BBR would like in a TSO/GSO skb, given ++ * a particular max gso size as a constraint. ++ */ ++static u32 bbr_tso_segs_generic(struct sock *sk, unsigned int mss_now, ++ u32 gso_max_size) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ u32 segs, r; ++ u64 bytes; ++ ++ /* Budget a TSO/GSO burst size allowance based on bw (pacing_rate). */ ++ bytes = sk->sk_pacing_rate >> sk->sk_pacing_shift; ++ ++ /* Budget a TSO/GSO burst size allowance based on min_rtt. For every ++ * K = 2^tso_rtt_shift microseconds of min_rtt, halve the burst. ++ * The min_rtt-based burst allowance is: 64 KBytes / 2^(min_rtt/K) ++ */ ++ if (bbr->params.tso_rtt_shift) { ++ r = bbr->min_rtt_us >> bbr->params.tso_rtt_shift; ++ if (r < BITS_PER_TYPE(u32)) /* prevent undefined behavior */ ++ bytes += GSO_MAX_SIZE >> r; ++ } ++ ++ bytes = min_t(u32, bytes, gso_max_size - 1 - MAX_TCP_HEADER); ++ segs = max_t(u32, bytes / mss_now, bbr_min_tso_segs(sk)); ++ return segs; ++} ++ ++/* Custom tcp_tso_autosize() for BBR, used at transmit time to cap skb size. */ ++static u32 bbr_tso_segs(struct sock *sk, unsigned int mss_now) ++{ ++ return bbr_tso_segs_generic(sk, mss_now, sk->sk_gso_max_size); ++} ++ ++/* Like bbr_tso_segs(), using mss_cache, ignoring driver's sk_gso_max_size. */ ++static u32 bbr_tso_segs_goal(struct sock *sk) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ ++ return bbr_tso_segs_generic(sk, tp->mss_cache, GSO_MAX_SIZE); ++} ++ ++/* Save "last known good" cwnd so we can restore it after losses or PROBE_RTT */ ++static void bbr_save_cwnd(struct sock *sk) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ if (bbr->prev_ca_state < TCP_CA_Recovery && bbr->mode != BBR_PROBE_RTT) ++ bbr->prior_cwnd = tp->snd_cwnd; /* this cwnd is good enough */ ++ else /* loss recovery or BBR_PROBE_RTT have temporarily cut cwnd */ ++ bbr->prior_cwnd = max(bbr->prior_cwnd, tp->snd_cwnd); ++} ++ ++static void bbr_cwnd_event(struct sock *sk, enum tcp_ca_event event) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ if (event == CA_EVENT_TX_START && tp->app_limited) { ++ bbr->idle_restart = 1; ++ bbr->ack_epoch_mstamp = tp->tcp_mstamp; ++ bbr->ack_epoch_acked = 0; ++ /* Avoid pointless buffer overflows: pace at est. bw if we don't ++ * need more speed (we're restarting from idle and app-limited). ++ */ ++ if (bbr->mode == BBR_PROBE_BW) ++ bbr_set_pacing_rate(sk, bbr_bw(sk), BBR_UNIT); ++ else if (bbr->mode == BBR_PROBE_RTT) ++ bbr_check_probe_rtt_done(sk); ++ } else if ((event == CA_EVENT_ECN_IS_CE || ++ event == CA_EVENT_ECN_NO_CE) && ++ bbr_ecn_enable && ++ bbr->params.precise_ece_ack) { ++ u32 state = bbr->ce_state; ++ dctcp_ece_ack_update(sk, event, &bbr->prior_rcv_nxt, &state); ++ bbr->ce_state = state; ++ if (tp->fast_ack_mode == 2 && event == CA_EVENT_ECN_IS_CE) ++ tcp_enter_quickack_mode(sk, TCP_MAX_QUICKACKS); ++ } ++} ++ ++/* Calculate bdp based on min RTT and the estimated bottleneck bandwidth: ++ * ++ * bdp = ceil(bw * min_rtt * gain) ++ * ++ * The key factor, gain, controls the amount of queue. While a small gain ++ * builds a smaller queue, it becomes more vulnerable to noise in RTT ++ * measurements (e.g., delayed ACKs or other ACK compression effects). This ++ * noise may cause BBR to under-estimate the rate. ++ */ ++static u32 bbr_bdp(struct sock *sk, u32 bw, int gain) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ u32 bdp; ++ u64 w; ++ ++ /* If we've never had a valid RTT sample, cap cwnd at the initial ++ * default. This should only happen when the connection is not using TCP ++ * timestamps and has retransmitted all of the SYN/SYNACK/data packets ++ * ACKed so far. In this case, an RTO can cut cwnd to 1, in which ++ * case we need to slow-start up toward something safe: initial cwnd. ++ */ ++ if (unlikely(bbr->min_rtt_us == ~0U)) /* no valid RTT samples yet? */ ++ return bbr->init_cwnd; /* be safe: cap at initial cwnd */ ++ ++ w = (u64)bw * bbr->min_rtt_us; ++ ++ /* Apply a gain to the given value, remove the BW_SCALE shift, and ++ * round the value up to avoid a negative feedback loop. ++ */ ++ bdp = (((w * gain) >> BBR_SCALE) + BW_UNIT - 1) / BW_UNIT; ++ ++ return bdp; ++} ++ ++/* To achieve full performance in high-speed paths, we budget enough cwnd to ++ * fit full-sized skbs in-flight on both end hosts to fully utilize the path: ++ * - one skb in sending host Qdisc, ++ * - one skb in sending host TSO/GSO engine ++ * - one skb being received by receiver host LRO/GRO/delayed-ACK engine ++ * Don't worry, at low rates (bbr_min_tso_rate) this won't bloat cwnd because ++ * in such cases tso_segs_goal is 1. The minimum cwnd is 4 packets, ++ * which allows 2 outstanding 2-packet sequences, to try to keep pipe ++ * full even with ACK-every-other-packet delayed ACKs. ++ */ ++static u32 bbr_quantization_budget(struct sock *sk, u32 cwnd) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ u32 tso_segs_goal; ++ ++ tso_segs_goal = 3 * bbr_tso_segs_goal(sk); ++ ++ /* Allow enough full-sized skbs in flight to utilize end systems. */ ++ if (bbr->params.cwnd_tso_budget == 1) { ++ cwnd = max_t(u32, cwnd, tso_segs_goal); ++ cwnd = max_t(u32, cwnd, bbr->params.cwnd_min_target); ++ } else { ++ cwnd += tso_segs_goal; ++ cwnd = (cwnd + 1) & ~1U; ++ } ++ /* Ensure gain cycling gets inflight above BDP even for small BDPs. */ ++ if (bbr->mode == BBR_PROBE_BW && bbr->cycle_idx == BBR_BW_PROBE_UP) ++ cwnd += 2; ++ ++ return cwnd; ++} ++ ++/* Find inflight based on min RTT and the estimated bottleneck bandwidth. */ ++static u32 bbr_inflight(struct sock *sk, u32 bw, int gain) ++{ ++ u32 inflight; ++ ++ inflight = bbr_bdp(sk, bw, gain); ++ inflight = bbr_quantization_budget(sk, inflight); ++ ++ return inflight; ++} ++ ++/* With pacing at lower layers, there's often less data "in the network" than ++ * "in flight". With TSQ and departure time pacing at lower layers (e.g. fq), ++ * we often have several skbs queued in the pacing layer with a pre-scheduled ++ * earliest departure time (EDT). BBR adapts its pacing rate based on the ++ * inflight level that it estimates has already been "baked in" by previous ++ * departure time decisions. We calculate a rough estimate of the number of our ++ * packets that might be in the network at the earliest departure time for the ++ * next skb scheduled: ++ * in_network_at_edt = inflight_at_edt - (EDT - now) * bw ++ * If we're increasing inflight, then we want to know if the transmit of the ++ * EDT skb will push inflight above the target, so inflight_at_edt includes ++ * bbr_tso_segs_goal() from the skb departing at EDT. If decreasing inflight, ++ * then estimate if inflight will sink too low just before the EDT transmit. ++ */ ++static u32 bbr_packets_in_net_at_edt(struct sock *sk, u32 inflight_now) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ u64 now_ns, edt_ns, interval_us; ++ u32 interval_delivered, inflight_at_edt; ++ ++ now_ns = tp->tcp_clock_cache; ++ edt_ns = max(tp->tcp_wstamp_ns, now_ns); ++ interval_us = div_u64(edt_ns - now_ns, NSEC_PER_USEC); ++ interval_delivered = (u64)bbr_bw(sk) * interval_us >> BW_SCALE; ++ inflight_at_edt = inflight_now; ++ if (bbr->pacing_gain > BBR_UNIT) /* increasing inflight */ ++ inflight_at_edt += bbr_tso_segs_goal(sk); /* include EDT skb */ ++ if (interval_delivered >= inflight_at_edt) ++ return 0; ++ return inflight_at_edt - interval_delivered; ++} ++ ++/* Find the cwnd increment based on estimate of ack aggregation */ ++static u32 bbr_ack_aggregation_cwnd(struct sock *sk) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ u32 max_aggr_cwnd, aggr_cwnd = 0; ++ ++ if (bbr->params.extra_acked_gain && ++ (bbr_full_bw_reached(sk) || bbr->params.extra_acked_in_startup)) { ++ max_aggr_cwnd = ((u64)bbr_bw(sk) * bbr_extra_acked_max_us) ++ / BW_UNIT; ++ aggr_cwnd = (bbr->params.extra_acked_gain * bbr_extra_acked(sk)) ++ >> BBR_SCALE; ++ aggr_cwnd = min(aggr_cwnd, max_aggr_cwnd); ++ } ++ ++ return aggr_cwnd; ++} ++ ++/* Returns the cwnd for PROBE_RTT mode. */ ++static u32 bbr_probe_rtt_cwnd(struct sock *sk) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ if (bbr->params.probe_rtt_cwnd_gain == 0) ++ return bbr->params.cwnd_min_target; ++ return max_t(u32, bbr->params.cwnd_min_target, ++ bbr_bdp(sk, bbr_bw(sk), bbr->params.probe_rtt_cwnd_gain)); ++} ++ ++/* Slow-start up toward target cwnd (if bw estimate is growing, or packet loss ++ * has drawn us down below target), or snap down to target if we're above it. ++ */ ++static void bbr_set_cwnd(struct sock *sk, const struct rate_sample *rs, ++ u32 acked, u32 bw, int gain, u32 cwnd, ++ struct bbr_context *ctx) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ u32 target_cwnd = 0, prev_cwnd = tp->snd_cwnd, max_probe; ++ ++ if (!acked) ++ goto done; /* no packet fully ACKed; just apply caps */ ++ ++ target_cwnd = bbr_bdp(sk, bw, gain); ++ ++ /* Increment the cwnd to account for excess ACKed data that seems ++ * due to aggregation (of data and/or ACKs) visible in the ACK stream. ++ */ ++ target_cwnd += bbr_ack_aggregation_cwnd(sk); ++ target_cwnd = bbr_quantization_budget(sk, target_cwnd); ++ ++ /* If we're below target cwnd, slow start cwnd toward target cwnd. */ ++ bbr->debug.target_cwnd = target_cwnd; ++ ++ /* Update cwnd and enable fast path if cwnd reaches target_cwnd. */ ++ bbr->try_fast_path = 0; ++ if (bbr_full_bw_reached(sk)) { /* only cut cwnd if we filled the pipe */ ++ cwnd += acked; ++ if (cwnd >= target_cwnd) { ++ cwnd = target_cwnd; ++ bbr->try_fast_path = 1; ++ } ++ } else if (cwnd < target_cwnd || cwnd < 2 * bbr->init_cwnd) { ++ cwnd += acked; ++ } else { ++ bbr->try_fast_path = 1; ++ } ++ ++ /* When growing cwnd, don't grow beyond twice what we just probed. */ ++ if (bbr->params.usage_based_cwnd) { ++ max_probe = max(2 * tp->max_packets_out, tp->snd_cwnd); ++ cwnd = min(cwnd, max_probe); ++ } ++ ++ cwnd = max_t(u32, cwnd, bbr->params.cwnd_min_target); ++done: ++ tp->snd_cwnd = min(cwnd, tp->snd_cwnd_clamp); /* apply global cap */ ++ if (bbr->mode == BBR_PROBE_RTT) /* drain queue, refresh min_rtt */ ++ tp->snd_cwnd = min_t(u32, tp->snd_cwnd, bbr_probe_rtt_cwnd(sk)); ++ ++ ctx->target_cwnd = target_cwnd; ++ ctx->log = (tp->snd_cwnd != prev_cwnd); ++} ++ ++/* See if we have reached next round trip */ ++static void bbr_update_round_start(struct sock *sk, ++ const struct rate_sample *rs, struct bbr_context *ctx) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ bbr->round_start = 0; ++ ++ /* See if we've reached the next RTT */ ++ if (rs->interval_us > 0 && ++ !before(rs->prior_delivered, bbr->next_rtt_delivered)) { ++ bbr->next_rtt_delivered = tp->delivered; ++ bbr->round_start = 1; ++ } ++} ++ ++/* Calculate the bandwidth based on how fast packets are delivered */ ++static void bbr_calculate_bw_sample(struct sock *sk, ++ const struct rate_sample *rs, struct bbr_context *ctx) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ u64 bw = 0; ++ ++ /* Divide delivered by the interval to find a (lower bound) bottleneck ++ * bandwidth sample. Delivered is in packets and interval_us in uS and ++ * ratio will be <<1 for most connections. So delivered is first scaled. ++ * Round up to allow growth at low rates, even with integer division. ++ */ ++ if (rs->interval_us > 0) { ++ if (WARN_ONCE(rs->delivered < 0, ++ "negative delivered: %d interval_us: %ld\n", ++ rs->delivered, rs->interval_us)) ++ return; ++ ++ bw = DIV_ROUND_UP_ULL((u64)rs->delivered * BW_UNIT, rs->interval_us); ++ } ++ ++ ctx->sample_bw = bw; ++ bbr->debug.rs_bw = bw; ++} ++ ++/* Estimates the windowed max degree of ack aggregation. ++ * This is used to provision extra in-flight data to keep sending during ++ * inter-ACK silences. ++ * ++ * Degree of ack aggregation is estimated as extra data acked beyond expected. ++ * ++ * max_extra_acked = "maximum recent excess data ACKed beyond max_bw * interval" ++ * cwnd += max_extra_acked ++ * ++ * Max extra_acked is clamped by cwnd and bw * bbr_extra_acked_max_us (100 ms). ++ * Max filter is an approximate sliding window of 5-10 (packet timed) round ++ * trips for non-startup phase, and 1-2 round trips for startup. ++ */ ++static void bbr_update_ack_aggregation(struct sock *sk, ++ const struct rate_sample *rs) ++{ ++ u32 epoch_us, expected_acked, extra_acked; ++ struct bbr *bbr = inet_csk_ca(sk); ++ struct tcp_sock *tp = tcp_sk(sk); ++ u32 extra_acked_win_rtts_thresh = bbr->params.extra_acked_win_rtts; ++ ++ if (!bbr->params.extra_acked_gain || rs->acked_sacked <= 0 || ++ rs->delivered < 0 || rs->interval_us <= 0) ++ return; ++ ++ if (bbr->round_start) { ++ bbr->extra_acked_win_rtts = min(0x1F, ++ bbr->extra_acked_win_rtts + 1); ++ if (bbr->params.extra_acked_in_startup && ++ !bbr_full_bw_reached(sk)) ++ extra_acked_win_rtts_thresh = 1; ++ if (bbr->extra_acked_win_rtts >= ++ extra_acked_win_rtts_thresh) { ++ bbr->extra_acked_win_rtts = 0; ++ bbr->extra_acked_win_idx = bbr->extra_acked_win_idx ? ++ 0 : 1; ++ bbr->extra_acked[bbr->extra_acked_win_idx] = 0; ++ } ++ } ++ ++ /* Compute how many packets we expected to be delivered over epoch. */ ++ epoch_us = tcp_stamp_us_delta(tp->delivered_mstamp, ++ bbr->ack_epoch_mstamp); ++ expected_acked = ((u64)bbr_bw(sk) * epoch_us) / BW_UNIT; ++ ++ /* Reset the aggregation epoch if ACK rate is below expected rate or ++ * significantly large no. of ack received since epoch (potentially ++ * quite old epoch). ++ */ ++ if (bbr->ack_epoch_acked <= expected_acked || ++ (bbr->ack_epoch_acked + rs->acked_sacked >= ++ bbr_ack_epoch_acked_reset_thresh)) { ++ bbr->ack_epoch_acked = 0; ++ bbr->ack_epoch_mstamp = tp->delivered_mstamp; ++ expected_acked = 0; ++ } ++ ++ /* Compute excess data delivered, beyond what was expected. */ ++ bbr->ack_epoch_acked = min_t(u32, 0xFFFFF, ++ bbr->ack_epoch_acked + rs->acked_sacked); ++ extra_acked = bbr->ack_epoch_acked - expected_acked; ++ extra_acked = min(extra_acked, tp->snd_cwnd); ++ if (extra_acked > bbr->extra_acked[bbr->extra_acked_win_idx]) ++ bbr->extra_acked[bbr->extra_acked_win_idx] = extra_acked; ++} ++ ++/* Estimate when the pipe is full, using the change in delivery rate: BBR ++ * estimates that STARTUP filled the pipe if the estimated bw hasn't changed by ++ * at least bbr_full_bw_thresh (25%) after bbr_full_bw_cnt (3) non-app-limited ++ * rounds. Why 3 rounds: 1: rwin autotuning grows the rwin, 2: we fill the ++ * higher rwin, 3: we get higher delivery rate samples. Or transient ++ * cross-traffic or radio noise can go away. CUBIC Hystart shares a similar ++ * design goal, but uses delay and inter-ACK spacing instead of bandwidth. ++ */ ++static void bbr_check_full_bw_reached(struct sock *sk, ++ const struct rate_sample *rs) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ u32 bw_thresh; ++ ++ if (bbr_full_bw_reached(sk) || !bbr->round_start || rs->is_app_limited) ++ return; ++ ++ bw_thresh = (u64)bbr->full_bw * bbr->params.full_bw_thresh >> BBR_SCALE; ++ if (bbr_max_bw(sk) >= bw_thresh) { ++ bbr->full_bw = bbr_max_bw(sk); ++ bbr->full_bw_cnt = 0; ++ return; ++ } ++ ++bbr->full_bw_cnt; ++ bbr->full_bw_reached = bbr->full_bw_cnt >= bbr->params.full_bw_cnt; ++} ++ ++/* If pipe is probably full, drain the queue and then enter steady-state. */ ++static bool bbr_check_drain(struct sock *sk, const struct rate_sample *rs, ++ struct bbr_context *ctx) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ if (bbr->mode == BBR_STARTUP && bbr_full_bw_reached(sk)) { ++ bbr->mode = BBR_DRAIN; /* drain queue we created */ ++ tcp_sk(sk)->snd_ssthresh = ++ bbr_inflight(sk, bbr_max_bw(sk), BBR_UNIT); ++ bbr2_reset_congestion_signals(sk); ++ } /* fall through to check if in-flight is already small: */ ++ if (bbr->mode == BBR_DRAIN && ++ bbr_packets_in_net_at_edt(sk, tcp_packets_in_flight(tcp_sk(sk))) <= ++ bbr_inflight(sk, bbr_max_bw(sk), BBR_UNIT)) ++ return true; /* exiting DRAIN now */ ++ return false; ++} ++ ++static void bbr_check_probe_rtt_done(struct sock *sk) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ if (!(bbr->probe_rtt_done_stamp && ++ after(tcp_jiffies32, bbr->probe_rtt_done_stamp))) ++ return; ++ ++ bbr->probe_rtt_min_stamp = tcp_jiffies32; /* schedule next PROBE_RTT */ ++ tp->snd_cwnd = max(tp->snd_cwnd, bbr->prior_cwnd); ++ bbr2_exit_probe_rtt(sk); ++} ++ ++/* The goal of PROBE_RTT mode is to have BBR flows cooperatively and ++ * periodically drain the bottleneck queue, to converge to measure the true ++ * min_rtt (unloaded propagation delay). This allows the flows to keep queues ++ * small (reducing queuing delay and packet loss) and achieve fairness among ++ * BBR flows. ++ * ++ * The min_rtt filter window is 10 seconds. When the min_rtt estimate expires, ++ * we enter PROBE_RTT mode and cap the cwnd at bbr_cwnd_min_target=4 packets. ++ * After at least bbr_probe_rtt_mode_ms=200ms and at least one packet-timed ++ * round trip elapsed with that flight size <= 4, we leave PROBE_RTT mode and ++ * re-enter the previous mode. BBR uses 200ms to approximately bound the ++ * performance penalty of PROBE_RTT's cwnd capping to roughly 2% (200ms/10s). ++ * ++ * Note that flows need only pay 2% if they are busy sending over the last 10 ++ * seconds. Interactive applications (e.g., Web, RPCs, video chunks) often have ++ * natural silences or low-rate periods within 10 seconds where the rate is low ++ * enough for long enough to drain its queue in the bottleneck. We pick up ++ * these min RTT measurements opportunistically with our min_rtt filter. :-) ++ */ ++static void bbr_update_min_rtt(struct sock *sk, const struct rate_sample *rs) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ bool probe_rtt_expired, min_rtt_expired; ++ u32 expire; ++ ++ /* Track min RTT in probe_rtt_win_ms to time next PROBE_RTT state. */ ++ expire = bbr->probe_rtt_min_stamp + ++ msecs_to_jiffies(bbr->params.probe_rtt_win_ms); ++ probe_rtt_expired = after(tcp_jiffies32, expire); ++ if (rs->rtt_us >= 0 && ++ (rs->rtt_us <= bbr->probe_rtt_min_us || ++ (probe_rtt_expired && !rs->is_ack_delayed))) { ++ bbr->probe_rtt_min_us = rs->rtt_us; ++ bbr->probe_rtt_min_stamp = tcp_jiffies32; ++ } ++ /* Track min RTT seen in the min_rtt_win_sec filter window: */ ++ expire = bbr->min_rtt_stamp + bbr->params.min_rtt_win_sec * HZ; ++ min_rtt_expired = after(tcp_jiffies32, expire); ++ if (bbr->probe_rtt_min_us <= bbr->min_rtt_us || ++ min_rtt_expired) { ++ bbr->min_rtt_us = bbr->probe_rtt_min_us; ++ bbr->min_rtt_stamp = bbr->probe_rtt_min_stamp; ++ } ++ ++ if (bbr->params.probe_rtt_mode_ms > 0 && probe_rtt_expired && ++ !bbr->idle_restart && bbr->mode != BBR_PROBE_RTT) { ++ bbr->mode = BBR_PROBE_RTT; /* dip, drain queue */ ++ bbr_save_cwnd(sk); /* note cwnd so we can restore it */ ++ bbr->probe_rtt_done_stamp = 0; ++ bbr->ack_phase = BBR_ACKS_PROBE_STOPPING; ++ bbr->next_rtt_delivered = tp->delivered; ++ } ++ ++ if (bbr->mode == BBR_PROBE_RTT) { ++ /* Ignore low rate samples during this mode. */ ++ tp->app_limited = ++ (tp->delivered + tcp_packets_in_flight(tp)) ? : 1; ++ /* Maintain min packets in flight for max(200 ms, 1 round). */ ++ if (!bbr->probe_rtt_done_stamp && ++ tcp_packets_in_flight(tp) <= bbr_probe_rtt_cwnd(sk)) { ++ bbr->probe_rtt_done_stamp = tcp_jiffies32 + ++ msecs_to_jiffies(bbr->params.probe_rtt_mode_ms); ++ bbr->probe_rtt_round_done = 0; ++ bbr->next_rtt_delivered = tp->delivered; ++ } else if (bbr->probe_rtt_done_stamp) { ++ if (bbr->round_start) ++ bbr->probe_rtt_round_done = 1; ++ if (bbr->probe_rtt_round_done) ++ bbr_check_probe_rtt_done(sk); ++ } ++ } ++ /* Restart after idle ends only once we process a new S/ACK for data */ ++ if (rs->delivered > 0) ++ bbr->idle_restart = 0; ++} ++ ++static void bbr_update_gains(struct sock *sk) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ switch (bbr->mode) { ++ case BBR_STARTUP: ++ bbr->pacing_gain = bbr->params.high_gain; ++ bbr->cwnd_gain = bbr->params.startup_cwnd_gain; ++ break; ++ case BBR_DRAIN: ++ bbr->pacing_gain = bbr->params.drain_gain; /* slow, to drain */ ++ bbr->cwnd_gain = bbr->params.startup_cwnd_gain; /* keep cwnd */ ++ break; ++ case BBR_PROBE_BW: ++ bbr->pacing_gain = bbr->params.pacing_gain[bbr->cycle_idx]; ++ bbr->cwnd_gain = bbr->params.cwnd_gain; ++ break; ++ case BBR_PROBE_RTT: ++ bbr->pacing_gain = BBR_UNIT; ++ bbr->cwnd_gain = BBR_UNIT; ++ break; ++ default: ++ WARN_ONCE(1, "BBR bad mode: %u\n", bbr->mode); ++ break; ++ } ++} ++ ++static void bbr_init(struct sock *sk) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ int i; ++ ++ WARN_ON_ONCE(tp->snd_cwnd >= bbr_cwnd_warn_val); ++ ++ bbr->initialized = 1; ++ bbr->params.high_gain = min(0x7FF, bbr_high_gain); ++ bbr->params.drain_gain = min(0x3FF, bbr_drain_gain); ++ bbr->params.startup_cwnd_gain = min(0x7FF, bbr_startup_cwnd_gain); ++ bbr->params.cwnd_gain = min(0x7FF, bbr_cwnd_gain); ++ bbr->params.cwnd_tso_budget = min(0x1U, bbr_cwnd_tso_budget); ++ bbr->params.cwnd_min_target = min(0xFU, bbr_cwnd_min_target); ++ bbr->params.min_rtt_win_sec = min(0x1FU, bbr_min_rtt_win_sec); ++ bbr->params.probe_rtt_mode_ms = min(0x1FFU, bbr_probe_rtt_mode_ms); ++ bbr->params.full_bw_cnt = min(0x7U, bbr_full_bw_cnt); ++ bbr->params.full_bw_thresh = min(0x3FFU, bbr_full_bw_thresh); ++ bbr->params.extra_acked_gain = min(0x7FF, bbr_extra_acked_gain); ++ bbr->params.extra_acked_win_rtts = min(0x1FU, bbr_extra_acked_win_rtts); ++ bbr->params.drain_to_target = bbr_drain_to_target ? 1 : 0; ++ bbr->params.precise_ece_ack = bbr_precise_ece_ack ? 1 : 0; ++ bbr->params.extra_acked_in_startup = bbr_extra_acked_in_startup ? 1 : 0; ++ bbr->params.probe_rtt_cwnd_gain = min(0xFFU, bbr_probe_rtt_cwnd_gain); ++ bbr->params.probe_rtt_win_ms = ++ min(0x3FFFU, ++ min_t(u32, bbr_probe_rtt_win_ms, ++ bbr->params.min_rtt_win_sec * MSEC_PER_SEC)); ++ for (i = 0; i < CYCLE_LEN; i++) ++ bbr->params.pacing_gain[i] = min(0x3FF, bbr_pacing_gain[i]); ++ bbr->params.usage_based_cwnd = bbr_usage_based_cwnd ? 1 : 0; ++ bbr->params.tso_rtt_shift = min(0xFU, bbr_tso_rtt_shift); ++ ++ bbr->debug.snd_isn = tp->snd_una; ++ bbr->debug.target_cwnd = 0; ++ bbr->debug.undo = 0; ++ ++ bbr->init_cwnd = min(0x7FU, tp->snd_cwnd); ++ bbr->prior_cwnd = tp->prior_cwnd; ++ tp->snd_ssthresh = TCP_INFINITE_SSTHRESH; ++ bbr->next_rtt_delivered = 0; ++ bbr->prev_ca_state = TCP_CA_Open; ++ bbr->packet_conservation = 0; ++ ++ bbr->probe_rtt_done_stamp = 0; ++ bbr->probe_rtt_round_done = 0; ++ bbr->probe_rtt_min_us = tcp_min_rtt(tp); ++ bbr->probe_rtt_min_stamp = tcp_jiffies32; ++ bbr->min_rtt_us = tcp_min_rtt(tp); ++ bbr->min_rtt_stamp = tcp_jiffies32; ++ ++ bbr->has_seen_rtt = 0; ++ bbr_init_pacing_rate_from_rtt(sk); ++ ++ bbr->round_start = 0; ++ bbr->idle_restart = 0; ++ bbr->full_bw_reached = 0; ++ bbr->full_bw = 0; ++ bbr->full_bw_cnt = 0; ++ bbr->cycle_mstamp = 0; ++ bbr->cycle_idx = 0; ++ bbr->mode = BBR_STARTUP; ++ bbr->debug.rs_bw = 0; ++ ++ bbr->ack_epoch_mstamp = tp->tcp_mstamp; ++ bbr->ack_epoch_acked = 0; ++ bbr->extra_acked_win_rtts = 0; ++ bbr->extra_acked_win_idx = 0; ++ bbr->extra_acked[0] = 0; ++ bbr->extra_acked[1] = 0; ++ ++ bbr->ce_state = 0; ++ bbr->prior_rcv_nxt = tp->rcv_nxt; ++ bbr->try_fast_path = 0; ++ ++ cmpxchg(&sk->sk_pacing_status, SK_PACING_NONE, SK_PACING_NEEDED); ++} ++ ++static u32 bbr_sndbuf_expand(struct sock *sk) ++{ ++ /* Provision 3 * cwnd since BBR may slow-start even during recovery. */ ++ return 3; ++} ++ ++/* __________________________________________________________________________ ++ * ++ * Functions new to BBR v2 ("bbr") congestion control are below here. ++ * __________________________________________________________________________ ++ */ ++ ++/* Incorporate a new bw sample into the current window of our max filter. */ ++static void bbr2_take_bw_hi_sample(struct sock *sk, u32 bw) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ bbr->bw_hi[1] = max(bw, bbr->bw_hi[1]); ++} ++ ++/* Keep max of last 1-2 cycles. Each PROBE_BW cycle, flip filter window. */ ++static void bbr2_advance_bw_hi_filter(struct sock *sk) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ if (!bbr->bw_hi[1]) ++ return; /* no samples in this window; remember old window */ ++ bbr->bw_hi[0] = bbr->bw_hi[1]; ++ bbr->bw_hi[1] = 0; ++} ++ ++/* How much do we want in flight? Our BDP, unless congestion cut cwnd. */ ++static u32 bbr2_target_inflight(struct sock *sk) ++{ ++ u32 bdp = bbr_inflight(sk, bbr_bw(sk), BBR_UNIT); ++ ++ return min(bdp, tcp_sk(sk)->snd_cwnd); ++} ++ ++static bool bbr2_is_probing_bandwidth(struct sock *sk) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ return (bbr->mode == BBR_STARTUP) || ++ (bbr->mode == BBR_PROBE_BW && ++ (bbr->cycle_idx == BBR_BW_PROBE_REFILL || ++ bbr->cycle_idx == BBR_BW_PROBE_UP)); ++} ++ ++/* Has the given amount of time elapsed since we marked the phase start? */ ++static bool bbr2_has_elapsed_in_phase(const struct sock *sk, u32 interval_us) ++{ ++ const struct tcp_sock *tp = tcp_sk(sk); ++ const struct bbr *bbr = inet_csk_ca(sk); ++ ++ return tcp_stamp_us_delta(tp->tcp_mstamp, ++ bbr->cycle_mstamp + interval_us) > 0; ++} ++ ++static void bbr2_handle_queue_too_high_in_startup(struct sock *sk) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ bbr->full_bw_reached = 1; ++ bbr->inflight_hi = bbr_inflight(sk, bbr_max_bw(sk), BBR_UNIT); ++} ++ ++/* Exit STARTUP upon N consecutive rounds with ECN mark rate > ecn_thresh. */ ++static void bbr2_check_ecn_too_high_in_startup(struct sock *sk, u32 ce_ratio) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ if (bbr_full_bw_reached(sk) || !bbr->ecn_eligible || ++ !bbr->params.full_ecn_cnt || !bbr->params.ecn_thresh) ++ return; ++ ++ if (ce_ratio >= bbr->params.ecn_thresh) ++ bbr->startup_ecn_rounds++; ++ else ++ bbr->startup_ecn_rounds = 0; ++ ++ if (bbr->startup_ecn_rounds >= bbr->params.full_ecn_cnt) { ++ bbr->debug.event = 'E'; /* ECN caused STARTUP exit */ ++ bbr2_handle_queue_too_high_in_startup(sk); ++ return; ++ } ++} ++ ++static void bbr2_update_ecn_alpha(struct sock *sk) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ s32 delivered, delivered_ce; ++ u64 alpha, ce_ratio; ++ u32 gain; ++ ++ if (bbr->params.ecn_factor == 0) ++ return; ++ ++ delivered = tp->delivered - bbr->alpha_last_delivered; ++ delivered_ce = tp->delivered_ce - bbr->alpha_last_delivered_ce; ++ ++ if (delivered == 0 || /* avoid divide by zero */ ++ WARN_ON_ONCE(delivered < 0 || delivered_ce < 0)) /* backwards? */ ++ return; ++ ++ /* See if we should use ECN sender logic for this connection. */ ++ if (!bbr->ecn_eligible && bbr_ecn_enable && ++ (bbr->min_rtt_us <= bbr->params.ecn_max_rtt_us || ++ !bbr->params.ecn_max_rtt_us)) ++ bbr->ecn_eligible = 1; ++ ++ ce_ratio = (u64)delivered_ce << BBR_SCALE; ++ do_div(ce_ratio, delivered); ++ gain = bbr->params.ecn_alpha_gain; ++ alpha = ((BBR_UNIT - gain) * bbr->ecn_alpha) >> BBR_SCALE; ++ alpha += (gain * ce_ratio) >> BBR_SCALE; ++ bbr->ecn_alpha = min_t(u32, alpha, BBR_UNIT); ++ ++ bbr->alpha_last_delivered = tp->delivered; ++ bbr->alpha_last_delivered_ce = tp->delivered_ce; ++ ++ bbr2_check_ecn_too_high_in_startup(sk, ce_ratio); ++} ++ ++/* Each round trip of BBR_BW_PROBE_UP, double volume of probing data. */ ++static void bbr2_raise_inflight_hi_slope(struct sock *sk) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ u32 growth_this_round, cnt; ++ ++ /* Calculate "slope": packets S/Acked per inflight_hi increment. */ ++ growth_this_round = 1 << bbr->bw_probe_up_rounds; ++ bbr->bw_probe_up_rounds = min(bbr->bw_probe_up_rounds + 1, 30); ++ cnt = tp->snd_cwnd / growth_this_round; ++ cnt = max(cnt, 1U); ++ bbr->bw_probe_up_cnt = cnt; ++ bbr->debug.event = 'G'; /* Grow inflight_hi slope */ ++} ++ ++/* In BBR_BW_PROBE_UP, not seeing high loss/ECN/queue, so raise inflight_hi. */ ++static void bbr2_probe_inflight_hi_upward(struct sock *sk, ++ const struct rate_sample *rs) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ u32 delta; ++ ++ if (!tp->is_cwnd_limited || tp->snd_cwnd < bbr->inflight_hi) { ++ bbr->bw_probe_up_acks = 0; /* don't accmulate unused credits */ ++ return; /* not fully using inflight_hi, so don't grow it */ ++ } ++ ++ /* For each bw_probe_up_cnt packets ACKed, increase inflight_hi by 1. */ ++ bbr->bw_probe_up_acks += rs->acked_sacked; ++ if (bbr->bw_probe_up_acks >= bbr->bw_probe_up_cnt) { ++ delta = bbr->bw_probe_up_acks / bbr->bw_probe_up_cnt; ++ bbr->bw_probe_up_acks -= delta * bbr->bw_probe_up_cnt; ++ bbr->inflight_hi += delta; ++ bbr->debug.event = 'I'; /* Increment inflight_hi */ ++ } ++ ++ if (bbr->round_start) ++ bbr2_raise_inflight_hi_slope(sk); ++} ++ ++/* Does loss/ECN rate for this sample say inflight is "too high"? ++ * This is used by both the bbr_check_loss_too_high_in_startup() function, ++ * which can be used in either v1 or v2, and the PROBE_UP phase of v2, which ++ * uses it to notice when loss/ECN rates suggest inflight is too high. ++ */ ++static bool bbr2_is_inflight_too_high(const struct sock *sk, ++ const struct rate_sample *rs) ++{ ++ const struct bbr *bbr = inet_csk_ca(sk); ++ u32 loss_thresh, ecn_thresh; ++ ++ if (rs->lost > 0 && rs->tx_in_flight) { ++ loss_thresh = (u64)rs->tx_in_flight * bbr->params.loss_thresh >> ++ BBR_SCALE; ++ if (rs->lost > loss_thresh) ++ return true; ++ } ++ ++ if (rs->delivered_ce > 0 && rs->delivered > 0 && ++ bbr->ecn_eligible && bbr->params.ecn_thresh) { ++ ecn_thresh = (u64)rs->delivered * bbr->params.ecn_thresh >> ++ BBR_SCALE; ++ if (rs->delivered_ce >= ecn_thresh) ++ return true; ++ } ++ ++ return false; ++} ++ ++/* Calculate the tx_in_flight level that corresponded to excessive loss. ++ * We find "lost_prefix" segs of the skb where loss rate went too high, ++ * by solving for "lost_prefix" in the following equation: ++ * lost / inflight >= loss_thresh ++ * (lost_prev + lost_prefix) / (inflight_prev + lost_prefix) >= loss_thresh ++ * Then we take that equation, convert it to fixed point, and ++ * round up to the nearest packet. ++ */ ++static u32 bbr2_inflight_hi_from_lost_skb(const struct sock *sk, ++ const struct rate_sample *rs, ++ const struct sk_buff *skb) ++{ ++ const struct bbr *bbr = inet_csk_ca(sk); ++ u32 loss_thresh = bbr->params.loss_thresh; ++ u32 pcount, divisor, inflight_hi; ++ s32 inflight_prev, lost_prev; ++ u64 loss_budget, lost_prefix; ++ ++ pcount = tcp_skb_pcount(skb); ++ ++ /* How much data was in flight before this skb? */ ++ inflight_prev = rs->tx_in_flight - pcount; ++ if (WARN_ONCE(inflight_prev < 0, ++ "tx_in_flight: %u pcount: %u reneg: %u", ++ rs->tx_in_flight, pcount, tcp_sk(sk)->is_sack_reneg)) ++ return ~0U; ++ ++ /* How much inflight data was marked lost before this skb? */ ++ lost_prev = rs->lost - pcount; ++ if (WARN_ON_ONCE(lost_prev < 0)) ++ return ~0U; ++ ++ /* At what prefix of this lost skb did losss rate exceed loss_thresh? */ ++ loss_budget = (u64)inflight_prev * loss_thresh + BBR_UNIT - 1; ++ loss_budget >>= BBR_SCALE; ++ if (lost_prev >= loss_budget) { ++ lost_prefix = 0; /* previous losses crossed loss_thresh */ ++ } else { ++ lost_prefix = loss_budget - lost_prev; ++ lost_prefix <<= BBR_SCALE; ++ divisor = BBR_UNIT - loss_thresh; ++ if (WARN_ON_ONCE(!divisor)) /* loss_thresh is 8 bits */ ++ return ~0U; ++ do_div(lost_prefix, divisor); ++ } ++ ++ inflight_hi = inflight_prev + lost_prefix; ++ return inflight_hi; ++} ++ ++/* If loss/ECN rates during probing indicated we may have overfilled a ++ * buffer, return an operating point that tries to leave unutilized headroom in ++ * the path for other flows, for fairness convergence and lower RTTs and loss. ++ */ ++static u32 bbr2_inflight_with_headroom(const struct sock *sk) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ u32 headroom, headroom_fraction; ++ ++ if (bbr->inflight_hi == ~0U) ++ return ~0U; ++ ++ headroom_fraction = bbr->params.inflight_headroom; ++ headroom = ((u64)bbr->inflight_hi * headroom_fraction) >> BBR_SCALE; ++ headroom = max(headroom, 1U); ++ return max_t(s32, bbr->inflight_hi - headroom, ++ bbr->params.cwnd_min_target); ++} ++ ++/* Bound cwnd to a sensible level, based on our current probing state ++ * machine phase and model of a good inflight level (inflight_lo, inflight_hi). ++ */ ++static void bbr2_bound_cwnd_for_inflight_model(struct sock *sk) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ u32 cap; ++ ++ /* tcp_rcv_synsent_state_process() currently calls tcp_ack() ++ * and thus cong_control() without first initializing us(!). ++ */ ++ if (!bbr->initialized) ++ return; ++ ++ cap = ~0U; ++ if (bbr->mode == BBR_PROBE_BW && ++ bbr->cycle_idx != BBR_BW_PROBE_CRUISE) { ++ /* Probe to see if more packets fit in the path. */ ++ cap = bbr->inflight_hi; ++ } else { ++ if (bbr->mode == BBR_PROBE_RTT || ++ (bbr->mode == BBR_PROBE_BW && ++ bbr->cycle_idx == BBR_BW_PROBE_CRUISE)) ++ cap = bbr2_inflight_with_headroom(sk); ++ } ++ /* Adapt to any loss/ECN since our last bw probe. */ ++ cap = min(cap, bbr->inflight_lo); ++ ++ cap = max_t(u32, cap, bbr->params.cwnd_min_target); ++ tp->snd_cwnd = min(cap, tp->snd_cwnd); ++} ++ ++/* Estimate a short-term lower bound on the capacity available now, based ++ * on measurements of the current delivery process and recent history. When we ++ * are seeing loss/ECN at times when we are not probing bw, then conservatively ++ * move toward flow balance by multiplicatively cutting our short-term ++ * estimated safe rate and volume of data (bw_lo and inflight_lo). We use a ++ * multiplicative decrease in order to converge to a lower capacity in time ++ * logarithmic in the magnitude of the decrease. ++ * ++ * However, we do not cut our short-term estimates lower than the current rate ++ * and volume of delivered data from this round trip, since from the current ++ * delivery process we can estimate the measured capacity available now. ++ * ++ * Anything faster than that approach would knowingly risk high loss, which can ++ * cause low bw for Reno/CUBIC and high loss recovery latency for ++ * request/response flows using any congestion control. ++ */ ++static void bbr2_adapt_lower_bounds(struct sock *sk) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ u32 ecn_cut, ecn_inflight_lo, beta; ++ ++ /* We only use lower-bound estimates when not probing bw. ++ * When probing we need to push inflight higher to probe bw. ++ */ ++ if (bbr2_is_probing_bandwidth(sk)) ++ return; ++ ++ /* ECN response. */ ++ if (bbr->ecn_in_round && bbr->ecn_eligible && bbr->params.ecn_factor) { ++ /* Reduce inflight to (1 - alpha*ecn_factor). */ ++ ecn_cut = (BBR_UNIT - ++ ((bbr->ecn_alpha * bbr->params.ecn_factor) >> ++ BBR_SCALE)); ++ if (bbr->inflight_lo == ~0U) ++ bbr->inflight_lo = tp->snd_cwnd; ++ ecn_inflight_lo = (u64)bbr->inflight_lo * ecn_cut >> BBR_SCALE; ++ } else { ++ ecn_inflight_lo = ~0U; ++ } ++ ++ /* Loss response. */ ++ if (bbr->loss_in_round) { ++ /* Reduce bw and inflight to (1 - beta). */ ++ if (bbr->bw_lo == ~0U) ++ bbr->bw_lo = bbr_max_bw(sk); ++ if (bbr->inflight_lo == ~0U) ++ bbr->inflight_lo = tp->snd_cwnd; ++ beta = bbr->params.beta; ++ bbr->bw_lo = ++ max_t(u32, bbr->bw_latest, ++ (u64)bbr->bw_lo * ++ (BBR_UNIT - beta) >> BBR_SCALE); ++ bbr->inflight_lo = ++ max_t(u32, bbr->inflight_latest, ++ (u64)bbr->inflight_lo * ++ (BBR_UNIT - beta) >> BBR_SCALE); ++ } ++ ++ /* Adjust to the lower of the levels implied by loss or ECN. */ ++ bbr->inflight_lo = min(bbr->inflight_lo, ecn_inflight_lo); ++} ++ ++/* Reset any short-term lower-bound adaptation to congestion, so that we can ++ * push our inflight up. ++ */ ++static void bbr2_reset_lower_bounds(struct sock *sk) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ bbr->bw_lo = ~0U; ++ bbr->inflight_lo = ~0U; ++} ++ ++/* After bw probing (STARTUP/PROBE_UP), reset signals before entering a state ++ * machine phase where we adapt our lower bound based on congestion signals. ++ */ ++static void bbr2_reset_congestion_signals(struct sock *sk) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ bbr->loss_in_round = 0; ++ bbr->ecn_in_round = 0; ++ bbr->loss_in_cycle = 0; ++ bbr->ecn_in_cycle = 0; ++ bbr->bw_latest = 0; ++ bbr->inflight_latest = 0; ++} ++ ++/* Update (most of) our congestion signals: track the recent rate and volume of ++ * delivered data, presence of loss, and EWMA degree of ECN marking. ++ */ ++static void bbr2_update_congestion_signals( ++ struct sock *sk, const struct rate_sample *rs, struct bbr_context *ctx) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ u64 bw; ++ ++ bbr->loss_round_start = 0; ++ if (rs->interval_us <= 0 || !rs->acked_sacked) ++ return; /* Not a valid observation */ ++ bw = ctx->sample_bw; ++ ++ if (!rs->is_app_limited || bw >= bbr_max_bw(sk)) ++ bbr2_take_bw_hi_sample(sk, bw); ++ ++ bbr->loss_in_round |= (rs->losses > 0); ++ ++ /* Update rate and volume of delivered data from latest round trip: */ ++ bbr->bw_latest = max_t(u32, bbr->bw_latest, ctx->sample_bw); ++ bbr->inflight_latest = max_t(u32, bbr->inflight_latest, rs->delivered); ++ ++ if (before(rs->prior_delivered, bbr->loss_round_delivered)) ++ return; /* skip the per-round-trip updates */ ++ /* Now do per-round-trip updates. */ ++ bbr->loss_round_delivered = tp->delivered; /* mark round trip */ ++ bbr->loss_round_start = 1; ++ bbr2_adapt_lower_bounds(sk); ++ ++ /* Update windowed "latest" (single-round-trip) filters. */ ++ bbr->loss_in_round = 0; ++ bbr->ecn_in_round = 0; ++ bbr->bw_latest = ctx->sample_bw; ++ bbr->inflight_latest = rs->delivered; ++} ++ ++/* Bandwidth probing can cause loss. To help coexistence with loss-based ++ * congestion control we spread out our probing in a Reno-conscious way. Due to ++ * the shape of the Reno sawtooth, the time required between loss epochs for an ++ * idealized Reno flow is a number of round trips that is the BDP of that ++ * flow. We count packet-timed round trips directly, since measured RTT can ++ * vary widely, and Reno is driven by packet-timed round trips. ++ */ ++static bool bbr2_is_reno_coexistence_probe_time(struct sock *sk) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ u32 inflight, rounds, reno_gain, reno_rounds; ++ ++ /* Random loss can shave some small percentage off of our inflight ++ * in each round. To survive this, flows need robust periodic probes. ++ */ ++ rounds = bbr->params.bw_probe_max_rounds; ++ ++ reno_gain = bbr->params.bw_probe_reno_gain; ++ if (reno_gain) { ++ inflight = bbr2_target_inflight(sk); ++ reno_rounds = ((u64)inflight * reno_gain) >> BBR_SCALE; ++ rounds = min(rounds, reno_rounds); ++ } ++ return bbr->rounds_since_probe >= rounds; ++} ++ ++/* How long do we want to wait before probing for bandwidth (and risking ++ * loss)? We randomize the wait, for better mixing and fairness convergence. ++ * ++ * We bound the Reno-coexistence inter-bw-probe time to be 62-63 round trips. ++ * This is calculated to allow fairness with a 25Mbps, 30ms Reno flow, ++ * (eg 4K video to a broadband user): ++ * BDP = 25Mbps * .030sec /(1514bytes) = 61.9 packets ++ * ++ * We bound the BBR-native inter-bw-probe wall clock time to be: ++ * (a) higher than 2 sec: to try to avoid causing loss for a long enough time ++ * to allow Reno at 30ms to get 4K video bw, the inter-bw-probe time must ++ * be at least: 25Mbps * .030sec / (1514bytes) * 0.030sec = 1.9secs ++ * (b) lower than 3 sec: to ensure flows can start probing in a reasonable ++ * amount of time to discover unutilized bw on human-scale interactive ++ * time-scales (e.g. perhaps traffic from a web page download that we ++ * were competing with is now complete). ++ */ ++static void bbr2_pick_probe_wait(struct sock *sk) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ /* Decide the random round-trip bound for wait until probe: */ ++ bbr->rounds_since_probe = ++ prandom_u32_max(bbr->params.bw_probe_rand_rounds); ++ /* Decide the random wall clock bound for wait until probe: */ ++ bbr->probe_wait_us = bbr->params.bw_probe_base_us + ++ prandom_u32_max(bbr->params.bw_probe_rand_us); ++} ++ ++static void bbr2_set_cycle_idx(struct sock *sk, int cycle_idx) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ bbr->cycle_idx = cycle_idx; ++ /* New phase, so need to update cwnd and pacing rate. */ ++ bbr->try_fast_path = 0; ++} ++ ++/* Send at estimated bw to fill the pipe, but not queue. We need this phase ++ * before PROBE_UP, because as soon as we send faster than the available bw ++ * we will start building a queue, and if the buffer is shallow we can cause ++ * loss. If we do not fill the pipe before we cause this loss, our bw_hi and ++ * inflight_hi estimates will underestimate. ++ */ ++static void bbr2_start_bw_probe_refill(struct sock *sk, u32 bw_probe_up_rounds) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ bbr2_reset_lower_bounds(sk); ++ if (bbr->inflight_hi != ~0U) ++ bbr->inflight_hi += bbr->params.refill_add_inc; ++ bbr->bw_probe_up_rounds = bw_probe_up_rounds; ++ bbr->bw_probe_up_acks = 0; ++ bbr->stopped_risky_probe = 0; ++ bbr->ack_phase = BBR_ACKS_REFILLING; ++ bbr->next_rtt_delivered = tp->delivered; ++ bbr2_set_cycle_idx(sk, BBR_BW_PROBE_REFILL); ++} ++ ++/* Now probe max deliverable data rate and volume. */ ++static void bbr2_start_bw_probe_up(struct sock *sk) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ bbr->ack_phase = BBR_ACKS_PROBE_STARTING; ++ bbr->next_rtt_delivered = tp->delivered; ++ bbr->cycle_mstamp = tp->tcp_mstamp; ++ bbr2_set_cycle_idx(sk, BBR_BW_PROBE_UP); ++ bbr2_raise_inflight_hi_slope(sk); ++} ++ ++/* Start a new PROBE_BW probing cycle of some wall clock length. Pick a wall ++ * clock time at which to probe beyond an inflight that we think to be ++ * safe. This will knowingly risk packet loss, so we want to do this rarely, to ++ * keep packet loss rates low. Also start a round-trip counter, to probe faster ++ * if we estimate a Reno flow at our BDP would probe faster. ++ */ ++static void bbr2_start_bw_probe_down(struct sock *sk) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ bbr2_reset_congestion_signals(sk); ++ bbr->bw_probe_up_cnt = ~0U; /* not growing inflight_hi any more */ ++ bbr2_pick_probe_wait(sk); ++ bbr->cycle_mstamp = tp->tcp_mstamp; /* start wall clock */ ++ bbr->ack_phase = BBR_ACKS_PROBE_STOPPING; ++ bbr->next_rtt_delivered = tp->delivered; ++ bbr2_set_cycle_idx(sk, BBR_BW_PROBE_DOWN); ++} ++ ++/* Cruise: maintain what we estimate to be a neutral, conservative ++ * operating point, without attempting to probe up for bandwidth or down for ++ * RTT, and only reducing inflight in response to loss/ECN signals. ++ */ ++static void bbr2_start_bw_probe_cruise(struct sock *sk) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ if (bbr->inflight_lo != ~0U) ++ bbr->inflight_lo = min(bbr->inflight_lo, bbr->inflight_hi); ++ ++ bbr2_set_cycle_idx(sk, BBR_BW_PROBE_CRUISE); ++} ++ ++/* Loss and/or ECN rate is too high while probing. ++ * Adapt (once per bw probe) by cutting inflight_hi and then restarting cycle. ++ */ ++static void bbr2_handle_inflight_too_high(struct sock *sk, ++ const struct rate_sample *rs) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ const u32 beta = bbr->params.beta; ++ ++ bbr->prev_probe_too_high = 1; ++ bbr->bw_probe_samples = 0; /* only react once per probe */ ++ bbr->debug.event = 'L'; /* Loss/ECN too high */ ++ /* If we are app-limited then we are not robustly ++ * probing the max volume of inflight data we think ++ * might be safe (analogous to how app-limited bw ++ * samples are not known to be robustly probing bw). ++ */ ++ if (!rs->is_app_limited) ++ bbr->inflight_hi = max_t(u32, rs->tx_in_flight, ++ (u64)bbr2_target_inflight(sk) * ++ (BBR_UNIT - beta) >> BBR_SCALE); ++ if (bbr->mode == BBR_PROBE_BW && bbr->cycle_idx == BBR_BW_PROBE_UP) ++ bbr2_start_bw_probe_down(sk); ++} ++ ++/* If we're seeing bw and loss samples reflecting our bw probing, adapt ++ * using the signals we see. If loss or ECN mark rate gets too high, then adapt ++ * inflight_hi downward. If we're able to push inflight higher without such ++ * signals, push higher: adapt inflight_hi upward. ++ */ ++static bool bbr2_adapt_upper_bounds(struct sock *sk, ++ const struct rate_sample *rs) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ /* Track when we'll see bw/loss samples resulting from our bw probes. */ ++ if (bbr->ack_phase == BBR_ACKS_PROBE_STARTING && bbr->round_start) ++ bbr->ack_phase = BBR_ACKS_PROBE_FEEDBACK; ++ if (bbr->ack_phase == BBR_ACKS_PROBE_STOPPING && bbr->round_start) { ++ /* End of samples from bw probing phase. */ ++ bbr->bw_probe_samples = 0; ++ bbr->ack_phase = BBR_ACKS_INIT; ++ /* At this point in the cycle, our current bw sample is also ++ * our best recent chance at finding the highest available bw ++ * for this flow. So now is the best time to forget the bw ++ * samples from the previous cycle, by advancing the window. ++ */ ++ if (bbr->mode == BBR_PROBE_BW && !rs->is_app_limited) ++ bbr2_advance_bw_hi_filter(sk); ++ /* If we had an inflight_hi, then probed and pushed inflight all ++ * the way up to hit that inflight_hi without seeing any ++ * high loss/ECN in all the resulting ACKs from that probing, ++ * then probe up again, this time letting inflight persist at ++ * inflight_hi for a round trip, then accelerating beyond. ++ */ ++ if (bbr->mode == BBR_PROBE_BW && ++ bbr->stopped_risky_probe && !bbr->prev_probe_too_high) { ++ bbr->debug.event = 'R'; /* reprobe */ ++ bbr2_start_bw_probe_refill(sk, 0); ++ return true; /* yes, decided state transition */ ++ } ++ } ++ ++ if (bbr2_is_inflight_too_high(sk, rs)) { ++ if (bbr->bw_probe_samples) /* sample is from bw probing? */ ++ bbr2_handle_inflight_too_high(sk, rs); ++ } else { ++ /* Loss/ECN rate is declared safe. Adjust upper bound upward. */ ++ if (bbr->inflight_hi == ~0U) /* no excess queue signals yet? */ ++ return false; ++ ++ /* To be resilient to random loss, we must raise inflight_hi ++ * if we observe in any phase that a higher level is safe. ++ */ ++ if (rs->tx_in_flight > bbr->inflight_hi) { ++ bbr->inflight_hi = rs->tx_in_flight; ++ bbr->debug.event = 'U'; /* raise up inflight_hi */ ++ } ++ ++ if (bbr->mode == BBR_PROBE_BW && ++ bbr->cycle_idx == BBR_BW_PROBE_UP) ++ bbr2_probe_inflight_hi_upward(sk, rs); ++ } ++ ++ return false; ++} ++ ++/* Check if it's time to probe for bandwidth now, and if so, kick it off. */ ++static bool bbr2_check_time_to_probe_bw(struct sock *sk) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ u32 n; ++ ++ /* If we seem to be at an operating point where we are not seeing loss ++ * but we are seeing ECN marks, then when the ECN marks cease we reprobe ++ * quickly (in case a burst of cross-traffic has ceased and freed up bw, ++ * or in case we are sharing with multiplicatively probing traffic). ++ */ ++ if (bbr->params.ecn_reprobe_gain && bbr->ecn_eligible && ++ bbr->ecn_in_cycle && !bbr->loss_in_cycle && ++ inet_csk(sk)->icsk_ca_state == TCP_CA_Open) { ++ bbr->debug.event = 'A'; /* *A*ll clear to probe *A*gain */ ++ /* Calculate n so that when bbr2_raise_inflight_hi_slope() ++ * computes growth_this_round as 2^n it will be roughly the ++ * desired volume of data (inflight_hi*ecn_reprobe_gain). ++ */ ++ n = ilog2((((u64)bbr->inflight_hi * ++ bbr->params.ecn_reprobe_gain) >> BBR_SCALE)); ++ bbr2_start_bw_probe_refill(sk, n); ++ return true; ++ } ++ ++ if (bbr2_has_elapsed_in_phase(sk, bbr->probe_wait_us) || ++ bbr2_is_reno_coexistence_probe_time(sk)) { ++ bbr2_start_bw_probe_refill(sk, 0); ++ return true; ++ } ++ return false; ++} ++ ++/* Is it time to transition from PROBE_DOWN to PROBE_CRUISE? */ ++static bool bbr2_check_time_to_cruise(struct sock *sk, u32 inflight, u32 bw) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ bool is_under_bdp, is_long_enough; ++ ++ /* Always need to pull inflight down to leave headroom in queue. */ ++ if (inflight > bbr2_inflight_with_headroom(sk)) ++ return false; ++ ++ is_under_bdp = inflight <= bbr_inflight(sk, bw, BBR_UNIT); ++ if (bbr->params.drain_to_target) ++ return is_under_bdp; ++ ++ is_long_enough = bbr2_has_elapsed_in_phase(sk, bbr->min_rtt_us); ++ return is_under_bdp || is_long_enough; ++} ++ ++/* PROBE_BW state machine: cruise, refill, probe for bw, or drain? */ ++static void bbr2_update_cycle_phase(struct sock *sk, ++ const struct rate_sample *rs) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ bool is_risky = false, is_queuing = false; ++ u32 inflight, bw; ++ ++ if (!bbr_full_bw_reached(sk)) ++ return; ++ ++ /* In DRAIN, PROBE_BW, or PROBE_RTT, adjust upper bounds. */ ++ if (bbr2_adapt_upper_bounds(sk, rs)) ++ return; /* already decided state transition */ ++ ++ if (bbr->mode != BBR_PROBE_BW) ++ return; ++ ++ inflight = bbr_packets_in_net_at_edt(sk, rs->prior_in_flight); ++ bw = bbr_max_bw(sk); ++ ++ switch (bbr->cycle_idx) { ++ /* First we spend most of our time cruising with a pacing_gain of 1.0, ++ * which paces at the estimated bw, to try to fully use the pipe ++ * without building queue. If we encounter loss/ECN marks, we adapt ++ * by slowing down. ++ */ ++ case BBR_BW_PROBE_CRUISE: ++ if (bbr2_check_time_to_probe_bw(sk)) ++ return; /* already decided state transition */ ++ break; ++ ++ /* After cruising, when it's time to probe, we first "refill": we send ++ * at the estimated bw to fill the pipe, before probing higher and ++ * knowingly risking overflowing the bottleneck buffer (causing loss). ++ */ ++ case BBR_BW_PROBE_REFILL: ++ if (bbr->round_start) { ++ /* After one full round trip of sending in REFILL, we ++ * start to see bw samples reflecting our REFILL, which ++ * may be putting too much data in flight. ++ */ ++ bbr->bw_probe_samples = 1; ++ bbr2_start_bw_probe_up(sk); ++ } ++ break; ++ ++ /* After we refill the pipe, we probe by using a pacing_gain > 1.0, to ++ * probe for bw. If we have not seen loss/ECN, we try to raise inflight ++ * to at least pacing_gain*BDP; note that this may take more than ++ * min_rtt if min_rtt is small (e.g. on a LAN). ++ * ++ * We terminate PROBE_UP bandwidth probing upon any of the following: ++ * ++ * (1) We've pushed inflight up to hit the inflight_hi target set in the ++ * most recent previous bw probe phase. Thus we want to start ++ * draining the queue immediately because it's very likely the most ++ * recently sent packets will fill the queue and cause drops. ++ * (checked here) ++ * (2) We have probed for at least 1*min_rtt_us, and the ++ * estimated queue is high enough (inflight > 1.25 * estimated_bdp). ++ * (checked here) ++ * (3) Loss filter says loss rate is "too high". ++ * (checked in bbr_is_inflight_too_high()) ++ * (4) ECN filter says ECN mark rate is "too high". ++ * (checked in bbr_is_inflight_too_high()) ++ */ ++ case BBR_BW_PROBE_UP: ++ if (bbr->prev_probe_too_high && ++ inflight >= bbr->inflight_hi) { ++ bbr->stopped_risky_probe = 1; ++ is_risky = true; ++ bbr->debug.event = 'D'; /* D for danger */ ++ } else if (bbr2_has_elapsed_in_phase(sk, bbr->min_rtt_us) && ++ inflight >= ++ bbr_inflight(sk, bw, ++ bbr->params.bw_probe_pif_gain)) { ++ is_queuing = true; ++ bbr->debug.event = 'Q'; /* building Queue */ ++ } ++ if (is_risky || is_queuing) { ++ bbr->prev_probe_too_high = 0; /* no loss/ECN (yet) */ ++ bbr2_start_bw_probe_down(sk); /* restart w/ down */ ++ } ++ break; ++ ++ /* After probing in PROBE_UP, we have usually accumulated some data in ++ * the bottleneck buffer (if bw probing didn't find more bw). We next ++ * enter PROBE_DOWN to try to drain any excess data from the queue. To ++ * do this, we use a pacing_gain < 1.0. We hold this pacing gain until ++ * our inflight is less then that target cruising point, which is the ++ * minimum of (a) the amount needed to leave headroom, and (b) the ++ * estimated BDP. Once inflight falls to match the target, we estimate ++ * the queue is drained; persisting would underutilize the pipe. ++ */ ++ case BBR_BW_PROBE_DOWN: ++ if (bbr2_check_time_to_probe_bw(sk)) ++ return; /* already decided state transition */ ++ if (bbr2_check_time_to_cruise(sk, inflight, bw)) ++ bbr2_start_bw_probe_cruise(sk); ++ break; ++ ++ default: ++ WARN_ONCE(1, "BBR invalid cycle index %u\n", bbr->cycle_idx); ++ } ++} ++ ++/* Exiting PROBE_RTT, so return to bandwidth probing in STARTUP or PROBE_BW. */ ++static void bbr2_exit_probe_rtt(struct sock *sk) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ bbr2_reset_lower_bounds(sk); ++ if (bbr_full_bw_reached(sk)) { ++ bbr->mode = BBR_PROBE_BW; ++ /* Raising inflight after PROBE_RTT may cause loss, so reset ++ * the PROBE_BW clock and schedule the next bandwidth probe for ++ * a friendly and randomized future point in time. ++ */ ++ bbr2_start_bw_probe_down(sk); ++ /* Since we are exiting PROBE_RTT, we know inflight is ++ * below our estimated BDP, so it is reasonable to cruise. ++ */ ++ bbr2_start_bw_probe_cruise(sk); ++ } else { ++ bbr->mode = BBR_STARTUP; ++ } ++} ++ ++/* Exit STARTUP based on loss rate > 1% and loss gaps in round >= N. Wait until ++ * the end of the round in recovery to get a good estimate of how many packets ++ * have been lost, and how many we need to drain with a low pacing rate. ++ */ ++static void bbr2_check_loss_too_high_in_startup(struct sock *sk, ++ const struct rate_sample *rs) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ if (bbr_full_bw_reached(sk)) ++ return; ++ ++ /* For STARTUP exit, check the loss rate at the end of each round trip ++ * of Recovery episodes in STARTUP. We check the loss rate at the end ++ * of the round trip to filter out noisy/low loss and have a better ++ * sense of inflight (extent of loss), so we can drain more accurately. ++ */ ++ if (rs->losses && bbr->loss_events_in_round < 0xf) ++ bbr->loss_events_in_round++; /* update saturating counter */ ++ if (bbr->params.full_loss_cnt && bbr->loss_round_start && ++ inet_csk(sk)->icsk_ca_state == TCP_CA_Recovery && ++ bbr->loss_events_in_round >= bbr->params.full_loss_cnt && ++ bbr2_is_inflight_too_high(sk, rs)) { ++ bbr->debug.event = 'P'; /* Packet loss caused STARTUP exit */ ++ bbr2_handle_queue_too_high_in_startup(sk); ++ return; ++ } ++ if (bbr->loss_round_start) ++ bbr->loss_events_in_round = 0; ++} ++ ++/* If we are done draining, advance into steady state operation in PROBE_BW. */ ++static void bbr2_check_drain(struct sock *sk, const struct rate_sample *rs, ++ struct bbr_context *ctx) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ if (bbr_check_drain(sk, rs, ctx)) { ++ bbr->mode = BBR_PROBE_BW; ++ bbr2_start_bw_probe_down(sk); ++ } ++} ++ ++static void bbr2_update_model(struct sock *sk, const struct rate_sample *rs, ++ struct bbr_context *ctx) ++{ ++ bbr2_update_congestion_signals(sk, rs, ctx); ++ bbr_update_ack_aggregation(sk, rs); ++ bbr2_check_loss_too_high_in_startup(sk, rs); ++ bbr_check_full_bw_reached(sk, rs); ++ bbr2_check_drain(sk, rs, ctx); ++ bbr2_update_cycle_phase(sk, rs); ++ bbr_update_min_rtt(sk, rs); ++} ++ ++/* Fast path for app-limited case. ++ * ++ * On each ack, we execute bbr state machine, which primarily consists of: ++ * 1) update model based on new rate sample, and ++ * 2) update control based on updated model or state change. ++ * ++ * There are certain workload/scenarios, e.g. app-limited case, where ++ * either we can skip updating model or we can skip update of both model ++ * as well as control. This provides signifcant softirq cpu savings for ++ * processing incoming acks. ++ * ++ * In case of app-limited, if there is no congestion (loss/ecn) and ++ * if observed bw sample is less than current estimated bw, then we can ++ * skip some of the computation in bbr state processing: ++ * ++ * - if there is no rtt/mode/phase change: In this case, since all the ++ * parameters of the network model are constant, we can skip model ++ * as well control update. ++ * ++ * - else we can skip rest of the model update. But we still need to ++ * update the control to account for the new rtt/mode/phase. ++ * ++ * Returns whether we can take fast path or not. ++ */ ++static bool bbr2_fast_path(struct sock *sk, bool *update_model, ++ const struct rate_sample *rs, struct bbr_context *ctx) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ u32 prev_min_rtt_us, prev_mode; ++ ++ if (bbr->params.fast_path && bbr->try_fast_path && ++ rs->is_app_limited && ctx->sample_bw < bbr_max_bw(sk) && ++ !bbr->loss_in_round && !bbr->ecn_in_round) { ++ prev_mode = bbr->mode; ++ prev_min_rtt_us = bbr->min_rtt_us; ++ bbr2_check_drain(sk, rs, ctx); ++ bbr2_update_cycle_phase(sk, rs); ++ bbr_update_min_rtt(sk, rs); ++ ++ if (bbr->mode == prev_mode && ++ bbr->min_rtt_us == prev_min_rtt_us && ++ bbr->try_fast_path) ++ return true; ++ ++ /* Skip model update, but control still needs to be updated */ ++ *update_model = false; ++ } ++ return false; ++} ++ ++void bbr2_main(struct sock *sk, const struct rate_sample *rs) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ struct bbr_context ctx = { 0 }; ++ bool update_model = true; ++ u32 bw; ++ ++ bbr->debug.event = '.'; /* init to default NOP (no event yet) */ ++ ++ bbr_update_round_start(sk, rs, &ctx); ++ if (bbr->round_start) { ++ bbr->rounds_since_probe = ++ min_t(s32, bbr->rounds_since_probe + 1, 0xFF); ++ bbr2_update_ecn_alpha(sk); ++ } ++ ++ bbr->ecn_in_round |= rs->is_ece; ++ bbr_calculate_bw_sample(sk, rs, &ctx); ++ ++ if (bbr2_fast_path(sk, &update_model, rs, &ctx)) ++ goto out; ++ ++ if (update_model) ++ bbr2_update_model(sk, rs, &ctx); ++ ++ bbr_update_gains(sk); ++ bw = bbr_bw(sk); ++ bbr_set_pacing_rate(sk, bw, bbr->pacing_gain); ++ bbr_set_cwnd(sk, rs, rs->acked_sacked, bw, bbr->cwnd_gain, ++ tp->snd_cwnd, &ctx); ++ bbr2_bound_cwnd_for_inflight_model(sk); ++ ++out: ++ bbr->prev_ca_state = inet_csk(sk)->icsk_ca_state; ++ bbr->loss_in_cycle |= rs->lost > 0; ++ bbr->ecn_in_cycle |= rs->delivered_ce > 0; ++ ++ bbr_debug(sk, rs->acked_sacked, rs, &ctx); ++} ++ ++/* Module parameters that are settable by TCP_CONGESTION_PARAMS are declared ++ * down here, so that the algorithm functions that use the parameters must use ++ * the per-socket parameters; if they accidentally use the global version ++ * then there will be a compile error. ++ * TODO(ncardwell): move all per-socket parameters down to this section. ++ */ ++ ++/* On losses, scale down inflight and pacing rate by beta scaled by BBR_SCALE. ++ * No loss response when 0. Max allwed value is 255. ++ */ ++static u32 bbr_beta = BBR_UNIT * 30 / 100; ++ ++/* Gain factor for ECN mark ratio samples, scaled by BBR_SCALE. ++ * Max allowed value is 255. ++ */ ++static u32 bbr_ecn_alpha_gain = BBR_UNIT * 1 / 16; /* 1/16 = 6.25% */ ++ ++/* The initial value for the ecn_alpha state variable. Default and max ++ * BBR_UNIT (256), representing 1.0. This allows a flow to respond quickly ++ * to congestion if the bottleneck is congested when the flow starts up. ++ */ ++static u32 bbr_ecn_alpha_init = BBR_UNIT; /* 1.0, to respond quickly */ ++ ++/* On ECN, cut inflight_lo to (1 - ecn_factor * ecn_alpha) scaled by BBR_SCALE. ++ * No ECN based bounding when 0. Max allwed value is 255. ++ */ ++static u32 bbr_ecn_factor = BBR_UNIT * 1 / 3; /* 1/3 = 33% */ ++ ++/* Estimate bw probing has gone too far if CE ratio exceeds this threshold. ++ * Scaled by BBR_SCALE. Disabled when 0. Max allowed is 255. ++ */ ++static u32 bbr_ecn_thresh = BBR_UNIT * 1 / 2; /* 1/2 = 50% */ ++ ++/* Max RTT (in usec) at which to use sender-side ECN logic. ++ * Disabled when 0 (ECN allowed at any RTT). ++ * Max allowed for the parameter is 524287 (0x7ffff) us, ~524 ms. ++ */ ++static u32 bbr_ecn_max_rtt_us = 5000; ++ ++/* If non-zero, if in a cycle with no losses but some ECN marks, after ECN ++ * clears then use a multiplicative increase to quickly reprobe bw by ++ * starting inflight probing at the given multiple of inflight_hi. ++ * Default for this experimental knob is 0 (disabled). ++ * Planned value for experiments: BBR_UNIT * 1 / 2 = 128, representing 0.5. ++ */ ++static u32 bbr_ecn_reprobe_gain; ++ ++/* Estimate bw probing has gone too far if loss rate exceeds this level. */ ++static u32 bbr_loss_thresh = BBR_UNIT * 2 / 100; /* 2% loss */ ++ ++/* Exit STARTUP if number of loss marking events in a Recovery round is >= N, ++ * and loss rate is higher than bbr_loss_thresh. ++ * Disabled if 0. Max allowed value is 15 (0xF). ++ */ ++static u32 bbr_full_loss_cnt = 8; ++ ++/* Exit STARTUP if number of round trips with ECN mark rate above ecn_thresh ++ * meets this count. Max allowed value is 3. ++ */ ++static u32 bbr_full_ecn_cnt = 2; ++ ++/* Fraction of unutilized headroom to try to leave in path upon high loss. */ ++static u32 bbr_inflight_headroom = BBR_UNIT * 15 / 100; ++ ++/* Multiplier to get target inflight (as multiple of BDP) for PROBE_UP phase. ++ * Default is 1.25x, as in BBR v1. Max allowed is 511. ++ */ ++static u32 bbr_bw_probe_pif_gain = BBR_UNIT * 5 / 4; ++ ++/* Multiplier to get Reno-style probe epoch duration as: k * BDP round trips. ++ * If zero, disables this BBR v2 Reno-style BDP-scaled coexistence mechanism. ++ * Max allowed is 511. ++ */ ++static u32 bbr_bw_probe_reno_gain = BBR_UNIT; ++ ++/* Max number of packet-timed rounds to wait before probing for bandwidth. If ++ * we want to tolerate 1% random loss per round, and not have this cut our ++ * inflight too much, we must probe for bw periodically on roughly this scale. ++ * If low, limits Reno/CUBIC coexistence; if high, limits loss tolerance. ++ * We aim to be fair with Reno/CUBIC up to a BDP of at least: ++ * BDP = 25Mbps * .030sec /(1514bytes) = 61.9 packets ++ */ ++static u32 bbr_bw_probe_max_rounds = 63; ++ ++/* Max amount of randomness to inject in round counting for Reno-coexistence. ++ * Max value is 15. ++ */ ++static u32 bbr_bw_probe_rand_rounds = 2; ++ ++/* Use BBR-native probe time scale starting at this many usec. ++ * We aim to be fair with Reno/CUBIC up to an inter-loss time epoch of at least: ++ * BDP*RTT = 25Mbps * .030sec /(1514bytes) * 0.030sec = 1.9 secs ++ */ ++static u32 bbr_bw_probe_base_us = 2 * USEC_PER_SEC; /* 2 secs */ ++ ++/* Use BBR-native probes spread over this many usec: */ ++static u32 bbr_bw_probe_rand_us = 1 * USEC_PER_SEC; /* 1 secs */ ++ ++/* Undo the model changes made in loss recovery if recovery was spurious? */ ++static bool bbr_undo = true; ++ ++/* Use fast path if app-limited, no loss/ECN, and target cwnd was reached? */ ++static bool bbr_fast_path = true; /* default: enabled */ ++ ++/* Use fast ack mode ? */ ++static int bbr_fast_ack_mode = 1; /* default: rwnd check off */ ++ ++/* How much to additively increase inflight_hi when entering REFILL? */ ++static u32 bbr_refill_add_inc; /* default: disabled */ ++ ++module_param_named(beta, bbr_beta, uint, 0644); ++module_param_named(ecn_alpha_gain, bbr_ecn_alpha_gain, uint, 0644); ++module_param_named(ecn_alpha_init, bbr_ecn_alpha_init, uint, 0644); ++module_param_named(ecn_factor, bbr_ecn_factor, uint, 0644); ++module_param_named(ecn_thresh, bbr_ecn_thresh, uint, 0644); ++module_param_named(ecn_max_rtt_us, bbr_ecn_max_rtt_us, uint, 0644); ++module_param_named(ecn_reprobe_gain, bbr_ecn_reprobe_gain, uint, 0644); ++module_param_named(loss_thresh, bbr_loss_thresh, uint, 0664); ++module_param_named(full_loss_cnt, bbr_full_loss_cnt, uint, 0664); ++module_param_named(full_ecn_cnt, bbr_full_ecn_cnt, uint, 0664); ++module_param_named(inflight_headroom, bbr_inflight_headroom, uint, 0664); ++module_param_named(bw_probe_pif_gain, bbr_bw_probe_pif_gain, uint, 0664); ++module_param_named(bw_probe_reno_gain, bbr_bw_probe_reno_gain, uint, 0664); ++module_param_named(bw_probe_max_rounds, bbr_bw_probe_max_rounds, uint, 0664); ++module_param_named(bw_probe_rand_rounds, bbr_bw_probe_rand_rounds, uint, 0664); ++module_param_named(bw_probe_base_us, bbr_bw_probe_base_us, uint, 0664); ++module_param_named(bw_probe_rand_us, bbr_bw_probe_rand_us, uint, 0664); ++module_param_named(undo, bbr_undo, bool, 0664); ++module_param_named(fast_path, bbr_fast_path, bool, 0664); ++module_param_named(fast_ack_mode, bbr_fast_ack_mode, uint, 0664); ++module_param_named(refill_add_inc, bbr_refill_add_inc, uint, 0664); ++ ++static void bbr2_init(struct sock *sk) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ bbr_init(sk); /* run shared init code for v1 and v2 */ ++ ++ /* BBR v2 parameters: */ ++ bbr->params.beta = min_t(u32, 0xFFU, bbr_beta); ++ bbr->params.ecn_alpha_gain = min_t(u32, 0xFFU, bbr_ecn_alpha_gain); ++ bbr->params.ecn_alpha_init = min_t(u32, BBR_UNIT, bbr_ecn_alpha_init); ++ bbr->params.ecn_factor = min_t(u32, 0xFFU, bbr_ecn_factor); ++ bbr->params.ecn_thresh = min_t(u32, 0xFFU, bbr_ecn_thresh); ++ bbr->params.ecn_max_rtt_us = min_t(u32, 0x7ffffU, bbr_ecn_max_rtt_us); ++ bbr->params.ecn_reprobe_gain = min_t(u32, 0x1FF, bbr_ecn_reprobe_gain); ++ bbr->params.loss_thresh = min_t(u32, 0xFFU, bbr_loss_thresh); ++ bbr->params.full_loss_cnt = min_t(u32, 0xFU, bbr_full_loss_cnt); ++ bbr->params.full_ecn_cnt = min_t(u32, 0x3U, bbr_full_ecn_cnt); ++ bbr->params.inflight_headroom = ++ min_t(u32, 0xFFU, bbr_inflight_headroom); ++ bbr->params.bw_probe_pif_gain = ++ min_t(u32, 0x1FFU, bbr_bw_probe_pif_gain); ++ bbr->params.bw_probe_reno_gain = ++ min_t(u32, 0x1FFU, bbr_bw_probe_reno_gain); ++ bbr->params.bw_probe_max_rounds = ++ min_t(u32, 0xFFU, bbr_bw_probe_max_rounds); ++ bbr->params.bw_probe_rand_rounds = ++ min_t(u32, 0xFU, bbr_bw_probe_rand_rounds); ++ bbr->params.bw_probe_base_us = ++ min_t(u32, (1 << 26) - 1, bbr_bw_probe_base_us); ++ bbr->params.bw_probe_rand_us = ++ min_t(u32, (1 << 26) - 1, bbr_bw_probe_rand_us); ++ bbr->params.undo = bbr_undo; ++ bbr->params.fast_path = bbr_fast_path ? 1 : 0; ++ bbr->params.refill_add_inc = min_t(u32, 0x3U, bbr_refill_add_inc); ++ ++ /* BBR v2 state: */ ++ bbr->initialized = 1; ++ /* Start sampling ECN mark rate after first full flight is ACKed: */ ++ bbr->loss_round_delivered = tp->delivered + 1; ++ bbr->loss_round_start = 0; ++ bbr->undo_bw_lo = 0; ++ bbr->undo_inflight_lo = 0; ++ bbr->undo_inflight_hi = 0; ++ bbr->loss_events_in_round = 0; ++ bbr->startup_ecn_rounds = 0; ++ bbr2_reset_congestion_signals(sk); ++ bbr->bw_lo = ~0U; ++ bbr->bw_hi[0] = 0; ++ bbr->bw_hi[1] = 0; ++ bbr->inflight_lo = ~0U; ++ bbr->inflight_hi = ~0U; ++ bbr->bw_probe_up_cnt = ~0U; ++ bbr->bw_probe_up_acks = 0; ++ bbr->bw_probe_up_rounds = 0; ++ bbr->probe_wait_us = 0; ++ bbr->stopped_risky_probe = 0; ++ bbr->ack_phase = BBR_ACKS_INIT; ++ bbr->rounds_since_probe = 0; ++ bbr->bw_probe_samples = 0; ++ bbr->prev_probe_too_high = 0; ++ bbr->ecn_eligible = 0; ++ bbr->ecn_alpha = bbr->params.ecn_alpha_init; ++ bbr->alpha_last_delivered = 0; ++ bbr->alpha_last_delivered_ce = 0; ++ ++ tp->fast_ack_mode = min_t(u32, 0x2U, bbr_fast_ack_mode); ++ ++ if ((tp->ecn_flags & TCP_ECN_OK) && bbr_ecn_enable) ++ tp->ecn_flags |= TCP_ECN_ECT_PERMANENT; ++} ++ ++/* Core TCP stack informs us that the given skb was just marked lost. */ ++static void bbr2_skb_marked_lost(struct sock *sk, const struct sk_buff *skb) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ struct tcp_skb_cb *scb = TCP_SKB_CB(skb); ++ struct rate_sample rs; ++ ++ /* Capture "current" data over the full round trip of loss, ++ * to have a better chance to see the full capacity of the path. ++ */ ++ if (!bbr->loss_in_round) /* first loss in this round trip? */ ++ bbr->loss_round_delivered = tp->delivered; /* set round trip */ ++ bbr->loss_in_round = 1; ++ bbr->loss_in_cycle = 1; ++ ++ if (!bbr->bw_probe_samples) ++ return; /* not an skb sent while probing for bandwidth */ ++ if (unlikely(!scb->tx.delivered_mstamp)) ++ return; /* skb was SACKed, reneged, marked lost; ignore it */ ++ /* We are probing for bandwidth. Construct a rate sample that ++ * estimates what happened in the flight leading up to this lost skb, ++ * then see if the loss rate went too high, and if so at which packet. ++ */ ++ memset(&rs, 0, sizeof(rs)); ++ rs.tx_in_flight = scb->tx.in_flight; ++ rs.lost = tp->lost - scb->tx.lost; ++ rs.is_app_limited = scb->tx.is_app_limited; ++ if (bbr2_is_inflight_too_high(sk, &rs)) { ++ rs.tx_in_flight = bbr2_inflight_hi_from_lost_skb(sk, &rs, skb); ++ bbr2_handle_inflight_too_high(sk, &rs); ++ } ++} ++ ++/* Revert short-term model if current loss recovery event was spurious. */ ++static u32 bbr2_undo_cwnd(struct sock *sk) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ bbr->debug.undo = 1; ++ bbr->full_bw = 0; /* spurious slow-down; reset full pipe detection */ ++ bbr->full_bw_cnt = 0; ++ bbr->loss_in_round = 0; ++ ++ if (!bbr->params.undo) ++ return tp->snd_cwnd; ++ ++ /* Revert to cwnd and other state saved before loss episode. */ ++ bbr->bw_lo = max(bbr->bw_lo, bbr->undo_bw_lo); ++ bbr->inflight_lo = max(bbr->inflight_lo, bbr->undo_inflight_lo); ++ bbr->inflight_hi = max(bbr->inflight_hi, bbr->undo_inflight_hi); ++ return bbr->prior_cwnd; ++} ++ ++/* Entering loss recovery, so save state for when we undo recovery. */ ++static u32 bbr2_ssthresh(struct sock *sk) ++{ ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ bbr_save_cwnd(sk); ++ /* For undo, save state that adapts based on loss signal. */ ++ bbr->undo_bw_lo = bbr->bw_lo; ++ bbr->undo_inflight_lo = bbr->inflight_lo; ++ bbr->undo_inflight_hi = bbr->inflight_hi; ++ return tcp_sk(sk)->snd_ssthresh; ++} ++ ++static enum tcp_bbr2_phase bbr2_get_phase(struct bbr *bbr) ++{ ++ switch (bbr->mode) { ++ case BBR_STARTUP: ++ return BBR2_PHASE_STARTUP; ++ case BBR_DRAIN: ++ return BBR2_PHASE_DRAIN; ++ case BBR_PROBE_BW: ++ break; ++ case BBR_PROBE_RTT: ++ return BBR2_PHASE_PROBE_RTT; ++ default: ++ return BBR2_PHASE_INVALID; ++ } ++ switch (bbr->cycle_idx) { ++ case BBR_BW_PROBE_UP: ++ return BBR2_PHASE_PROBE_BW_UP; ++ case BBR_BW_PROBE_DOWN: ++ return BBR2_PHASE_PROBE_BW_DOWN; ++ case BBR_BW_PROBE_CRUISE: ++ return BBR2_PHASE_PROBE_BW_CRUISE; ++ case BBR_BW_PROBE_REFILL: ++ return BBR2_PHASE_PROBE_BW_REFILL; ++ default: ++ return BBR2_PHASE_INVALID; ++ } ++} ++ ++static size_t bbr2_get_info(struct sock *sk, u32 ext, int *attr, ++ union tcp_cc_info *info) ++{ ++ if (ext & (1 << (INET_DIAG_BBRINFO - 1)) || ++ ext & (1 << (INET_DIAG_VEGASINFO - 1))) { ++ struct bbr *bbr = inet_csk_ca(sk); ++ u64 bw = bbr_bw_bytes_per_sec(sk, bbr_bw(sk)); ++ u64 bw_hi = bbr_bw_bytes_per_sec(sk, bbr_max_bw(sk)); ++ u64 bw_lo = bbr->bw_lo == ~0U ? ++ ~0ULL : bbr_bw_bytes_per_sec(sk, bbr->bw_lo); ++ ++ memset(&info->bbr2, 0, sizeof(info->bbr2)); ++ info->bbr2.bbr_bw_lsb = (u32)bw; ++ info->bbr2.bbr_bw_msb = (u32)(bw >> 32); ++ info->bbr2.bbr_min_rtt = bbr->min_rtt_us; ++ info->bbr2.bbr_pacing_gain = bbr->pacing_gain; ++ info->bbr2.bbr_cwnd_gain = bbr->cwnd_gain; ++ info->bbr2.bbr_bw_hi_lsb = (u32)bw_hi; ++ info->bbr2.bbr_bw_hi_msb = (u32)(bw_hi >> 32); ++ info->bbr2.bbr_bw_lo_lsb = (u32)bw_lo; ++ info->bbr2.bbr_bw_lo_msb = (u32)(bw_lo >> 32); ++ info->bbr2.bbr_mode = bbr->mode; ++ info->bbr2.bbr_phase = (__u8)bbr2_get_phase(bbr); ++ info->bbr2.bbr_version = (__u8)2; ++ info->bbr2.bbr_inflight_lo = bbr->inflight_lo; ++ info->bbr2.bbr_inflight_hi = bbr->inflight_hi; ++ info->bbr2.bbr_extra_acked = bbr_extra_acked(sk); ++ *attr = INET_DIAG_BBRINFO; ++ return sizeof(info->bbr2); ++ } ++ return 0; ++} ++ ++static void bbr2_set_state(struct sock *sk, u8 new_state) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ struct bbr *bbr = inet_csk_ca(sk); ++ ++ if (new_state == TCP_CA_Loss) { ++ struct rate_sample rs = { .losses = 1 }; ++ struct bbr_context ctx = { 0 }; ++ ++ bbr->prev_ca_state = TCP_CA_Loss; ++ bbr->full_bw = 0; ++ if (!bbr2_is_probing_bandwidth(sk) && bbr->inflight_lo == ~0U) { ++ /* bbr_adapt_lower_bounds() needs cwnd before ++ * we suffered an RTO, to update inflight_lo: ++ */ ++ bbr->inflight_lo = ++ max(tp->snd_cwnd, bbr->prior_cwnd); ++ } ++ bbr_debug(sk, 0, &rs, &ctx); ++ } else if (bbr->prev_ca_state == TCP_CA_Loss && ++ new_state != TCP_CA_Loss) { ++ tp->snd_cwnd = max(tp->snd_cwnd, bbr->prior_cwnd); ++ bbr->try_fast_path = 0; /* bound cwnd using latest model */ ++ } ++} ++ ++static struct tcp_congestion_ops tcp_bbr2_cong_ops __read_mostly = { ++ .flags = TCP_CONG_NON_RESTRICTED | TCP_CONG_WANTS_CE_EVENTS, ++ .name = "bbr2", ++ .owner = THIS_MODULE, ++ .init = bbr2_init, ++ .cong_control = bbr2_main, ++ .sndbuf_expand = bbr_sndbuf_expand, ++ .skb_marked_lost = bbr2_skb_marked_lost, ++ .undo_cwnd = bbr2_undo_cwnd, ++ .cwnd_event = bbr_cwnd_event, ++ .ssthresh = bbr2_ssthresh, ++ .tso_segs = bbr_tso_segs, ++ .get_info = bbr2_get_info, ++ .set_state = bbr2_set_state, ++}; ++ ++static int __init bbr_register(void) ++{ ++ BUILD_BUG_ON(sizeof(struct bbr) > ICSK_CA_PRIV_SIZE); ++ return tcp_register_congestion_control(&tcp_bbr2_cong_ops); ++} ++ ++static void __exit bbr_unregister(void) ++{ ++ tcp_unregister_congestion_control(&tcp_bbr2_cong_ops); ++} ++ ++module_init(bbr_register); ++module_exit(bbr_unregister); ++ ++MODULE_AUTHOR("Van Jacobson "); ++MODULE_AUTHOR("Neal Cardwell "); ++MODULE_AUTHOR("Yuchung Cheng "); ++MODULE_AUTHOR("Soheil Hassas Yeganeh "); ++MODULE_AUTHOR("Priyaranjan Jha "); ++MODULE_AUTHOR("Yousuk Seung "); ++MODULE_AUTHOR("Kevin Yang "); ++MODULE_AUTHOR("Arjun Roy "); ++ ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_DESCRIPTION("TCP BBR (Bottleneck Bandwidth and RTT)"); +diff --git a/net/ipv4/tcp_bbr.c b/net/ipv4/tcp_bbr.c +index 32772d6ded4e..2d6677521575 100644 +--- a/net/ipv4/tcp_bbr.c ++++ b/net/ipv4/tcp_bbr.c +@@ -292,26 +292,40 @@ + sk->sk_pacing_rate = rate; + } + +-/* override sysctl_tcp_min_tso_segs */ + static u32 bbr_min_tso_segs(struct sock *sk) + { + return sk->sk_pacing_rate < (bbr_min_tso_rate >> 3) ? 1 : 2; + } + ++/* Return the number of segments BBR would like in a TSO/GSO skb, given ++ * a particular max gso size as a constraint. ++ */ ++static u32 bbr_tso_segs_generic(struct sock *sk, unsigned int mss_now, ++ u32 gso_max_size) ++{ ++ u32 segs; ++ u32 bytes; ++ ++ /* Budget a TSO/GSO burst size allowance based on bw (pacing_rate). */ ++ bytes = sk->sk_pacing_rate >> sk->sk_pacing_shift; ++ ++ bytes = min_t(u32, bytes, gso_max_size - 1 - MAX_TCP_HEADER); ++ segs = max_t(u32, bytes / mss_now, bbr_min_tso_segs(sk)); ++ return segs; ++} ++ ++/* Custom tcp_tso_autosize() for BBR, used at transmit time to cap skb size. */ ++static u32 bbr_tso_segs(struct sock *sk, unsigned int mss_now) ++{ ++ return bbr_tso_segs_generic(sk, mss_now, sk->sk_gso_max_size); ++} ++ ++/* Like bbr_tso_segs(), using mss_cache, ignoring driver's sk_gso_max_size. */ + static u32 bbr_tso_segs_goal(struct sock *sk) + { + struct tcp_sock *tp = tcp_sk(sk); +- u32 segs, bytes; + +- /* Sort of tcp_tso_autosize() but ignoring +- * driver provided sk_gso_max_size. +- */ +- bytes = min_t(unsigned long, +- sk->sk_pacing_rate >> READ_ONCE(sk->sk_pacing_shift), +- GSO_MAX_SIZE - 1 - MAX_TCP_HEADER); +- segs = max_t(u32, bytes / tp->mss_cache, bbr_min_tso_segs(sk)); +- +- return min(segs, 0x7FU); ++ return bbr_tso_segs_generic(sk, tp->mss_cache, GSO_MAX_SIZE); + } + + /* Save "last known good" cwnd so we can restore it after losses or PROBE_RTT */ +@@ -1147,7 +1161,7 @@ + .undo_cwnd = bbr_undo_cwnd, + .cwnd_event = bbr_cwnd_event, + .ssthresh = bbr_ssthresh, +- .min_tso_segs = bbr_min_tso_segs, ++ .tso_segs = bbr_tso_segs, + .get_info = bbr_get_info, + .set_state = bbr_set_state, + }; +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index 9b48aec29aca..5d41c97d9c5e 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -2682,6 +2682,7 @@ + tp->rx_opt.dsack = 0; + tp->rx_opt.num_sacks = 0; + tp->rcv_ooopack = 0; ++ tp->fast_ack_mode = 0; + + + /* Clean up fastopen related fields */ +diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c +index c445a81d144e..4a9a6b20d1e7 100644 +--- a/net/ipv4/tcp_cong.c ++++ b/net/ipv4/tcp_cong.c +@@ -179,6 +179,7 @@ + const struct inet_connection_sock *icsk = inet_csk(sk); + + tcp_sk(sk)->prior_ssthresh = 0; ++ tcp_sk(sk)->fast_ack_mode = 0; + if (icsk->icsk_ca_ops->init) + icsk->icsk_ca_ops->init(sk); + if (tcp_ca_needs_ecn(sk)) +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index 88b987ca9ebb..c3538bd0d008 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -284,7 +284,7 @@ + tcp_enter_quickack_mode(sk, 2); + break; + case INET_ECN_CE: +- if (tcp_ca_needs_ecn(sk)) ++ if (tcp_ca_wants_ce_events(sk)) + tcp_ca_event(sk, CA_EVENT_ECN_IS_CE); + + if (!(tp->ecn_flags & TCP_ECN_DEMAND_CWR)) { +@@ -295,7 +295,7 @@ + tp->ecn_flags |= TCP_ECN_SEEN; + break; + default: +- if (tcp_ca_needs_ecn(sk)) ++ if (tcp_ca_wants_ce_events(sk)) + tcp_ca_event(sk, CA_EVENT_ECN_NO_CE); + tp->ecn_flags |= TCP_ECN_SEEN; + break; +@@ -957,8 +957,14 @@ + + tcp_sum_lost(tp, skb); + if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_LOST|TCPCB_SACKED_ACKED))) { ++ struct sock *sk = (struct sock *)tp; ++ const struct tcp_congestion_ops *ca_ops; ++ + tp->lost_out += tcp_skb_pcount(skb); + TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; ++ ca_ops = inet_csk(sk)->icsk_ca_ops; ++ if (ca_ops->skb_marked_lost) ++ ca_ops->skb_marked_lost(sk, skb); + } + } + +@@ -1314,6 +1320,17 @@ + WARN_ON_ONCE(tcp_skb_pcount(skb) < pcount); + tcp_skb_pcount_add(skb, -pcount); + ++ /* Adjust tx.in_flight as pcount is shifted from skb to prev. */ ++ if (WARN_ONCE(TCP_SKB_CB(skb)->tx.in_flight < pcount, ++ "prev in_flight: %u skb in_flight: %u pcount: %u", ++ TCP_SKB_CB(prev)->tx.in_flight, ++ TCP_SKB_CB(skb)->tx.in_flight, ++ pcount)) ++ TCP_SKB_CB(skb)->tx.in_flight = 0; ++ else ++ TCP_SKB_CB(skb)->tx.in_flight -= pcount; ++ TCP_SKB_CB(prev)->tx.in_flight += pcount; ++ + /* When we're adding to gso_segs == 1, gso_size will be zero, + * in theory this shouldn't be necessary but as long as DSACK + * code can come after this skb later on it's better to keep +@@ -3087,7 +3104,6 @@ + long seq_rtt_us = -1L; + long ca_rtt_us = -1L; + u32 pkts_acked = 0; +- u32 last_in_flight = 0; + bool rtt_update; + int flag = 0; + +@@ -3125,7 +3141,6 @@ + if (!first_ackt) + first_ackt = last_ackt; + +- last_in_flight = TCP_SKB_CB(skb)->tx.in_flight; + if (before(start_seq, reord)) + reord = start_seq; + if (!after(scb->end_seq, tp->high_seq)) +@@ -3186,8 +3201,8 @@ + seq_rtt_us = tcp_stamp_us_delta(tp->tcp_mstamp, first_ackt); + ca_rtt_us = tcp_stamp_us_delta(tp->tcp_mstamp, last_ackt); + +- if (pkts_acked == 1 && last_in_flight < tp->mss_cache && +- last_in_flight && !prior_sacked && fully_acked && ++ if (pkts_acked == 1 && fully_acked && !prior_sacked && ++ (tp->snd_una - prior_snd_una) < tp->mss_cache && + sack->rate->prior_delivered + 1 == tp->delivered && + !(flag & (FLAG_CA_ALERT | FLAG_SYN_ACKED))) { + /* Conservatively mark a delayed ACK. It's typically +@@ -3244,9 +3259,10 @@ + + if (icsk->icsk_ca_ops->pkts_acked) { + struct ack_sample sample = { .pkts_acked = pkts_acked, +- .rtt_us = sack->rate->rtt_us, +- .in_flight = last_in_flight }; ++ .rtt_us = sack->rate->rtt_us }; + ++ sample.in_flight = tp->mss_cache * ++ (tp->delivered - sack->rate->prior_delivered); + icsk->icsk_ca_ops->pkts_acked(sk, &sample); + } + +@@ -3645,6 +3661,7 @@ + + prior_fack = tcp_is_sack(tp) ? tcp_highest_sack_seq(tp) : tp->snd_una; + rs.prior_in_flight = tcp_packets_in_flight(tp); ++ tcp_rate_check_app_limited(sk); + + /* ts_recent update must be made after we are sure that the packet + * is in window. +@@ -3737,6 +3754,7 @@ + delivered = tcp_newly_delivered(sk, delivered, flag); + lost = tp->lost - lost; /* freshly marked lost */ + rs.is_ack_delayed = !!(flag & FLAG_ACK_MAYBE_DELAYED); ++ rs.is_ece = !!(flag & FLAG_ECE); + tcp_rate_gen(sk, delivered, lost, is_sack_reneg, sack_state.rate); + tcp_cong_control(sk, ack, delivered, flag, sack_state.rate); + tcp_xmit_recovery(sk, rexmit); +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index be6d22b8190f..4943f96aade8 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -376,7 +376,8 @@ + th->cwr = 1; + skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN; + } +- } else if (!tcp_ca_needs_ecn(sk)) { ++ } else if (!(tp->ecn_flags & TCP_ECN_ECT_PERMANENT) && ++ !tcp_ca_needs_ecn(sk)) { + /* ACK or retransmitted segment: clear ECT|CE */ + INET_ECN_dontxmit(sk); + } +@@ -1037,8 +1038,6 @@ + tp->tcp_wstamp_ns = max(tp->tcp_wstamp_ns, tp->tcp_clock_cache); + skb->skb_mstamp_ns = tp->tcp_wstamp_ns; + if (clone_it) { +- TCP_SKB_CB(skb)->tx.in_flight = TCP_SKB_CB(skb)->end_seq +- - tp->snd_una; + oskb = skb; + + tcp_skb_tsorted_save(oskb) { +@@ -1308,7 +1307,7 @@ + { + struct tcp_sock *tp = tcp_sk(sk); + struct sk_buff *buff; +- int nsize, old_factor; ++ int nsize, old_factor, inflight_prev; + long limit; + int nlen; + u8 flags; +@@ -1386,6 +1385,15 @@ + + if (diff) + tcp_adjust_pcount(sk, skb, diff); ++ ++ /* Set buff tx.in_flight as if buff were sent by itself. */ ++ inflight_prev = TCP_SKB_CB(skb)->tx.in_flight - old_factor; ++ /* if (WARN_ONCE(inflight_prev < 0, ++ "inconsistent: tx.in_flight: %u old_factor: %d", ++ TCP_SKB_CB(skb)->tx.in_flight, old_factor)) */ ++ if (inflight_prev < 0) inflight_prev = 0; ++ TCP_SKB_CB(buff)->tx.in_flight = inflight_prev + ++ tcp_skb_pcount(buff); + } + + /* Link BUFF into the send queue. */ +@@ -1754,13 +1762,12 @@ + static u32 tcp_tso_segs(struct sock *sk, unsigned int mss_now) + { + const struct tcp_congestion_ops *ca_ops = inet_csk(sk)->icsk_ca_ops; +- u32 min_tso, tso_segs; +- +- min_tso = ca_ops->min_tso_segs ? +- ca_ops->min_tso_segs(sk) : +- sock_net(sk)->ipv4.sysctl_tcp_min_tso_segs; ++ u32 tso_segs; + +- tso_segs = tcp_tso_autosize(sk, mss_now, min_tso); ++ tso_segs = ca_ops->tso_segs ? ++ ca_ops->tso_segs(sk, mss_now) : ++ tcp_tso_autosize(sk, mss_now, ++ sock_net(sk)->ipv4.sysctl_tcp_min_tso_segs); + return min_t(u32, tso_segs, sk->sk_gso_max_segs); + } + +@@ -2398,6 +2405,7 @@ + skb->skb_mstamp_ns = tp->tcp_wstamp_ns = tp->tcp_clock_cache; + list_move_tail(&skb->tcp_tsorted_anchor, &tp->tsorted_sent_queue); + tcp_init_tso_segs(skb, mss_now); ++ tcp_set_tx_in_flight(sk, skb); + goto repair; /* Skip network transmission */ + } + +diff --git a/net/ipv4/tcp_rate.c b/net/ipv4/tcp_rate.c +index 0de693565963..796fa6e5310c 100644 +--- a/net/ipv4/tcp_rate.c ++++ b/net/ipv4/tcp_rate.c +@@ -34,6 +34,24 @@ + * ready to send in the write queue. + */ + ++void tcp_set_tx_in_flight(struct sock *sk, struct sk_buff *skb) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); ++ u32 in_flight; ++ ++ /* Check, sanitize, and record packets in flight after skb was sent. */ ++ in_flight = tcp_packets_in_flight(tp) + tcp_skb_pcount(skb); ++ if (WARN_ONCE(in_flight > TCPCB_IN_FLIGHT_MAX, ++ "insane in_flight %u cc %s mss %u " ++ "cwnd %u pif %u %u %u %u\n", ++ in_flight, inet_csk(sk)->icsk_ca_ops->name, ++ tp->mss_cache, tp->snd_cwnd, ++ tp->packets_out, tp->retrans_out, ++ tp->sacked_out, tp->lost_out)) ++ in_flight = TCPCB_IN_FLIGHT_MAX; ++ TCP_SKB_CB(skb)->tx.in_flight = in_flight; ++} ++ + /* Snapshot the current delivery information in the skb, to generate + * a rate sample later when the skb is (s)acked in tcp_rate_skb_delivered(). + */ +@@ -65,7 +83,10 @@ + TCP_SKB_CB(skb)->tx.first_tx_mstamp = tp->first_tx_mstamp; + TCP_SKB_CB(skb)->tx.delivered_mstamp = tp->delivered_mstamp; + TCP_SKB_CB(skb)->tx.delivered = tp->delivered; ++ TCP_SKB_CB(skb)->tx.delivered_ce = tp->delivered_ce; ++ TCP_SKB_CB(skb)->tx.lost = tp->lost; + TCP_SKB_CB(skb)->tx.is_app_limited = tp->app_limited ? 1 : 0; ++ tcp_set_tx_in_flight(sk, skb); + } + + /* When an skb is sacked or acked, we fill in the rate sample with the (prior) +@@ -86,15 +107,19 @@ + + if (!rs->prior_delivered || + after(scb->tx.delivered, rs->prior_delivered)) { ++ rs->prior_lost = scb->tx.lost; ++ rs->prior_delivered_ce = scb->tx.delivered_ce; + rs->prior_delivered = scb->tx.delivered; + rs->prior_mstamp = scb->tx.delivered_mstamp; + rs->is_app_limited = scb->tx.is_app_limited; + rs->is_retrans = scb->sacked & TCPCB_RETRANS; ++ rs->tx_in_flight = scb->tx.in_flight; + + /* Record send time of most recently ACKed packet: */ + tp->first_tx_mstamp = tcp_skb_timestamp_us(skb); + /* Find the duration of the "send phase" of this window: */ +- rs->interval_us = tcp_stamp_us_delta(tp->first_tx_mstamp, ++ rs->interval_us = tcp_stamp32_us_delta( ++ tp->first_tx_mstamp, + scb->tx.first_tx_mstamp); + + } +@@ -137,6 +162,11 @@ + return; + } + rs->delivered = tp->delivered - rs->prior_delivered; ++ rs->lost = tp->lost - rs->prior_lost; ++ ++ rs->delivered_ce = tp->delivered_ce - rs->prior_delivered_ce; ++ /* delivered_ce occupies less than 32 bits in the skb control block */ ++ rs->delivered_ce &= TCPCB_DELIVERED_CE_MASK; + + /* Model sending data and receiving ACKs as separate pipeline phases + * for a window. Usually the ACK phase is longer, but with ACK +@@ -144,7 +174,7 @@ + * longer phase. + */ + snd_us = rs->interval_us; /* send phase */ +- ack_us = tcp_stamp_us_delta(tp->tcp_mstamp, ++ ack_us = tcp_stamp32_us_delta(tp->tcp_mstamp, + rs->prior_mstamp); /* ack phase */ + rs->interval_us = max(snd_us, ack_us); + +diff -rNEZbwBdu3 a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c +--- a/net/ipv4/tcp_timer.c 2021-06-03 14:59:17.000000000 +0800 ++++ b/net/ipv4/tcp_timer.c 2021-07-23 16:23:30.821912330 +0800 +@@ -602,6 +602,7 @@ + goto out; + } + ++ tcp_rate_check_app_limited(sk); + tcp_mstamp_refresh(tcp_sk(sk)); + event = icsk->icsk_pending; + diff --git a/PATCH/BBRv2/openwrt-kmod-bbr2.patch b/PATCH/BBRv2/openwrt-kmod-bbr2.patch new file mode 100644 index 000000000..88505851c --- /dev/null +++ b/PATCH/BBRv2/openwrt-kmod-bbr2.patch @@ -0,0 +1,37 @@ +From 85a75a212cece40387394cd49bc0d203222e8a69 Mon Sep 17 00:00:00 2001 +From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> +Date: Fri, 23 Jul 2021 16:59:43 +0800 +Subject: [PATCH] Update netsupport.mk + +--- + package/kernel/linux/modules/netsupport.mk | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/package/kernel/linux/modules/netsupport.mk b/package/kernel/linux/modules/netsupport.mk +index 0c68b394d1e2..164322838008 100644 +--- a/package/kernel/linux/modules/netsupport.mk ++++ b/package/kernel/linux/modules/netsupport.mk +@@ -948,6 +948,23 @@ endef + + $(eval $(call KernelPackage,tcp-bbr)) + ++define KernelPackage/tcp-bbr2 ++ SUBMENU:=$(NETWORK_SUPPORT_MENU) ++ TITLE:=BBRv2 TCP congestion control ++ KCONFIG:= \ ++ CONFIG_TCP_CONG_ADVANCED=y \ ++ CONFIG_TCP_CONG_BBR2 ++ FILES:=$(LINUX_DIR)/net/ipv4/tcp_bbr2.ko ++ AUTOLOAD:=$(call AutoLoad,74,tcp_bbr2) ++endef ++ ++define KernelPackage/tcp-bbr2/description ++ Kernel module for BBRv2 (Bottleneck Bandwidth and RTT) TCP congestion ++ control. It requires the fq ("Fair Queue") pacing packet scheduler. ++ For kernel 4.13+, TCP internal pacing is implemented as fallback. ++endef ++ ++$(eval $(call KernelPackage,tcp-bbr2)) + + define KernelPackage/ax25 + SUBMENU:=$(NETWORK_SUPPORT_MENU) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 0935fdc34..59bfa0923 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -40,11 +40,8 @@ svn co https://github.com/openwrt/packages/trunk/libs/dtc feeds/packages/libs/dt #' >> ./target/linux/generic/config-5.4 # BBRv2 -wget -P target/linux/generic/hack-5.4/ https://github.com/Ysurac/openmptcprouter/raw/develop/root/target/linux/generic/hack-5.4/692-tcp_nanqinlang.patch -wget -P target/linux/generic/hack-5.4/ https://github.com/Ysurac/openmptcprouter/raw/develop/root/target/linux/generic/hack-5.4/693-tcp_bbr2.patch -wget https://github.com/google/bbr/commit/3d76056.patch -O target/linux/generic/hack-5.4/694-tcp_bbr2.patch -wget -qO - https://github.com/Ysurac/openmptcprouter/raw/develop/patches/nanqinlang.patch | patch -p1 -wget -qO - https://github.com/Ysurac/openmptcprouter/raw/develop/patches/bbr2.patch | patch -p1 +patch -p1 < ../PATCH/BBRv2/openwrt-kmod-bbr2.patch +cp -f ../PATCH/BBRv2/693-tcp_bbr2.patch ./target/linux/generic/hack-5.4/693-tcp_bbr2.patch # OPENSSL wget -qO - https://github.com/mj22226/openwrt/commit/5e1063.patch | patch -p1 From 73dd4b3b95d7875571b2e17fa9f399851d2a1529 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sat, 24 Jul 2021 01:44:24 +0800 Subject: [PATCH 168/244] Wireguard --- SEED/R2S/config.seed | 1 + SEED/R4S/config.seed | 1 + SEED/X86/config.seed | 1 + 3 files changed, 3 insertions(+) diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 828ca2495..7bd5a331c 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -88,6 +88,7 @@ CONFIG_PACKAGE_luci-proto-ppp=y ### APPLICATION ### #CONFIG_PACKAGE_luci-app-adguardhome=y #CONFIG_PACKAGE_adguardhome=y +CONFIG_PACKAGE_luci-app-wireguard=y CONFIG_PACKAGE_luci-app-argon-config=y CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index b3c26e343..ed9d1fc45 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -86,6 +86,7 @@ CONFIG_PACKAGE_luci-proto-ppp=y ### APPLICATION ### #CONFIG_PACKAGE_luci-app-adguardhome=y #CONFIG_PACKAGE_adguardhome=y +CONFIG_PACKAGE_luci-app-wireguard=y CONFIG_PACKAGE_luci-app-argon-config=y CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index 4115050a4..3bdcff258 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -86,6 +86,7 @@ CONFIG_PACKAGE_luci-proto-ppp=y ### APPLICATION ### #CONFIG_PACKAGE_luci-app-adguardhome=y #CONFIG_PACKAGE_adguardhome=y +CONFIG_PACKAGE_luci-app-wireguard=y CONFIG_PACKAGE_luci-app-argon-config=y CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y From b0acc6927ac78c09e3faef01c23f11137379d0c3 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sat, 24 Jul 2021 14:45:40 +0800 Subject: [PATCH 169/244] Refresh BBRv2 Patch --- ...v2_congestion_control_for_Linux_TCP.patch} | 120 ++++++++++++------ SCRIPTS/02_prepare_package.sh | 5 +- 2 files changed, 85 insertions(+), 40 deletions(-) rename PATCH/BBRv2/{693-tcp_bbr2.patch => 693-Add_BBRv2_congestion_control_for_Linux_TCP.patch} (97%) diff --git a/PATCH/BBRv2/693-tcp_bbr2.patch b/PATCH/BBRv2/693-Add_BBRv2_congestion_control_for_Linux_TCP.patch similarity index 97% rename from PATCH/BBRv2/693-tcp_bbr2.patch rename to PATCH/BBRv2/693-Add_BBRv2_congestion_control_for_Linux_TCP.patch index dc7a9d1b9..902bbfc1b 100644 --- a/PATCH/BBRv2/693-tcp_bbr2.patch +++ b/PATCH/BBRv2/693-Add_BBRv2_congestion_control_for_Linux_TCP.patch @@ -1,18 +1,44 @@ -From 3d76056b85feab3aade8007eb560c3451e7d3433 Mon Sep 17 00:00:00 2001 -From: Adithya Abraham Philip -Date: Fri, 11 Jun 2021 21:56:10 +0000 -Subject: [PATCH] net-tcp_bbr: v2: Fix missing ECT markings on retransmits for BBRv2 +From a18c15e88577391df9dc2d9dcf15d39e459daa17 Mon Sep 17 00:00:00 2001 +From: Neal Cardwell +Date: Tue, 11 Jun 2019 12:54:22 -0400 +Subject: [PATCH] net-tcp_bbr: v2: BBRv2 ("bbr2") congestion control for Linux TCP -Adds a new flag TCP_ECN_ECT_PERMANENT that is used by CCAs to -indicate that retransmitted packets and pure ACKs must have the -ECT bit set. This is a necessary fix for BBRv2, which when using -ECN expects ECT to be set even on retransmitted packets and ACKs. -Currently CCAs like BBRv2 which can use ECN but don't "need" it -do not have a way to indicate that ECT should be set on -retransmissions/ACKs. +BBR v2 is an enhacement to the BBR v1 algorithm. It's designed to aim for lower +queues, lower loss, and better Reno/CUBIC coexistence than BBR v1. -Signed-off-by: Adithya Abraham Philip -Signed-off-by: Neal Cardwell +BBR v2 maintains the core of BBR v1: an explicit model of the network +path that is two-dimensional, adapting to estimate the (a) maximum +available bandwidth and (b) maximum safe volume of data a flow can +keep in-flight in the network. It maintains the estimated BDP as a +core guide for estimating an appropriate level of in-flight data. + +o Include: +https://github.com/google/bbr/commit/e5fe52d14 +https://github.com/google/bbr/commit/9ec103688 +https://github.com/google/bbr/commit/824a49a77 +https://github.com/google/bbr/commit/1f1c88e4a +https://github.com/google/bbr/commit/535abb7af +https://github.com/google/bbr/commit/831329194 +https://github.com/google/bbr/commit/115c522f1 +https://github.com/google/bbr/commit/1d807593c +https://github.com/google/bbr/commit/bedc8f36a +https://github.com/google/bbr/commit/7feb2a444 +https://github.com/google/bbr/commit/419a582ff +https://github.com/google/bbr/commit/8a68f6366 +https://github.com/google/bbr/commit/948c31273 +https://github.com/google/bbr/commit/1cd7f04b1 +https://github.com/google/bbr/commit/d19d4d25d +https://github.com/google/bbr/commit/a18c15e88 +https://github.com/google/bbr/commit/4caa947cf +https://github.com/google/bbr/commit/55105fea3 +https://github.com/google/bbr/commit/8d11b540f +https://github.com/google/bbr/commit/ab41f1902 +https://github.com/google/bbr/commit/74f603c70 +https://github.com/google/bbr/commit/3d76056b8 + +Effort: net-tcp_bbr +Origin-9xx-SHA1: 2c84098e60bed6d67dde23cd7538c51dee273102 +Change-Id: I125cf26ba2a7a686f2fa5e87f4c2afceb65f7a05 --- diff --git a/include/linux/tcp.h b/include/linux/tcp.h index ca6f01531e64..145b15f5d07e 100644 @@ -2963,44 +2989,45 @@ index 32772d6ded4e..2d6677521575 100644 return sk->sk_pacing_rate < (bbr_min_tso_rate >> 3) ? 1 : 2; } +-static u32 bbr_tso_segs_goal(struct sock *sk) +/* Return the number of segments BBR would like in a TSO/GSO skb, given + * a particular max gso size as a constraint. + */ +static u32 bbr_tso_segs_generic(struct sock *sk, unsigned int mss_now, + u32 gso_max_size) -+{ + { +- struct tcp_sock *tp = tcp_sk(sk); +- u32 segs, bytes; + u32 segs; -+ u32 bytes; -+ ++ u64 bytes; + +- /* Sort of tcp_tso_autosize() but ignoring +- * driver provided sk_gso_max_size. +- */ +- bytes = min_t(unsigned long, +- sk->sk_pacing_rate >> READ_ONCE(sk->sk_pacing_shift), +- GSO_MAX_SIZE - 1 - MAX_TCP_HEADER); +- segs = max_t(u32, bytes / tp->mss_cache, bbr_min_tso_segs(sk)); + /* Budget a TSO/GSO burst size allowance based on bw (pacing_rate). */ + bytes = sk->sk_pacing_rate >> sk->sk_pacing_shift; -+ + +- return min(segs, 0x7FU); + bytes = min_t(u32, bytes, gso_max_size - 1 - MAX_TCP_HEADER); + segs = max_t(u32, bytes / mss_now, bbr_min_tso_segs(sk)); + return segs; +} + +/* Custom tcp_tso_autosize() for BBR, used at transmit time to cap skb size. */ -+static u32 bbr_tso_segs(struct sock *sk, unsigned int mss_now) +++static u32 bbr_tso_segs(struct sock *sk, unsigned int mss_now) +{ + return bbr_tso_segs_generic(sk, mss_now, sk->sk_gso_max_size); +} + +/* Like bbr_tso_segs(), using mss_cache, ignoring driver's sk_gso_max_size. */ - static u32 bbr_tso_segs_goal(struct sock *sk) - { - struct tcp_sock *tp = tcp_sk(sk); -- u32 segs, bytes; - -- /* Sort of tcp_tso_autosize() but ignoring -- * driver provided sk_gso_max_size. -- */ -- bytes = min_t(unsigned long, -- sk->sk_pacing_rate >> READ_ONCE(sk->sk_pacing_shift), -- GSO_MAX_SIZE - 1 - MAX_TCP_HEADER); -- segs = max_t(u32, bytes / tp->mss_cache, bbr_min_tso_segs(sk)); -- -- return min(segs, 0x7FU); ++ ++static u32 bbr_tso_segs_goal(struct sock *sk) ++{ ++ struct tcp_sock *tp = tcp_sk(sk); + return bbr_tso_segs_generic(sk, tp->mss_cache, GSO_MAX_SIZE); } @@ -3149,6 +3176,22 @@ index 88b987ca9ebb..c3538bd0d008 100644 tcp_rate_gen(sk, delivered, lost, is_sack_reneg, sack_state.rate); tcp_cong_control(sk, ack, delivered, flag, sack_state.rate); tcp_xmit_recovery(sk, rexmit); +@@ -5261,13 +5279,14 @@ + + /* More than one full frame received... */ + if (((tp->rcv_nxt - tp->rcv_wup) > inet_csk(sk)->icsk_ack.rcv_mss && ++ (tp->fast_ack_mode == 1 || + /* ... and right edge of window advances far enough. + * (tcp_recvmsg() will send ACK otherwise). + * If application uses SO_RCVLOWAT, we want send ack now if + * we have not received enough bytes to satisfy the condition. + */ + (tp->rcv_nxt - tp->copied_seq < sk->sk_rcvlowat || +- __tcp_select_window(sk) >= tp->rcv_wnd)) || ++ __tcp_select_window(sk) >= tp->rcv_wnd))) || + /* We ACK each frame or... */ + tcp_in_quickack_mode(sk) || + /* Protocol state mandates a one-time immediate ACK */ diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index be6d22b8190f..4943f96aade8 100644 --- a/net/ipv4/tcp_output.c @@ -3188,10 +3231,10 @@ index be6d22b8190f..4943f96aade8 100644 + + /* Set buff tx.in_flight as if buff were sent by itself. */ + inflight_prev = TCP_SKB_CB(skb)->tx.in_flight - old_factor; -+ /* if (WARN_ONCE(inflight_prev < 0, ++ if (WARN_ONCE(inflight_prev < 0, + "inconsistent: tx.in_flight: %u old_factor: %d", -+ TCP_SKB_CB(skb)->tx.in_flight, old_factor)) */ -+ if (inflight_prev < 0) inflight_prev = 0; ++ TCP_SKB_CB(skb)->tx.in_flight, old_factor)) ++ inflight_prev = 0; + TCP_SKB_CB(buff)->tx.in_flight = inflight_prev + + tcp_skb_pcount(buff); } @@ -3306,9 +3349,10 @@ index 0de693565963..796fa6e5310c 100644 rs->prior_mstamp); /* ack phase */ rs->interval_us = max(snd_us, ack_us); -diff -rNEZbwBdu3 a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c ---- a/net/ipv4/tcp_timer.c 2021-06-03 14:59:17.000000000 +0800 -+++ b/net/ipv4/tcp_timer.c 2021-07-23 16:23:30.821912330 +0800 +diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c +index dd5a6317a801..1da66d4bbb08 100644 +--- a/net/ipv4/tcp_timer.c ++++ b/net/ipv4/tcp_timer.c @@ -602,6 +602,7 @@ goto out; } diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 59bfa0923..d2ca85a34 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -41,10 +41,11 @@ svn co https://github.com/openwrt/packages/trunk/libs/dtc feeds/packages/libs/dt # BBRv2 patch -p1 < ../PATCH/BBRv2/openwrt-kmod-bbr2.patch -cp -f ../PATCH/BBRv2/693-tcp_bbr2.patch ./target/linux/generic/hack-5.4/693-tcp_bbr2.patch +cp -f ../PATCH/BBRv2/693-Add_BBRv2_congestion_control_for_Linux_TCP.patch ./target/linux/generic/hack-5.4/693-Add_BBRv2_congestion_control_for_Linux_TCP.patch +wget -qO - https://github.com/openwrt/openwrt/commit/cfaf039.patch | patch -p1 # OPENSSL -wget -qO - https://github.com/mj22226/openwrt/commit/5e1063.patch | patch -p1 +wget -qO - https://github.com/mj22226/openwrt/commit/5e10633.patch | patch -p1 ### 必要的 Patches ### # Patch arm64 型号名称 From 27c35daa384cbccd6da517f4d75d9822f9a6465b Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 26 Jul 2021 15:13:05 +0800 Subject: [PATCH 170/244] Socat --- SCRIPTS/02_prepare_package.sh | 7 ++++++- SEED/R2S/config.seed | 1 + SEED/R4S/config.seed | 1 + SEED/X86/config.seed | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index d2ca85a34..86cc861e3 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -65,6 +65,7 @@ popd # Patch FireWall 以增添 FullCone 功能 mkdir package/network/config/firewall/patches wget -P package/network/config/firewall/patches/ https://github.com/immortalwrt/immortalwrt/raw/master/package/network/config/firewall/patches/fullconenat.patch +wget -qO- https://github.com/msylgj/R2S-R4S-OpenWrt/raw/21.02/SCRIPTS/fix_firewall_flock.patch | patch -p1 # Patch LuCI 以增添 FullCone 开关 patch -p1 < ../PATCH/firewall/luci-app-firewall_add_fullcone.patch # FullCone 相关组件 @@ -227,6 +228,9 @@ git clone -b master --depth 1 https://github.com/destan19/OpenAppFilter.git pack git clone -b master --depth 1 https://github.com/NateLol/luci-app-oled.git package/new/luci-app-oled # OpenClash git clone -b master --depth 1 https://github.com/vernesong/OpenClash.git package/new/luci-app-openclash +pushd package/new/luci-app-openclash +wget -qO - https://github.com/vernesong/OpenClash/pull/1499.patch | patch -p1 +popd # 花生壳内网穿透 #svn co https://github.com/QiuSimons/dragino2-teasiu/trunk/package/teasiu/luci-app-phtunnel package/new/luci-app-phtunnel #svn co https://github.com/QiuSimons/dragino2-teasiu/trunk/package/teasiu/phtunnel package/new/phtunnel @@ -313,8 +317,9 @@ sed -i '/result.encrypt_method/a\result.fast_open = "1"' root/usr/share/shadowso sed -i 's,ispip.clang.cn/all_cn,cdn.jsdelivr.net/gh/QiuSimons/Chnroute@master/dist/chnroute/chnroute,' root/etc/init.d/shadowsocksr sed -i 's,YW5vbnltb3Vz/domain-list-community/release/gfwlist.txt,Loyalsoldier/v2ray-rules-dat/release/gfw.txt,' root/etc/init.d/shadowsocksr sed -i '/Clang.CN.CIDR/a\o:value("https://cdn.jsdelivr.net/gh/QiuSimons/Chnroute@master/dist/chnroute/chnroute.txt", translate("QiuSimons/Chnroute"))' luasrc/model/cbi/shadowsocksr/advanced.lua - popd +# socat +svn co https://github.com/Lienol/openwrt-package/trunk/luci-app-socat package/new/luci-app-socat # 订阅转换 svn co https://github.com/immortalwrt/packages/trunk/net/subconverter feeds/packages/net/subconverter ln -sf ../../../feeds/packages/net/subconverter ./package/feeds/packages/subconverter diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 7bd5a331c..9d67664ad 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -89,6 +89,7 @@ CONFIG_PACKAGE_luci-proto-ppp=y #CONFIG_PACKAGE_luci-app-adguardhome=y #CONFIG_PACKAGE_adguardhome=y CONFIG_PACKAGE_luci-app-wireguard=y +CONFIG_PACKAGE_luci-app-socat=y CONFIG_PACKAGE_luci-app-argon-config=y CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index ed9d1fc45..8fddae1cc 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -87,6 +87,7 @@ CONFIG_PACKAGE_luci-proto-ppp=y #CONFIG_PACKAGE_luci-app-adguardhome=y #CONFIG_PACKAGE_adguardhome=y CONFIG_PACKAGE_luci-app-wireguard=y +CONFIG_PACKAGE_luci-app-socat=y CONFIG_PACKAGE_luci-app-argon-config=y CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index 3bdcff258..5540d1ae2 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -87,6 +87,7 @@ CONFIG_PACKAGE_luci-proto-ppp=y #CONFIG_PACKAGE_luci-app-adguardhome=y #CONFIG_PACKAGE_adguardhome=y CONFIG_PACKAGE_luci-app-wireguard=y +CONFIG_PACKAGE_luci-app-socat=y CONFIG_PACKAGE_luci-app-argon-config=y CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y From 441b2c2bfd3e0b032c085d04445e292339b7a3cb Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 22 Jul 2021 17:29:13 +0800 Subject: [PATCH 171/244] TWEAK --- SCRIPTS/02_prepare_package.sh | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 86cc861e3..f8dc66cb4 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -22,23 +22,6 @@ sed -i '/unshift/d' scripts/download.pl sed -i '/mirror02/d' scripts/download.pl echo "net.netfilter.nf_conntrack_helper = 1" >> ./package/kernel/linux/files/sysctl-nf-conntrack.conf -# GCC11 -rm -rf ./toolchain/gcc -svn co https://github.com/openwrt/openwrt/trunk/toolchain/gcc toolchain/gcc -rm -rf ./package/network/utils/bpftools -svn co https://github.com/openwrt/openwrt/trunk/package/network/utils/bpftools package/network/utils/bpftools -rm -rf ./package/libs/elfutils -svn co https://github.com/neheb/openwrt/branches/elf/package/libs/elfutils package/libs/elfutils -rm -rf ./feeds/packages/libs/dtc -svn co https://github.com/openwrt/packages/trunk/libs/dtc feeds/packages/libs/dtc - -# MPTCP -#wget -P target/linux/generic/hack-5.4/ https://github.com/Ysurac/openmptcprouter/raw/develop/root/target/linux/generic/hack-5.4/690-mptcp_trunk.patch -#wget -P target/linux/generic/hack-5.4/ https://github.com/Ysurac/openmptcprouter/raw/develop/root/target/linux/generic/hack-5.4/998-ndpi-netfilter.patch -#echo ' -#CONFIG_CRYPTO_SHA256=y -#' >> ./target/linux/generic/config-5.4 - # BBRv2 patch -p1 < ../PATCH/BBRv2/openwrt-kmod-bbr2.patch cp -f ../PATCH/BBRv2/693-Add_BBRv2_congestion_control_for_Linux_TCP.patch ./target/linux/generic/hack-5.4/693-Add_BBRv2_congestion_control_for_Linux_TCP.patch @@ -184,6 +167,7 @@ git clone --depth 1 https://github.com/garypang13/luci-app-dnsfilter.git package # Dnsproxy svn co https://github.com/immortalwrt/packages/trunk/net/dnsproxy feeds/packages/net/dnsproxy ln -sf ../../../feeds/packages/net/dnsproxy ./package/feeds/packages/dnsproxy +sed -i '/CURDIR/d' feeds/packages/net/dnsproxy/Makefile svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/luci-app-dnsproxy package/new/luci-app-dnsproxy # Edge 主题 git clone -b master --depth 1 https://github.com/garypang13/luci-theme-edge.git package/new/luci-theme-edge @@ -227,9 +211,9 @@ git clone -b master --depth 1 https://github.com/destan19/OpenAppFilter.git pack # OLED 驱动程序 git clone -b master --depth 1 https://github.com/NateLol/luci-app-oled.git package/new/luci-app-oled # OpenClash -git clone -b master --depth 1 https://github.com/vernesong/OpenClash.git package/new/luci-app-openclash +git clone --single-branch --depth 1 -b dev https://github.com/vernesong/OpenClash.git package/new/luci-app-openclash pushd package/new/luci-app-openclash -wget -qO - https://github.com/vernesong/OpenClash/pull/1499.patch | patch -p1 +#wget -qO - https://github.com/vernesong/OpenClash/pull/1499.patch | patch -p1 popd # 花生壳内网穿透 #svn co https://github.com/QiuSimons/dragino2-teasiu/trunk/package/teasiu/luci-app-phtunnel package/new/luci-app-phtunnel From fc2270ca2cf7c6a719a4d0c6dddaa32375dbb52b Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 27 Jul 2021 13:14:48 +0800 Subject: [PATCH 172/244] Disable SFE --- SCRIPTS/02_prepare_package.sh | 14 +++++++------- SEED/R2S/config.seed | 7 +++---- SEED/R4S/config.seed | 7 +++---- SEED/X86/config.seed | 7 +++---- 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index f8dc66cb4..0920e2b91 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -56,15 +56,15 @@ cp -rf ../openwrt-lienol/package/network/fullconenat ./package/network/fullconen ### Shortcut-FE 部分 ### # Patch Kernel 以支持 Shortcut-FE -pushd target/linux/generic/hack-5.4 -wget https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/generic/hack-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch -popd +#pushd target/linux/generic/hack-5.4 +#wget https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/generic/hack-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch +#popd # Patch LuCI 以增添 Shortcut-FE 开关 -patch -p1 < ../PATCH/firewall/luci-app-firewall_add_sfe_switch.patch +#patch -p1 < ../PATCH/firewall/luci-app-firewall_add_sfe_switch.patch # Shortcut-FE 相关组件 -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/shortcut-fe package/lean/shortcut-fe -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/fast-classifier package/lean/fast-classifier -wget -P package/base-files/files/etc/init.d/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/shortcut-fe +#svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/shortcut-fe package/lean/shortcut-fe +#svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/fast-classifier package/lean/fast-classifier +#wget -P package/base-files/files/etc/init.d/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/shortcut-fe ### 获取额外的基础软件包 ### # AutoCore diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 9d67664ad..ee9213c24 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -13,7 +13,6 @@ CONFIG_NODEJS_14=y CONFIG_NODEJS_ICU_NONE=y CONFIG_DEVEL=y CONFIG_TOOLCHAINOPTS=y -CONFIG_GCC_USE_VERSION_11=y ### BASIC ### CONFIG_PACKAGE_r8169-firmware=y @@ -40,8 +39,8 @@ CONFIG_PACKAGE_iptables-mod-nat-extra=y CONFIG_PACKAGE_kmod-fs-f2fs=y CONFIG_PACKAGE_kmod-ipt-nat6=y CONFIG_PACKAGE_kmod-tun=y -CONFIG_PACKAGE_kmod-shortcut-fe=y -CONFIG_PACKAGE_kmod-fast-classifier=y +#CONFIG_PACKAGE_kmod-shortcut-fe=y +#CONFIG_PACKAGE_kmod-fast-classifier=y CONFIG_PACKAGE_kmod-usb2=y CONFIG_PACKAGE_kmod-usb2-pci=y CONFIG_PACKAGE_kmod-usb3=y @@ -129,7 +128,7 @@ CONFIG_PACKAGE_luci-app-zerotier=y CONFIG_PACKAGE_zerotier=y CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y -#CONFIG_PACKAGE_subconverter=y +CONFIG_PACKAGE_subconverter=y CONFIG_PACKAGE_dnsproxy=y CONFIG_PACKAGE_luci-app-dnsfilter=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index 8fddae1cc..fe01cd954 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -13,7 +13,6 @@ CONFIG_NODEJS_14=y CONFIG_NODEJS_ICU_NONE=y CONFIG_DEVEL=y CONFIG_TOOLCHAINOPTS=y -CONFIG_GCC_USE_VERSION_11=y ### BASIC ### CONFIG_PACKAGE_r8169-firmware=y @@ -41,8 +40,8 @@ CONFIG_PACKAGE_kmod-fs-f2fs=y CONFIG_PACKAGE_kmod-ipt-nat6=y CONFIG_PACKAGE_kmod-tun=y CONFIG_PACKAGE_kmod-r8168=y -CONFIG_PACKAGE_kmod-shortcut-fe=y -CONFIG_PACKAGE_kmod-fast-classifier=y +#CONFIG_PACKAGE_kmod-shortcut-fe=y +#CONFIG_PACKAGE_kmod-fast-classifier=y # CONFIG_PACKAGE_kmod-shortcut-fe-cm is not set CONFIG_PACKAGE_libiwinfo=y CONFIG_PACKAGE_libiwinfo-lua=y @@ -126,7 +125,7 @@ CONFIG_PACKAGE_luci-app-zerotier=y CONFIG_PACKAGE_zerotier=y CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y -#CONFIG_PACKAGE_subconverter=y +CONFIG_PACKAGE_subconverter=y CONFIG_PACKAGE_dnsproxy=y CONFIG_PACKAGE_luci-app-dnsfilter=y diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index 5540d1ae2..3c2c51f02 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -14,7 +14,6 @@ CONFIG_NODEJS_14=y CONFIG_NODEJS_ICU_NONE=y CONFIG_DEVEL=y CONFIG_TOOLCHAINOPTS=y -CONFIG_GCC_USE_VERSION_11=y ### BASIC ### CONFIG_PACKAGE_addition-trans-zh=y @@ -39,8 +38,8 @@ CONFIG_PACKAGE_iptables-mod-nat-extra=y CONFIG_PACKAGE_kmod-fs-f2fs=y CONFIG_PACKAGE_kmod-ipt-nat6=y CONFIG_PACKAGE_kmod-tun=y -CONFIG_PACKAGE_kmod-shortcut-fe=y -CONFIG_PACKAGE_kmod-fast-classifier=y +#CONFIG_PACKAGE_kmod-shortcut-fe=y +#CONFIG_PACKAGE_kmod-fast-classifier=y # CONFIG_PACKAGE_kmod-shortcut-fe-cm is not set CONFIG_PACKAGE_libiwinfo=y CONFIG_PACKAGE_libiwinfo-lua=y @@ -126,7 +125,7 @@ CONFIG_PACKAGE_luci-app-zerotier=y CONFIG_PACKAGE_zerotier=y CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y -#CONFIG_PACKAGE_subconverter=y +CONFIG_PACKAGE_subconverter=y CONFIG_PACKAGE_dnsproxy=y CONFIG_PACKAGE_luci-app-dnsfilter=y From 6ace5d025decd5f6721dcdfbb1829e4883be3b6d Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 28 Jul 2021 00:10:36 +0800 Subject: [PATCH 173/244] mess around with cflags --- SCRIPTS/02_prepare_package.sh | 12 +++++++++++- SCRIPTS/R2S/02_target_only.sh | 2 +- SCRIPTS/R4S/02_target_only.sh | 2 +- SCRIPTS/X86/02_target_only.sh | 2 -- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 0920e2b91..53f34f406 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -3,7 +3,7 @@ clear ### 基础部分 ### # 使用 O3 级别的优化 -sed -i 's/Os/O3/g' include/target.mk +sed -i 's/Os/O3 -funsafe-math-optimizations -funroll-loops -ffunction-sections -fdata-sections -Wl,--gc-sections/g' include/target.mk # 更新 Feeds ./scripts/feeds update -a ./scripts/feeds install -a @@ -27,6 +27,16 @@ patch -p1 < ../PATCH/BBRv2/openwrt-kmod-bbr2.patch cp -f ../PATCH/BBRv2/693-Add_BBRv2_congestion_control_for_Linux_TCP.patch ./target/linux/generic/hack-5.4/693-Add_BBRv2_congestion_control_for_Linux_TCP.patch wget -qO - https://github.com/openwrt/openwrt/commit/cfaf039.patch | patch -p1 +# Grub 2 +wget -qO - https://github.com/QiuSimons/openwrt-NoTengoBattery/commit/afed16a.patch | patch -p1 + +# Haproxy +rm -rf ./feeds/packages/net/haproxy +svn co https://github.com/openwrt/packages/trunk/net/haproxy feeds/packages/net/haproxy +pushd feeds/packages +wget -qO - https://github.com/QiuSimons/packages/commit/e365bd2.patch | patch -p1 +popd + # OPENSSL wget -qO - https://github.com/mj22226/openwrt/commit/5e10633.patch | patch -p1 diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index ef617e961..0c51c31c1 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -2,7 +2,7 @@ clear # 使用专属优化 -sed -i 's,-mcpu=generic,-march=armv8-a+crypto+crc -mabi=lp64,g' include/target.mk +sed -i 's,-mcpu=generic,-mcpu=cortex-a53+crypto,g' include/target.mk cp -f ../PATCH/mbedtls/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch ./package/libs/mbedtls/patches/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch # R2S_TL diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index 8f3f7edd9..3b248648e 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -14,7 +14,7 @@ cp -f ../PATCH/target_r4s/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoP cp -f ../PATCH/target_r4s/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch ./target/linux/rockchip/patches-5.4/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch # 使用特定的优化 -sed -i 's,-mcpu=generic,-march=armv8-a+crypto+crc -mabi=lp64,g' include/target.mk +sed -i 's,-mcpu=generic,-mcpu=cortex-a72.cortex-a53+crypto,g' include/target.mk cp -f ../PATCH/mbedtls/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch ./package/libs/mbedtls/patches/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch sed -i 's,kmod-r8169,kmod-r8168,g' target/linux/rockchip/image/armv8.mk diff --git a/SCRIPTS/X86/02_target_only.sh b/SCRIPTS/X86/02_target_only.sh index 8695203f3..14ec2f515 100644 --- a/SCRIPTS/X86/02_target_only.sh +++ b/SCRIPTS/X86/02_target_only.sh @@ -1,7 +1,5 @@ #!/bin/bash -# 使用 O2 级别的优化 -sed -i 's/O3/O2/g' include/target.mk # 在 X86 架构下移除 Shadowsocks-rust sed -i '/Rust:/d' package/lean/luci-app-ssr-plus/Makefile From 30600ef621ebf095c633601df320cd8554484857 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 2 Aug 2021 12:29:46 +0800 Subject: [PATCH 174/244] ready for rc4 --- .github/workflows/R2S-OpenWrt.yml | 4 ++-- .github/workflows/R4S-OpenWrt.yml | 4 ++-- .github/workflows/X86-OpenWrt.yml | 4 ++-- SCRIPTS/02_prepare_package.sh | 9 +++++++++ SCRIPTS/R2S/02_target_only.sh | 7 ------- SCRIPTS/R4S/02_target_only.sh | 7 ------- 6 files changed, 15 insertions(+), 20 deletions(-) diff --git a/.github/workflows/R2S-OpenWrt.yml b/.github/workflows/R2S-OpenWrt.yml index 1daa72210..78f6ae514 100644 --- a/.github/workflows/R2S-OpenWrt.yml +++ b/.github/workflows/R2S-OpenWrt.yml @@ -136,9 +136,9 @@ jobs: id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-R2S-R4S-X86-21.02.0-RC3 + name: OpenWRT-R2S-R4S-X86-21.02.0-RC4 allowUpdates: true - tag: 21.02.0-rc3 + tag: 21.02.0-rc4 commit: master replacesArtifacts: true token: ${{ secrets.workflow_token }} diff --git a/.github/workflows/R4S-OpenWrt.yml b/.github/workflows/R4S-OpenWrt.yml index ac00cd33a..229c860c9 100644 --- a/.github/workflows/R4S-OpenWrt.yml +++ b/.github/workflows/R4S-OpenWrt.yml @@ -136,9 +136,9 @@ jobs: id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-R2S-R4S-X86-21.02.0-RC3 + name: OpenWRT-R2S-R4S-X86-21.02.0-RC4 allowUpdates: true - tag: 21.02.0-rc3 + tag: 21.02.0-rc4 commit: master replacesArtifacts: true token: ${{ secrets.workflow_token }} diff --git a/.github/workflows/X86-OpenWrt.yml b/.github/workflows/X86-OpenWrt.yml index 663d664c7..f95b7089c 100644 --- a/.github/workflows/X86-OpenWrt.yml +++ b/.github/workflows/X86-OpenWrt.yml @@ -136,9 +136,9 @@ jobs: id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-R2S-R4S-X86-21.02.0-RC3 + name: OpenWRT-R2S-R4S-X86-21.02.0-RC4 allowUpdates: true - tag: 21.02.0-rc3 + tag: 21.02.0-rc4 commit: master replacesArtifacts: true token: ${{ secrets.workflow_token }} diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 53f34f406..68cf7ed60 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -77,6 +77,12 @@ cp -rf ../openwrt-lienol/package/network/fullconenat ./package/network/fullconen #wget -P package/base-files/files/etc/init.d/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/shortcut-fe ### 获取额外的基础软件包 ### +# 更换为 ImmortalWrt Uboot 以及 Target +rm -rf ./target/linux/rockchip +svn co https://github.com/immortalwrt/immortalwrt/branches/master/target/linux/rockchip target/linux/rockchip +rm -rf ./package/boot/uboot-rockchip +svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/boot/uboot-rockchip package/boot/uboot-rockchip +svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/boot/arm-trusted-firmware-rockchip-vendor package/boot/arm-trusted-firmware-rockchip-vendor # AutoCore svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/emortal/autocore package/lean/autocore rm -rf ./feeds/packages/utils/coremark @@ -103,6 +109,8 @@ ln -sf ../../../feeds/packages/lang/node-yarn ./package/feeds/packages/node-yarn #svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/kernel/r8168 package/new/r8168 git clone -b master --depth 1 https://github.com/BROBIRD/openwrt-r8168.git package/new/r8168 patch -p1 < ../PATCH/r8168/r8168-fix_LAN_led-for_r4s-from_TL.patch +# R8152驱动 +svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/kernel/r8152 package/new/r8152 # UPX 可执行软件压缩 sed -i '/patchelf pkgconf/i\tools-y += ucl upx' ./tools/Makefile sed -i '\/autoconf\/compile :=/i\$(curdir)/upx/compile := $(curdir)/ucl/compile' ./tools/Makefile @@ -254,6 +262,7 @@ svn co https://github.com/xiaorouji/openwrt-passwall/trunk/ssocks package/new/ss svn co https://github.com/xiaorouji/openwrt-passwall/trunk/xray-core package/new/xray-core svn co https://github.com/xiaorouji/openwrt-passwall/trunk/v2ray-plugin package/new/v2ray-plugin svn co https://github.com/xiaorouji/openwrt-passwall/trunk/xray-plugin package/new/xray-plugin +svn co https://github.com/xiaorouji/openwrt-passwall/trunk/hysteria package/new/hysteria # qBittorrent 下载 svn co https://github.com/garypang13/openwrt-static-qb/trunk/qBittorrent-Enhanced-Edition package/lean/qBittorrent-Enhanced-Edition sed -i 's/4.3.3.10/4.3.4.10/g' package/lean/qBittorrent-Enhanced-Edition/Makefile diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index 0c51c31c1..04ff5abac 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -5,13 +5,6 @@ clear sed -i 's,-mcpu=generic,-mcpu=cortex-a53+crypto,g' include/target.mk cp -f ../PATCH/mbedtls/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch ./package/libs/mbedtls/patches/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch -# R2S_TL -rm -rf ./target/linux/rockchip -svn co https://github.com/immortalwrt/immortalwrt/branches/master/target/linux/rockchip target/linux/rockchip -rm -rf ./package/boot/uboot-rockchip -svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/boot/uboot-rockchip package/boot/uboot-rockchip -svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/boot/arm-trusted-firmware-rk3328 package/boot/arm-trusted-firmware-rk3328 - #增加风扇调速(被动散热不香么? wget -P target/linux/rockchip/armv8/base-files/etc/init.d/ https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3328/base-files/etc/init.d/fa-rk3328-pwmfan wget -P target/linux/rockchip/armv8/base-files/usr/bin/ https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3328/base-files/usr/bin/start-rk3328-pwm-fan.sh diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index 3b248648e..60908c627 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -1,13 +1,6 @@ #!/bin/bash clear -# 更换为 ImmortalWrt Uboot 以及 Target -rm -rf ./target/linux/rockchip -svn co https://github.com/immortalwrt/immortalwrt/branches/master/target/linux/rockchip target/linux/rockchip -rm -rf ./package/boot/uboot-rockchip -svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/boot/uboot-rockchip package/boot/uboot-rockchip -svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/boot/arm-trusted-firmware-rk3328 package/boot/arm-trusted-firmware-rk3328 - # 超频到 2.2/1.8 GHz rm -rf ./target/linux/rockchip/patches-5.4/992-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch cp -f ../PATCH/target_r4s/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch ./target/linux/rockchip/patches-5.4/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch From 03111986320e244d21de6724bc5e3aefd27c973c Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 10 Aug 2021 13:23:27 +0800 Subject: [PATCH 175/244] Cleaned up some code --- .github/workflows/R2S-OpenWrt.yml | 4 ++-- .github/workflows/R4S-OpenWrt.yml | 4 ++-- .github/workflows/X86-OpenWrt.yml | 4 ++-- SCRIPTS/01_get_ready.sh | 6 +++--- SCRIPTS/02_prepare_package.sh | 26 +++++++++++++------------- SCRIPTS/R2S/02_target_only.sh | 13 ------------- SCRIPTS/R4S/02_target_only.sh | 18 ------------------ SCRIPTS/X86/02_target_only.sh | 10 ---------- 8 files changed, 22 insertions(+), 63 deletions(-) diff --git a/.github/workflows/R2S-OpenWrt.yml b/.github/workflows/R2S-OpenWrt.yml index 78f6ae514..683a7cd00 100644 --- a/.github/workflows/R2S-OpenWrt.yml +++ b/.github/workflows/R2S-OpenWrt.yml @@ -93,7 +93,7 @@ jobs: df -h cd openwrt let make_process=$(nproc)+2 - make toolchain/install -j${make_process} V=s + make toolchain/install -j${make_process} || make toolchain/install -j${make_process} V=s - name: Compile Openwrt id: compileopenwrt continue-on-error: true @@ -101,7 +101,7 @@ jobs: df -h cd openwrt let Make_Process=$(nproc)+2 - make -j${Make_Process} V=w + make -j${Make_Process} || make -j${Make_Process} V=s echo $? - name: If Error if: steps.compileopenwrt.outcome == 'failure' diff --git a/.github/workflows/R4S-OpenWrt.yml b/.github/workflows/R4S-OpenWrt.yml index 229c860c9..23551c7c4 100644 --- a/.github/workflows/R4S-OpenWrt.yml +++ b/.github/workflows/R4S-OpenWrt.yml @@ -93,7 +93,7 @@ jobs: df -h cd openwrt let make_process=$(nproc)+2 - make toolchain/install -j${make_process} V=s + make toolchain/install -j${make_process} || make toolchain/install -j${make_process} V=s - name: Compile Openwrt id: compileopenwrt continue-on-error: true @@ -101,7 +101,7 @@ jobs: df -h cd openwrt let Make_Process=$(nproc)+2 - make -j${Make_Process} V=w + make -j${Make_Process} || make -j${Make_Process} V=s echo $? - name: If Error if: steps.compileopenwrt.outcome == 'failure' diff --git a/.github/workflows/X86-OpenWrt.yml b/.github/workflows/X86-OpenWrt.yml index f95b7089c..74bd3dab5 100644 --- a/.github/workflows/X86-OpenWrt.yml +++ b/.github/workflows/X86-OpenWrt.yml @@ -93,7 +93,7 @@ jobs: df -h cd openwrt let make_process=$(nproc)+2 - make toolchain/install -j${make_process} V=s + make toolchain/install -j${make_process} || make toolchain/install -j${make_process} V=s - name: Compile Openwrt id: compileopenwrt continue-on-error: true @@ -101,7 +101,7 @@ jobs: df -h cd openwrt let Make_Process=$(nproc)+2 - make -j${Make_Process} V=w + make -j${Make_Process} || make -j${Make_Process} V=s echo $? - name: If Error if: steps.compileopenwrt.outcome == 'failure' diff --git a/SCRIPTS/01_get_ready.sh b/SCRIPTS/01_get_ready.sh index 57b5834cb..c4ee97996 100644 --- a/SCRIPTS/01_get_ready.sh +++ b/SCRIPTS/01_get_ready.sh @@ -21,8 +21,8 @@ cp -rf ./openwrt_new/* ./openwrt/ # 获取源代码 #git clone --single-branch -b openwrt-21.02 https://github.com/openwrt/openwrt openwrt git clone -b main --depth 1 https://github.com/Lienol/openwrt.git openwrt-lienol -git clone -b main --depth 1 https://github.com/Lienol/openwrt-packages packages-lienol -git clone -b main --depth 1 https://github.com/Lienol/openwrt-luci luci-lienol -git clone -b linksys-ea6350v3-mastertrack --depth 1 https://github.com/NoTengoBattery/openwrt NoTengoBattery +#git clone -b main --depth 1 https://github.com/Lienol/openwrt-packages packages-lienol +#git clone -b main --depth 1 https://github.com/Lienol/openwrt-luci luci-lienol +#git clone -b linksys-ea6350v3-mastertrack --depth 1 https://github.com/NoTengoBattery/openwrt NoTengoBattery exit 0 diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 68cf7ed60..fd35cc394 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -22,34 +22,30 @@ sed -i '/unshift/d' scripts/download.pl sed -i '/mirror02/d' scripts/download.pl echo "net.netfilter.nf_conntrack_helper = 1" >> ./package/kernel/linux/files/sysctl-nf-conntrack.conf +### 必要的 Patches ### +# Patch arm64 型号名称 +wget -P target/linux/generic/hack-5.4/ https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/generic/hack-5.4/312-arm64-cpuinfo-Add-model-name-in-proc-cpuinfo-for-64bit-ta.patch +# Patch jsonc +patch -p1 < ../PATCH/jsonc/use_json_object_new_int64.patch +# Patch dnsmasq +patch -p1 < ../PATCH/dnsmasq/dnsmasq-add-filter-aaaa-option.patch +patch -p1 < ../PATCH/dnsmasq/luci-add-filter-aaaa-option.patch +cp -f ../PATCH/dnsmasq/900-add-filter-aaaa-option.patch ./package/network/services/dnsmasq/patches/900-add-filter-aaaa-option.patch # BBRv2 patch -p1 < ../PATCH/BBRv2/openwrt-kmod-bbr2.patch cp -f ../PATCH/BBRv2/693-Add_BBRv2_congestion_control_for_Linux_TCP.patch ./target/linux/generic/hack-5.4/693-Add_BBRv2_congestion_control_for_Linux_TCP.patch wget -qO - https://github.com/openwrt/openwrt/commit/cfaf039.patch | patch -p1 - # Grub 2 wget -qO - https://github.com/QiuSimons/openwrt-NoTengoBattery/commit/afed16a.patch | patch -p1 - # Haproxy rm -rf ./feeds/packages/net/haproxy svn co https://github.com/openwrt/packages/trunk/net/haproxy feeds/packages/net/haproxy pushd feeds/packages wget -qO - https://github.com/QiuSimons/packages/commit/e365bd2.patch | patch -p1 popd - # OPENSSL wget -qO - https://github.com/mj22226/openwrt/commit/5e10633.patch | patch -p1 -### 必要的 Patches ### -# Patch arm64 型号名称 -wget -P target/linux/generic/hack-5.4/ https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/generic/hack-5.4/312-arm64-cpuinfo-Add-model-name-in-proc-cpuinfo-for-64bit-ta.patch -# Patch jsonc -patch -p1 < ../PATCH/jsonc/use_json_object_new_int64.patch -# Patch dnsmasq -patch -p1 < ../PATCH/dnsmasq/dnsmasq-add-filter-aaaa-option.patch -patch -p1 < ../PATCH/dnsmasq/luci-add-filter-aaaa-option.patch -cp -f ../PATCH/dnsmasq/900-add-filter-aaaa-option.patch ./package/network/services/dnsmasq/patches/900-add-filter-aaaa-option.patch - ### Fullcone-NAT 部分 ### # Patch Kernel 以解决 FullCone 冲突 pushd target/linux/generic/hack-5.4 @@ -83,6 +79,10 @@ svn co https://github.com/immortalwrt/immortalwrt/branches/master/target/linux/r rm -rf ./package/boot/uboot-rockchip svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/boot/uboot-rockchip package/boot/uboot-rockchip svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/boot/arm-trusted-firmware-rockchip-vendor package/boot/arm-trusted-firmware-rockchip-vendor +# R4S超频到 2.2/1.8 GHz +rm -rf ./target/linux/rockchip/patches-5.4/992-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch +cp -f ../PATCH/target_r4s/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch ./target/linux/rockchip/patches-5.4/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch +cp -f ../PATCH/target_r4s/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch ./target/linux/rockchip/patches-5.4/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch # AutoCore svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/emortal/autocore package/lean/autocore rm -rf ./feeds/packages/utils/coremark diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index 04ff5abac..203aa2af0 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -28,19 +28,6 @@ wget https://downloads.openwrt.org/releases/${latest_version}/targets/rockchip/a zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' > .vermagic sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic/' include/kernel-defaults.mk -# 内核加解密组件 -echo ' -' >> ./target/linux/rockchip/armv8/config-5.4 - -# MPTCP -#echo ' -#CONFIG_MPTCP=y -#CONFIG_MPTCP_PM_ADVANCED=y -#CONFIG_MPTCP_FULLMESH=y -#CONFIG_DEFAULT_FULLMESH=y -#CONFIG_DEFAULT_MPTCP_PM="fullmesh" -#' >> ./target/linux/rockchip/armv8/config-5.4 - # 预配置一些插件 cp -rf ../PATCH/files ./files diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index 60908c627..f7bbb5452 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -1,11 +1,6 @@ #!/bin/bash clear -# 超频到 2.2/1.8 GHz -rm -rf ./target/linux/rockchip/patches-5.4/992-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch -cp -f ../PATCH/target_r4s/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch ./target/linux/rockchip/patches-5.4/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch -cp -f ../PATCH/target_r4s/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch ./target/linux/rockchip/patches-5.4/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch - # 使用特定的优化 sed -i 's,-mcpu=generic,-mcpu=cortex-a72.cortex-a53+crypto,g' include/target.mk cp -f ../PATCH/mbedtls/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch ./package/libs/mbedtls/patches/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch @@ -31,19 +26,6 @@ sed -i '/set_interface_core 20 "eth1"/a\ethtool -C eth0 rx-usecs 1000 rx-frames rm -rf ./package/kernel/linux/modules/video.mk wget -P package/kernel/linux/modules/ https://github.com/immortalwrt/immortalwrt/raw/master/package/kernel/linux/modules/video.mk -# 内核加解密模块 -echo ' -' >> ./target/linux/rockchip/armv8/config-5.4 - -# MPTCP -#echo ' -#CONFIG_MPTCP=y -#CONFIG_MPTCP_PM_ADVANCED=y -#CONFIG_MPTCP_FULLMESH=y -#CONFIG_DEFAULT_FULLMESH=y -#CONFIG_DEFAULT_MPTCP_PM="fullmesh" -#' >> ./target/linux/rockchip/armv8/config-5.4 - #Vermagic latest_version="$(curl -s https://github.com/openwrt/openwrt/releases |grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" |sed -n '/21/p' |sed -n 1p |sed 's/v//g' |sed 's/.tar.gz//g')" wget https://downloads.openwrt.org/releases/${latest_version}/targets/rockchip/armv8/packages/Packages.gz diff --git a/SCRIPTS/X86/02_target_only.sh b/SCRIPTS/X86/02_target_only.sh index 14ec2f515..5c0ff3183 100644 --- a/SCRIPTS/X86/02_target_only.sh +++ b/SCRIPTS/X86/02_target_only.sh @@ -1,6 +1,5 @@ #!/bin/bash - # 在 X86 架构下移除 Shadowsocks-rust sed -i '/Rust:/d' package/lean/luci-app-ssr-plus/Makefile sed -i '/Rust:/d' package/new/luci-app-passwall/Makefile @@ -11,15 +10,6 @@ echo ' CONFIG_CRYPTO_AES_NI_INTEL=y ' >> ./target/linux/x86/64/config-5.4 -# MPTCP -#echo ' -#CONFIG_MPTCP=y -#CONFIG_MPTCP_PM_ADVANCED=y -#CONFIG_MPTCP_FULLMESH=y -#CONFIG_DEFAULT_FULLMESH=y -#CONFIG_DEFAULT_MPTCP_PM="fullmesh" -#' >> ./target/linux/x86/64/config-5.4 - #Vermagic latest_version="$(curl -s https://github.com/openwrt/openwrt/releases |grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" |sed -n '/21/p' |sed -n 1p |sed 's/v//g' |sed 's/.tar.gz//g')" wget https://downloads.openwrt.org/releases/${latest_version}/targets/x86/64/packages/Packages.gz From 68a87638701905f9c7d678965757a8795f2cfbb2 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 10 Aug 2021 16:59:33 +0800 Subject: [PATCH 176/244] Add CacULE Scheduler Support Update 02_prepare_package.sh Update 02_target_only.sh Update 02_target_only.sh --- SCRIPTS/02_prepare_package.sh | 5 +++++ SCRIPTS/R2S/02_target_only.sh | 6 ++++++ SCRIPTS/R4S/02_target_only.sh | 6 ++++++ 3 files changed, 17 insertions(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index fd35cc394..c08657d52 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -35,6 +35,11 @@ cp -f ../PATCH/dnsmasq/900-add-filter-aaaa-option.patch ./package/network/servic patch -p1 < ../PATCH/BBRv2/openwrt-kmod-bbr2.patch cp -f ../PATCH/BBRv2/693-Add_BBRv2_congestion_control_for_Linux_TCP.patch ./target/linux/generic/hack-5.4/693-Add_BBRv2_congestion_control_for_Linux_TCP.patch wget -qO - https://github.com/openwrt/openwrt/commit/cfaf039.patch | patch -p1 +# CacULE +wget -qO - https://github.com/QiuSimons/openwrt-NoTengoBattery/commit/7d44cab.patch | patch -p1 +wget https://github.com/hamadmarri/cacule-cpu-scheduler/raw/master/patches/CacULE/v5.4/cacule-5.4.patch -O ./target/linux/generic/hack-5.4/694-cacule-5.4.patch +# UKSM +cp -f ../PATCH/UKSM/695-uksm-5.4.patch ./target/linux/generic/hack-5.4/695-uksm-5.4.patch # Grub 2 wget -qO - https://github.com/QiuSimons/openwrt-NoTengoBattery/commit/afed16a.patch | patch -p1 # Haproxy diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index 203aa2af0..a597c8dd7 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -9,6 +9,12 @@ cp -f ../PATCH/mbedtls/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.p wget -P target/linux/rockchip/armv8/base-files/etc/init.d/ https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3328/base-files/etc/init.d/fa-rk3328-pwmfan wget -P target/linux/rockchip/armv8/base-files/usr/bin/ https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3328/base-files/usr/bin/start-rk3328-pwm-fan.sh +# CacULE +sed -i '/CONFIG_NR_CPUS/d' ./target/linux/rockchip/armv8/config-5.4 +echo ' +CONFIG_NR_CPUS=4 +' >> ./target/linux/rockchip/armv8/config-5.4 + # 配置 IRQ 并默认关闭 eth0 offloading rx/rx sed -i '/set_interface_core 4 "eth1"/a\set_interface_core 8 "ff160000" "ff160000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity sed -i '/set_interface_core 4 "eth1"/a\set_interface_core 1 "ff150000" "ff150000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index f7bbb5452..440006295 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -18,6 +18,12 @@ CONFIG_CRYPTO_DEV_ROCKCHIP=y CONFIG_HW_RANDOM_ROCKCHIP=y ' >> ./target/linux/rockchip/armv8/config-5.4 +# CacULE +sed -i '/CONFIG_NR_CPUS/d' ./target/linux/rockchip/armv8/config-5.4 +echo ' +CONFIG_NR_CPUS=6 +' >> ./target/linux/rockchip/armv8/config-5.4 + # IRQ 调优 sed -i '/set_interface_core 20 "eth1"/a\set_interface_core 8 "ff3c0000" "ff3c0000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity sed -i '/set_interface_core 20 "eth1"/a\ethtool -C eth0 rx-usecs 1000 rx-frames 25 tx-usecs 100 tx-frames 25' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity From 67101e8553e72d6ef9d27e4768f2b1f84ca3263f Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 11 Aug 2021 11:07:03 +0800 Subject: [PATCH 177/244] Add UKSM Support --- PATCH/UKSM/695-uksm-5.4.patch | 6942 +++++++++++++++++++++++++++++++++ README.md | 15 +- SCRIPTS/02_prepare_package.sh | 38 +- SCRIPTS/R2S/02_target_only.sh | 6 + SCRIPTS/R4S/02_target_only.sh | 14 +- SCRIPTS/X86/02_target_only.sh | 6 + SEED/R2S/config.seed | 10 +- SEED/R4S/config.seed | 1 + SEED/X86/config.seed | 1 + 9 files changed, 6986 insertions(+), 47 deletions(-) create mode 100644 PATCH/UKSM/695-uksm-5.4.patch diff --git a/PATCH/UKSM/695-uksm-5.4.patch b/PATCH/UKSM/695-uksm-5.4.patch new file mode 100644 index 000000000..e558144b6 --- /dev/null +++ b/PATCH/UKSM/695-uksm-5.4.patch @@ -0,0 +1,6942 @@ +diff --git a/Documentation/vm/uksm.txt b/Documentation/vm/uksm.txt +new file mode 100644 +index 000000000000..be19a3127001 +--- /dev/null ++++ b/Documentation/vm/uksm.txt +@@ -0,0 +1,61 @@ ++The Ultra Kernel Samepage Merging feature ++---------------------------------------------- ++/* ++ * Ultra KSM. Copyright (C) 2011-2012 Nai Xia ++ * ++ * This is an improvement upon KSM. Some basic data structures and routines ++ * are borrowed from ksm.c . ++ * ++ * Its new features: ++ * 1. Full system scan: ++ * It automatically scans all user processes' anonymous VMAs. Kernel-user ++ * interaction to submit a memory area to KSM is no longer needed. ++ * ++ * 2. Rich area detection: ++ * It automatically detects rich areas containing abundant duplicated ++ * pages based. Rich areas are given a full scan speed. Poor areas are ++ * sampled at a reasonable speed with very low CPU consumption. ++ * ++ * 3. Ultra Per-page scan speed improvement: ++ * A new hash algorithm is proposed. As a result, on a machine with ++ * Core(TM)2 Quad Q9300 CPU in 32-bit mode and 800MHZ DDR2 main memory, it ++ * can scan memory areas that does not contain duplicated pages at speed of ++ * 627MB/sec ~ 2445MB/sec and can merge duplicated areas at speed of ++ * 477MB/sec ~ 923MB/sec. ++ * ++ * 4. Thrashing area avoidance: ++ * Thrashing area(an VMA that has frequent Ksm page break-out) can be ++ * filtered out. My benchmark shows it's more efficient than KSM's per-page ++ * hash value based volatile page detection. ++ * ++ * ++ * 5. Misc changes upon KSM: ++ * * It has a fully x86-opitmized memcmp dedicated for 4-byte-aligned page ++ * comparison. It's much faster than default C version on x86. ++ * * rmap_item now has an struct *page member to loosely cache a ++ * address-->page mapping, which reduces too much time-costly ++ * follow_page(). ++ * * The VMA creation/exit procedures are hooked to let the Ultra KSM know. ++ * * try_to_merge_two_pages() now can revert a pte if it fails. No break_ ++ * ksm is needed for this case. ++ * ++ * 6. Full Zero Page consideration(contributed by Figo Zhang) ++ * Now uksmd consider full zero pages as special pages and merge them to an ++ * special unswappable uksm zero page. ++ */ ++ ++ChangeLog: ++ ++2012-05-05 The creation of this Doc ++2012-05-08 UKSM 0.1.1.1 libc crash bug fix, api clean up, doc clean up. ++2012-05-28 UKSM 0.1.1.2 bug fix release ++2012-06-26 UKSM 0.1.2-beta1 first beta release for 0.1.2 ++2012-07-2 UKSM 0.1.2-beta2 ++2012-07-10 UKSM 0.1.2-beta3 ++2012-07-26 UKSM 0.1.2 Fine grained speed control, more scan optimization. ++2012-10-13 UKSM 0.1.2.1 Bug fixes. ++2012-12-31 UKSM 0.1.2.2 Minor bug fixes. ++2014-07-02 UKSM 0.1.2.3 Fix a " __this_cpu_read() in preemptible bug". ++2015-04-22 UKSM 0.1.2.4 Fix a race condition that can sometimes trigger anonying warnings. ++2016-09-10 UKSM 0.1.2.5 Fix a bug in dedup ratio calculation. ++2017-02-26 UKSM 0.1.2.6 Fix a bug in hugetlbpage handling and a race bug with page migration. +diff --git a/fs/exec.c b/fs/exec.c +index 555e93c7dec8..7e1cfd568e6c 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -63,6 +63,7 @@ + #include + #include + #include ++#include + + #include + #include +diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c +index 8c1f1bb1a5ce..62e28cf10bbf 100644 +--- a/fs/proc/meminfo.c ++++ b/fs/proc/meminfo.c +@@ -105,7 +105,10 @@ static int meminfo_proc_show(struct seq_file *m, void *v) + global_zone_page_state(NR_KERNEL_STACK_KB)); + show_val_kb(m, "PageTables: ", + global_zone_page_state(NR_PAGETABLE)); +- ++#ifdef CONFIG_UKSM ++ show_val_kb(m, "KsmZeroPages: ", ++ global_zone_page_state(NR_UKSM_ZERO_PAGES)); ++#endif + show_val_kb(m, "NFS_Unstable: ", + global_node_page_state(NR_UNSTABLE_NFS)); + show_val_kb(m, "Bounce: ", +diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h +index 818691846c90..b2169f37c696 100644 +--- a/include/asm-generic/pgtable.h ++++ b/include/asm-generic/pgtable.h +@@ -855,12 +855,25 @@ extern void untrack_pfn(struct vm_area_struct *vma, unsigned long pfn, + extern void untrack_pfn_moved(struct vm_area_struct *vma); + #endif + ++#ifdef CONFIG_UKSM ++static inline int is_uksm_zero_pfn(unsigned long pfn) ++{ ++ extern unsigned long uksm_zero_pfn; ++ return pfn == uksm_zero_pfn; ++} ++#else ++static inline int is_uksm_zero_pfn(unsigned long pfn) ++{ ++ return 0; ++} ++#endif ++ + #ifdef __HAVE_COLOR_ZERO_PAGE + static inline int is_zero_pfn(unsigned long pfn) + { + extern unsigned long zero_pfn; + unsigned long offset_from_zero_pfn = pfn - zero_pfn; +- return offset_from_zero_pfn <= (zero_page_mask >> PAGE_SHIFT); ++ return offset_from_zero_pfn <= (zero_page_mask >> PAGE_SHIFT) || is_uksm_zero_pfn(pfn); + } + + #define my_zero_pfn(addr) page_to_pfn(ZERO_PAGE(addr)) +@@ -869,7 +882,7 @@ static inline int is_zero_pfn(unsigned long pfn) + static inline int is_zero_pfn(unsigned long pfn) + { + extern unsigned long zero_pfn; +- return pfn == zero_pfn; ++ return (pfn == zero_pfn) || (is_uksm_zero_pfn(pfn)); + } + + static inline unsigned long my_zero_pfn(unsigned long addr) +diff --git a/include/linux/ksm.h b/include/linux/ksm.h +index e48b1e453ff5..095d59310ce0 100644 +--- a/include/linux/ksm.h ++++ b/include/linux/ksm.h +@@ -1,4 +1,4 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ ++/* SPDX-License-Identifier: GPL-3.0 */ + #ifndef __LINUX_KSM_H + #define __LINUX_KSM_H + /* +@@ -21,20 +21,16 @@ struct mem_cgroup; + #ifdef CONFIG_KSM + int ksm_madvise(struct vm_area_struct *vma, unsigned long start, + unsigned long end, int advice, unsigned long *vm_flags); +-int __ksm_enter(struct mm_struct *mm); +-void __ksm_exit(struct mm_struct *mm); + +-static inline int ksm_fork(struct mm_struct *mm, struct mm_struct *oldmm) ++static inline struct stable_node *page_stable_node(struct page *page) + { +- if (test_bit(MMF_VM_MERGEABLE, &oldmm->flags)) +- return __ksm_enter(mm); +- return 0; ++ return PageKsm(page) ? page_rmapping(page) : NULL; + } + +-static inline void ksm_exit(struct mm_struct *mm) ++static inline void set_page_stable_node(struct page *page, ++ struct stable_node *stable_node) + { +- if (test_bit(MMF_VM_MERGEABLE, &mm->flags)) +- __ksm_exit(mm); ++ page->mapping = (void *)((unsigned long)stable_node | PAGE_MAPPING_KSM); + } + + /* +@@ -56,6 +52,33 @@ void ksm_migrate_page(struct page *newpage, struct page *oldpage); + bool reuse_ksm_page(struct page *page, + struct vm_area_struct *vma, unsigned long address); + ++#ifdef CONFIG_KSM_LEGACY ++int __ksm_enter(struct mm_struct *mm); ++void __ksm_exit(struct mm_struct *mm); ++static inline int ksm_fork(struct mm_struct *mm, struct mm_struct *oldmm) ++{ ++ if (test_bit(MMF_VM_MERGEABLE, &oldmm->flags)) ++ return __ksm_enter(mm); ++ return 0; ++} ++ ++static inline void ksm_exit(struct mm_struct *mm) ++{ ++ if (test_bit(MMF_VM_MERGEABLE, &mm->flags)) ++ __ksm_exit(mm); ++} ++ ++#elif defined(CONFIG_UKSM) ++static inline int ksm_fork(struct mm_struct *mm, struct mm_struct *oldmm) ++{ ++ return 0; ++} ++ ++static inline void ksm_exit(struct mm_struct *mm) ++{ ++} ++#endif /* !CONFIG_UKSM */ ++ + #else /* !CONFIG_KSM */ + + static inline int ksm_fork(struct mm_struct *mm, struct mm_struct *oldmm) +@@ -96,4 +119,6 @@ static inline bool reuse_ksm_page(struct page *page, + #endif /* CONFIG_MMU */ + #endif /* !CONFIG_KSM */ + ++#include ++ + #endif /* __LINUX_KSM_H */ +diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h +index 270aa8fd2800..8e1eaf6a2de3 100644 +--- a/include/linux/mm_types.h ++++ b/include/linux/mm_types.h +@@ -353,6 +353,9 @@ struct vm_area_struct { + struct mempolicy *vm_policy; /* NUMA policy for the VMA */ + #endif + struct vm_userfaultfd_ctx vm_userfaultfd_ctx; ++#ifdef CONFIG_UKSM ++ struct vma_slot *uksm_vma_slot; ++#endif + } __randomize_layout; + + struct core_thread { +diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h +index bda20282746b..dab82e7cc3df 100644 +--- a/include/linux/mmzone.h ++++ b/include/linux/mmzone.h +@@ -206,6 +206,9 @@ enum zone_stat_item { + NR_ZSPAGES, /* allocated in zsmalloc */ + #endif + NR_FREE_CMA_PAGES, ++#ifdef CONFIG_UKSM ++ NR_UKSM_ZERO_PAGES, ++#endif + NR_VM_ZONE_STAT_ITEMS }; + + enum node_stat_item { +diff --git a/include/linux/sradix-tree.h b/include/linux/sradix-tree.h +new file mode 100644 +index 000000000000..d71edba6b63f +--- /dev/null ++++ b/include/linux/sradix-tree.h +@@ -0,0 +1,77 @@ ++#ifndef _LINUX_SRADIX_TREE_H ++#define _LINUX_SRADIX_TREE_H ++ ++ ++#define INIT_SRADIX_TREE(root, mask) \ ++do { \ ++ (root)->height = 0; \ ++ (root)->gfp_mask = (mask); \ ++ (root)->rnode = NULL; \ ++} while (0) ++ ++#define ULONG_BITS (sizeof(unsigned long) * 8) ++#define SRADIX_TREE_INDEX_BITS (8 /* CHAR_BIT */ * sizeof(unsigned long)) ++//#define SRADIX_TREE_MAP_SHIFT 6 ++//#define SRADIX_TREE_MAP_SIZE (1UL << SRADIX_TREE_MAP_SHIFT) ++//#define SRADIX_TREE_MAP_MASK (SRADIX_TREE_MAP_SIZE-1) ++ ++struct sradix_tree_node { ++ unsigned int height; /* Height from the bottom */ ++ unsigned int count; ++ unsigned int fulls; /* Number of full sublevel trees */ ++ struct sradix_tree_node *parent; ++ void *stores[0]; ++}; ++ ++/* A simple radix tree implementation */ ++struct sradix_tree_root { ++ unsigned int height; ++ struct sradix_tree_node *rnode; ++ ++ /* Where found to have available empty stores in its sublevels */ ++ struct sradix_tree_node *enter_node; ++ unsigned int shift; ++ unsigned int stores_size; ++ unsigned int mask; ++ unsigned long min; /* The first hole index */ ++ unsigned long num; ++ //unsigned long *height_to_maxindex; ++ ++ /* How the node is allocated and freed. */ ++ struct sradix_tree_node *(*alloc)(void); ++ void (*free)(struct sradix_tree_node *node); ++ ++ /* When a new node is added and removed */ ++ void (*extend)(struct sradix_tree_node *parent, struct sradix_tree_node *child); ++ void (*assign)(struct sradix_tree_node *node, unsigned int index, void *item); ++ void (*rm)(struct sradix_tree_node *node, unsigned int offset); ++}; ++ ++struct sradix_tree_path { ++ struct sradix_tree_node *node; ++ int offset; ++}; ++ ++static inline ++void init_sradix_tree_root(struct sradix_tree_root *root, unsigned long shift) ++{ ++ root->height = 0; ++ root->rnode = NULL; ++ root->shift = shift; ++ root->stores_size = 1UL << shift; ++ root->mask = root->stores_size - 1; ++} ++ ++ ++extern void *sradix_tree_next(struct sradix_tree_root *root, ++ struct sradix_tree_node *node, unsigned long index, ++ int (*iter)(void *, unsigned long)); ++ ++extern int sradix_tree_enter(struct sradix_tree_root *root, void **item, int num); ++ ++extern void sradix_tree_delete_from_leaf(struct sradix_tree_root *root, ++ struct sradix_tree_node *node, unsigned long index); ++ ++extern void *sradix_tree_lookup(struct sradix_tree_root *root, unsigned long index); ++ ++#endif /* _LINUX_SRADIX_TREE_H */ +diff --git a/include/linux/uksm.h b/include/linux/uksm.h +new file mode 100644 +index 000000000000..bb8651f534f2 +--- /dev/null ++++ b/include/linux/uksm.h +@@ -0,0 +1,149 @@ ++#ifndef __LINUX_UKSM_H ++#define __LINUX_UKSM_H ++/* ++ * Memory merging support. ++ * ++ * This code enables dynamic sharing of identical pages found in different ++ * memory areas, even if they are not shared by fork(). ++ */ ++ ++/* if !CONFIG_UKSM this file should not be compiled at all. */ ++#ifdef CONFIG_UKSM ++ ++#include ++#include ++#include ++#include ++#include ++ ++extern unsigned long zero_pfn __read_mostly; ++extern unsigned long uksm_zero_pfn __read_mostly; ++extern struct page *empty_uksm_zero_page; ++ ++/* must be done before linked to mm */ ++extern void uksm_vma_add_new(struct vm_area_struct *vma); ++extern void uksm_remove_vma(struct vm_area_struct *vma); ++ ++#define UKSM_SLOT_NEED_SORT (1 << 0) ++#define UKSM_SLOT_NEED_RERAND (1 << 1) ++#define UKSM_SLOT_SCANNED (1 << 2) /* It's scanned in this round */ ++#define UKSM_SLOT_FUL_SCANNED (1 << 3) ++#define UKSM_SLOT_IN_UKSM (1 << 4) ++ ++struct vma_slot { ++ struct sradix_tree_node *snode; ++ unsigned long sindex; ++ ++ struct list_head slot_list; ++ unsigned long fully_scanned_round; ++ unsigned long dedup_num; ++ unsigned long pages_scanned; ++ unsigned long this_sampled; ++ unsigned long last_scanned; ++ unsigned long pages_to_scan; ++ struct scan_rung *rung; ++ struct page **rmap_list_pool; ++ unsigned int *pool_counts; ++ unsigned long pool_size; ++ struct vm_area_struct *vma; ++ struct mm_struct *mm; ++ unsigned long ctime_j; ++ unsigned long pages; ++ unsigned long flags; ++ unsigned long pages_cowed; /* pages cowed this round */ ++ unsigned long pages_merged; /* pages merged this round */ ++ unsigned long pages_bemerged; ++ ++ /* when it has page merged in this eval round */ ++ struct list_head dedup_list; ++}; ++ ++static inline void uksm_unmap_zero_page(pte_t pte) ++{ ++ if (pte_pfn(pte) == uksm_zero_pfn) ++ __dec_zone_page_state(empty_uksm_zero_page, NR_UKSM_ZERO_PAGES); ++} ++ ++static inline void uksm_map_zero_page(pte_t pte) ++{ ++ if (pte_pfn(pte) == uksm_zero_pfn) ++ __inc_zone_page_state(empty_uksm_zero_page, NR_UKSM_ZERO_PAGES); ++} ++ ++static inline void uksm_cow_page(struct vm_area_struct *vma, struct page *page) ++{ ++ if (vma->uksm_vma_slot && PageKsm(page)) ++ vma->uksm_vma_slot->pages_cowed++; ++} ++ ++static inline void uksm_cow_pte(struct vm_area_struct *vma, pte_t pte) ++{ ++ if (vma->uksm_vma_slot && pte_pfn(pte) == uksm_zero_pfn) ++ vma->uksm_vma_slot->pages_cowed++; ++} ++ ++static inline int uksm_flags_can_scan(unsigned long vm_flags) ++{ ++#ifdef VM_SAO ++ if (vm_flags & VM_SAO) ++ return 0; ++#endif ++ ++ return !(vm_flags & (VM_PFNMAP | VM_IO | VM_DONTEXPAND | ++ VM_HUGETLB | VM_MIXEDMAP | VM_SHARED ++ | VM_MAYSHARE | VM_GROWSUP | VM_GROWSDOWN)); ++} ++ ++static inline void uksm_vm_flags_mod(unsigned long *vm_flags_p) ++{ ++ if (uksm_flags_can_scan(*vm_flags_p)) ++ *vm_flags_p |= VM_MERGEABLE; ++} ++ ++/* ++ * Just a wrapper for BUG_ON for where ksm_zeropage must not be. TODO: it will ++ * be removed when uksm zero page patch is stable enough. ++ */ ++static inline void uksm_bugon_zeropage(pte_t pte) ++{ ++ BUG_ON(pte_pfn(pte) == uksm_zero_pfn); ++} ++#else ++static inline void uksm_vma_add_new(struct vm_area_struct *vma) ++{ ++} ++ ++static inline void uksm_remove_vma(struct vm_area_struct *vma) ++{ ++} ++ ++static inline void uksm_unmap_zero_page(pte_t pte) ++{ ++} ++ ++static inline void uksm_map_zero_page(pte_t pte) ++{ ++} ++ ++static inline void uksm_cow_page(struct vm_area_struct *vma, struct page *page) ++{ ++} ++ ++static inline void uksm_cow_pte(struct vm_area_struct *vma, pte_t pte) ++{ ++} ++ ++static inline int uksm_flags_can_scan(unsigned long vm_flags) ++{ ++ return 0; ++} ++ ++static inline void uksm_vm_flags_mod(unsigned long *vm_flags_p) ++{ ++} ++ ++static inline void uksm_bugon_zeropage(pte_t pte) ++{ ++} ++#endif /* !CONFIG_UKSM */ ++#endif /* __LINUX_UKSM_H */ +diff --git a/kernel/fork.c b/kernel/fork.c +index 13b38794efb5..acb562745f1c 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -595,7 +595,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm, + __vma_link_rb(mm, tmp, rb_link, rb_parent); + rb_link = &tmp->vm_rb.rb_right; + rb_parent = &tmp->vm_rb; +- ++ uksm_vma_add_new(tmp); + mm->map_count++; + if (!(tmp->vm_flags & VM_WIPEONFORK)) + retval = copy_page_range(mm, oldmm, mpnt); +diff --git a/lib/Makefile b/lib/Makefile +index c5892807e06f..4b0d37da9fa0 100644 +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -25,7 +25,7 @@ CFLAGS_string.o := $(call cc-option, -fno-stack-protector) + endif + + lib-y := ctype.o string.o vsprintf.o cmdline.o \ +- rbtree.o radix-tree.o timerqueue.o xarray.o \ ++ rbtree.o radix-tree.o sradix-tree.o timerqueue.o xarray.o \ + idr.o extable.o sha1.o irq_regs.o argv_split.o \ + flex_proportions.o ratelimit.o show_mem.o \ + is_single_threaded.o plist.o decompress.o kobject_uevent.o \ +diff --git a/lib/sradix-tree.c b/lib/sradix-tree.c +new file mode 100644 +index 000000000000..ab21e6309b93 +--- /dev/null ++++ b/lib/sradix-tree.c +@@ -0,0 +1,476 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static inline int sradix_node_full(struct sradix_tree_root *root, struct sradix_tree_node *node) ++{ ++ return node->fulls == root->stores_size || ++ (node->height == 1 && node->count == root->stores_size); ++} ++ ++/* ++ * Extend a sradix tree so it can store key @index. ++ */ ++static int sradix_tree_extend(struct sradix_tree_root *root, unsigned long index) ++{ ++ struct sradix_tree_node *node; ++ unsigned int height; ++ ++ if (unlikely(root->rnode == NULL)) { ++ if (!(node = root->alloc())) ++ return -ENOMEM; ++ ++ node->height = 1; ++ root->rnode = node; ++ root->height = 1; ++ } ++ ++ /* Figure out what the height should be. */ ++ height = root->height; ++ index >>= root->shift * height; ++ ++ while (index) { ++ index >>= root->shift; ++ height++; ++ } ++ ++ while (height > root->height) { ++ unsigned int newheight; ++ ++ if (!(node = root->alloc())) ++ return -ENOMEM; ++ ++ /* Increase the height. */ ++ node->stores[0] = root->rnode; ++ root->rnode->parent = node; ++ if (root->extend) ++ root->extend(node, root->rnode); ++ ++ newheight = root->height + 1; ++ node->height = newheight; ++ node->count = 1; ++ if (sradix_node_full(root, root->rnode)) ++ node->fulls = 1; ++ ++ root->rnode = node; ++ root->height = newheight; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Search the next item from the current node, that is not NULL ++ * and can satify root->iter(). ++ */ ++void *sradix_tree_next(struct sradix_tree_root *root, ++ struct sradix_tree_node *node, unsigned long index, ++ int (*iter)(void *item, unsigned long height)) ++{ ++ unsigned long offset; ++ void *item; ++ ++ if (unlikely(node == NULL)) { ++ node = root->rnode; ++ for (offset = 0; offset < root->stores_size; offset++) { ++ item = node->stores[offset]; ++ if (item && (!iter || iter(item, node->height))) ++ break; ++ } ++ ++ if (unlikely(offset >= root->stores_size)) ++ return NULL; ++ ++ if (node->height == 1) ++ return item; ++ else ++ goto go_down; ++ } ++ ++ while (node) { ++ offset = (index & root->mask) + 1; ++ for (; offset < root->stores_size; offset++) { ++ item = node->stores[offset]; ++ if (item && (!iter || iter(item, node->height))) ++ break; ++ } ++ ++ if (offset < root->stores_size) ++ break; ++ ++ node = node->parent; ++ index >>= root->shift; ++ } ++ ++ if (!node) ++ return NULL; ++ ++ while (node->height > 1) { ++go_down: ++ node = item; ++ for (offset = 0; offset < root->stores_size; offset++) { ++ item = node->stores[offset]; ++ if (item && (!iter || iter(item, node->height))) ++ break; ++ } ++ ++ if (unlikely(offset >= root->stores_size)) ++ return NULL; ++ } ++ ++ BUG_ON(offset > root->stores_size); ++ ++ return item; ++} ++ ++/* ++ * Blindly insert the item to the tree. Typically, we reuse the ++ * first empty store item. ++ */ ++int sradix_tree_enter(struct sradix_tree_root *root, void **item, int num) ++{ ++ unsigned long index; ++ unsigned int height; ++ struct sradix_tree_node *node, *tmp = NULL; ++ int offset, offset_saved; ++ void **store = NULL; ++ int error, i, j, shift; ++ ++go_on: ++ index = root->min; ++ ++ if (root->enter_node && !sradix_node_full(root, root->enter_node)) { ++ node = root->enter_node; ++ BUG_ON((index >> (root->shift * root->height))); ++ } else { ++ node = root->rnode; ++ if (node == NULL || (index >> (root->shift * root->height)) ++ || sradix_node_full(root, node)) { ++ error = sradix_tree_extend(root, index); ++ if (error) ++ return error; ++ ++ node = root->rnode; ++ } ++ } ++ ++ ++ height = node->height; ++ shift = (height - 1) * root->shift; ++ offset = (index >> shift) & root->mask; ++ while (shift > 0) { ++ offset_saved = offset; ++ for (; offset < root->stores_size; offset++) { ++ store = &node->stores[offset]; ++ tmp = *store; ++ ++ if (!tmp || !sradix_node_full(root, tmp)) ++ break; ++ } ++ BUG_ON(offset >= root->stores_size); ++ ++ if (offset != offset_saved) { ++ index += (offset - offset_saved) << shift; ++ index &= ~((1UL << shift) - 1); ++ } ++ ++ if (!tmp) { ++ if (!(tmp = root->alloc())) ++ return -ENOMEM; ++ ++ tmp->height = shift / root->shift; ++ *store = tmp; ++ tmp->parent = node; ++ node->count++; ++// if (root->extend) ++// root->extend(node, tmp); ++ } ++ ++ node = tmp; ++ shift -= root->shift; ++ offset = (index >> shift) & root->mask; ++ } ++ ++ BUG_ON(node->height != 1); ++ ++ ++ store = &node->stores[offset]; ++ for (i = 0, j = 0; ++ j < root->stores_size - node->count && ++ i < root->stores_size - offset && j < num; i++) { ++ if (!store[i]) { ++ store[i] = item[j]; ++ if (root->assign) ++ root->assign(node, index + i, item[j]); ++ j++; ++ } ++ } ++ ++ node->count += j; ++ root->num += j; ++ num -= j; ++ ++ while (sradix_node_full(root, node)) { ++ node = node->parent; ++ if (!node) ++ break; ++ ++ node->fulls++; ++ } ++ ++ if (unlikely(!node)) { ++ /* All nodes are full */ ++ root->min = 1 << (root->height * root->shift); ++ root->enter_node = NULL; ++ } else { ++ root->min = index + i - 1; ++ root->min |= (1UL << (node->height - 1)) - 1; ++ root->min++; ++ root->enter_node = node; ++ } ++ ++ if (num) { ++ item += j; ++ goto go_on; ++ } ++ ++ return 0; ++} ++ ++ ++/** ++ * sradix_tree_shrink - shrink height of a sradix tree to minimal ++ * @root sradix tree root ++ * ++ */ ++static inline void sradix_tree_shrink(struct sradix_tree_root *root) ++{ ++ /* try to shrink tree height */ ++ while (root->height > 1) { ++ struct sradix_tree_node *to_free = root->rnode; ++ ++ /* ++ * The candidate node has more than one child, or its child ++ * is not at the leftmost store, we cannot shrink. ++ */ ++ if (to_free->count != 1 || !to_free->stores[0]) ++ break; ++ ++ root->rnode = to_free->stores[0]; ++ root->rnode->parent = NULL; ++ root->height--; ++ if (unlikely(root->enter_node == to_free)) ++ root->enter_node = NULL; ++ root->free(to_free); ++ } ++} ++ ++/* ++ * Del the item on the known leaf node and index ++ */ ++void sradix_tree_delete_from_leaf(struct sradix_tree_root *root, ++ struct sradix_tree_node *node, unsigned long index) ++{ ++ unsigned int offset; ++ struct sradix_tree_node *start, *end; ++ ++ BUG_ON(node->height != 1); ++ ++ start = node; ++ while (node && !(--node->count)) ++ node = node->parent; ++ ++ end = node; ++ if (!node) { ++ root->rnode = NULL; ++ root->height = 0; ++ root->min = 0; ++ root->num = 0; ++ root->enter_node = NULL; ++ } else { ++ offset = (index >> (root->shift * (node->height - 1))) & root->mask; ++ if (root->rm) ++ root->rm(node, offset); ++ node->stores[offset] = NULL; ++ root->num--; ++ if (root->min > index) { ++ root->min = index; ++ root->enter_node = node; ++ } ++ } ++ ++ if (start != end) { ++ do { ++ node = start; ++ start = start->parent; ++ if (unlikely(root->enter_node == node)) ++ root->enter_node = end; ++ root->free(node); ++ } while (start != end); ++ ++ /* ++ * Note that shrink may free "end", so enter_node still need to ++ * be checked inside. ++ */ ++ sradix_tree_shrink(root); ++ } else if (node->count == root->stores_size - 1) { ++ /* It WAS a full leaf node. Update the ancestors */ ++ node = node->parent; ++ while (node) { ++ node->fulls--; ++ if (node->fulls != root->stores_size - 1) ++ break; ++ ++ node = node->parent; ++ } ++ } ++} ++ ++void *sradix_tree_lookup(struct sradix_tree_root *root, unsigned long index) ++{ ++ unsigned int height, offset; ++ struct sradix_tree_node *node; ++ int shift; ++ ++ node = root->rnode; ++ if (node == NULL || (index >> (root->shift * root->height))) ++ return NULL; ++ ++ height = root->height; ++ shift = (height - 1) * root->shift; ++ ++ do { ++ offset = (index >> shift) & root->mask; ++ node = node->stores[offset]; ++ if (!node) ++ return NULL; ++ ++ shift -= root->shift; ++ } while (shift >= 0); ++ ++ return node; ++} ++ ++/* ++ * Return the item if it exists, otherwise create it in place ++ * and return the created item. ++ */ ++void *sradix_tree_lookup_create(struct sradix_tree_root *root, ++ unsigned long index, void *(*item_alloc)(void)) ++{ ++ unsigned int height, offset; ++ struct sradix_tree_node *node, *tmp; ++ void *item; ++ int shift, error; ++ ++ if (root->rnode == NULL || (index >> (root->shift * root->height))) { ++ if (item_alloc) { ++ error = sradix_tree_extend(root, index); ++ if (error) ++ return NULL; ++ } else { ++ return NULL; ++ } ++ } ++ ++ node = root->rnode; ++ height = root->height; ++ shift = (height - 1) * root->shift; ++ ++ do { ++ offset = (index >> shift) & root->mask; ++ if (!node->stores[offset]) { ++ if (!(tmp = root->alloc())) ++ return NULL; ++ ++ tmp->height = shift / root->shift; ++ node->stores[offset] = tmp; ++ tmp->parent = node; ++ node->count++; ++ node = tmp; ++ } else { ++ node = node->stores[offset]; ++ } ++ ++ shift -= root->shift; ++ } while (shift > 0); ++ ++ BUG_ON(node->height != 1); ++ offset = index & root->mask; ++ if (node->stores[offset]) { ++ return node->stores[offset]; ++ } else if (item_alloc) { ++ if (!(item = item_alloc())) ++ return NULL; ++ ++ node->stores[offset] = item; ++ ++ /* ++ * NOTE: we do NOT call root->assign here, since this item is ++ * newly created by us having no meaning. Caller can call this ++ * if it's necessary to do so. ++ */ ++ ++ node->count++; ++ root->num++; ++ ++ while (sradix_node_full(root, node)) { ++ node = node->parent; ++ if (!node) ++ break; ++ ++ node->fulls++; ++ } ++ ++ if (unlikely(!node)) { ++ /* All nodes are full */ ++ root->min = 1 << (root->height * root->shift); ++ } else { ++ if (root->min == index) { ++ root->min |= (1UL << (node->height - 1)) - 1; ++ root->min++; ++ root->enter_node = node; ++ } ++ } ++ ++ return item; ++ } else { ++ return NULL; ++ } ++ ++} ++ ++int sradix_tree_delete(struct sradix_tree_root *root, unsigned long index) ++{ ++ unsigned int height, offset; ++ struct sradix_tree_node *node; ++ int shift; ++ ++ node = root->rnode; ++ if (node == NULL || (index >> (root->shift * root->height))) ++ return -ENOENT; ++ ++ height = root->height; ++ shift = (height - 1) * root->shift; ++ ++ do { ++ offset = (index >> shift) & root->mask; ++ node = node->stores[offset]; ++ if (!node) ++ return -ENOENT; ++ ++ shift -= root->shift; ++ } while (shift > 0); ++ ++ offset = index & root->mask; ++ if (!node->stores[offset]) ++ return -ENOENT; ++ ++ sradix_tree_delete_from_leaf(root, node, index); ++ ++ return 0; ++} +diff --git a/mm/Kconfig b/mm/Kconfig +index a5dae9a7eb51..eda3a78226b0 100644 +--- a/mm/Kconfig ++++ b/mm/Kconfig +@@ -299,6 +299,32 @@ config KSM + See Documentation/vm/ksm.rst for more information: KSM is inactive + until a program has madvised that an area is MADV_MERGEABLE, and + root has set /sys/kernel/mm/ksm/run to 1 (if CONFIG_SYSFS is set). ++choice ++ prompt "Choose UKSM/KSM strategy" ++ default UKSM ++ depends on KSM ++ help ++ This option allows to select a UKSM/KSM stragety. ++ ++config UKSM ++ bool "Ultra-KSM for page merging" ++ depends on KSM ++ help ++ UKSM is inspired by the Linux kernel project \u2014 KSM(Kernel Same ++ page Merging), but with a fundamentally rewritten core algorithm. With ++ an advanced algorithm, UKSM now can transparently scans all anonymously ++ mapped user space applications with an significantly improved scan speed ++ and CPU efficiency. Since KVM is friendly to KSM, KVM can also benefit from ++ UKSM. Now UKSM has its first stable release and first real world enterprise user. ++ For more information, please goto its project page. ++ (github.com/dolohow/uksm) ++ ++config KSM_LEGACY ++ bool "Legacy KSM implementation" ++ depends on KSM ++ help ++ The legacy KSM implementation from Red Hat. ++endchoice + + config DEFAULT_MMAP_MIN_ADDR + int "Low address space to protect from user allocation" +diff --git a/mm/Makefile b/mm/Makefile +index d996846697ef..786cb9fad4b9 100644 +--- a/mm/Makefile ++++ b/mm/Makefile +@@ -66,7 +66,8 @@ obj-$(CONFIG_SPARSEMEM) += sparse.o + obj-$(CONFIG_SPARSEMEM_VMEMMAP) += sparse-vmemmap.o + obj-$(CONFIG_SLOB) += slob.o + obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o +-obj-$(CONFIG_KSM) += ksm.o ++obj-$(CONFIG_KSM_LEGACY) += ksm.o ++obj-$(CONFIG_UKSM) += uksm.o + obj-$(CONFIG_PAGE_POISONING) += page_poison.o + obj-$(CONFIG_SLAB) += slab.o + obj-$(CONFIG_SLUB) += slub.o +diff --git a/mm/ksm.c b/mm/ksm.c +index 7905934cd3ad..3e9d0064eaf2 100644 +--- a/mm/ksm.c ++++ b/mm/ksm.c +@@ -857,17 +857,6 @@ static int unmerge_ksm_pages(struct vm_area_struct *vma, + return err; + } + +-static inline struct stable_node *page_stable_node(struct page *page) +-{ +- return PageKsm(page) ? page_rmapping(page) : NULL; +-} +- +-static inline void set_page_stable_node(struct page *page, +- struct stable_node *stable_node) +-{ +- page->mapping = (void *)((unsigned long)stable_node | PAGE_MAPPING_KSM); +-} +- + #ifdef CONFIG_SYSFS + /* + * Only called through the sysfs control interface: +diff --git a/mm/memory.c b/mm/memory.c +index 45442d9a4f52..9beaa229bb0d 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -144,6 +144,25 @@ EXPORT_SYMBOL(zero_pfn); + + unsigned long highest_memmap_pfn __read_mostly; + ++#ifdef CONFIG_UKSM ++unsigned long uksm_zero_pfn __read_mostly; ++EXPORT_SYMBOL_GPL(uksm_zero_pfn); ++struct page *empty_uksm_zero_page; ++ ++static int __init setup_uksm_zero_page(void) ++{ ++ empty_uksm_zero_page = alloc_pages(__GFP_ZERO & ~__GFP_MOVABLE, 0); ++ if (!empty_uksm_zero_page) ++ panic("Oh boy, that early out of memory?"); ++ ++ SetPageReserved(empty_uksm_zero_page); ++ uksm_zero_pfn = page_to_pfn(empty_uksm_zero_page); ++ ++ return 0; ++} ++core_initcall(setup_uksm_zero_page); ++#endif ++ + /* + * CONFIG_MMU architectures set up ZERO_PAGE in their paging_init() + */ +@@ -159,6 +178,7 @@ void mm_trace_rss_stat(struct mm_struct *mm, int member, long count) + trace_rss_stat(mm, member, count); + } + ++ + #if defined(SPLIT_RSS_COUNTING) + + void sync_mm_rss(struct mm_struct *mm) +@@ -790,8 +810,13 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, + get_page(page); + page_dup_rmap(page, false); + rss[mm_counter(page)]++; ++ ++ /* Should return NULL in vm_normal_page() */ ++ uksm_bugon_zeropage(pte); + } else if (pte_devmap(pte)) { + page = pte_page(pte); ++ } else { ++ uksm_map_zero_page(pte); + } + + out_set_pte: +@@ -1064,8 +1089,10 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb, + ptent = ptep_get_and_clear_full(mm, addr, pte, + tlb->fullmm); + tlb_remove_tlb_entry(tlb, pte, addr); +- if (unlikely(!page)) ++ if (unlikely(!page)) { ++ uksm_unmap_zero_page(ptent); + continue; ++ } + + if (!PageAnon(page)) { + if (pte_dirty(ptent)) { +@@ -2230,6 +2257,7 @@ static inline bool cow_user_page(struct page *dst, struct page *src, + + if (likely(src)) { + copy_user_highpage(dst, src, addr, vma); ++ uksm_cow_page(vma, src); + return true; + } + +@@ -2457,6 +2485,7 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf) + vmf->address); + if (!new_page) + goto oom; ++ uksm_cow_pte(vma, vmf->orig_pte); + } else { + new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, + vmf->address); +@@ -2498,7 +2527,9 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf) + mm_counter_file(old_page)); + inc_mm_counter_fast(mm, MM_ANONPAGES); + } ++ uksm_bugon_zeropage(vmf->orig_pte); + } else { ++ uksm_unmap_zero_page(vmf->orig_pte); + inc_mm_counter_fast(mm, MM_ANONPAGES); + } + flush_cache_page(vma, vmf->address, pte_pfn(vmf->orig_pte)); +diff --git a/mm/mmap.c b/mm/mmap.c +index a7d8c84d19b7..797582240047 100644 +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -46,6 +46,7 @@ + #include + #include + #include ++#include + #include + + #include +@@ -184,6 +185,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma) + if (vma->vm_file) + fput(vma->vm_file); + mpol_put(vma_policy(vma)); ++ uksm_remove_vma(vma); + vm_area_free(vma); + return next; + } +@@ -736,9 +738,16 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, + long adjust_next = 0; + int remove_next = 0; + ++/* ++ * to avoid deadlock, ksm_remove_vma must be done before any spin_lock is ++ * acquired ++ */ ++ uksm_remove_vma(vma); ++ + if (next && !insert) { + struct vm_area_struct *exporter = NULL, *importer = NULL; + ++ uksm_remove_vma(next); + if (end >= next->vm_end) { + /* + * vma expands, overlapping all the next, and +@@ -871,6 +880,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, + end_changed = true; + } + vma->vm_pgoff = pgoff; ++ + if (adjust_next) { + next->vm_start += adjust_next << PAGE_SHIFT; + next->vm_pgoff += adjust_next; +@@ -976,6 +986,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, + if (remove_next == 2) { + remove_next = 1; + end = next->vm_end; ++ uksm_remove_vma(next); + goto again; + } + else if (next) +@@ -1002,10 +1013,14 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, + */ + VM_WARN_ON(mm->highest_vm_end != vm_end_gap(vma)); + } ++ } else { ++ if (next && !insert) ++ uksm_vma_add_new(next); + } + if (insert && file) + uprobe_mmap(insert); + ++ uksm_vma_add_new(vma); + validate_mm(mm); + + return 0; +@@ -1465,6 +1480,9 @@ unsigned long do_mmap(struct file *file, unsigned long addr, + vm_flags |= calc_vm_prot_bits(prot, pkey) | calc_vm_flag_bits(flags) | + mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; + ++ /* If uksm is enabled, we add VM_MERGEABLE to new VMAs. */ ++ uksm_vm_flags_mod(&vm_flags); ++ + if (flags & MAP_LOCKED) + if (!can_do_mlock()) + return -EPERM; +@@ -1835,6 +1853,7 @@ unsigned long mmap_region(struct file *file, unsigned long addr, + allow_write_access(file); + } + file = vma->vm_file; ++ uksm_vma_add_new(vma); + out: + perf_event_mmap(vma); + +@@ -1877,6 +1896,7 @@ unsigned long mmap_region(struct file *file, unsigned long addr, + if (vm_flags & VM_DENYWRITE) + allow_write_access(file); + free_vma: ++ uksm_remove_vma(vma); + vm_area_free(vma); + unacct_error: + if (charged) +@@ -2706,6 +2726,8 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma, + else + err = vma_adjust(vma, vma->vm_start, addr, vma->vm_pgoff, new); + ++ uksm_vma_add_new(new); ++ + /* Success. */ + if (!err) + return 0; +@@ -3011,6 +3033,7 @@ static int do_brk_flags(unsigned long addr, unsigned long len, unsigned long fla + if ((flags & (~VM_EXEC)) != 0) + return -EINVAL; + flags |= VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; ++ uksm_vm_flags_mod(&flags); + + error = get_unmapped_area(NULL, addr, len, 0, MAP_FIXED); + if (offset_in_page(error)) +@@ -3061,6 +3084,7 @@ static int do_brk_flags(unsigned long addr, unsigned long len, unsigned long fla + vma->vm_flags = flags; + vma->vm_page_prot = vm_get_page_prot(flags); + vma_link(mm, vma, prev, rb_link, rb_parent); ++ uksm_vma_add_new(vma); + out: + perf_event_mmap(vma); + mm->total_vm += len >> PAGE_SHIFT; +@@ -3138,6 +3162,12 @@ void exit_mmap(struct mm_struct *mm) + up_write(&mm->mmap_sem); + } + ++ /* ++ * Taking write lock on mmap_sem does not harm others, ++ * but it's crucial for uksm to avoid races. ++ */ ++ down_write(&mm->mmap_sem); ++ + if (mm->locked_vm) { + vma = mm->mmap; + while (vma) { +@@ -3172,6 +3202,11 @@ void exit_mmap(struct mm_struct *mm) + vma = remove_vma(vma); + } + vm_unacct_memory(nr_accounted); ++ ++ mm->mmap = NULL; ++ mm->mm_rb = RB_ROOT; ++ vmacache_invalidate(mm); ++ up_write(&mm->mmap_sem); + } + + /* Insert vm structure into process list sorted by address +@@ -3279,6 +3314,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, + new_vma->vm_ops->open(new_vma); + vma_link(mm, new_vma, prev, rb_link, rb_parent); + *need_rmap_locks = false; ++ uksm_vma_add_new(new_vma); + } + return new_vma; + +@@ -3429,6 +3465,7 @@ static struct vm_area_struct *__install_special_mapping( + vm_stat_account(mm, vma->vm_flags, len >> PAGE_SHIFT); + + perf_event_mmap(vma); ++ uksm_vma_add_new(vma); + + return vma; + +diff --git a/mm/uksm.c b/mm/uksm.c +new file mode 100644 +index 000000000000..ef068d5dc307 +--- /dev/null ++++ b/mm/uksm.c +@@ -0,0 +1,5613 @@ ++/* ++ * Ultra KSM. Copyright (C) 2011-2012 Nai Xia ++ * ++ * This is an improvement upon KSM. Some basic data structures and routines ++ * are borrowed from ksm.c . ++ * ++ * Its new features: ++ * 1. Full system scan: ++ * It automatically scans all user processes' anonymous VMAs. Kernel-user ++ * interaction to submit a memory area to KSM is no longer needed. ++ * ++ * 2. Rich area detection: ++ * It automatically detects rich areas containing abundant duplicated ++ * pages based. Rich areas are given a full scan speed. Poor areas are ++ * sampled at a reasonable speed with very low CPU consumption. ++ * ++ * 3. Ultra Per-page scan speed improvement: ++ * A new hash algorithm is proposed. As a result, on a machine with ++ * Core(TM)2 Quad Q9300 CPU in 32-bit mode and 800MHZ DDR2 main memory, it ++ * can scan memory areas that does not contain duplicated pages at speed of ++ * 627MB/sec ~ 2445MB/sec and can merge duplicated areas at speed of ++ * 477MB/sec ~ 923MB/sec. ++ * ++ * 4. Thrashing area avoidance: ++ * Thrashing area(an VMA that has frequent Ksm page break-out) can be ++ * filtered out. My benchmark shows it's more efficient than KSM's per-page ++ * hash value based volatile page detection. ++ * ++ * ++ * 5. Misc changes upon KSM: ++ * * It has a fully x86-opitmized memcmp dedicated for 4-byte-aligned page ++ * comparison. It's much faster than default C version on x86. ++ * * rmap_item now has an struct *page member to loosely cache a ++ * address-->page mapping, which reduces too much time-costly ++ * follow_page(). ++ * * The VMA creation/exit procedures are hooked to let the Ultra KSM know. ++ * * try_to_merge_two_pages() now can revert a pte if it fails. No break_ ++ * ksm is needed for this case. ++ * ++ * 6. Full Zero Page consideration(contributed by Figo Zhang) ++ * Now uksmd consider full zero pages as special pages and merge them to an ++ * special unswappable uksm zero page. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include "internal.h" ++ ++#ifdef CONFIG_X86 ++#undef memcmp ++ ++#ifdef CONFIG_X86_32 ++#define memcmp memcmpx86_32 ++/* ++ * Compare 4-byte-aligned address s1 and s2, with length n ++ */ ++int memcmpx86_32(void *s1, void *s2, size_t n) ++{ ++ size_t num = n / 4; ++ register int res; ++ ++ __asm__ __volatile__ ++ ( ++ "testl %3,%3\n\t" ++ "repe; cmpsd\n\t" ++ "je 1f\n\t" ++ "sbbl %0,%0\n\t" ++ "orl $1,%0\n" ++ "1:" ++ : "=&a" (res), "+&S" (s1), "+&D" (s2), "+&c" (num) ++ : "0" (0) ++ : "cc"); ++ ++ return res; ++} ++ ++/* ++ * Check the page is all zero ? ++ */ ++static int is_full_zero(const void *s1, size_t len) ++{ ++ unsigned char same; ++ ++ len /= 4; ++ ++ __asm__ __volatile__ ++ ("repe; scasl;" ++ "sete %0" ++ : "=qm" (same), "+D" (s1), "+c" (len) ++ : "a" (0) ++ : "cc"); ++ ++ return same; ++} ++ ++ ++#elif defined(CONFIG_X86_64) ++#define memcmp memcmpx86_64 ++/* ++ * Compare 8-byte-aligned address s1 and s2, with length n ++ */ ++int memcmpx86_64(void *s1, void *s2, size_t n) ++{ ++ size_t num = n / 8; ++ register int res; ++ ++ __asm__ __volatile__ ++ ( ++ "testq %q3,%q3\n\t" ++ "repe; cmpsq\n\t" ++ "je 1f\n\t" ++ "sbbq %q0,%q0\n\t" ++ "orq $1,%q0\n" ++ "1:" ++ : "=&a" (res), "+&S" (s1), "+&D" (s2), "+&c" (num) ++ : "0" (0) ++ : "cc"); ++ ++ return res; ++} ++ ++static int is_full_zero(const void *s1, size_t len) ++{ ++ unsigned char same; ++ ++ len /= 8; ++ ++ __asm__ __volatile__ ++ ("repe; scasq;" ++ "sete %0" ++ : "=qm" (same), "+D" (s1), "+c" (len) ++ : "a" (0) ++ : "cc"); ++ ++ return same; ++} ++ ++#endif ++#else ++static int is_full_zero(const void *s1, size_t len) ++{ ++ unsigned long *src = s1; ++ int i; ++ ++ len /= sizeof(*src); ++ ++ for (i = 0; i < len; i++) { ++ if (src[i]) ++ return 0; ++ } ++ ++ return 1; ++} ++#endif ++ ++#define UKSM_RUNG_ROUND_FINISHED (1 << 0) ++#define TIME_RATIO_SCALE 10000 ++ ++#define SLOT_TREE_NODE_SHIFT 8 ++#define SLOT_TREE_NODE_STORE_SIZE (1UL << SLOT_TREE_NODE_SHIFT) ++struct slot_tree_node { ++ unsigned long size; ++ struct sradix_tree_node snode; ++ void *stores[SLOT_TREE_NODE_STORE_SIZE]; ++}; ++ ++static struct kmem_cache *slot_tree_node_cachep; ++ ++static struct sradix_tree_node *slot_tree_node_alloc(void) ++{ ++ struct slot_tree_node *p; ++ ++ p = kmem_cache_zalloc(slot_tree_node_cachep, GFP_KERNEL | ++ __GFP_NORETRY | __GFP_NOWARN); ++ if (!p) ++ return NULL; ++ ++ return &p->snode; ++} ++ ++static void slot_tree_node_free(struct sradix_tree_node *node) ++{ ++ struct slot_tree_node *p; ++ ++ p = container_of(node, struct slot_tree_node, snode); ++ kmem_cache_free(slot_tree_node_cachep, p); ++} ++ ++static void slot_tree_node_extend(struct sradix_tree_node *parent, ++ struct sradix_tree_node *child) ++{ ++ struct slot_tree_node *p, *c; ++ ++ p = container_of(parent, struct slot_tree_node, snode); ++ c = container_of(child, struct slot_tree_node, snode); ++ ++ p->size += c->size; ++} ++ ++void slot_tree_node_assign(struct sradix_tree_node *node, ++ unsigned int index, void *item) ++{ ++ struct vma_slot *slot = item; ++ struct slot_tree_node *cur; ++ ++ slot->snode = node; ++ slot->sindex = index; ++ ++ while (node) { ++ cur = container_of(node, struct slot_tree_node, snode); ++ cur->size += slot->pages; ++ node = node->parent; ++ } ++} ++ ++void slot_tree_node_rm(struct sradix_tree_node *node, unsigned int offset) ++{ ++ struct vma_slot *slot; ++ struct slot_tree_node *cur; ++ unsigned long pages; ++ ++ if (node->height == 1) { ++ slot = node->stores[offset]; ++ pages = slot->pages; ++ } else { ++ cur = container_of(node->stores[offset], ++ struct slot_tree_node, snode); ++ pages = cur->size; ++ } ++ ++ while (node) { ++ cur = container_of(node, struct slot_tree_node, snode); ++ cur->size -= pages; ++ node = node->parent; ++ } ++} ++ ++unsigned long slot_iter_index; ++int slot_iter(void *item, unsigned long height) ++{ ++ struct slot_tree_node *node; ++ struct vma_slot *slot; ++ ++ if (height == 1) { ++ slot = item; ++ if (slot_iter_index < slot->pages) { ++ /*in this one*/ ++ return 1; ++ } else { ++ slot_iter_index -= slot->pages; ++ return 0; ++ } ++ ++ } else { ++ node = container_of(item, struct slot_tree_node, snode); ++ if (slot_iter_index < node->size) { ++ /*in this one*/ ++ return 1; ++ } else { ++ slot_iter_index -= node->size; ++ return 0; ++ } ++ } ++} ++ ++ ++static inline void slot_tree_init_root(struct sradix_tree_root *root) ++{ ++ init_sradix_tree_root(root, SLOT_TREE_NODE_SHIFT); ++ root->alloc = slot_tree_node_alloc; ++ root->free = slot_tree_node_free; ++ root->extend = slot_tree_node_extend; ++ root->assign = slot_tree_node_assign; ++ root->rm = slot_tree_node_rm; ++} ++ ++void slot_tree_init(void) ++{ ++ slot_tree_node_cachep = kmem_cache_create("slot_tree_node", ++ sizeof(struct slot_tree_node), 0, ++ SLAB_PANIC | SLAB_RECLAIM_ACCOUNT, ++ NULL); ++} ++ ++ ++/* Each rung of this ladder is a list of VMAs having a same scan ratio */ ++struct scan_rung { ++ //struct list_head scanned_list; ++ struct sradix_tree_root vma_root; ++ struct sradix_tree_root vma_root2; ++ ++ struct vma_slot *current_scan; ++ unsigned long current_offset; ++ ++ /* ++ * The initial value for current_offset, it should loop over ++ * [0~ step - 1] to let all slot have its chance to be scanned. ++ */ ++ unsigned long offset_init; ++ unsigned long step; /* dynamic step for current_offset */ ++ unsigned int flags; ++ unsigned long pages_to_scan; ++ //unsigned long fully_scanned_slots; ++ /* ++ * a little bit tricky - if cpu_time_ratio > 0, then the value is the ++ * the cpu time ratio it can spend in rung_i for every scan ++ * period. if < 0, then it is the cpu time ratio relative to the ++ * max cpu percentage user specified. Both in unit of ++ * 1/TIME_RATIO_SCALE ++ */ ++ int cpu_ratio; ++ ++ /* ++ * How long it will take for all slots in this rung to be fully ++ * scanned? If it's zero, we don't care about the cover time: ++ * it's fully scanned. ++ */ ++ unsigned int cover_msecs; ++ //unsigned long vma_num; ++ //unsigned long pages; /* Sum of all slot's pages in rung */ ++}; ++ ++/** ++ * node of either the stable or unstale rbtree ++ * ++ */ ++struct tree_node { ++ struct rb_node node; /* link in the main (un)stable rbtree */ ++ struct rb_root sub_root; /* rb_root for sublevel collision rbtree */ ++ u32 hash; ++ unsigned long count; /* TODO: merged with sub_root */ ++ struct list_head all_list; /* all tree nodes in stable/unstable tree */ ++}; ++ ++/** ++ * struct stable_node - node of the stable rbtree ++ * @node: rb node of this ksm page in the stable tree ++ * @hlist: hlist head of rmap_items using this ksm page ++ * @kpfn: page frame number of this ksm page ++ */ ++struct stable_node { ++ struct rb_node node; /* link in sub-rbtree */ ++ struct tree_node *tree_node; /* it's tree node root in stable tree, NULL if it's in hell list */ ++ struct hlist_head hlist; ++ unsigned long kpfn; ++ u32 hash_max; /* if ==0 then it's not been calculated yet */ ++ struct list_head all_list; /* in a list for all stable nodes */ ++}; ++ ++/** ++ * struct node_vma - group rmap_items linked in a same stable ++ * node together. ++ */ ++struct node_vma { ++ union { ++ struct vma_slot *slot; ++ unsigned long key; /* slot is used as key sorted on hlist */ ++ }; ++ struct hlist_node hlist; ++ struct hlist_head rmap_hlist; ++ struct stable_node *head; ++}; ++ ++/** ++ * struct rmap_item - reverse mapping item for virtual addresses ++ * @rmap_list: next rmap_item in mm_slot's singly-linked rmap_list ++ * @anon_vma: pointer to anon_vma for this mm,address, when in stable tree ++ * @mm: the memory structure this rmap_item is pointing into ++ * @address: the virtual address this rmap_item tracks (+ flags in low bits) ++ * @node: rb node of this rmap_item in the unstable tree ++ * @head: pointer to stable_node heading this list in the stable tree ++ * @hlist: link into hlist of rmap_items hanging off that stable_node ++ */ ++struct rmap_item { ++ struct vma_slot *slot; ++ struct page *page; ++ unsigned long address; /* + low bits used for flags below */ ++ unsigned long hash_round; ++ unsigned long entry_index; ++ union { ++ struct {/* when in unstable tree */ ++ struct rb_node node; ++ struct tree_node *tree_node; ++ u32 hash_max; ++ }; ++ struct { /* when in stable tree */ ++ struct node_vma *head; ++ struct hlist_node hlist; ++ struct anon_vma *anon_vma; ++ }; ++ }; ++} __aligned(4); ++ ++struct rmap_list_entry { ++ union { ++ struct rmap_item *item; ++ unsigned long addr; ++ }; ++ /* lowest bit is used for is_addr tag */ ++} __aligned(4); /* 4 aligned to fit in to pages*/ ++ ++ ++/* Basic data structure definition ends */ ++ ++ ++/* ++ * Flags for rmap_item to judge if it's listed in the stable/unstable tree. ++ * The flags use the low bits of rmap_item.address ++ */ ++#define UNSTABLE_FLAG 0x1 ++#define STABLE_FLAG 0x2 ++#define get_rmap_addr(x) ((x)->address & PAGE_MASK) ++ ++/* ++ * rmap_list_entry helpers ++ */ ++#define IS_ADDR_FLAG 1 ++#define is_addr(ptr) ((unsigned long)(ptr) & IS_ADDR_FLAG) ++#define set_is_addr(ptr) ((ptr) |= IS_ADDR_FLAG) ++#define get_clean_addr(ptr) (((ptr) & ~(__typeof__(ptr))IS_ADDR_FLAG)) ++ ++ ++/* ++ * High speed caches for frequently allocated and freed structs ++ */ ++static struct kmem_cache *rmap_item_cache; ++static struct kmem_cache *stable_node_cache; ++static struct kmem_cache *node_vma_cache; ++static struct kmem_cache *vma_slot_cache; ++static struct kmem_cache *tree_node_cache; ++#define UKSM_KMEM_CACHE(__struct, __flags) kmem_cache_create("uksm_"#__struct,\ ++ sizeof(struct __struct), __alignof__(struct __struct),\ ++ (__flags), NULL) ++ ++/* Array of all scan_rung, uksm_scan_ladder[0] having the minimum scan ratio */ ++#define SCAN_LADDER_SIZE 4 ++static struct scan_rung uksm_scan_ladder[SCAN_LADDER_SIZE]; ++ ++/* The evaluation rounds uksmd has finished */ ++static unsigned long long uksm_eval_round = 1; ++ ++/* ++ * we add 1 to this var when we consider we should rebuild the whole ++ * unstable tree. ++ */ ++static unsigned long uksm_hash_round = 1; ++ ++/* ++ * How many times the whole memory is scanned. ++ */ ++static unsigned long long fully_scanned_round = 1; ++ ++/* The total number of virtual pages of all vma slots */ ++static u64 uksm_pages_total; ++ ++/* The number of pages has been scanned since the start up */ ++static u64 uksm_pages_scanned; ++ ++static u64 scanned_virtual_pages; ++ ++/* The number of pages has been scanned since last encode_benefit call */ ++static u64 uksm_pages_scanned_last; ++ ++/* If the scanned number is tooo large, we encode it here */ ++static u64 pages_scanned_stored; ++ ++static unsigned long pages_scanned_base; ++ ++/* The number of nodes in the stable tree */ ++static unsigned long uksm_pages_shared; ++ ++/* The number of page slots additionally sharing those nodes */ ++static unsigned long uksm_pages_sharing; ++ ++/* The number of nodes in the unstable tree */ ++static unsigned long uksm_pages_unshared; ++ ++/* ++ * Milliseconds ksmd should sleep between scans, ++ * >= 100ms to be consistent with ++ * scan_time_to_sleep_msec() ++ */ ++static unsigned int uksm_sleep_jiffies; ++ ++/* The real value for the uksmd next sleep */ ++static unsigned int uksm_sleep_real; ++ ++/* Saved value for user input uksm_sleep_jiffies when it's enlarged */ ++static unsigned int uksm_sleep_saved; ++ ++/* Max percentage of cpu utilization ksmd can take to scan in one batch */ ++static unsigned int uksm_max_cpu_percentage; ++ ++static int uksm_cpu_governor; ++ ++static char *uksm_cpu_governor_str[4] = { "full", "medium", "low", "quiet" }; ++ ++struct uksm_cpu_preset_s { ++ int cpu_ratio[SCAN_LADDER_SIZE]; ++ unsigned int cover_msecs[SCAN_LADDER_SIZE]; ++ unsigned int max_cpu; /* percentage */ ++}; ++ ++struct uksm_cpu_preset_s uksm_cpu_preset[4] = { ++ { {20, 40, -2500, -10000}, {1000, 500, 200, 50}, 95}, ++ { {20, 30, -2500, -10000}, {1000, 500, 400, 100}, 50}, ++ { {10, 20, -5000, -10000}, {1500, 1000, 1000, 250}, 20}, ++ { {10, 20, 40, 75}, {2000, 1000, 1000, 1000}, 1}, ++}; ++ ++/* The default value for uksm_ema_page_time if it's not initialized */ ++#define UKSM_PAGE_TIME_DEFAULT 500 ++ ++/*cost to scan one page by expotional moving average in nsecs */ ++static unsigned long uksm_ema_page_time = UKSM_PAGE_TIME_DEFAULT; ++ ++/* The expotional moving average alpha weight, in percentage. */ ++#define EMA_ALPHA 20 ++ ++/* ++ * The threshold used to filter out thrashing areas, ++ * If it == 0, filtering is disabled, otherwise it's the percentage up-bound ++ * of the thrashing ratio of all areas. Any area with a bigger thrashing ratio ++ * will be considered as having a zero duplication ratio. ++ */ ++static unsigned int uksm_thrash_threshold = 50; ++ ++/* How much dedup ratio is considered to be abundant*/ ++static unsigned int uksm_abundant_threshold = 10; ++ ++/* All slots having merged pages in this eval round. */ ++struct list_head vma_slot_dedup = LIST_HEAD_INIT(vma_slot_dedup); ++ ++/* How many times the ksmd has slept since startup */ ++static unsigned long long uksm_sleep_times; ++ ++#define UKSM_RUN_STOP 0 ++#define UKSM_RUN_MERGE 1 ++static unsigned int uksm_run = 1; ++ ++static DECLARE_WAIT_QUEUE_HEAD(uksm_thread_wait); ++static DEFINE_MUTEX(uksm_thread_mutex); ++ ++/* ++ * List vma_slot_new is for newly created vma_slot waiting to be added by ++ * ksmd. If one cannot be added(e.g. due to it's too small), it's moved to ++ * vma_slot_noadd. vma_slot_del is the list for vma_slot whose corresponding ++ * VMA has been removed/freed. ++ */ ++struct list_head vma_slot_new = LIST_HEAD_INIT(vma_slot_new); ++struct list_head vma_slot_noadd = LIST_HEAD_INIT(vma_slot_noadd); ++struct list_head vma_slot_del = LIST_HEAD_INIT(vma_slot_del); ++static DEFINE_SPINLOCK(vma_slot_list_lock); ++ ++/* The unstable tree heads */ ++static struct rb_root root_unstable_tree = RB_ROOT; ++ ++/* ++ * All tree_nodes are in a list to be freed at once when unstable tree is ++ * freed after each scan round. ++ */ ++static struct list_head unstable_tree_node_list = ++ LIST_HEAD_INIT(unstable_tree_node_list); ++ ++/* List contains all stable nodes */ ++static struct list_head stable_node_list = LIST_HEAD_INIT(stable_node_list); ++ ++/* ++ * When the hash strength is changed, the stable tree must be delta_hashed and ++ * re-structured. We use two set of below structs to speed up the ++ * re-structuring of stable tree. ++ */ ++static struct list_head ++stable_tree_node_list[2] = {LIST_HEAD_INIT(stable_tree_node_list[0]), ++ LIST_HEAD_INIT(stable_tree_node_list[1])}; ++ ++static struct list_head *stable_tree_node_listp = &stable_tree_node_list[0]; ++static struct rb_root root_stable_tree[2] = {RB_ROOT, RB_ROOT}; ++static struct rb_root *root_stable_treep = &root_stable_tree[0]; ++static unsigned long stable_tree_index; ++ ++/* The hash strength needed to hash a full page */ ++#define HASH_STRENGTH_FULL (PAGE_SIZE / sizeof(u32)) ++ ++/* The hash strength needed for loop-back hashing */ ++#define HASH_STRENGTH_MAX (HASH_STRENGTH_FULL + 10) ++ ++/* The random offsets in a page */ ++static u32 *random_nums; ++ ++/* The hash strength */ ++static unsigned long hash_strength = HASH_STRENGTH_FULL >> 4; ++ ++/* The delta value each time the hash strength increases or decreases */ ++static unsigned long hash_strength_delta; ++#define HASH_STRENGTH_DELTA_MAX 5 ++ ++/* The time we have saved due to random_sample_hash */ ++static u64 rshash_pos; ++ ++/* The time we have wasted due to hash collision */ ++static u64 rshash_neg; ++ ++struct uksm_benefit { ++ u64 pos; ++ u64 neg; ++ u64 scanned; ++ unsigned long base; ++} benefit; ++ ++/* ++ * The relative cost of memcmp, compared to 1 time unit of random sample ++ * hash, this value is tested when ksm module is initialized ++ */ ++static unsigned long memcmp_cost; ++ ++static unsigned long rshash_neg_cont_zero; ++static unsigned long rshash_cont_obscure; ++ ++/* The possible states of hash strength adjustment heuristic */ ++enum rshash_states { ++ RSHASH_STILL, ++ RSHASH_TRYUP, ++ RSHASH_TRYDOWN, ++ RSHASH_NEW, ++ RSHASH_PRE_STILL, ++}; ++ ++/* The possible direction we are about to adjust hash strength */ ++enum rshash_direct { ++ GO_UP, ++ GO_DOWN, ++ OBSCURE, ++ STILL, ++}; ++ ++/* random sampling hash state machine */ ++static struct { ++ enum rshash_states state; ++ enum rshash_direct pre_direct; ++ u8 below_count; ++ /* Keep a lookup window of size 5, iff above_count/below_count > 3 ++ * in this window we stop trying. ++ */ ++ u8 lookup_window_index; ++ u64 stable_benefit; ++ unsigned long turn_point_down; ++ unsigned long turn_benefit_down; ++ unsigned long turn_point_up; ++ unsigned long turn_benefit_up; ++ unsigned long stable_point; ++} rshash_state; ++ ++/*zero page hash table, hash_strength [0 ~ HASH_STRENGTH_MAX]*/ ++static u32 *zero_hash_table; ++ ++static inline struct node_vma *alloc_node_vma(void) ++{ ++ struct node_vma *node_vma; ++ ++ node_vma = kmem_cache_zalloc(node_vma_cache, GFP_KERNEL | ++ __GFP_NORETRY | __GFP_NOWARN); ++ if (node_vma) { ++ INIT_HLIST_HEAD(&node_vma->rmap_hlist); ++ INIT_HLIST_NODE(&node_vma->hlist); ++ } ++ return node_vma; ++} ++ ++static inline void free_node_vma(struct node_vma *node_vma) ++{ ++ kmem_cache_free(node_vma_cache, node_vma); ++} ++ ++ ++static inline struct vma_slot *alloc_vma_slot(void) ++{ ++ struct vma_slot *slot; ++ ++ /* ++ * In case ksm is not initialized by now. ++ * Oops, we need to consider the call site of uksm_init() in the future. ++ */ ++ if (!vma_slot_cache) ++ return NULL; ++ ++ slot = kmem_cache_zalloc(vma_slot_cache, GFP_KERNEL | ++ __GFP_NORETRY | __GFP_NOWARN); ++ if (slot) { ++ INIT_LIST_HEAD(&slot->slot_list); ++ INIT_LIST_HEAD(&slot->dedup_list); ++ slot->flags |= UKSM_SLOT_NEED_RERAND; ++ } ++ return slot; ++} ++ ++static inline void free_vma_slot(struct vma_slot *vma_slot) ++{ ++ kmem_cache_free(vma_slot_cache, vma_slot); ++} ++ ++ ++ ++static inline struct rmap_item *alloc_rmap_item(void) ++{ ++ struct rmap_item *rmap_item; ++ ++ rmap_item = kmem_cache_zalloc(rmap_item_cache, GFP_KERNEL | ++ __GFP_NORETRY | __GFP_NOWARN); ++ if (rmap_item) { ++ /* bug on lowest bit is not clear for flag use */ ++ BUG_ON(is_addr(rmap_item)); ++ } ++ return rmap_item; ++} ++ ++static inline void free_rmap_item(struct rmap_item *rmap_item) ++{ ++ rmap_item->slot = NULL; /* debug safety */ ++ kmem_cache_free(rmap_item_cache, rmap_item); ++} ++ ++static inline struct stable_node *alloc_stable_node(void) ++{ ++ struct stable_node *node; ++ ++ node = kmem_cache_alloc(stable_node_cache, GFP_KERNEL | ++ __GFP_NORETRY | __GFP_NOWARN); ++ if (!node) ++ return NULL; ++ ++ INIT_HLIST_HEAD(&node->hlist); ++ list_add(&node->all_list, &stable_node_list); ++ return node; ++} ++ ++static inline void free_stable_node(struct stable_node *stable_node) ++{ ++ list_del(&stable_node->all_list); ++ kmem_cache_free(stable_node_cache, stable_node); ++} ++ ++static inline struct tree_node *alloc_tree_node(struct list_head *list) ++{ ++ struct tree_node *node; ++ ++ node = kmem_cache_zalloc(tree_node_cache, GFP_KERNEL | ++ __GFP_NORETRY | __GFP_NOWARN); ++ if (!node) ++ return NULL; ++ ++ list_add(&node->all_list, list); ++ return node; ++} ++ ++static inline void free_tree_node(struct tree_node *node) ++{ ++ list_del(&node->all_list); ++ kmem_cache_free(tree_node_cache, node); ++} ++ ++static void uksm_drop_anon_vma(struct rmap_item *rmap_item) ++{ ++ struct anon_vma *anon_vma = rmap_item->anon_vma; ++ ++ put_anon_vma(anon_vma); ++} ++ ++ ++/** ++ * Remove a stable node from stable_tree, may unlink from its tree_node and ++ * may remove its parent tree_node if no other stable node is pending. ++ * ++ * @stable_node The node need to be removed ++ * @unlink_rb Will this node be unlinked from the rbtree? ++ * @remove_tree_ node Will its tree_node be removed if empty? ++ */ ++static void remove_node_from_stable_tree(struct stable_node *stable_node, ++ int unlink_rb, int remove_tree_node) ++{ ++ struct node_vma *node_vma; ++ struct rmap_item *rmap_item; ++ struct hlist_node *n; ++ ++ if (!hlist_empty(&stable_node->hlist)) { ++ hlist_for_each_entry_safe(node_vma, n, ++ &stable_node->hlist, hlist) { ++ hlist_for_each_entry(rmap_item, &node_vma->rmap_hlist, hlist) { ++ uksm_pages_sharing--; ++ ++ uksm_drop_anon_vma(rmap_item); ++ rmap_item->address &= PAGE_MASK; ++ } ++ free_node_vma(node_vma); ++ cond_resched(); ++ } ++ ++ /* the last one is counted as shared */ ++ uksm_pages_shared--; ++ uksm_pages_sharing++; ++ } ++ ++ if (stable_node->tree_node && unlink_rb) { ++ rb_erase(&stable_node->node, ++ &stable_node->tree_node->sub_root); ++ ++ if (RB_EMPTY_ROOT(&stable_node->tree_node->sub_root) && ++ remove_tree_node) { ++ rb_erase(&stable_node->tree_node->node, ++ root_stable_treep); ++ free_tree_node(stable_node->tree_node); ++ } else { ++ stable_node->tree_node->count--; ++ } ++ } ++ ++ free_stable_node(stable_node); ++} ++ ++ ++/* ++ * get_uksm_page: checks if the page indicated by the stable node ++ * is still its ksm page, despite having held no reference to it. ++ * In which case we can trust the content of the page, and it ++ * returns the gotten page; but if the page has now been zapped, ++ * remove the stale node from the stable tree and return NULL. ++ * ++ * You would expect the stable_node to hold a reference to the ksm page. ++ * But if it increments the page's count, swapping out has to wait for ++ * ksmd to come around again before it can free the page, which may take ++ * seconds or even minutes: much too unresponsive. So instead we use a ++ * "keyhole reference": access to the ksm page from the stable node peeps ++ * out through its keyhole to see if that page still holds the right key, ++ * pointing back to this stable node. This relies on freeing a PageAnon ++ * page to reset its page->mapping to NULL, and relies on no other use of ++ * a page to put something that might look like our key in page->mapping. ++ * ++ * include/linux/pagemap.h page_cache_get_speculative() is a good reference, ++ * but this is different - made simpler by uksm_thread_mutex being held, but ++ * interesting for assuming that no other use of the struct page could ever ++ * put our expected_mapping into page->mapping (or a field of the union which ++ * coincides with page->mapping). The RCU calls are not for KSM at all, but ++ * to keep the page_count protocol described with page_cache_get_speculative. ++ * ++ * Note: it is possible that get_uksm_page() will return NULL one moment, ++ * then page the next, if the page is in between page_freeze_refs() and ++ * page_unfreeze_refs(): this shouldn't be a problem anywhere, the page ++ * is on its way to being freed; but it is an anomaly to bear in mind. ++ * ++ * @unlink_rb: if the removal of this node will firstly unlink from ++ * its rbtree. stable_node_reinsert will prevent this when restructuring the ++ * node from its old tree. ++ * ++ * @remove_tree_node: if this is the last one of its tree_node, will the ++ * tree_node be freed ? If we are inserting stable node, this tree_node may ++ * be reused, so don't free it. ++ */ ++static struct page *get_uksm_page(struct stable_node *stable_node, ++ int unlink_rb, int remove_tree_node) ++{ ++ struct page *page; ++ void *expected_mapping; ++ unsigned long kpfn; ++ ++ expected_mapping = (void *)((unsigned long)stable_node | ++ PAGE_MAPPING_KSM); ++again: ++ kpfn = READ_ONCE(stable_node->kpfn); ++ page = pfn_to_page(kpfn); ++ ++ /* ++ * page is computed from kpfn, so on most architectures reading ++ * page->mapping is naturally ordered after reading node->kpfn, ++ * but on Alpha we need to be more careful. ++ */ ++ smp_read_barrier_depends(); ++ ++ if (READ_ONCE(page->mapping) != expected_mapping) ++ goto stale; ++ ++ /* ++ * We cannot do anything with the page while its refcount is 0. ++ * Usually 0 means free, or tail of a higher-order page: in which ++ * case this node is no longer referenced, and should be freed; ++ * however, it might mean that the page is under page_freeze_refs(). ++ * The __remove_mapping() case is easy, again the node is now stale; ++ * but if page is swapcache in migrate_page_move_mapping(), it might ++ * still be our page, in which case it's essential to keep the node. ++ */ ++ while (!get_page_unless_zero(page)) { ++ /* ++ * Another check for page->mapping != expected_mapping would ++ * work here too. We have chosen the !PageSwapCache test to ++ * optimize the common case, when the page is or is about to ++ * be freed: PageSwapCache is cleared (under spin_lock_irq) ++ * in the freeze_refs section of __remove_mapping(); but Anon ++ * page->mapping reset to NULL later, in free_pages_prepare(). ++ */ ++ if (!PageSwapCache(page)) ++ goto stale; ++ cpu_relax(); ++ } ++ ++ if (READ_ONCE(page->mapping) != expected_mapping) { ++ put_page(page); ++ goto stale; ++ } ++ ++ lock_page(page); ++ if (READ_ONCE(page->mapping) != expected_mapping) { ++ unlock_page(page); ++ put_page(page); ++ goto stale; ++ } ++ unlock_page(page); ++ return page; ++stale: ++ /* ++ * We come here from above when page->mapping or !PageSwapCache ++ * suggests that the node is stale; but it might be under migration. ++ * We need smp_rmb(), matching the smp_wmb() in ksm_migrate_page(), ++ * before checking whether node->kpfn has been changed. ++ */ ++ smp_rmb(); ++ if (stable_node->kpfn != kpfn) ++ goto again; ++ ++ remove_node_from_stable_tree(stable_node, unlink_rb, remove_tree_node); ++ ++ return NULL; ++} ++ ++/* ++ * Removing rmap_item from stable or unstable tree. ++ * This function will clean the information from the stable/unstable tree. ++ */ ++static inline void remove_rmap_item_from_tree(struct rmap_item *rmap_item) ++{ ++ if (rmap_item->address & STABLE_FLAG) { ++ struct stable_node *stable_node; ++ struct node_vma *node_vma; ++ struct page *page; ++ ++ node_vma = rmap_item->head; ++ stable_node = node_vma->head; ++ page = get_uksm_page(stable_node, 1, 1); ++ if (!page) ++ goto out; ++ ++ /* ++ * page lock is needed because it's racing with ++ * try_to_unmap_ksm(), etc. ++ */ ++ lock_page(page); ++ hlist_del(&rmap_item->hlist); ++ ++ if (hlist_empty(&node_vma->rmap_hlist)) { ++ hlist_del(&node_vma->hlist); ++ free_node_vma(node_vma); ++ } ++ unlock_page(page); ++ ++ put_page(page); ++ if (hlist_empty(&stable_node->hlist)) { ++ /* do NOT call remove_node_from_stable_tree() here, ++ * it's possible for a forked rmap_item not in ++ * stable tree while the in-tree rmap_items were ++ * deleted. ++ */ ++ uksm_pages_shared--; ++ } else ++ uksm_pages_sharing--; ++ ++ ++ uksm_drop_anon_vma(rmap_item); ++ } else if (rmap_item->address & UNSTABLE_FLAG) { ++ if (rmap_item->hash_round == uksm_hash_round) { ++ ++ rb_erase(&rmap_item->node, ++ &rmap_item->tree_node->sub_root); ++ if (RB_EMPTY_ROOT(&rmap_item->tree_node->sub_root)) { ++ rb_erase(&rmap_item->tree_node->node, ++ &root_unstable_tree); ++ ++ free_tree_node(rmap_item->tree_node); ++ } else ++ rmap_item->tree_node->count--; ++ } ++ uksm_pages_unshared--; ++ } ++ ++ rmap_item->address &= PAGE_MASK; ++ rmap_item->hash_max = 0; ++ ++out: ++ cond_resched(); /* we're called from many long loops */ ++} ++ ++static inline int slot_in_uksm(struct vma_slot *slot) ++{ ++ return list_empty(&slot->slot_list); ++} ++ ++/* ++ * Test if the mm is exiting ++ */ ++static inline bool uksm_test_exit(struct mm_struct *mm) ++{ ++ return atomic_read(&mm->mm_users) == 0; ++} ++ ++static inline unsigned long vma_pool_size(struct vma_slot *slot) ++{ ++ return round_up(sizeof(struct rmap_list_entry) * slot->pages, ++ PAGE_SIZE) >> PAGE_SHIFT; ++} ++ ++#define CAN_OVERFLOW_U64(x, delta) (U64_MAX - (x) < (delta)) ++ ++/* must be done with sem locked */ ++static int slot_pool_alloc(struct vma_slot *slot) ++{ ++ unsigned long pool_size; ++ ++ if (slot->rmap_list_pool) ++ return 0; ++ ++ pool_size = vma_pool_size(slot); ++ slot->rmap_list_pool = kcalloc(pool_size, sizeof(struct page *), ++ GFP_KERNEL); ++ if (!slot->rmap_list_pool) ++ return -ENOMEM; ++ ++ slot->pool_counts = kcalloc(pool_size, sizeof(unsigned int), ++ GFP_KERNEL); ++ if (!slot->pool_counts) { ++ kfree(slot->rmap_list_pool); ++ return -ENOMEM; ++ } ++ ++ slot->pool_size = pool_size; ++ BUG_ON(CAN_OVERFLOW_U64(uksm_pages_total, slot->pages)); ++ slot->flags |= UKSM_SLOT_IN_UKSM; ++ uksm_pages_total += slot->pages; ++ ++ return 0; ++} ++ ++/* ++ * Called after vma is unlinked from its mm ++ */ ++void uksm_remove_vma(struct vm_area_struct *vma) ++{ ++ struct vma_slot *slot; ++ ++ if (!vma->uksm_vma_slot) ++ return; ++ ++ spin_lock(&vma_slot_list_lock); ++ slot = vma->uksm_vma_slot; ++ if (!slot) ++ goto out; ++ ++ if (slot_in_uksm(slot)) { ++ /** ++ * This slot has been added by ksmd, so move to the del list ++ * waiting ksmd to free it. ++ */ ++ list_add_tail(&slot->slot_list, &vma_slot_del); ++ } else { ++ /** ++ * It's still on new list. It's ok to free slot directly. ++ */ ++ list_del(&slot->slot_list); ++ free_vma_slot(slot); ++ } ++out: ++ vma->uksm_vma_slot = NULL; ++ spin_unlock(&vma_slot_list_lock); ++} ++ ++/** ++ * Need to do two things: ++ * 1. check if slot was moved to del list ++ * 2. make sure the mmap_sem is manipulated under valid vma. ++ * ++ * My concern here is that in some cases, this may make ++ * vma_slot_list_lock() waiters to serialized further by some ++ * sem->wait_lock, can this really be expensive? ++ * ++ * ++ * @return ++ * 0: if successfully locked mmap_sem ++ * -ENOENT: this slot was moved to del list ++ * -EBUSY: vma lock failed ++ */ ++static int try_down_read_slot_mmap_sem(struct vma_slot *slot) ++{ ++ struct vm_area_struct *vma; ++ struct mm_struct *mm; ++ struct rw_semaphore *sem; ++ ++ spin_lock(&vma_slot_list_lock); ++ ++ /* the slot_list was removed and inited from new list, when it enters ++ * uksm_list. If now it's not empty, then it must be moved to del list ++ */ ++ if (!slot_in_uksm(slot)) { ++ spin_unlock(&vma_slot_list_lock); ++ return -ENOENT; ++ } ++ ++ BUG_ON(slot->pages != vma_pages(slot->vma)); ++ /* Ok, vma still valid */ ++ vma = slot->vma; ++ mm = vma->vm_mm; ++ sem = &mm->mmap_sem; ++ ++ if (uksm_test_exit(mm)) { ++ spin_unlock(&vma_slot_list_lock); ++ return -ENOENT; ++ } ++ ++ if (down_read_trylock(sem)) { ++ spin_unlock(&vma_slot_list_lock); ++ if (slot_pool_alloc(slot)) { ++ uksm_remove_vma(vma); ++ up_read(sem); ++ return -ENOENT; ++ } ++ return 0; ++ } ++ ++ spin_unlock(&vma_slot_list_lock); ++ return -EBUSY; ++} ++ ++static inline unsigned long ++vma_page_address(struct page *page, struct vm_area_struct *vma) ++{ ++ pgoff_t pgoff = page->index; ++ unsigned long address; ++ ++ address = vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT); ++ if (unlikely(address < vma->vm_start || address >= vma->vm_end)) { ++ /* page should be within @vma mapping range */ ++ return -EFAULT; ++ } ++ return address; ++} ++ ++ ++/* return 0 on success with the item's mmap_sem locked */ ++static inline int get_mergeable_page_lock_mmap(struct rmap_item *item) ++{ ++ struct mm_struct *mm; ++ struct vma_slot *slot = item->slot; ++ int err = -EINVAL; ++ ++ struct page *page; ++ ++ /* ++ * try_down_read_slot_mmap_sem() returns non-zero if the slot ++ * has been removed by uksm_remove_vma(). ++ */ ++ if (try_down_read_slot_mmap_sem(slot)) ++ return -EBUSY; ++ ++ mm = slot->vma->vm_mm; ++ ++ if (uksm_test_exit(mm)) ++ goto failout_up; ++ ++ page = item->page; ++ rcu_read_lock(); ++ if (!get_page_unless_zero(page)) { ++ rcu_read_unlock(); ++ goto failout_up; ++ } ++ ++ /* No need to consider huge page here. */ ++ if (item->slot->vma->anon_vma != page_anon_vma(page) || ++ vma_page_address(page, item->slot->vma) != get_rmap_addr(item)) { ++ /* ++ * TODO: ++ * should we release this item becase of its stale page ++ * mapping? ++ */ ++ put_page(page); ++ rcu_read_unlock(); ++ goto failout_up; ++ } ++ rcu_read_unlock(); ++ return 0; ++ ++failout_up: ++ up_read(&mm->mmap_sem); ++ return err; ++} ++ ++/* ++ * What kind of VMA is considered ? ++ */ ++static inline int vma_can_enter(struct vm_area_struct *vma) ++{ ++ return uksm_flags_can_scan(vma->vm_flags); ++} ++ ++/* ++ * Called whenever a fresh new vma is created A new vma_slot. ++ * is created and inserted into a global list Must be called. ++ * after vma is inserted to its mm. ++ */ ++void uksm_vma_add_new(struct vm_area_struct *vma) ++{ ++ struct vma_slot *slot; ++ ++ if (!vma_can_enter(vma)) { ++ vma->uksm_vma_slot = NULL; ++ return; ++ } ++ ++ slot = alloc_vma_slot(); ++ if (!slot) { ++ vma->uksm_vma_slot = NULL; ++ return; ++ } ++ ++ vma->uksm_vma_slot = slot; ++ vma->vm_flags |= VM_MERGEABLE; ++ slot->vma = vma; ++ slot->mm = vma->vm_mm; ++ slot->ctime_j = jiffies; ++ slot->pages = vma_pages(vma); ++ spin_lock(&vma_slot_list_lock); ++ list_add_tail(&slot->slot_list, &vma_slot_new); ++ spin_unlock(&vma_slot_list_lock); ++} ++ ++/* 32/3 < they < 32/2 */ ++#define shiftl 8 ++#define shiftr 12 ++ ++#define HASH_FROM_TO(from, to) \ ++for (index = from; index < to; index++) { \ ++ pos = random_nums[index]; \ ++ hash += key[pos]; \ ++ hash += (hash << shiftl); \ ++ hash ^= (hash >> shiftr); \ ++} ++ ++ ++#define HASH_FROM_DOWN_TO(from, to) \ ++for (index = from - 1; index >= to; index--) { \ ++ hash ^= (hash >> shiftr); \ ++ hash ^= (hash >> (shiftr*2)); \ ++ hash -= (hash << shiftl); \ ++ hash += (hash << (shiftl*2)); \ ++ pos = random_nums[index]; \ ++ hash -= key[pos]; \ ++} ++ ++/* ++ * The main random sample hash function. ++ */ ++static u32 random_sample_hash(void *addr, u32 hash_strength) ++{ ++ u32 hash = 0xdeadbeef; ++ int index, pos, loop = hash_strength; ++ u32 *key = (u32 *)addr; ++ ++ if (loop > HASH_STRENGTH_FULL) ++ loop = HASH_STRENGTH_FULL; ++ ++ HASH_FROM_TO(0, loop); ++ ++ if (hash_strength > HASH_STRENGTH_FULL) { ++ loop = hash_strength - HASH_STRENGTH_FULL; ++ HASH_FROM_TO(0, loop); ++ } ++ ++ return hash; ++} ++ ++ ++/** ++ * It's used when hash strength is adjusted ++ * ++ * @addr The page's virtual address ++ * @from The original hash strength ++ * @to The hash strength changed to ++ * @hash The hash value generated with "from" hash value ++ * ++ * return the hash value ++ */ ++static u32 delta_hash(void *addr, int from, int to, u32 hash) ++{ ++ u32 *key = (u32 *)addr; ++ int index, pos; /* make sure they are int type */ ++ ++ if (to > from) { ++ if (from >= HASH_STRENGTH_FULL) { ++ from -= HASH_STRENGTH_FULL; ++ to -= HASH_STRENGTH_FULL; ++ HASH_FROM_TO(from, to); ++ } else if (to <= HASH_STRENGTH_FULL) { ++ HASH_FROM_TO(from, to); ++ } else { ++ HASH_FROM_TO(from, HASH_STRENGTH_FULL); ++ HASH_FROM_TO(0, to - HASH_STRENGTH_FULL); ++ } ++ } else { ++ if (from <= HASH_STRENGTH_FULL) { ++ HASH_FROM_DOWN_TO(from, to); ++ } else if (to >= HASH_STRENGTH_FULL) { ++ from -= HASH_STRENGTH_FULL; ++ to -= HASH_STRENGTH_FULL; ++ HASH_FROM_DOWN_TO(from, to); ++ } else { ++ HASH_FROM_DOWN_TO(from - HASH_STRENGTH_FULL, 0); ++ HASH_FROM_DOWN_TO(HASH_STRENGTH_FULL, to); ++ } ++ } ++ ++ return hash; ++} ++ ++/** ++ * ++ * Called when: rshash_pos or rshash_neg is about to overflow or a scan round ++ * has finished. ++ * ++ * return 0 if no page has been scanned since last call, 1 otherwise. ++ */ ++static inline int encode_benefit(void) ++{ ++ u64 scanned_delta, pos_delta, neg_delta; ++ unsigned long base = benefit.base; ++ ++ scanned_delta = uksm_pages_scanned - uksm_pages_scanned_last; ++ ++ if (!scanned_delta) ++ return 0; ++ ++ scanned_delta >>= base; ++ pos_delta = rshash_pos >> base; ++ neg_delta = rshash_neg >> base; ++ ++ if (CAN_OVERFLOW_U64(benefit.pos, pos_delta) || ++ CAN_OVERFLOW_U64(benefit.neg, neg_delta) || ++ CAN_OVERFLOW_U64(benefit.scanned, scanned_delta)) { ++ benefit.scanned >>= 1; ++ benefit.neg >>= 1; ++ benefit.pos >>= 1; ++ benefit.base++; ++ scanned_delta >>= 1; ++ pos_delta >>= 1; ++ neg_delta >>= 1; ++ } ++ ++ benefit.pos += pos_delta; ++ benefit.neg += neg_delta; ++ benefit.scanned += scanned_delta; ++ ++ BUG_ON(!benefit.scanned); ++ ++ rshash_pos = rshash_neg = 0; ++ uksm_pages_scanned_last = uksm_pages_scanned; ++ ++ return 1; ++} ++ ++static inline void reset_benefit(void) ++{ ++ benefit.pos = 0; ++ benefit.neg = 0; ++ benefit.base = 0; ++ benefit.scanned = 0; ++} ++ ++static inline void inc_rshash_pos(unsigned long delta) ++{ ++ if (CAN_OVERFLOW_U64(rshash_pos, delta)) ++ encode_benefit(); ++ ++ rshash_pos += delta; ++} ++ ++static inline void inc_rshash_neg(unsigned long delta) ++{ ++ if (CAN_OVERFLOW_U64(rshash_neg, delta)) ++ encode_benefit(); ++ ++ rshash_neg += delta; ++} ++ ++ ++static inline u32 page_hash(struct page *page, unsigned long hash_strength, ++ int cost_accounting) ++{ ++ u32 val; ++ unsigned long delta; ++ ++ void *addr = kmap_atomic(page); ++ ++ val = random_sample_hash(addr, hash_strength); ++ kunmap_atomic(addr); ++ ++ if (cost_accounting) { ++ if (hash_strength < HASH_STRENGTH_FULL) ++ delta = HASH_STRENGTH_FULL - hash_strength; ++ else ++ delta = 0; ++ ++ inc_rshash_pos(delta); ++ } ++ ++ return val; ++} ++ ++static int memcmp_pages_with_cost(struct page *page1, struct page *page2, ++ int cost_accounting) ++{ ++ char *addr1, *addr2; ++ int ret; ++ ++ addr1 = kmap_atomic(page1); ++ addr2 = kmap_atomic(page2); ++ ret = memcmp(addr1, addr2, PAGE_SIZE); ++ kunmap_atomic(addr2); ++ kunmap_atomic(addr1); ++ ++ if (cost_accounting) ++ inc_rshash_neg(memcmp_cost); ++ ++ return ret; ++} ++ ++static inline int pages_identical_with_cost(struct page *page1, struct page *page2) ++{ ++ return !memcmp_pages_with_cost(page1, page2, 0); ++} ++ ++static inline int is_page_full_zero(struct page *page) ++{ ++ char *addr; ++ int ret; ++ ++ addr = kmap_atomic(page); ++ ret = is_full_zero(addr, PAGE_SIZE); ++ kunmap_atomic(addr); ++ ++ return ret; ++} ++ ++static int write_protect_page(struct vm_area_struct *vma, struct page *page, ++ pte_t *orig_pte, pte_t *old_pte) ++{ ++ struct mm_struct *mm = vma->vm_mm; ++ struct page_vma_mapped_walk pvmw = { ++ .page = page, ++ .vma = vma, ++ }; ++ struct mmu_notifier_range range; ++ int swapped; ++ int err = -EFAULT; ++ ++ pvmw.address = page_address_in_vma(page, vma); ++ if (pvmw.address == -EFAULT) ++ goto out; ++ ++ BUG_ON(PageTransCompound(page)); ++ ++ mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, mm, pvmw.address, ++ pvmw.address + PAGE_SIZE); ++ mmu_notifier_invalidate_range_start(&range); ++ ++ if (!page_vma_mapped_walk(&pvmw)) ++ goto out_mn; ++ if (WARN_ONCE(!pvmw.pte, "Unexpected PMD mapping?")) ++ goto out_unlock; ++ ++ if (old_pte) ++ *old_pte = *pvmw.pte; ++ ++ if (pte_write(*pvmw.pte) || pte_dirty(*pvmw.pte) || ++ (pte_protnone(*pvmw.pte) && pte_savedwrite(*pvmw.pte)) || mm_tlb_flush_pending(mm)) { ++ pte_t entry; ++ ++ swapped = PageSwapCache(page); ++ flush_cache_page(vma, pvmw.address, page_to_pfn(page)); ++ /* ++ * Ok this is tricky, when get_user_pages_fast() run it doesn't ++ * take any lock, therefore the check that we are going to make ++ * with the pagecount against the mapcount is racey and ++ * O_DIRECT can happen right after the check. ++ * So we clear the pte and flush the tlb before the check ++ * this assure us that no O_DIRECT can happen after the check ++ * or in the middle of the check. ++ */ ++ entry = ptep_clear_flush_notify(vma, pvmw.address, pvmw.pte); ++ /* ++ * Check that no O_DIRECT or similar I/O is in progress on the ++ * page ++ */ ++ if (page_mapcount(page) + 1 + swapped != page_count(page)) { ++ set_pte_at(mm, pvmw.address, pvmw.pte, entry); ++ goto out_unlock; ++ } ++ if (pte_dirty(entry)) ++ set_page_dirty(page); ++ ++ if (pte_protnone(entry)) ++ entry = pte_mkclean(pte_clear_savedwrite(entry)); ++ else ++ entry = pte_mkclean(pte_wrprotect(entry)); ++ ++ set_pte_at_notify(mm, pvmw.address, pvmw.pte, entry); ++ } ++ *orig_pte = *pvmw.pte; ++ err = 0; ++ ++out_unlock: ++ page_vma_mapped_walk_done(&pvmw); ++out_mn: ++ mmu_notifier_invalidate_range_end(&range); ++out: ++ return err; ++} ++ ++#define MERGE_ERR_PGERR 1 /* the page is invalid cannot continue */ ++#define MERGE_ERR_COLLI 2 /* there is a collision */ ++#define MERGE_ERR_COLLI_MAX 3 /* collision at the max hash strength */ ++#define MERGE_ERR_CHANGED 4 /* the page has changed since last hash */ ++ ++ ++/** ++ * replace_page - replace page in vma by new ksm page ++ * @vma: vma that holds the pte pointing to page ++ * @page: the page we are replacing by kpage ++ * @kpage: the ksm page we replace page by ++ * @orig_pte: the original value of the pte ++ * ++ * Returns 0 on success, MERGE_ERR_PGERR on failure. ++ */ ++static int replace_page(struct vm_area_struct *vma, struct page *page, ++ struct page *kpage, pte_t orig_pte) ++{ ++ struct mm_struct *mm = vma->vm_mm; ++ struct mmu_notifier_range range; ++ pgd_t *pgd; ++ p4d_t *p4d; ++ pud_t *pud; ++ pmd_t *pmd; ++ pte_t *ptep; ++ spinlock_t *ptl; ++ pte_t entry; ++ ++ unsigned long addr; ++ int err = MERGE_ERR_PGERR; ++ ++ addr = page_address_in_vma(page, vma); ++ if (addr == -EFAULT) ++ goto out; ++ ++ pgd = pgd_offset(mm, addr); ++ if (!pgd_present(*pgd)) ++ goto out; ++ ++ p4d = p4d_offset(pgd, addr); ++ pud = pud_offset(p4d, addr); ++ if (!pud_present(*pud)) ++ goto out; ++ ++ pmd = pmd_offset(pud, addr); ++ BUG_ON(pmd_trans_huge(*pmd)); ++ if (!pmd_present(*pmd)) ++ goto out; ++ ++ mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, mm, addr, ++ addr + PAGE_SIZE); ++ mmu_notifier_invalidate_range_start(&range); ++ ++ ptep = pte_offset_map_lock(mm, pmd, addr, &ptl); ++ if (!pte_same(*ptep, orig_pte)) { ++ pte_unmap_unlock(ptep, ptl); ++ goto out_mn; ++ } ++ ++ flush_cache_page(vma, addr, pte_pfn(*ptep)); ++ ptep_clear_flush_notify(vma, addr, ptep); ++ entry = mk_pte(kpage, vma->vm_page_prot); ++ ++ /* special treatment is needed for zero_page */ ++ if ((page_to_pfn(kpage) == uksm_zero_pfn) || ++ (page_to_pfn(kpage) == zero_pfn)) { ++ entry = pte_mkspecial(entry); ++ dec_mm_counter(mm, MM_ANONPAGES); ++ inc_zone_page_state(page, NR_UKSM_ZERO_PAGES); ++ } else { ++ get_page(kpage); ++ page_add_anon_rmap(kpage, vma, addr, false); ++ } ++ ++ set_pte_at_notify(mm, addr, ptep, entry); ++ ++ page_remove_rmap(page, false); ++ if (!page_mapped(page)) ++ try_to_free_swap(page); ++ put_page(page); ++ ++ pte_unmap_unlock(ptep, ptl); ++ err = 0; ++out_mn: ++ mmu_notifier_invalidate_range_end(&range); ++out: ++ return err; ++} ++ ++ ++/** ++ * Fully hash a page with HASH_STRENGTH_MAX return a non-zero hash value. The ++ * zero hash value at HASH_STRENGTH_MAX is used to indicated that its ++ * hash_max member has not been calculated. ++ * ++ * @page The page needs to be hashed ++ * @hash_old The hash value calculated with current hash strength ++ * ++ * return the new hash value calculated at HASH_STRENGTH_MAX ++ */ ++static inline u32 page_hash_max(struct page *page, u32 hash_old) ++{ ++ u32 hash_max = 0; ++ void *addr; ++ ++ addr = kmap_atomic(page); ++ hash_max = delta_hash(addr, hash_strength, ++ HASH_STRENGTH_MAX, hash_old); ++ ++ kunmap_atomic(addr); ++ ++ if (!hash_max) ++ hash_max = 1; ++ ++ inc_rshash_neg(HASH_STRENGTH_MAX - hash_strength); ++ return hash_max; ++} ++ ++/* ++ * We compare the hash again, to ensure that it is really a hash collision ++ * instead of being caused by page write. ++ */ ++static inline int check_collision(struct rmap_item *rmap_item, ++ u32 hash) ++{ ++ int err; ++ struct page *page = rmap_item->page; ++ ++ /* if this rmap_item has already been hash_maxed, then the collision ++ * must appears in the second-level rbtree search. In this case we check ++ * if its hash_max value has been changed. Otherwise, the collision ++ * happens in the first-level rbtree search, so we check against it's ++ * current hash value. ++ */ ++ if (rmap_item->hash_max) { ++ inc_rshash_neg(memcmp_cost); ++ inc_rshash_neg(HASH_STRENGTH_MAX - hash_strength); ++ ++ if (rmap_item->hash_max == page_hash_max(page, hash)) ++ err = MERGE_ERR_COLLI; ++ else ++ err = MERGE_ERR_CHANGED; ++ } else { ++ inc_rshash_neg(memcmp_cost + hash_strength); ++ ++ if (page_hash(page, hash_strength, 0) == hash) ++ err = MERGE_ERR_COLLI; ++ else ++ err = MERGE_ERR_CHANGED; ++ } ++ ++ return err; ++} ++ ++/** ++ * Try to merge a rmap_item.page with a kpage in stable node. kpage must ++ * already be a ksm page. ++ * ++ * @return 0 if the pages were merged, -EFAULT otherwise. ++ */ ++static int try_to_merge_with_uksm_page(struct rmap_item *rmap_item, ++ struct page *kpage, u32 hash) ++{ ++ struct vm_area_struct *vma = rmap_item->slot->vma; ++ struct mm_struct *mm = vma->vm_mm; ++ pte_t orig_pte = __pte(0); ++ int err = MERGE_ERR_PGERR; ++ struct page *page; ++ ++ if (uksm_test_exit(mm)) ++ goto out; ++ ++ page = rmap_item->page; ++ ++ if (page == kpage) { /* ksm page forked */ ++ err = 0; ++ goto out; ++ } ++ ++ /* ++ * We need the page lock to read a stable PageSwapCache in ++ * write_protect_page(). We use trylock_page() instead of ++ * lock_page() because we don't want to wait here - we ++ * prefer to continue scanning and merging different pages, ++ * then come back to this page when it is unlocked. ++ */ ++ if (!trylock_page(page)) ++ goto out; ++ ++ if (!PageAnon(page) || !PageKsm(kpage)) ++ goto out_unlock; ++ ++ if (PageTransCompound(page)) { ++ err = split_huge_page(page); ++ if (err) ++ goto out_unlock; ++ } ++ ++ /* ++ * If this anonymous page is mapped only here, its pte may need ++ * to be write-protected. If it's mapped elsewhere, all of its ++ * ptes are necessarily already write-protected. But in either ++ * case, we need to lock and check page_count is not raised. ++ */ ++ if (write_protect_page(vma, page, &orig_pte, NULL) == 0) { ++ if (pages_identical_with_cost(page, kpage)) ++ err = replace_page(vma, page, kpage, orig_pte); ++ else ++ err = check_collision(rmap_item, hash); ++ } ++ ++ if ((vma->vm_flags & VM_LOCKED) && kpage && !err) { ++ munlock_vma_page(page); ++ if (!PageMlocked(kpage)) { ++ unlock_page(page); ++ lock_page(kpage); ++ mlock_vma_page(kpage); ++ page = kpage; /* for final unlock */ ++ } ++ } ++ ++out_unlock: ++ unlock_page(page); ++out: ++ return err; ++} ++ ++ ++ ++/** ++ * If two pages fail to merge in try_to_merge_two_pages, then we have a chance ++ * to restore a page mapping that has been changed in try_to_merge_two_pages. ++ * ++ * @return 0 on success. ++ */ ++static int restore_uksm_page_pte(struct vm_area_struct *vma, unsigned long addr, ++ pte_t orig_pte, pte_t wprt_pte) ++{ ++ struct mm_struct *mm = vma->vm_mm; ++ pgd_t *pgd; ++ p4d_t *p4d; ++ pud_t *pud; ++ pmd_t *pmd; ++ pte_t *ptep; ++ spinlock_t *ptl; ++ ++ int err = -EFAULT; ++ ++ pgd = pgd_offset(mm, addr); ++ if (!pgd_present(*pgd)) ++ goto out; ++ ++ p4d = p4d_offset(pgd, addr); ++ pud = pud_offset(p4d, addr); ++ if (!pud_present(*pud)) ++ goto out; ++ ++ pmd = pmd_offset(pud, addr); ++ if (!pmd_present(*pmd)) ++ goto out; ++ ++ ptep = pte_offset_map_lock(mm, pmd, addr, &ptl); ++ if (!pte_same(*ptep, wprt_pte)) { ++ /* already copied, let it be */ ++ pte_unmap_unlock(ptep, ptl); ++ goto out; ++ } ++ ++ /* ++ * Good boy, still here. When we still get the ksm page, it does not ++ * return to the free page pool, there is no way that a pte was changed ++ * to other page and gets back to this page. And remind that ksm page ++ * do not reuse in do_wp_page(). So it's safe to restore the original ++ * pte. ++ */ ++ flush_cache_page(vma, addr, pte_pfn(*ptep)); ++ ptep_clear_flush_notify(vma, addr, ptep); ++ set_pte_at_notify(mm, addr, ptep, orig_pte); ++ ++ pte_unmap_unlock(ptep, ptl); ++ err = 0; ++out: ++ return err; ++} ++ ++/** ++ * try_to_merge_two_pages() - take two identical pages and prepare ++ * them to be merged into one page(rmap_item->page) ++ * ++ * @return 0 if we successfully merged two identical pages into ++ * one ksm page. MERGE_ERR_COLLI if it's only a hash collision ++ * search in rbtree. MERGE_ERR_CHANGED if rmap_item has been ++ * changed since it's hashed. MERGE_ERR_PGERR otherwise. ++ * ++ */ ++static int try_to_merge_two_pages(struct rmap_item *rmap_item, ++ struct rmap_item *tree_rmap_item, ++ u32 hash) ++{ ++ pte_t orig_pte1 = __pte(0), orig_pte2 = __pte(0); ++ pte_t wprt_pte1 = __pte(0), wprt_pte2 = __pte(0); ++ struct vm_area_struct *vma1 = rmap_item->slot->vma; ++ struct vm_area_struct *vma2 = tree_rmap_item->slot->vma; ++ struct page *page = rmap_item->page; ++ struct page *tree_page = tree_rmap_item->page; ++ int err = MERGE_ERR_PGERR; ++ struct address_space *saved_mapping; ++ ++ ++ if (rmap_item->page == tree_rmap_item->page) ++ goto out; ++ ++ if (!trylock_page(page)) ++ goto out; ++ ++ if (!PageAnon(page)) ++ goto out_unlock; ++ ++ if (PageTransCompound(page)) { ++ err = split_huge_page(page); ++ if (err) ++ goto out_unlock; ++ } ++ ++ if (write_protect_page(vma1, page, &wprt_pte1, &orig_pte1) != 0) { ++ unlock_page(page); ++ goto out; ++ } ++ ++ /* ++ * While we hold page lock, upgrade page from ++ * PageAnon+anon_vma to PageKsm+NULL stable_node: ++ * stable_tree_insert() will update stable_node. ++ */ ++ saved_mapping = page->mapping; ++ set_page_stable_node(page, NULL); ++ mark_page_accessed(page); ++ if (!PageDirty(page)) ++ SetPageDirty(page); ++ ++ unlock_page(page); ++ ++ if (!trylock_page(tree_page)) ++ goto restore_out; ++ ++ if (!PageAnon(tree_page)) { ++ unlock_page(tree_page); ++ goto restore_out; ++ } ++ ++ if (PageTransCompound(tree_page)) { ++ err = split_huge_page(tree_page); ++ if (err) { ++ unlock_page(tree_page); ++ goto restore_out; ++ } ++ } ++ ++ if (write_protect_page(vma2, tree_page, &wprt_pte2, &orig_pte2) != 0) { ++ unlock_page(tree_page); ++ goto restore_out; ++ } ++ ++ if (pages_identical_with_cost(page, tree_page)) { ++ err = replace_page(vma2, tree_page, page, wprt_pte2); ++ if (err) { ++ unlock_page(tree_page); ++ goto restore_out; ++ } ++ ++ if ((vma2->vm_flags & VM_LOCKED)) { ++ munlock_vma_page(tree_page); ++ if (!PageMlocked(page)) { ++ unlock_page(tree_page); ++ lock_page(page); ++ mlock_vma_page(page); ++ tree_page = page; /* for final unlock */ ++ } ++ } ++ ++ unlock_page(tree_page); ++ ++ goto out; /* success */ ++ ++ } else { ++ if (tree_rmap_item->hash_max && ++ tree_rmap_item->hash_max == rmap_item->hash_max) { ++ err = MERGE_ERR_COLLI_MAX; ++ } else if (page_hash(page, hash_strength, 0) == ++ page_hash(tree_page, hash_strength, 0)) { ++ inc_rshash_neg(memcmp_cost + hash_strength * 2); ++ err = MERGE_ERR_COLLI; ++ } else { ++ err = MERGE_ERR_CHANGED; ++ } ++ ++ unlock_page(tree_page); ++ } ++ ++restore_out: ++ lock_page(page); ++ if (!restore_uksm_page_pte(vma1, get_rmap_addr(rmap_item), ++ orig_pte1, wprt_pte1)) ++ page->mapping = saved_mapping; ++ ++out_unlock: ++ unlock_page(page); ++out: ++ return err; ++} ++ ++static inline int hash_cmp(u32 new_val, u32 node_val) ++{ ++ if (new_val > node_val) ++ return 1; ++ else if (new_val < node_val) ++ return -1; ++ else ++ return 0; ++} ++ ++static inline u32 rmap_item_hash_max(struct rmap_item *item, u32 hash) ++{ ++ u32 hash_max = item->hash_max; ++ ++ if (!hash_max) { ++ hash_max = page_hash_max(item->page, hash); ++ ++ item->hash_max = hash_max; ++ } ++ ++ return hash_max; ++} ++ ++ ++ ++/** ++ * stable_tree_search() - search the stable tree for a page ++ * ++ * @item: the rmap_item we are comparing with ++ * @hash: the hash value of this item->page already calculated ++ * ++ * @return the page we have found, NULL otherwise. The page returned has ++ * been gotten. ++ */ ++static struct page *stable_tree_search(struct rmap_item *item, u32 hash) ++{ ++ struct rb_node *node = root_stable_treep->rb_node; ++ struct tree_node *tree_node; ++ unsigned long hash_max; ++ struct page *page = item->page; ++ struct stable_node *stable_node; ++ ++ stable_node = page_stable_node(page); ++ if (stable_node) { ++ /* ksm page forked, that is ++ * if (PageKsm(page) && !in_stable_tree(rmap_item)) ++ * it's actually gotten once outside. ++ */ ++ get_page(page); ++ return page; ++ } ++ ++ while (node) { ++ int cmp; ++ ++ tree_node = rb_entry(node, struct tree_node, node); ++ ++ cmp = hash_cmp(hash, tree_node->hash); ++ ++ if (cmp < 0) ++ node = node->rb_left; ++ else if (cmp > 0) ++ node = node->rb_right; ++ else ++ break; ++ } ++ ++ if (!node) ++ return NULL; ++ ++ if (tree_node->count == 1) { ++ stable_node = rb_entry(tree_node->sub_root.rb_node, ++ struct stable_node, node); ++ BUG_ON(!stable_node); ++ ++ goto get_page_out; ++ } ++ ++ /* ++ * ok, we have to search the second ++ * level subtree, hash the page to a ++ * full strength. ++ */ ++ node = tree_node->sub_root.rb_node; ++ BUG_ON(!node); ++ hash_max = rmap_item_hash_max(item, hash); ++ ++ while (node) { ++ int cmp; ++ ++ stable_node = rb_entry(node, struct stable_node, node); ++ ++ cmp = hash_cmp(hash_max, stable_node->hash_max); ++ ++ if (cmp < 0) ++ node = node->rb_left; ++ else if (cmp > 0) ++ node = node->rb_right; ++ else ++ goto get_page_out; ++ } ++ ++ return NULL; ++ ++get_page_out: ++ page = get_uksm_page(stable_node, 1, 1); ++ return page; ++} ++ ++static int try_merge_rmap_item(struct rmap_item *item, ++ struct page *kpage, ++ struct page *tree_page) ++{ ++ struct vm_area_struct *vma = item->slot->vma; ++ struct page_vma_mapped_walk pvmw = { ++ .page = kpage, ++ .vma = vma, ++ }; ++ ++ pvmw.address = get_rmap_addr(item); ++ if (!page_vma_mapped_walk(&pvmw)) ++ return 0; ++ ++ if (pte_write(*pvmw.pte)) { ++ /* has changed, abort! */ ++ page_vma_mapped_walk_done(&pvmw); ++ return 0; ++ } ++ ++ get_page(tree_page); ++ page_add_anon_rmap(tree_page, vma, pvmw.address, false); ++ ++ flush_cache_page(vma, pvmw.address, page_to_pfn(kpage)); ++ ptep_clear_flush_notify(vma, pvmw.address, pvmw.pte); ++ set_pte_at_notify(vma->vm_mm, pvmw.address, pvmw.pte, ++ mk_pte(tree_page, vma->vm_page_prot)); ++ ++ page_remove_rmap(kpage, false); ++ put_page(kpage); ++ ++ page_vma_mapped_walk_done(&pvmw); ++ ++ return 1; ++} ++ ++/** ++ * try_to_merge_with_stable_page() - when two rmap_items need to be inserted ++ * into stable tree, the page was found to be identical to a stable ksm page, ++ * this is the last chance we can merge them into one. ++ * ++ * @item1: the rmap_item holding the page which we wanted to insert ++ * into stable tree. ++ * @item2: the other rmap_item we found when unstable tree search ++ * @oldpage: the page currently mapped by the two rmap_items ++ * @tree_page: the page we found identical in stable tree node ++ * @success1: return if item1 is successfully merged ++ * @success2: return if item2 is successfully merged ++ */ ++static void try_merge_with_stable(struct rmap_item *item1, ++ struct rmap_item *item2, ++ struct page **kpage, ++ struct page *tree_page, ++ int *success1, int *success2) ++{ ++ struct vm_area_struct *vma1 = item1->slot->vma; ++ struct vm_area_struct *vma2 = item2->slot->vma; ++ *success1 = 0; ++ *success2 = 0; ++ ++ if (unlikely(*kpage == tree_page)) { ++ /* I don't think this can really happen */ ++ pr_warn("UKSM: unexpected condition detected in " ++ "%s -- *kpage == tree_page !\n", __func__); ++ *success1 = 1; ++ *success2 = 1; ++ return; ++ } ++ ++ if (!PageAnon(*kpage) || !PageKsm(*kpage)) ++ goto failed; ++ ++ if (!trylock_page(tree_page)) ++ goto failed; ++ ++ /* If the oldpage is still ksm and still pointed ++ * to in the right place, and still write protected, ++ * we are confident it's not changed, no need to ++ * memcmp anymore. ++ * be ware, we cannot take nested pte locks, ++ * deadlock risk. ++ */ ++ if (!try_merge_rmap_item(item1, *kpage, tree_page)) ++ goto unlock_failed; ++ ++ /* ok, then vma2, remind that pte1 already set */ ++ if (!try_merge_rmap_item(item2, *kpage, tree_page)) ++ goto success_1; ++ ++ *success2 = 1; ++success_1: ++ *success1 = 1; ++ ++ ++ if ((*success1 && vma1->vm_flags & VM_LOCKED) || ++ (*success2 && vma2->vm_flags & VM_LOCKED)) { ++ munlock_vma_page(*kpage); ++ if (!PageMlocked(tree_page)) ++ mlock_vma_page(tree_page); ++ } ++ ++ /* ++ * We do not need oldpage any more in the caller, so can break the lock ++ * now. ++ */ ++ unlock_page(*kpage); ++ *kpage = tree_page; /* Get unlocked outside. */ ++ return; ++ ++unlock_failed: ++ unlock_page(tree_page); ++failed: ++ return; ++} ++ ++static inline void stable_node_hash_max(struct stable_node *node, ++ struct page *page, u32 hash) ++{ ++ u32 hash_max = node->hash_max; ++ ++ if (!hash_max) { ++ hash_max = page_hash_max(page, hash); ++ node->hash_max = hash_max; ++ } ++} ++ ++static inline ++struct stable_node *new_stable_node(struct tree_node *tree_node, ++ struct page *kpage, u32 hash_max) ++{ ++ struct stable_node *new_stable_node; ++ ++ new_stable_node = alloc_stable_node(); ++ if (!new_stable_node) ++ return NULL; ++ ++ new_stable_node->kpfn = page_to_pfn(kpage); ++ new_stable_node->hash_max = hash_max; ++ new_stable_node->tree_node = tree_node; ++ set_page_stable_node(kpage, new_stable_node); ++ ++ return new_stable_node; ++} ++ ++static inline ++struct stable_node *first_level_insert(struct tree_node *tree_node, ++ struct rmap_item *rmap_item, ++ struct rmap_item *tree_rmap_item, ++ struct page **kpage, u32 hash, ++ int *success1, int *success2) ++{ ++ int cmp; ++ struct page *tree_page; ++ u32 hash_max = 0; ++ struct stable_node *stable_node, *new_snode; ++ struct rb_node *parent = NULL, **new; ++ ++ /* this tree node contains no sub-tree yet */ ++ stable_node = rb_entry(tree_node->sub_root.rb_node, ++ struct stable_node, node); ++ ++ tree_page = get_uksm_page(stable_node, 1, 0); ++ if (tree_page) { ++ cmp = memcmp_pages_with_cost(*kpage, tree_page, 1); ++ if (!cmp) { ++ try_merge_with_stable(rmap_item, tree_rmap_item, kpage, ++ tree_page, success1, success2); ++ put_page(tree_page); ++ if (!*success1 && !*success2) ++ goto failed; ++ ++ return stable_node; ++ ++ } else { ++ /* ++ * collision in first level try to create a subtree. ++ * A new node need to be created. ++ */ ++ put_page(tree_page); ++ ++ stable_node_hash_max(stable_node, tree_page, ++ tree_node->hash); ++ hash_max = rmap_item_hash_max(rmap_item, hash); ++ cmp = hash_cmp(hash_max, stable_node->hash_max); ++ ++ parent = &stable_node->node; ++ if (cmp < 0) ++ new = &parent->rb_left; ++ else if (cmp > 0) ++ new = &parent->rb_right; ++ else ++ goto failed; ++ } ++ ++ } else { ++ /* the only stable_node deleted, we reuse its tree_node. ++ */ ++ parent = NULL; ++ new = &tree_node->sub_root.rb_node; ++ } ++ ++ new_snode = new_stable_node(tree_node, *kpage, hash_max); ++ if (!new_snode) ++ goto failed; ++ ++ rb_link_node(&new_snode->node, parent, new); ++ rb_insert_color(&new_snode->node, &tree_node->sub_root); ++ tree_node->count++; ++ *success1 = *success2 = 1; ++ ++ return new_snode; ++ ++failed: ++ return NULL; ++} ++ ++static inline ++struct stable_node *stable_subtree_insert(struct tree_node *tree_node, ++ struct rmap_item *rmap_item, ++ struct rmap_item *tree_rmap_item, ++ struct page **kpage, u32 hash, ++ int *success1, int *success2) ++{ ++ struct page *tree_page; ++ u32 hash_max; ++ struct stable_node *stable_node, *new_snode; ++ struct rb_node *parent, **new; ++ ++research: ++ parent = NULL; ++ new = &tree_node->sub_root.rb_node; ++ BUG_ON(!*new); ++ hash_max = rmap_item_hash_max(rmap_item, hash); ++ while (*new) { ++ int cmp; ++ ++ stable_node = rb_entry(*new, struct stable_node, node); ++ ++ cmp = hash_cmp(hash_max, stable_node->hash_max); ++ ++ if (cmp < 0) { ++ parent = *new; ++ new = &parent->rb_left; ++ } else if (cmp > 0) { ++ parent = *new; ++ new = &parent->rb_right; ++ } else { ++ tree_page = get_uksm_page(stable_node, 1, 0); ++ if (tree_page) { ++ cmp = memcmp_pages_with_cost(*kpage, tree_page, 1); ++ if (!cmp) { ++ try_merge_with_stable(rmap_item, ++ tree_rmap_item, kpage, ++ tree_page, success1, success2); ++ ++ put_page(tree_page); ++ if (!*success1 && !*success2) ++ goto failed; ++ /* ++ * successfully merged with a stable ++ * node ++ */ ++ return stable_node; ++ } else { ++ put_page(tree_page); ++ goto failed; ++ } ++ } else { ++ /* ++ * stable node may be deleted, ++ * and subtree maybe ++ * restructed, cannot ++ * continue, research it. ++ */ ++ if (tree_node->count) { ++ goto research; ++ } else { ++ /* reuse the tree node*/ ++ parent = NULL; ++ new = &tree_node->sub_root.rb_node; ++ } ++ } ++ } ++ } ++ ++ new_snode = new_stable_node(tree_node, *kpage, hash_max); ++ if (!new_snode) ++ goto failed; ++ ++ rb_link_node(&new_snode->node, parent, new); ++ rb_insert_color(&new_snode->node, &tree_node->sub_root); ++ tree_node->count++; ++ *success1 = *success2 = 1; ++ ++ return new_snode; ++ ++failed: ++ return NULL; ++} ++ ++ ++/** ++ * stable_tree_insert() - try to insert a merged page in unstable tree to ++ * the stable tree ++ * ++ * @kpage: the page need to be inserted ++ * @hash: the current hash of this page ++ * @rmap_item: the rmap_item being scanned ++ * @tree_rmap_item: the rmap_item found on unstable tree ++ * @success1: return if rmap_item is merged ++ * @success2: return if tree_rmap_item is merged ++ * ++ * @return the stable_node on stable tree if at least one ++ * rmap_item is inserted into stable tree, NULL ++ * otherwise. ++ */ ++static struct stable_node * ++stable_tree_insert(struct page **kpage, u32 hash, ++ struct rmap_item *rmap_item, ++ struct rmap_item *tree_rmap_item, ++ int *success1, int *success2) ++{ ++ struct rb_node **new = &root_stable_treep->rb_node; ++ struct rb_node *parent = NULL; ++ struct stable_node *stable_node; ++ struct tree_node *tree_node; ++ u32 hash_max = 0; ++ ++ *success1 = *success2 = 0; ++ ++ while (*new) { ++ int cmp; ++ ++ tree_node = rb_entry(*new, struct tree_node, node); ++ ++ cmp = hash_cmp(hash, tree_node->hash); ++ ++ if (cmp < 0) { ++ parent = *new; ++ new = &parent->rb_left; ++ } else if (cmp > 0) { ++ parent = *new; ++ new = &parent->rb_right; ++ } else ++ break; ++ } ++ ++ if (*new) { ++ if (tree_node->count == 1) { ++ stable_node = first_level_insert(tree_node, rmap_item, ++ tree_rmap_item, kpage, ++ hash, success1, success2); ++ } else { ++ stable_node = stable_subtree_insert(tree_node, ++ rmap_item, tree_rmap_item, kpage, ++ hash, success1, success2); ++ } ++ } else { ++ ++ /* no tree node found */ ++ tree_node = alloc_tree_node(stable_tree_node_listp); ++ if (!tree_node) { ++ stable_node = NULL; ++ goto out; ++ } ++ ++ stable_node = new_stable_node(tree_node, *kpage, hash_max); ++ if (!stable_node) { ++ free_tree_node(tree_node); ++ goto out; ++ } ++ ++ tree_node->hash = hash; ++ rb_link_node(&tree_node->node, parent, new); ++ rb_insert_color(&tree_node->node, root_stable_treep); ++ parent = NULL; ++ new = &tree_node->sub_root.rb_node; ++ ++ rb_link_node(&stable_node->node, parent, new); ++ rb_insert_color(&stable_node->node, &tree_node->sub_root); ++ tree_node->count++; ++ *success1 = *success2 = 1; ++ } ++ ++out: ++ return stable_node; ++} ++ ++ ++/** ++ * get_tree_rmap_item_page() - try to get the page and lock the mmap_sem ++ * ++ * @return 0 on success, -EBUSY if unable to lock the mmap_sem, ++ * -EINVAL if the page mapping has been changed. ++ */ ++static inline int get_tree_rmap_item_page(struct rmap_item *tree_rmap_item) ++{ ++ int err; ++ ++ err = get_mergeable_page_lock_mmap(tree_rmap_item); ++ ++ if (err == -EINVAL) { ++ /* its page map has been changed, remove it */ ++ remove_rmap_item_from_tree(tree_rmap_item); ++ } ++ ++ /* The page is gotten and mmap_sem is locked now. */ ++ return err; ++} ++ ++ ++/** ++ * unstable_tree_search_insert() - search an unstable tree rmap_item with the ++ * same hash value. Get its page and trylock the mmap_sem ++ */ ++static inline ++struct rmap_item *unstable_tree_search_insert(struct rmap_item *rmap_item, ++ u32 hash) ++ ++{ ++ struct rb_node **new = &root_unstable_tree.rb_node; ++ struct rb_node *parent = NULL; ++ struct tree_node *tree_node; ++ u32 hash_max; ++ struct rmap_item *tree_rmap_item; ++ ++ while (*new) { ++ int cmp; ++ ++ tree_node = rb_entry(*new, struct tree_node, node); ++ ++ cmp = hash_cmp(hash, tree_node->hash); ++ ++ if (cmp < 0) { ++ parent = *new; ++ new = &parent->rb_left; ++ } else if (cmp > 0) { ++ parent = *new; ++ new = &parent->rb_right; ++ } else ++ break; ++ } ++ ++ if (*new) { ++ /* got the tree_node */ ++ if (tree_node->count == 1) { ++ tree_rmap_item = rb_entry(tree_node->sub_root.rb_node, ++ struct rmap_item, node); ++ BUG_ON(!tree_rmap_item); ++ ++ goto get_page_out; ++ } ++ ++ /* well, search the collision subtree */ ++ new = &tree_node->sub_root.rb_node; ++ BUG_ON(!*new); ++ hash_max = rmap_item_hash_max(rmap_item, hash); ++ ++ while (*new) { ++ int cmp; ++ ++ tree_rmap_item = rb_entry(*new, struct rmap_item, ++ node); ++ ++ cmp = hash_cmp(hash_max, tree_rmap_item->hash_max); ++ parent = *new; ++ if (cmp < 0) ++ new = &parent->rb_left; ++ else if (cmp > 0) ++ new = &parent->rb_right; ++ else ++ goto get_page_out; ++ } ++ } else { ++ /* alloc a new tree_node */ ++ tree_node = alloc_tree_node(&unstable_tree_node_list); ++ if (!tree_node) ++ return NULL; ++ ++ tree_node->hash = hash; ++ rb_link_node(&tree_node->node, parent, new); ++ rb_insert_color(&tree_node->node, &root_unstable_tree); ++ parent = NULL; ++ new = &tree_node->sub_root.rb_node; ++ } ++ ++ /* did not found even in sub-tree */ ++ rmap_item->tree_node = tree_node; ++ rmap_item->address |= UNSTABLE_FLAG; ++ rmap_item->hash_round = uksm_hash_round; ++ rb_link_node(&rmap_item->node, parent, new); ++ rb_insert_color(&rmap_item->node, &tree_node->sub_root); ++ ++ uksm_pages_unshared++; ++ return NULL; ++ ++get_page_out: ++ if (tree_rmap_item->page == rmap_item->page) ++ return NULL; ++ ++ if (get_tree_rmap_item_page(tree_rmap_item)) ++ return NULL; ++ ++ return tree_rmap_item; ++} ++ ++static void hold_anon_vma(struct rmap_item *rmap_item, ++ struct anon_vma *anon_vma) ++{ ++ rmap_item->anon_vma = anon_vma; ++ get_anon_vma(anon_vma); ++} ++ ++ ++/** ++ * stable_tree_append() - append a rmap_item to a stable node. Deduplication ++ * ratio statistics is done in this function. ++ * ++ */ ++static void stable_tree_append(struct rmap_item *rmap_item, ++ struct stable_node *stable_node, int logdedup) ++{ ++ struct node_vma *node_vma = NULL, *new_node_vma, *node_vma_cont = NULL; ++ unsigned long key = (unsigned long)rmap_item->slot; ++ unsigned long factor = rmap_item->slot->rung->step; ++ ++ BUG_ON(!stable_node); ++ rmap_item->address |= STABLE_FLAG; ++ ++ if (hlist_empty(&stable_node->hlist)) { ++ uksm_pages_shared++; ++ goto node_vma_new; ++ } else { ++ uksm_pages_sharing++; ++ } ++ ++ hlist_for_each_entry(node_vma, &stable_node->hlist, hlist) { ++ if (node_vma->key >= key) ++ break; ++ ++ if (logdedup) { ++ node_vma->slot->pages_bemerged += factor; ++ if (list_empty(&node_vma->slot->dedup_list)) ++ list_add(&node_vma->slot->dedup_list, ++ &vma_slot_dedup); ++ } ++ } ++ ++ if (node_vma) { ++ if (node_vma->key == key) { ++ node_vma_cont = hlist_entry_safe(node_vma->hlist.next, struct node_vma, hlist); ++ goto node_vma_ok; ++ } else if (node_vma->key > key) { ++ node_vma_cont = node_vma; ++ } ++ } ++ ++node_vma_new: ++ /* no same vma already in node, alloc a new node_vma */ ++ new_node_vma = alloc_node_vma(); ++ BUG_ON(!new_node_vma); ++ new_node_vma->head = stable_node; ++ new_node_vma->slot = rmap_item->slot; ++ ++ if (!node_vma) { ++ hlist_add_head(&new_node_vma->hlist, &stable_node->hlist); ++ } else if (node_vma->key != key) { ++ if (node_vma->key < key) ++ hlist_add_behind(&new_node_vma->hlist, &node_vma->hlist); ++ else { ++ hlist_add_before(&new_node_vma->hlist, ++ &node_vma->hlist); ++ } ++ ++ } ++ node_vma = new_node_vma; ++ ++node_vma_ok: /* ok, ready to add to the list */ ++ rmap_item->head = node_vma; ++ hlist_add_head(&rmap_item->hlist, &node_vma->rmap_hlist); ++ hold_anon_vma(rmap_item, rmap_item->slot->vma->anon_vma); ++ if (logdedup) { ++ rmap_item->slot->pages_merged++; ++ if (node_vma_cont) { ++ node_vma = node_vma_cont; ++ hlist_for_each_entry_continue(node_vma, hlist) { ++ node_vma->slot->pages_bemerged += factor; ++ if (list_empty(&node_vma->slot->dedup_list)) ++ list_add(&node_vma->slot->dedup_list, ++ &vma_slot_dedup); ++ } ++ } ++ } ++} ++ ++/* ++ * We use break_ksm to break COW on a ksm page: it's a stripped down ++ * ++ * if (get_user_pages(addr, 1, 1, 1, &page, NULL) == 1) ++ * put_page(page); ++ * ++ * but taking great care only to touch a ksm page, in a VM_MERGEABLE vma, ++ * in case the application has unmapped and remapped mm,addr meanwhile. ++ * Could a ksm page appear anywhere else? Actually yes, in a VM_PFNMAP ++ * mmap of /dev/mem or /dev/kmem, where we would not want to touch it. ++ */ ++static int break_ksm(struct vm_area_struct *vma, unsigned long addr) ++{ ++ struct page *page; ++ int ret = 0; ++ ++ do { ++ cond_resched(); ++ page = follow_page(vma, addr, FOLL_GET | FOLL_MIGRATION | FOLL_REMOTE); ++ if (IS_ERR_OR_NULL(page)) ++ break; ++ if (PageKsm(page)) { ++ ret = handle_mm_fault(vma, addr, ++ FAULT_FLAG_WRITE | FAULT_FLAG_REMOTE); ++ } else ++ ret = VM_FAULT_WRITE; ++ put_page(page); ++ } while (!(ret & (VM_FAULT_WRITE | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | VM_FAULT_OOM))); ++ /* ++ * We must loop because handle_mm_fault() may back out if there's ++ * any difficulty e.g. if pte accessed bit gets updated concurrently. ++ * ++ * VM_FAULT_WRITE is what we have been hoping for: it indicates that ++ * COW has been broken, even if the vma does not permit VM_WRITE; ++ * but note that a concurrent fault might break PageKsm for us. ++ * ++ * VM_FAULT_SIGBUS could occur if we race with truncation of the ++ * backing file, which also invalidates anonymous pages: that's ++ * okay, that truncation will have unmapped the PageKsm for us. ++ * ++ * VM_FAULT_OOM: at the time of writing (late July 2009), setting ++ * aside mem_cgroup limits, VM_FAULT_OOM would only be set if the ++ * current task has TIF_MEMDIE set, and will be OOM killed on return ++ * to user; and ksmd, having no mm, would never be chosen for that. ++ * ++ * But if the mm is in a limited mem_cgroup, then the fault may fail ++ * with VM_FAULT_OOM even if the current task is not TIF_MEMDIE; and ++ * even ksmd can fail in this way - though it's usually breaking ksm ++ * just to undo a merge it made a moment before, so unlikely to oom. ++ * ++ * That's a pity: we might therefore have more kernel pages allocated ++ * than we're counting as nodes in the stable tree; but uksm_do_scan ++ * will retry to break_cow on each pass, so should recover the page ++ * in due course. The important thing is to not let VM_MERGEABLE ++ * be cleared while any such pages might remain in the area. ++ */ ++ return (ret & VM_FAULT_OOM) ? -ENOMEM : 0; ++} ++ ++static void break_cow(struct rmap_item *rmap_item) ++{ ++ struct vm_area_struct *vma = rmap_item->slot->vma; ++ struct mm_struct *mm = vma->vm_mm; ++ unsigned long addr = get_rmap_addr(rmap_item); ++ ++ if (uksm_test_exit(mm)) ++ goto out; ++ ++ break_ksm(vma, addr); ++out: ++ return; ++} ++ ++/* ++ * Though it's very tempting to unmerge in_stable_tree(rmap_item)s rather ++ * than check every pte of a given vma, the locking doesn't quite work for ++ * that - an rmap_item is assigned to the stable tree after inserting ksm ++ * page and upping mmap_sem. Nor does it fit with the way we skip dup'ing ++ * rmap_items from parent to child at fork time (so as not to waste time ++ * if exit comes before the next scan reaches it). ++ * ++ * Similarly, although we'd like to remove rmap_items (so updating counts ++ * and freeing memory) when unmerging an area, it's easier to leave that ++ * to the next pass of ksmd - consider, for example, how ksmd might be ++ * in cmp_and_merge_page on one of the rmap_items we would be removing. ++ */ ++inline int unmerge_uksm_pages(struct vm_area_struct *vma, ++ unsigned long start, unsigned long end) ++{ ++ unsigned long addr; ++ int err = 0; ++ ++ for (addr = start; addr < end && !err; addr += PAGE_SIZE) { ++ if (uksm_test_exit(vma->vm_mm)) ++ break; ++ if (signal_pending(current)) ++ err = -ERESTARTSYS; ++ else ++ err = break_ksm(vma, addr); ++ } ++ return err; ++} ++ ++static inline void inc_uksm_pages_scanned(void) ++{ ++ u64 delta; ++ ++ ++ if (uksm_pages_scanned == U64_MAX) { ++ encode_benefit(); ++ ++ delta = uksm_pages_scanned >> pages_scanned_base; ++ ++ if (CAN_OVERFLOW_U64(pages_scanned_stored, delta)) { ++ pages_scanned_stored >>= 1; ++ delta >>= 1; ++ pages_scanned_base++; ++ } ++ ++ pages_scanned_stored += delta; ++ ++ uksm_pages_scanned = uksm_pages_scanned_last = 0; ++ } ++ ++ uksm_pages_scanned++; ++} ++ ++static inline int find_zero_page_hash(int strength, u32 hash) ++{ ++ return (zero_hash_table[strength] == hash); ++} ++ ++static ++int cmp_and_merge_zero_page(struct vm_area_struct *vma, struct page *page) ++{ ++ struct page *zero_page = empty_uksm_zero_page; ++ struct mm_struct *mm = vma->vm_mm; ++ pte_t orig_pte = __pte(0); ++ int err = -EFAULT; ++ ++ if (uksm_test_exit(mm)) ++ goto out; ++ ++ if (!trylock_page(page)) ++ goto out; ++ ++ if (!PageAnon(page)) ++ goto out_unlock; ++ ++ if (PageTransCompound(page)) { ++ err = split_huge_page(page); ++ if (err) ++ goto out_unlock; ++ } ++ ++ if (write_protect_page(vma, page, &orig_pte, 0) == 0) { ++ if (is_page_full_zero(page)) ++ err = replace_page(vma, page, zero_page, orig_pte); ++ } ++ ++out_unlock: ++ unlock_page(page); ++out: ++ return err; ++} ++ ++/* ++ * cmp_and_merge_page() - first see if page can be merged into the stable ++ * tree; if not, compare hash to previous and if it's the same, see if page ++ * can be inserted into the unstable tree, or merged with a page already there ++ * and both transferred to the stable tree. ++ * ++ * @page: the page that we are searching identical page to. ++ * @rmap_item: the reverse mapping into the virtual address of this page ++ */ ++static void cmp_and_merge_page(struct rmap_item *rmap_item, u32 hash) ++{ ++ struct rmap_item *tree_rmap_item; ++ struct page *page; ++ struct page *kpage = NULL; ++ u32 hash_max; ++ int err; ++ unsigned int success1, success2; ++ struct stable_node *snode; ++ int cmp; ++ struct rb_node *parent = NULL, **new; ++ ++ remove_rmap_item_from_tree(rmap_item); ++ page = rmap_item->page; ++ ++ /* We first start with searching the page inside the stable tree */ ++ kpage = stable_tree_search(rmap_item, hash); ++ if (kpage) { ++ err = try_to_merge_with_uksm_page(rmap_item, kpage, ++ hash); ++ if (!err) { ++ /* ++ * The page was successfully merged, add ++ * its rmap_item to the stable tree. ++ * page lock is needed because it's ++ * racing with try_to_unmap_ksm(), etc. ++ */ ++ lock_page(kpage); ++ snode = page_stable_node(kpage); ++ stable_tree_append(rmap_item, snode, 1); ++ unlock_page(kpage); ++ put_page(kpage); ++ return; /* success */ ++ } ++ put_page(kpage); ++ ++ /* ++ * if it's a collision and it has been search in sub-rbtree ++ * (hash_max != 0), we want to abort, because if it is ++ * successfully merged in unstable tree, the collision trends to ++ * happen again. ++ */ ++ if (err == MERGE_ERR_COLLI && rmap_item->hash_max) ++ return; ++ } ++ ++ tree_rmap_item = ++ unstable_tree_search_insert(rmap_item, hash); ++ if (tree_rmap_item) { ++ err = try_to_merge_two_pages(rmap_item, tree_rmap_item, hash); ++ /* ++ * As soon as we merge this page, we want to remove the ++ * rmap_item of the page we have merged with from the unstable ++ * tree, and insert it instead as new node in the stable tree. ++ */ ++ if (!err) { ++ kpage = page; ++ remove_rmap_item_from_tree(tree_rmap_item); ++ lock_page(kpage); ++ snode = stable_tree_insert(&kpage, hash, ++ rmap_item, tree_rmap_item, ++ &success1, &success2); ++ ++ /* ++ * Do not log dedup for tree item, it's not counted as ++ * scanned in this round. ++ */ ++ if (success2) ++ stable_tree_append(tree_rmap_item, snode, 0); ++ ++ /* ++ * The order of these two stable append is important: ++ * we are scanning rmap_item. ++ */ ++ if (success1) ++ stable_tree_append(rmap_item, snode, 1); ++ ++ /* ++ * The original kpage may be unlocked inside ++ * stable_tree_insert() already. This page ++ * should be unlocked before doing ++ * break_cow(). ++ */ ++ unlock_page(kpage); ++ ++ if (!success1) ++ break_cow(rmap_item); ++ ++ if (!success2) ++ break_cow(tree_rmap_item); ++ ++ } else if (err == MERGE_ERR_COLLI) { ++ BUG_ON(tree_rmap_item->tree_node->count > 1); ++ ++ rmap_item_hash_max(tree_rmap_item, ++ tree_rmap_item->tree_node->hash); ++ ++ hash_max = rmap_item_hash_max(rmap_item, hash); ++ cmp = hash_cmp(hash_max, tree_rmap_item->hash_max); ++ parent = &tree_rmap_item->node; ++ if (cmp < 0) ++ new = &parent->rb_left; ++ else if (cmp > 0) ++ new = &parent->rb_right; ++ else ++ goto put_up_out; ++ ++ rmap_item->tree_node = tree_rmap_item->tree_node; ++ rmap_item->address |= UNSTABLE_FLAG; ++ rmap_item->hash_round = uksm_hash_round; ++ rb_link_node(&rmap_item->node, parent, new); ++ rb_insert_color(&rmap_item->node, ++ &tree_rmap_item->tree_node->sub_root); ++ rmap_item->tree_node->count++; ++ } else { ++ /* ++ * either one of the page has changed or they collide ++ * at the max hash, we consider them as ill items. ++ */ ++ remove_rmap_item_from_tree(tree_rmap_item); ++ } ++put_up_out: ++ put_page(tree_rmap_item->page); ++ up_read(&tree_rmap_item->slot->vma->vm_mm->mmap_sem); ++ } ++} ++ ++ ++ ++ ++static inline unsigned long get_pool_index(struct vma_slot *slot, ++ unsigned long index) ++{ ++ unsigned long pool_index; ++ ++ pool_index = (sizeof(struct rmap_list_entry *) * index) >> PAGE_SHIFT; ++ if (pool_index >= slot->pool_size) ++ BUG(); ++ return pool_index; ++} ++ ++static inline unsigned long index_page_offset(unsigned long index) ++{ ++ return offset_in_page(sizeof(struct rmap_list_entry *) * index); ++} ++ ++static inline ++struct rmap_list_entry *get_rmap_list_entry(struct vma_slot *slot, ++ unsigned long index, int need_alloc) ++{ ++ unsigned long pool_index; ++ struct page *page; ++ void *addr; ++ ++ ++ pool_index = get_pool_index(slot, index); ++ if (!slot->rmap_list_pool[pool_index]) { ++ if (!need_alloc) ++ return NULL; ++ ++ page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN); ++ if (!page) ++ return NULL; ++ ++ slot->rmap_list_pool[pool_index] = page; ++ } ++ ++ addr = kmap(slot->rmap_list_pool[pool_index]); ++ addr += index_page_offset(index); ++ ++ return addr; ++} ++ ++static inline void put_rmap_list_entry(struct vma_slot *slot, ++ unsigned long index) ++{ ++ unsigned long pool_index; ++ ++ pool_index = get_pool_index(slot, index); ++ BUG_ON(!slot->rmap_list_pool[pool_index]); ++ kunmap(slot->rmap_list_pool[pool_index]); ++} ++ ++static inline int entry_is_new(struct rmap_list_entry *entry) ++{ ++ return !entry->item; ++} ++ ++static inline unsigned long get_index_orig_addr(struct vma_slot *slot, ++ unsigned long index) ++{ ++ return slot->vma->vm_start + (index << PAGE_SHIFT); ++} ++ ++static inline unsigned long get_entry_address(struct rmap_list_entry *entry) ++{ ++ unsigned long addr; ++ ++ if (is_addr(entry->addr)) ++ addr = get_clean_addr(entry->addr); ++ else if (entry->item) ++ addr = get_rmap_addr(entry->item); ++ else ++ BUG(); ++ ++ return addr; ++} ++ ++static inline struct rmap_item *get_entry_item(struct rmap_list_entry *entry) ++{ ++ if (is_addr(entry->addr)) ++ return NULL; ++ ++ return entry->item; ++} ++ ++static inline void inc_rmap_list_pool_count(struct vma_slot *slot, ++ unsigned long index) ++{ ++ unsigned long pool_index; ++ ++ pool_index = get_pool_index(slot, index); ++ BUG_ON(!slot->rmap_list_pool[pool_index]); ++ slot->pool_counts[pool_index]++; ++} ++ ++static inline void dec_rmap_list_pool_count(struct vma_slot *slot, ++ unsigned long index) ++{ ++ unsigned long pool_index; ++ ++ pool_index = get_pool_index(slot, index); ++ BUG_ON(!slot->rmap_list_pool[pool_index]); ++ BUG_ON(!slot->pool_counts[pool_index]); ++ slot->pool_counts[pool_index]--; ++} ++ ++static inline int entry_has_rmap(struct rmap_list_entry *entry) ++{ ++ return !is_addr(entry->addr) && entry->item; ++} ++ ++static inline void swap_entries(struct rmap_list_entry *entry1, ++ unsigned long index1, ++ struct rmap_list_entry *entry2, ++ unsigned long index2) ++{ ++ struct rmap_list_entry tmp; ++ ++ /* swapping two new entries is meaningless */ ++ BUG_ON(entry_is_new(entry1) && entry_is_new(entry2)); ++ ++ tmp = *entry1; ++ *entry1 = *entry2; ++ *entry2 = tmp; ++ ++ if (entry_has_rmap(entry1)) ++ entry1->item->entry_index = index1; ++ ++ if (entry_has_rmap(entry2)) ++ entry2->item->entry_index = index2; ++ ++ if (entry_has_rmap(entry1) && !entry_has_rmap(entry2)) { ++ inc_rmap_list_pool_count(entry1->item->slot, index1); ++ dec_rmap_list_pool_count(entry1->item->slot, index2); ++ } else if (!entry_has_rmap(entry1) && entry_has_rmap(entry2)) { ++ inc_rmap_list_pool_count(entry2->item->slot, index2); ++ dec_rmap_list_pool_count(entry2->item->slot, index1); ++ } ++} ++ ++static inline void free_entry_item(struct rmap_list_entry *entry) ++{ ++ unsigned long index; ++ struct rmap_item *item; ++ ++ if (!is_addr(entry->addr)) { ++ BUG_ON(!entry->item); ++ item = entry->item; ++ entry->addr = get_rmap_addr(item); ++ set_is_addr(entry->addr); ++ index = item->entry_index; ++ remove_rmap_item_from_tree(item); ++ dec_rmap_list_pool_count(item->slot, index); ++ free_rmap_item(item); ++ } ++} ++ ++static inline int pool_entry_boundary(unsigned long index) ++{ ++ unsigned long linear_addr; ++ ++ linear_addr = sizeof(struct rmap_list_entry *) * index; ++ return index && !offset_in_page(linear_addr); ++} ++ ++static inline void try_free_last_pool(struct vma_slot *slot, ++ unsigned long index) ++{ ++ unsigned long pool_index; ++ ++ pool_index = get_pool_index(slot, index); ++ if (slot->rmap_list_pool[pool_index] && ++ !slot->pool_counts[pool_index]) { ++ __free_page(slot->rmap_list_pool[pool_index]); ++ slot->rmap_list_pool[pool_index] = NULL; ++ slot->flags |= UKSM_SLOT_NEED_SORT; ++ } ++ ++} ++ ++static inline unsigned long vma_item_index(struct vm_area_struct *vma, ++ struct rmap_item *item) ++{ ++ return (get_rmap_addr(item) - vma->vm_start) >> PAGE_SHIFT; ++} ++ ++static int within_same_pool(struct vma_slot *slot, ++ unsigned long i, unsigned long j) ++{ ++ unsigned long pool_i, pool_j; ++ ++ pool_i = get_pool_index(slot, i); ++ pool_j = get_pool_index(slot, j); ++ ++ return (pool_i == pool_j); ++} ++ ++static void sort_rmap_entry_list(struct vma_slot *slot) ++{ ++ unsigned long i, j; ++ struct rmap_list_entry *entry, *swap_entry; ++ ++ entry = get_rmap_list_entry(slot, 0, 0); ++ for (i = 0; i < slot->pages; ) { ++ ++ if (!entry) ++ goto skip_whole_pool; ++ ++ if (entry_is_new(entry)) ++ goto next_entry; ++ ++ if (is_addr(entry->addr)) { ++ entry->addr = 0; ++ goto next_entry; ++ } ++ ++ j = vma_item_index(slot->vma, entry->item); ++ if (j == i) ++ goto next_entry; ++ ++ if (within_same_pool(slot, i, j)) ++ swap_entry = entry + j - i; ++ else ++ swap_entry = get_rmap_list_entry(slot, j, 1); ++ ++ swap_entries(entry, i, swap_entry, j); ++ if (!within_same_pool(slot, i, j)) ++ put_rmap_list_entry(slot, j); ++ continue; ++ ++skip_whole_pool: ++ i += PAGE_SIZE / sizeof(*entry); ++ if (i < slot->pages) ++ entry = get_rmap_list_entry(slot, i, 0); ++ continue; ++ ++next_entry: ++ if (i >= slot->pages - 1 || ++ !within_same_pool(slot, i, i + 1)) { ++ put_rmap_list_entry(slot, i); ++ if (i + 1 < slot->pages) ++ entry = get_rmap_list_entry(slot, i + 1, 0); ++ } else ++ entry++; ++ i++; ++ continue; ++ } ++ ++ /* free empty pool entries which contain no rmap_item */ ++ /* CAN be simplied to based on only pool_counts when bug freed !!!!! */ ++ for (i = 0; i < slot->pool_size; i++) { ++ unsigned char has_rmap; ++ void *addr; ++ ++ if (!slot->rmap_list_pool[i]) ++ continue; ++ ++ has_rmap = 0; ++ addr = kmap(slot->rmap_list_pool[i]); ++ BUG_ON(!addr); ++ for (j = 0; j < PAGE_SIZE / sizeof(*entry); j++) { ++ entry = (struct rmap_list_entry *)addr + j; ++ if (is_addr(entry->addr)) ++ continue; ++ if (!entry->item) ++ continue; ++ has_rmap = 1; ++ } ++ kunmap(slot->rmap_list_pool[i]); ++ if (!has_rmap) { ++ BUG_ON(slot->pool_counts[i]); ++ __free_page(slot->rmap_list_pool[i]); ++ slot->rmap_list_pool[i] = NULL; ++ } ++ } ++ ++ slot->flags &= ~UKSM_SLOT_NEED_SORT; ++} ++ ++/* ++ * vma_fully_scanned() - if all the pages in this slot have been scanned. ++ */ ++static inline int vma_fully_scanned(struct vma_slot *slot) ++{ ++ return slot->pages_scanned == slot->pages; ++} ++ ++/** ++ * get_next_rmap_item() - Get the next rmap_item in a vma_slot according to ++ * its random permutation. This function is embedded with the random ++ * permutation index management code. ++ */ ++static struct rmap_item *get_next_rmap_item(struct vma_slot *slot, u32 *hash) ++{ ++ unsigned long rand_range, addr, swap_index, scan_index; ++ struct rmap_item *item = NULL; ++ struct rmap_list_entry *scan_entry, *swap_entry = NULL; ++ struct page *page; ++ ++ scan_index = swap_index = slot->pages_scanned % slot->pages; ++ ++ if (pool_entry_boundary(scan_index)) ++ try_free_last_pool(slot, scan_index - 1); ++ ++ if (vma_fully_scanned(slot)) { ++ if (slot->flags & UKSM_SLOT_NEED_SORT) ++ slot->flags |= UKSM_SLOT_NEED_RERAND; ++ else ++ slot->flags &= ~UKSM_SLOT_NEED_RERAND; ++ if (slot->flags & UKSM_SLOT_NEED_SORT) ++ sort_rmap_entry_list(slot); ++ } ++ ++ scan_entry = get_rmap_list_entry(slot, scan_index, 1); ++ if (!scan_entry) ++ return NULL; ++ ++ if (entry_is_new(scan_entry)) { ++ scan_entry->addr = get_index_orig_addr(slot, scan_index); ++ set_is_addr(scan_entry->addr); ++ } ++ ++ if (slot->flags & UKSM_SLOT_NEED_RERAND) { ++ rand_range = slot->pages - scan_index; ++ BUG_ON(!rand_range); ++ swap_index = scan_index + (prandom_u32() % rand_range); ++ } ++ ++ if (swap_index != scan_index) { ++ swap_entry = get_rmap_list_entry(slot, swap_index, 1); ++ ++ if (!swap_entry) ++ return NULL; ++ ++ if (entry_is_new(swap_entry)) { ++ swap_entry->addr = get_index_orig_addr(slot, ++ swap_index); ++ set_is_addr(swap_entry->addr); ++ } ++ swap_entries(scan_entry, scan_index, swap_entry, swap_index); ++ } ++ ++ addr = get_entry_address(scan_entry); ++ item = get_entry_item(scan_entry); ++ BUG_ON(addr > slot->vma->vm_end || addr < slot->vma->vm_start); ++ ++ page = follow_page(slot->vma, addr, FOLL_GET); ++ if (IS_ERR_OR_NULL(page)) ++ goto nopage; ++ ++ if (!PageAnon(page)) ++ goto putpage; ++ ++ /*check is zero_page pfn or uksm_zero_page*/ ++ if ((page_to_pfn(page) == zero_pfn) ++ || (page_to_pfn(page) == uksm_zero_pfn)) ++ goto putpage; ++ ++ flush_anon_page(slot->vma, page, addr); ++ flush_dcache_page(page); ++ ++ ++ *hash = page_hash(page, hash_strength, 1); ++ inc_uksm_pages_scanned(); ++ /*if the page content all zero, re-map to zero-page*/ ++ if (find_zero_page_hash(hash_strength, *hash)) { ++ if (!cmp_and_merge_zero_page(slot->vma, page)) { ++ slot->pages_merged++; ++ ++ /* For full-zero pages, no need to create rmap item */ ++ goto putpage; ++ } else { ++ inc_rshash_neg(memcmp_cost / 2); ++ } ++ } ++ ++ if (!item) { ++ item = alloc_rmap_item(); ++ if (item) { ++ /* It has already been zeroed */ ++ item->slot = slot; ++ item->address = addr; ++ item->entry_index = scan_index; ++ scan_entry->item = item; ++ inc_rmap_list_pool_count(slot, scan_index); ++ } else ++ goto putpage; ++ } ++ ++ BUG_ON(item->slot != slot); ++ /* the page may have changed */ ++ item->page = page; ++ put_rmap_list_entry(slot, scan_index); ++ if (swap_entry) ++ put_rmap_list_entry(slot, swap_index); ++ return item; ++ ++putpage: ++ put_page(page); ++ page = NULL; ++nopage: ++ /* no page, store addr back and free rmap_item if possible */ ++ free_entry_item(scan_entry); ++ put_rmap_list_entry(slot, scan_index); ++ if (swap_entry) ++ put_rmap_list_entry(slot, swap_index); ++ return NULL; ++} ++ ++static inline int in_stable_tree(struct rmap_item *rmap_item) ++{ ++ return rmap_item->address & STABLE_FLAG; ++} ++ ++/** ++ * scan_vma_one_page() - scan the next page in a vma_slot. Called with ++ * mmap_sem locked. ++ */ ++static noinline void scan_vma_one_page(struct vma_slot *slot) ++{ ++ u32 hash; ++ struct mm_struct *mm; ++ struct rmap_item *rmap_item = NULL; ++ struct vm_area_struct *vma = slot->vma; ++ ++ mm = vma->vm_mm; ++ BUG_ON(!mm); ++ BUG_ON(!slot); ++ ++ rmap_item = get_next_rmap_item(slot, &hash); ++ if (!rmap_item) ++ goto out1; ++ ++ if (PageKsm(rmap_item->page) && in_stable_tree(rmap_item)) ++ goto out2; ++ ++ cmp_and_merge_page(rmap_item, hash); ++out2: ++ put_page(rmap_item->page); ++out1: ++ slot->pages_scanned++; ++ slot->this_sampled++; ++ if (slot->fully_scanned_round != fully_scanned_round) ++ scanned_virtual_pages++; ++ ++ if (vma_fully_scanned(slot)) ++ slot->fully_scanned_round = fully_scanned_round; ++} ++ ++static inline unsigned long rung_get_pages(struct scan_rung *rung) ++{ ++ struct slot_tree_node *node; ++ ++ if (!rung->vma_root.rnode) ++ return 0; ++ ++ node = container_of(rung->vma_root.rnode, struct slot_tree_node, snode); ++ ++ return node->size; ++} ++ ++#define RUNG_SAMPLED_MIN 3 ++ ++static inline ++void uksm_calc_rung_step(struct scan_rung *rung, ++ unsigned long page_time, unsigned long ratio) ++{ ++ unsigned long sampled, pages; ++ ++ /* will be fully scanned ? */ ++ if (!rung->cover_msecs) { ++ rung->step = 1; ++ return; ++ } ++ ++ sampled = rung->cover_msecs * (NSEC_PER_MSEC / TIME_RATIO_SCALE) ++ * ratio / page_time; ++ ++ /* ++ * Before we finsish a scan round and expensive per-round jobs, ++ * we need to have a chance to estimate the per page time. So ++ * the sampled number can not be too small. ++ */ ++ if (sampled < RUNG_SAMPLED_MIN) ++ sampled = RUNG_SAMPLED_MIN; ++ ++ pages = rung_get_pages(rung); ++ if (likely(pages > sampled)) ++ rung->step = pages / sampled; ++ else ++ rung->step = 1; ++} ++ ++static inline int step_need_recalc(struct scan_rung *rung) ++{ ++ unsigned long pages, stepmax; ++ ++ pages = rung_get_pages(rung); ++ stepmax = pages / RUNG_SAMPLED_MIN; ++ ++ return pages && (rung->step > pages || ++ (stepmax && rung->step > stepmax)); ++} ++ ++static inline ++void reset_current_scan(struct scan_rung *rung, int finished, int step_recalc) ++{ ++ struct vma_slot *slot; ++ ++ if (finished) ++ rung->flags |= UKSM_RUNG_ROUND_FINISHED; ++ ++ if (step_recalc || step_need_recalc(rung)) { ++ uksm_calc_rung_step(rung, uksm_ema_page_time, rung->cpu_ratio); ++ BUG_ON(step_need_recalc(rung)); ++ } ++ ++ slot_iter_index = prandom_u32() % rung->step; ++ BUG_ON(!rung->vma_root.rnode); ++ slot = sradix_tree_next(&rung->vma_root, NULL, 0, slot_iter); ++ BUG_ON(!slot); ++ ++ rung->current_scan = slot; ++ rung->current_offset = slot_iter_index; ++} ++ ++static inline struct sradix_tree_root *slot_get_root(struct vma_slot *slot) ++{ ++ return &slot->rung->vma_root; ++} ++ ++/* ++ * return if resetted. ++ */ ++static int advance_current_scan(struct scan_rung *rung) ++{ ++ unsigned short n; ++ struct vma_slot *slot, *next = NULL; ++ ++ BUG_ON(!rung->vma_root.num); ++ ++ slot = rung->current_scan; ++ n = (slot->pages - rung->current_offset) % rung->step; ++ slot_iter_index = rung->step - n; ++ next = sradix_tree_next(&rung->vma_root, slot->snode, ++ slot->sindex, slot_iter); ++ ++ if (next) { ++ rung->current_offset = slot_iter_index; ++ rung->current_scan = next; ++ return 0; ++ } else { ++ reset_current_scan(rung, 1, 0); ++ return 1; ++ } ++} ++ ++static inline void rung_rm_slot(struct vma_slot *slot) ++{ ++ struct scan_rung *rung = slot->rung; ++ struct sradix_tree_root *root; ++ ++ if (rung->current_scan == slot) ++ advance_current_scan(rung); ++ ++ root = slot_get_root(slot); ++ sradix_tree_delete_from_leaf(root, slot->snode, slot->sindex); ++ slot->snode = NULL; ++ if (step_need_recalc(rung)) { ++ uksm_calc_rung_step(rung, uksm_ema_page_time, rung->cpu_ratio); ++ BUG_ON(step_need_recalc(rung)); ++ } ++ ++ /* In case advance_current_scan loop back to this slot again */ ++ if (rung->vma_root.num && rung->current_scan == slot) ++ reset_current_scan(slot->rung, 1, 0); ++} ++ ++static inline void rung_add_new_slots(struct scan_rung *rung, ++ struct vma_slot **slots, unsigned long num) ++{ ++ int err; ++ struct vma_slot *slot; ++ unsigned long i; ++ struct sradix_tree_root *root = &rung->vma_root; ++ ++ err = sradix_tree_enter(root, (void **)slots, num); ++ BUG_ON(err); ++ ++ for (i = 0; i < num; i++) { ++ slot = slots[i]; ++ slot->rung = rung; ++ BUG_ON(vma_fully_scanned(slot)); ++ } ++ ++ if (rung->vma_root.num == num) ++ reset_current_scan(rung, 0, 1); ++} ++ ++static inline int rung_add_one_slot(struct scan_rung *rung, ++ struct vma_slot *slot) ++{ ++ int err; ++ ++ err = sradix_tree_enter(&rung->vma_root, (void **)&slot, 1); ++ if (err) ++ return err; ++ ++ slot->rung = rung; ++ if (rung->vma_root.num == 1) ++ reset_current_scan(rung, 0, 1); ++ ++ return 0; ++} ++ ++/* ++ * Return true if the slot is deleted from its rung. ++ */ ++static inline int vma_rung_enter(struct vma_slot *slot, struct scan_rung *rung) ++{ ++ struct scan_rung *old_rung = slot->rung; ++ int err; ++ ++ if (old_rung == rung) ++ return 0; ++ ++ rung_rm_slot(slot); ++ err = rung_add_one_slot(rung, slot); ++ if (err) { ++ err = rung_add_one_slot(old_rung, slot); ++ WARN_ON(err); /* OOPS, badly OOM, we lost this slot */ ++ } ++ ++ return 1; ++} ++ ++static inline int vma_rung_up(struct vma_slot *slot) ++{ ++ struct scan_rung *rung; ++ ++ rung = slot->rung; ++ if (slot->rung != &uksm_scan_ladder[SCAN_LADDER_SIZE-1]) ++ rung++; ++ ++ return vma_rung_enter(slot, rung); ++} ++ ++static inline int vma_rung_down(struct vma_slot *slot) ++{ ++ struct scan_rung *rung; ++ ++ rung = slot->rung; ++ if (slot->rung != &uksm_scan_ladder[0]) ++ rung--; ++ ++ return vma_rung_enter(slot, rung); ++} ++ ++/** ++ * cal_dedup_ratio() - Calculate the deduplication ratio for this slot. ++ */ ++static unsigned long cal_dedup_ratio(struct vma_slot *slot) ++{ ++ unsigned long ret; ++ unsigned long pages; ++ ++ pages = slot->this_sampled; ++ if (!pages) ++ return 0; ++ ++ BUG_ON(slot->pages_scanned == slot->last_scanned); ++ ++ ret = slot->pages_merged; ++ ++ /* Thrashing area filtering */ ++ if (ret && uksm_thrash_threshold) { ++ if (slot->pages_cowed * 100 / slot->pages_merged ++ > uksm_thrash_threshold) { ++ ret = 0; ++ } else { ++ ret = slot->pages_merged - slot->pages_cowed; ++ } ++ } ++ ++ return ret * 100 / pages; ++} ++ ++/** ++ * cal_dedup_ratio() - Calculate the deduplication ratio for this slot. ++ */ ++static unsigned long cal_dedup_ratio_old(struct vma_slot *slot) ++{ ++ unsigned long ret; ++ unsigned long pages; ++ ++ pages = slot->pages; ++ if (!pages) ++ return 0; ++ ++ ret = slot->pages_bemerged; ++ ++ /* Thrashing area filtering */ ++ if (ret && uksm_thrash_threshold) { ++ if (slot->pages_cowed * 100 / slot->pages_bemerged ++ > uksm_thrash_threshold) { ++ ret = 0; ++ } else { ++ ret = slot->pages_bemerged - slot->pages_cowed; ++ } ++ } ++ ++ return ret * 100 / pages; ++} ++ ++/** ++ * stable_node_reinsert() - When the hash_strength has been adjusted, the ++ * stable tree need to be restructured, this is the function re-inserting the ++ * stable node. ++ */ ++static inline void stable_node_reinsert(struct stable_node *new_node, ++ struct page *page, ++ struct rb_root *root_treep, ++ struct list_head *tree_node_listp, ++ u32 hash) ++{ ++ struct rb_node **new = &root_treep->rb_node; ++ struct rb_node *parent = NULL; ++ struct stable_node *stable_node; ++ struct tree_node *tree_node; ++ struct page *tree_page; ++ int cmp; ++ ++ while (*new) { ++ int cmp; ++ ++ tree_node = rb_entry(*new, struct tree_node, node); ++ ++ cmp = hash_cmp(hash, tree_node->hash); ++ ++ if (cmp < 0) { ++ parent = *new; ++ new = &parent->rb_left; ++ } else if (cmp > 0) { ++ parent = *new; ++ new = &parent->rb_right; ++ } else ++ break; ++ } ++ ++ if (*new) { ++ /* find a stable tree node with same first level hash value */ ++ stable_node_hash_max(new_node, page, hash); ++ if (tree_node->count == 1) { ++ stable_node = rb_entry(tree_node->sub_root.rb_node, ++ struct stable_node, node); ++ tree_page = get_uksm_page(stable_node, 1, 0); ++ if (tree_page) { ++ stable_node_hash_max(stable_node, ++ tree_page, hash); ++ put_page(tree_page); ++ ++ /* prepare for stable node insertion */ ++ ++ cmp = hash_cmp(new_node->hash_max, ++ stable_node->hash_max); ++ parent = &stable_node->node; ++ if (cmp < 0) ++ new = &parent->rb_left; ++ else if (cmp > 0) ++ new = &parent->rb_right; ++ else ++ goto failed; ++ ++ goto add_node; ++ } else { ++ /* the only stable_node deleted, the tree node ++ * was not deleted. ++ */ ++ goto tree_node_reuse; ++ } ++ } ++ ++ /* well, search the collision subtree */ ++ new = &tree_node->sub_root.rb_node; ++ parent = NULL; ++ BUG_ON(!*new); ++ while (*new) { ++ int cmp; ++ ++ stable_node = rb_entry(*new, struct stable_node, node); ++ ++ cmp = hash_cmp(new_node->hash_max, ++ stable_node->hash_max); ++ ++ if (cmp < 0) { ++ parent = *new; ++ new = &parent->rb_left; ++ } else if (cmp > 0) { ++ parent = *new; ++ new = &parent->rb_right; ++ } else { ++ /* oh, no, still a collision */ ++ goto failed; ++ } ++ } ++ ++ goto add_node; ++ } ++ ++ /* no tree node found */ ++ tree_node = alloc_tree_node(tree_node_listp); ++ if (!tree_node) { ++ pr_err("UKSM: memory allocation error!\n"); ++ goto failed; ++ } else { ++ tree_node->hash = hash; ++ rb_link_node(&tree_node->node, parent, new); ++ rb_insert_color(&tree_node->node, root_treep); ++ ++tree_node_reuse: ++ /* prepare for stable node insertion */ ++ parent = NULL; ++ new = &tree_node->sub_root.rb_node; ++ } ++ ++add_node: ++ rb_link_node(&new_node->node, parent, new); ++ rb_insert_color(&new_node->node, &tree_node->sub_root); ++ new_node->tree_node = tree_node; ++ tree_node->count++; ++ return; ++ ++failed: ++ /* This can only happen when two nodes have collided ++ * in two levels. ++ */ ++ new_node->tree_node = NULL; ++ return; ++} ++ ++static inline void free_all_tree_nodes(struct list_head *list) ++{ ++ struct tree_node *node, *tmp; ++ ++ list_for_each_entry_safe(node, tmp, list, all_list) { ++ free_tree_node(node); ++ } ++} ++ ++/** ++ * stable_tree_delta_hash() - Delta hash the stable tree from previous hash ++ * strength to the current hash_strength. It re-structures the hole tree. ++ */ ++static inline void stable_tree_delta_hash(u32 prev_hash_strength) ++{ ++ struct stable_node *node, *tmp; ++ struct rb_root *root_new_treep; ++ struct list_head *new_tree_node_listp; ++ ++ stable_tree_index = (stable_tree_index + 1) % 2; ++ root_new_treep = &root_stable_tree[stable_tree_index]; ++ new_tree_node_listp = &stable_tree_node_list[stable_tree_index]; ++ *root_new_treep = RB_ROOT; ++ BUG_ON(!list_empty(new_tree_node_listp)); ++ ++ /* ++ * we need to be safe, the node could be removed by get_uksm_page() ++ */ ++ list_for_each_entry_safe(node, tmp, &stable_node_list, all_list) { ++ void *addr; ++ struct page *node_page; ++ u32 hash; ++ ++ /* ++ * We are completely re-structuring the stable nodes to a new ++ * stable tree. We don't want to touch the old tree unlinks and ++ * old tree_nodes. The old tree_nodes will be freed at once. ++ */ ++ node_page = get_uksm_page(node, 0, 0); ++ if (!node_page) ++ continue; ++ ++ if (node->tree_node) { ++ hash = node->tree_node->hash; ++ ++ addr = kmap_atomic(node_page); ++ ++ hash = delta_hash(addr, prev_hash_strength, ++ hash_strength, hash); ++ kunmap_atomic(addr); ++ } else { ++ /* ++ *it was not inserted to rbtree due to collision in last ++ *round scan. ++ */ ++ hash = page_hash(node_page, hash_strength, 0); ++ } ++ ++ stable_node_reinsert(node, node_page, root_new_treep, ++ new_tree_node_listp, hash); ++ put_page(node_page); ++ } ++ ++ root_stable_treep = root_new_treep; ++ free_all_tree_nodes(stable_tree_node_listp); ++ BUG_ON(!list_empty(stable_tree_node_listp)); ++ stable_tree_node_listp = new_tree_node_listp; ++} ++ ++static inline void inc_hash_strength(unsigned long delta) ++{ ++ hash_strength += 1 << delta; ++ if (hash_strength > HASH_STRENGTH_MAX) ++ hash_strength = HASH_STRENGTH_MAX; ++} ++ ++static inline void dec_hash_strength(unsigned long delta) ++{ ++ unsigned long change = 1 << delta; ++ ++ if (hash_strength <= change + 1) ++ hash_strength = 1; ++ else ++ hash_strength -= change; ++} ++ ++static inline void inc_hash_strength_delta(void) ++{ ++ hash_strength_delta++; ++ if (hash_strength_delta > HASH_STRENGTH_DELTA_MAX) ++ hash_strength_delta = HASH_STRENGTH_DELTA_MAX; ++} ++ ++static inline unsigned long get_current_neg_ratio(void) ++{ ++ u64 pos = benefit.pos; ++ u64 neg = benefit.neg; ++ ++ if (!neg) ++ return 0; ++ ++ if (!pos || neg > pos) ++ return 100; ++ ++ if (neg > div64_u64(U64_MAX, 100)) ++ pos = div64_u64(pos, 100); ++ else ++ neg *= 100; ++ ++ return div64_u64(neg, pos); ++} ++ ++static inline unsigned long get_current_benefit(void) ++{ ++ u64 pos = benefit.pos; ++ u64 neg = benefit.neg; ++ u64 scanned = benefit.scanned; ++ ++ if (neg > pos) ++ return 0; ++ ++ return div64_u64((pos - neg), scanned); ++} ++ ++static inline int judge_rshash_direction(void) ++{ ++ u64 current_neg_ratio, stable_benefit; ++ u64 current_benefit, delta = 0; ++ int ret = STILL; ++ ++ /* ++ * Try to probe a value after the boot, and in case the system ++ * are still for a long time. ++ */ ++ if ((fully_scanned_round & 0xFFULL) == 10) { ++ ret = OBSCURE; ++ goto out; ++ } ++ ++ current_neg_ratio = get_current_neg_ratio(); ++ ++ if (current_neg_ratio == 0) { ++ rshash_neg_cont_zero++; ++ if (rshash_neg_cont_zero > 2) ++ return GO_DOWN; ++ else ++ return STILL; ++ } ++ rshash_neg_cont_zero = 0; ++ ++ if (current_neg_ratio > 90) { ++ ret = GO_UP; ++ goto out; ++ } ++ ++ current_benefit = get_current_benefit(); ++ stable_benefit = rshash_state.stable_benefit; ++ ++ if (!stable_benefit) { ++ ret = OBSCURE; ++ goto out; ++ } ++ ++ if (current_benefit > stable_benefit) ++ delta = current_benefit - stable_benefit; ++ else if (current_benefit < stable_benefit) ++ delta = stable_benefit - current_benefit; ++ ++ delta = div64_u64(100 * delta, stable_benefit); ++ ++ if (delta > 50) { ++ rshash_cont_obscure++; ++ if (rshash_cont_obscure > 2) ++ return OBSCURE; ++ else ++ return STILL; ++ } ++ ++out: ++ rshash_cont_obscure = 0; ++ return ret; ++} ++ ++/** ++ * rshash_adjust() - The main function to control the random sampling state ++ * machine for hash strength adapting. ++ * ++ * return true if hash_strength has changed. ++ */ ++static inline int rshash_adjust(void) ++{ ++ unsigned long prev_hash_strength = hash_strength; ++ ++ if (!encode_benefit()) ++ return 0; ++ ++ switch (rshash_state.state) { ++ case RSHASH_STILL: ++ switch (judge_rshash_direction()) { ++ case GO_UP: ++ if (rshash_state.pre_direct == GO_DOWN) ++ hash_strength_delta = 0; ++ ++ inc_hash_strength(hash_strength_delta); ++ inc_hash_strength_delta(); ++ rshash_state.stable_benefit = get_current_benefit(); ++ rshash_state.pre_direct = GO_UP; ++ break; ++ ++ case GO_DOWN: ++ if (rshash_state.pre_direct == GO_UP) ++ hash_strength_delta = 0; ++ ++ dec_hash_strength(hash_strength_delta); ++ inc_hash_strength_delta(); ++ rshash_state.stable_benefit = get_current_benefit(); ++ rshash_state.pre_direct = GO_DOWN; ++ break; ++ ++ case OBSCURE: ++ rshash_state.stable_point = hash_strength; ++ rshash_state.turn_point_down = hash_strength; ++ rshash_state.turn_point_up = hash_strength; ++ rshash_state.turn_benefit_down = get_current_benefit(); ++ rshash_state.turn_benefit_up = get_current_benefit(); ++ rshash_state.lookup_window_index = 0; ++ rshash_state.state = RSHASH_TRYDOWN; ++ dec_hash_strength(hash_strength_delta); ++ inc_hash_strength_delta(); ++ break; ++ ++ case STILL: ++ break; ++ default: ++ BUG(); ++ } ++ break; ++ ++ case RSHASH_TRYDOWN: ++ if (rshash_state.lookup_window_index++ % 5 == 0) ++ rshash_state.below_count = 0; ++ ++ if (get_current_benefit() < rshash_state.stable_benefit) ++ rshash_state.below_count++; ++ else if (get_current_benefit() > ++ rshash_state.turn_benefit_down) { ++ rshash_state.turn_point_down = hash_strength; ++ rshash_state.turn_benefit_down = get_current_benefit(); ++ } ++ ++ if (rshash_state.below_count >= 3 || ++ judge_rshash_direction() == GO_UP || ++ hash_strength == 1) { ++ hash_strength = rshash_state.stable_point; ++ hash_strength_delta = 0; ++ inc_hash_strength(hash_strength_delta); ++ inc_hash_strength_delta(); ++ rshash_state.lookup_window_index = 0; ++ rshash_state.state = RSHASH_TRYUP; ++ hash_strength_delta = 0; ++ } else { ++ dec_hash_strength(hash_strength_delta); ++ inc_hash_strength_delta(); ++ } ++ break; ++ ++ case RSHASH_TRYUP: ++ if (rshash_state.lookup_window_index++ % 5 == 0) ++ rshash_state.below_count = 0; ++ ++ if (get_current_benefit() < rshash_state.turn_benefit_down) ++ rshash_state.below_count++; ++ else if (get_current_benefit() > rshash_state.turn_benefit_up) { ++ rshash_state.turn_point_up = hash_strength; ++ rshash_state.turn_benefit_up = get_current_benefit(); ++ } ++ ++ if (rshash_state.below_count >= 3 || ++ judge_rshash_direction() == GO_DOWN || ++ hash_strength == HASH_STRENGTH_MAX) { ++ hash_strength = rshash_state.turn_benefit_up > ++ rshash_state.turn_benefit_down ? ++ rshash_state.turn_point_up : ++ rshash_state.turn_point_down; ++ ++ rshash_state.state = RSHASH_PRE_STILL; ++ } else { ++ inc_hash_strength(hash_strength_delta); ++ inc_hash_strength_delta(); ++ } ++ ++ break; ++ ++ case RSHASH_NEW: ++ case RSHASH_PRE_STILL: ++ rshash_state.stable_benefit = get_current_benefit(); ++ rshash_state.state = RSHASH_STILL; ++ hash_strength_delta = 0; ++ break; ++ default: ++ BUG(); ++ } ++ ++ /* rshash_neg = rshash_pos = 0; */ ++ reset_benefit(); ++ ++ if (prev_hash_strength != hash_strength) ++ stable_tree_delta_hash(prev_hash_strength); ++ ++ return prev_hash_strength != hash_strength; ++} ++ ++/** ++ * round_update_ladder() - The main function to do update of all the ++ * adjustments whenever a scan round is finished. ++ */ ++static noinline void round_update_ladder(void) ++{ ++ int i; ++ unsigned long dedup; ++ struct vma_slot *slot, *tmp_slot; ++ ++ for (i = 0; i < SCAN_LADDER_SIZE; i++) ++ uksm_scan_ladder[i].flags &= ~UKSM_RUNG_ROUND_FINISHED; ++ ++ list_for_each_entry_safe(slot, tmp_slot, &vma_slot_dedup, dedup_list) { ++ ++ /* slot may be rung_rm_slot() when mm exits */ ++ if (slot->snode) { ++ dedup = cal_dedup_ratio_old(slot); ++ if (dedup && dedup >= uksm_abundant_threshold) ++ vma_rung_up(slot); ++ } ++ ++ slot->pages_bemerged = 0; ++ slot->pages_cowed = 0; ++ ++ list_del_init(&slot->dedup_list); ++ } ++} ++ ++static void uksm_del_vma_slot(struct vma_slot *slot) ++{ ++ int i, j; ++ struct rmap_list_entry *entry; ++ ++ if (slot->snode) { ++ /* ++ * In case it just failed when entering the rung, it's not ++ * necessary. ++ */ ++ rung_rm_slot(slot); ++ } ++ ++ if (!list_empty(&slot->dedup_list)) ++ list_del(&slot->dedup_list); ++ ++ if (!slot->rmap_list_pool || !slot->pool_counts) { ++ /* In case it OOMed in uksm_vma_enter() */ ++ goto out; ++ } ++ ++ for (i = 0; i < slot->pool_size; i++) { ++ void *addr; ++ ++ if (!slot->rmap_list_pool[i]) ++ continue; ++ ++ addr = kmap(slot->rmap_list_pool[i]); ++ for (j = 0; j < PAGE_SIZE / sizeof(*entry); j++) { ++ entry = (struct rmap_list_entry *)addr + j; ++ if (is_addr(entry->addr)) ++ continue; ++ if (!entry->item) ++ continue; ++ ++ remove_rmap_item_from_tree(entry->item); ++ free_rmap_item(entry->item); ++ slot->pool_counts[i]--; ++ } ++ BUG_ON(slot->pool_counts[i]); ++ kunmap(slot->rmap_list_pool[i]); ++ __free_page(slot->rmap_list_pool[i]); ++ } ++ kfree(slot->rmap_list_pool); ++ kfree(slot->pool_counts); ++ ++out: ++ slot->rung = NULL; ++ if (slot->flags & UKSM_SLOT_IN_UKSM) { ++ BUG_ON(uksm_pages_total < slot->pages); ++ uksm_pages_total -= slot->pages; ++ } ++ ++ if (slot->fully_scanned_round == fully_scanned_round) ++ scanned_virtual_pages -= slot->pages; ++ else ++ scanned_virtual_pages -= slot->pages_scanned; ++ free_vma_slot(slot); ++} ++ ++ ++#define SPIN_LOCK_PERIOD 32 ++static struct vma_slot *cleanup_slots[SPIN_LOCK_PERIOD]; ++static inline void cleanup_vma_slots(void) ++{ ++ struct vma_slot *slot; ++ int i; ++ ++ i = 0; ++ spin_lock(&vma_slot_list_lock); ++ while (!list_empty(&vma_slot_del)) { ++ slot = list_entry(vma_slot_del.next, ++ struct vma_slot, slot_list); ++ list_del(&slot->slot_list); ++ cleanup_slots[i++] = slot; ++ if (i == SPIN_LOCK_PERIOD) { ++ spin_unlock(&vma_slot_list_lock); ++ while (--i >= 0) ++ uksm_del_vma_slot(cleanup_slots[i]); ++ i = 0; ++ spin_lock(&vma_slot_list_lock); ++ } ++ } ++ spin_unlock(&vma_slot_list_lock); ++ ++ while (--i >= 0) ++ uksm_del_vma_slot(cleanup_slots[i]); ++} ++ ++/* ++ * Expotional moving average formula ++ */ ++static inline unsigned long ema(unsigned long curr, unsigned long last_ema) ++{ ++ /* ++ * For a very high burst, even the ema cannot work well, a false very ++ * high per-page time estimation can result in feedback in very high ++ * overhead of context switch and rung update -- this will then lead ++ * to higher per-paper time, this may not converge. ++ * ++ * Instead, we try to approach this value in a binary manner. ++ */ ++ if (curr > last_ema * 10) ++ return last_ema * 2; ++ ++ return (EMA_ALPHA * curr + (100 - EMA_ALPHA) * last_ema) / 100; ++} ++ ++/* ++ * convert cpu ratio in 1/TIME_RATIO_SCALE configured by user to ++ * nanoseconds based on current uksm_sleep_jiffies. ++ */ ++static inline unsigned long cpu_ratio_to_nsec(unsigned int ratio) ++{ ++ return NSEC_PER_USEC * jiffies_to_usecs(uksm_sleep_jiffies) / ++ (TIME_RATIO_SCALE - ratio) * ratio; ++} ++ ++ ++static inline unsigned long rung_real_ratio(int cpu_time_ratio) ++{ ++ unsigned long ret; ++ ++ BUG_ON(!cpu_time_ratio); ++ ++ if (cpu_time_ratio > 0) ++ ret = cpu_time_ratio; ++ else ++ ret = (unsigned long)(-cpu_time_ratio) * ++ uksm_max_cpu_percentage / 100UL; ++ ++ return ret ? ret : 1; ++} ++ ++static noinline void uksm_calc_scan_pages(void) ++{ ++ struct scan_rung *ladder = uksm_scan_ladder; ++ unsigned long sleep_usecs, nsecs; ++ unsigned long ratio; ++ int i; ++ unsigned long per_page; ++ ++ if (uksm_ema_page_time > 100000 || ++ (((unsigned long) uksm_eval_round & (256UL - 1)) == 0UL)) ++ uksm_ema_page_time = UKSM_PAGE_TIME_DEFAULT; ++ ++ per_page = uksm_ema_page_time; ++ BUG_ON(!per_page); ++ ++ /* ++ * For every 8 eval round, we try to probe a uksm_sleep_jiffies value ++ * based on saved user input. ++ */ ++ if (((unsigned long) uksm_eval_round & (8UL - 1)) == 0UL) ++ uksm_sleep_jiffies = uksm_sleep_saved; ++ ++ /* We require a rung scan at least 1 page in a period. */ ++ nsecs = per_page; ++ ratio = rung_real_ratio(ladder[0].cpu_ratio); ++ if (cpu_ratio_to_nsec(ratio) < nsecs) { ++ sleep_usecs = nsecs * (TIME_RATIO_SCALE - ratio) / ratio ++ / NSEC_PER_USEC; ++ uksm_sleep_jiffies = usecs_to_jiffies(sleep_usecs) + 1; ++ } ++ ++ for (i = 0; i < SCAN_LADDER_SIZE; i++) { ++ ratio = rung_real_ratio(ladder[i].cpu_ratio); ++ ladder[i].pages_to_scan = cpu_ratio_to_nsec(ratio) / ++ per_page; ++ BUG_ON(!ladder[i].pages_to_scan); ++ uksm_calc_rung_step(&ladder[i], per_page, ratio); ++ } ++} ++ ++/* ++ * From the scan time of this round (ns) to next expected min sleep time ++ * (ms), be careful of the possible overflows. ratio is taken from ++ * rung_real_ratio() ++ */ ++static inline ++unsigned int scan_time_to_sleep(unsigned long long scan_time, unsigned long ratio) ++{ ++ scan_time >>= 20; /* to msec level now */ ++ BUG_ON(scan_time > (ULONG_MAX / TIME_RATIO_SCALE)); ++ ++ return (unsigned int) ((unsigned long) scan_time * ++ (TIME_RATIO_SCALE - ratio) / ratio); ++} ++ ++#define __round_mask(x, y) ((__typeof__(x))((y)-1)) ++#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) ++ ++static void uksm_vma_enter(struct vma_slot **slots, unsigned long num) ++{ ++ struct scan_rung *rung; ++ ++ rung = &uksm_scan_ladder[0]; ++ rung_add_new_slots(rung, slots, num); ++} ++ ++static struct vma_slot *batch_slots[SLOT_TREE_NODE_STORE_SIZE]; ++ ++static void uksm_enter_all_slots(void) ++{ ++ struct vma_slot *slot; ++ unsigned long index; ++ struct list_head empty_vma_list; ++ int i; ++ ++ i = 0; ++ index = 0; ++ INIT_LIST_HEAD(&empty_vma_list); ++ ++ spin_lock(&vma_slot_list_lock); ++ while (!list_empty(&vma_slot_new)) { ++ slot = list_entry(vma_slot_new.next, ++ struct vma_slot, slot_list); ++ ++ if (!slot->vma->anon_vma) { ++ list_move(&slot->slot_list, &empty_vma_list); ++ } else if (vma_can_enter(slot->vma)) { ++ batch_slots[index++] = slot; ++ list_del_init(&slot->slot_list); ++ } else { ++ list_move(&slot->slot_list, &vma_slot_noadd); ++ } ++ ++ if (++i == SPIN_LOCK_PERIOD || ++ (index && !(index % SLOT_TREE_NODE_STORE_SIZE))) { ++ spin_unlock(&vma_slot_list_lock); ++ ++ if (index && !(index % SLOT_TREE_NODE_STORE_SIZE)) { ++ uksm_vma_enter(batch_slots, index); ++ index = 0; ++ } ++ i = 0; ++ cond_resched(); ++ spin_lock(&vma_slot_list_lock); ++ } ++ } ++ ++ list_splice(&empty_vma_list, &vma_slot_new); ++ ++ spin_unlock(&vma_slot_list_lock); ++ ++ if (index) ++ uksm_vma_enter(batch_slots, index); ++ ++} ++ ++static inline int rung_round_finished(struct scan_rung *rung) ++{ ++ return rung->flags & UKSM_RUNG_ROUND_FINISHED; ++} ++ ++static inline void judge_slot(struct vma_slot *slot) ++{ ++ struct scan_rung *rung = slot->rung; ++ unsigned long dedup; ++ int deleted; ++ ++ dedup = cal_dedup_ratio(slot); ++ if (vma_fully_scanned(slot) && uksm_thrash_threshold) ++ deleted = vma_rung_enter(slot, &uksm_scan_ladder[0]); ++ else if (dedup && dedup >= uksm_abundant_threshold) ++ deleted = vma_rung_up(slot); ++ else ++ deleted = vma_rung_down(slot); ++ ++ slot->pages_merged = 0; ++ slot->pages_cowed = 0; ++ slot->this_sampled = 0; ++ ++ if (vma_fully_scanned(slot)) ++ slot->pages_scanned = 0; ++ ++ slot->last_scanned = slot->pages_scanned; ++ ++ /* If its deleted in above, then rung was already advanced. */ ++ if (!deleted) ++ advance_current_scan(rung); ++} ++ ++ ++static inline int hash_round_finished(void) ++{ ++ if (scanned_virtual_pages > (uksm_pages_total >> 2)) { ++ scanned_virtual_pages = 0; ++ if (uksm_pages_scanned) ++ fully_scanned_round++; ++ ++ return 1; ++ } else { ++ return 0; ++ } ++} ++ ++#define UKSM_MMSEM_BATCH 5 ++#define BUSY_RETRY 100 ++ ++/** ++ * uksm_do_scan() - the main worker function. ++ */ ++static noinline void uksm_do_scan(void) ++{ ++ struct vma_slot *slot, *iter; ++ struct mm_struct *busy_mm; ++ unsigned char round_finished, all_rungs_emtpy; ++ int i, err, mmsem_batch; ++ unsigned long pcost; ++ long long delta_exec; ++ unsigned long vpages, max_cpu_ratio; ++ unsigned long long start_time, end_time, scan_time; ++ unsigned int expected_jiffies; ++ ++ might_sleep(); ++ ++ vpages = 0; ++ ++ start_time = task_sched_runtime(current); ++ max_cpu_ratio = 0; ++ mmsem_batch = 0; ++ ++ for (i = 0; i < SCAN_LADDER_SIZE;) { ++ struct scan_rung *rung = &uksm_scan_ladder[i]; ++ unsigned long ratio; ++ int busy_retry; ++ ++ if (!rung->pages_to_scan) { ++ i++; ++ continue; ++ } ++ ++ if (!rung->vma_root.num) { ++ rung->pages_to_scan = 0; ++ i++; ++ continue; ++ } ++ ++ ratio = rung_real_ratio(rung->cpu_ratio); ++ if (ratio > max_cpu_ratio) ++ max_cpu_ratio = ratio; ++ ++ busy_retry = BUSY_RETRY; ++ /* ++ * Do not consider rung_round_finished() here, just used up the ++ * rung->pages_to_scan quota. ++ */ ++ while (rung->pages_to_scan && rung->vma_root.num && ++ likely(!freezing(current))) { ++ int reset = 0; ++ ++ slot = rung->current_scan; ++ ++ BUG_ON(vma_fully_scanned(slot)); ++ ++ if (mmsem_batch) ++ err = 0; ++ else ++ err = try_down_read_slot_mmap_sem(slot); ++ ++ if (err == -ENOENT) { ++rm_slot: ++ rung_rm_slot(slot); ++ continue; ++ } ++ ++ busy_mm = slot->mm; ++ ++ if (err == -EBUSY) { ++ /* skip other vmas on the same mm */ ++ do { ++ reset = advance_current_scan(rung); ++ iter = rung->current_scan; ++ busy_retry--; ++ if (iter->vma->vm_mm != busy_mm || ++ !busy_retry || reset) ++ break; ++ } while (1); ++ ++ if (iter->vma->vm_mm != busy_mm) { ++ continue; ++ } else { ++ /* scan round finsished */ ++ break; ++ } ++ } ++ ++ BUG_ON(!vma_can_enter(slot->vma)); ++ if (uksm_test_exit(slot->vma->vm_mm)) { ++ mmsem_batch = 0; ++ up_read(&slot->vma->vm_mm->mmap_sem); ++ goto rm_slot; ++ } ++ ++ if (mmsem_batch) ++ mmsem_batch--; ++ else ++ mmsem_batch = UKSM_MMSEM_BATCH; ++ ++ /* Ok, we have take the mmap_sem, ready to scan */ ++ scan_vma_one_page(slot); ++ rung->pages_to_scan--; ++ vpages++; ++ ++ if (rung->current_offset + rung->step > slot->pages - 1 ++ || vma_fully_scanned(slot)) { ++ up_read(&slot->vma->vm_mm->mmap_sem); ++ judge_slot(slot); ++ mmsem_batch = 0; ++ } else { ++ rung->current_offset += rung->step; ++ if (!mmsem_batch) ++ up_read(&slot->vma->vm_mm->mmap_sem); ++ } ++ ++ busy_retry = BUSY_RETRY; ++ cond_resched(); ++ } ++ ++ if (mmsem_batch) { ++ up_read(&slot->vma->vm_mm->mmap_sem); ++ mmsem_batch = 0; ++ } ++ ++ if (freezing(current)) ++ break; ++ ++ cond_resched(); ++ } ++ end_time = task_sched_runtime(current); ++ delta_exec = end_time - start_time; ++ ++ if (freezing(current)) ++ return; ++ ++ cleanup_vma_slots(); ++ uksm_enter_all_slots(); ++ ++ round_finished = 1; ++ all_rungs_emtpy = 1; ++ for (i = 0; i < SCAN_LADDER_SIZE; i++) { ++ struct scan_rung *rung = &uksm_scan_ladder[i]; ++ ++ if (rung->vma_root.num) { ++ all_rungs_emtpy = 0; ++ if (!rung_round_finished(rung)) ++ round_finished = 0; ++ } ++ } ++ ++ if (all_rungs_emtpy) ++ round_finished = 0; ++ ++ if (round_finished) { ++ round_update_ladder(); ++ uksm_eval_round++; ++ ++ if (hash_round_finished() && rshash_adjust()) { ++ /* Reset the unstable root iff hash strength changed */ ++ uksm_hash_round++; ++ root_unstable_tree = RB_ROOT; ++ free_all_tree_nodes(&unstable_tree_node_list); ++ } ++ ++ /* ++ * A number of pages can hang around indefinitely on per-cpu ++ * pagevecs, raised page count preventing write_protect_page ++ * from merging them. Though it doesn't really matter much, ++ * it is puzzling to see some stuck in pages_volatile until ++ * other activity jostles them out, and they also prevented ++ * LTP's KSM test from succeeding deterministically; so drain ++ * them here (here rather than on entry to uksm_do_scan(), ++ * so we don't IPI too often when pages_to_scan is set low). ++ */ ++ lru_add_drain_all(); ++ } ++ ++ ++ if (vpages && delta_exec > 0) { ++ pcost = (unsigned long) delta_exec / vpages; ++ if (likely(uksm_ema_page_time)) ++ uksm_ema_page_time = ema(pcost, uksm_ema_page_time); ++ else ++ uksm_ema_page_time = pcost; ++ } ++ ++ uksm_calc_scan_pages(); ++ uksm_sleep_real = uksm_sleep_jiffies; ++ /* in case of radical cpu bursts, apply the upper bound */ ++ end_time = task_sched_runtime(current); ++ if (max_cpu_ratio && end_time > start_time) { ++ scan_time = end_time - start_time; ++ expected_jiffies = msecs_to_jiffies( ++ scan_time_to_sleep(scan_time, max_cpu_ratio)); ++ ++ if (expected_jiffies > uksm_sleep_real) ++ uksm_sleep_real = expected_jiffies; ++ ++ /* We have a 1 second up bound for responsiveness. */ ++ if (jiffies_to_msecs(uksm_sleep_real) > MSEC_PER_SEC) ++ uksm_sleep_real = msecs_to_jiffies(1000); ++ } ++ ++ return; ++} ++ ++static int ksmd_should_run(void) ++{ ++ return uksm_run & UKSM_RUN_MERGE; ++} ++ ++static int uksm_scan_thread(void *nothing) ++{ ++ set_freezable(); ++ set_user_nice(current, 5); ++ ++ while (!kthread_should_stop()) { ++ mutex_lock(&uksm_thread_mutex); ++ if (ksmd_should_run()) ++ uksm_do_scan(); ++ mutex_unlock(&uksm_thread_mutex); ++ ++ try_to_freeze(); ++ ++ if (ksmd_should_run()) { ++ schedule_timeout_interruptible(uksm_sleep_real); ++ uksm_sleep_times++; ++ } else { ++ wait_event_freezable(uksm_thread_wait, ++ ksmd_should_run() || kthread_should_stop()); ++ } ++ } ++ return 0; ++} ++ ++void rmap_walk_ksm(struct page *page, struct rmap_walk_control *rwc) ++{ ++ struct stable_node *stable_node; ++ struct node_vma *node_vma; ++ struct rmap_item *rmap_item; ++ int search_new_forks = 0; ++ unsigned long address; ++ ++ VM_BUG_ON_PAGE(!PageKsm(page), page); ++ VM_BUG_ON_PAGE(!PageLocked(page), page); ++ ++ stable_node = page_stable_node(page); ++ if (!stable_node) ++ return; ++again: ++ hlist_for_each_entry(node_vma, &stable_node->hlist, hlist) { ++ hlist_for_each_entry(rmap_item, &node_vma->rmap_hlist, hlist) { ++ struct anon_vma *anon_vma = rmap_item->anon_vma; ++ struct anon_vma_chain *vmac; ++ struct vm_area_struct *vma; ++ ++ cond_resched(); ++ anon_vma_lock_read(anon_vma); ++ anon_vma_interval_tree_foreach(vmac, &anon_vma->rb_root, ++ 0, ULONG_MAX) { ++ cond_resched(); ++ vma = vmac->vma; ++ address = get_rmap_addr(rmap_item); ++ ++ if (address < vma->vm_start || ++ address >= vma->vm_end) ++ continue; ++ ++ if ((rmap_item->slot->vma == vma) == ++ search_new_forks) ++ continue; ++ ++ if (rwc->invalid_vma && rwc->invalid_vma(vma, rwc->arg)) ++ continue; ++ ++ if (!rwc->rmap_one(page, vma, address, rwc->arg)) { ++ anon_vma_unlock_read(anon_vma); ++ return; ++ } ++ ++ if (rwc->done && rwc->done(page)) { ++ anon_vma_unlock_read(anon_vma); ++ return; ++ } ++ } ++ anon_vma_unlock_read(anon_vma); ++ } ++ } ++ if (!search_new_forks++) ++ goto again; ++} ++ ++#ifdef CONFIG_MIGRATION ++/* Common ksm interface but may be specific to uksm */ ++void ksm_migrate_page(struct page *newpage, struct page *oldpage) ++{ ++ struct stable_node *stable_node; ++ ++ VM_BUG_ON_PAGE(!PageLocked(oldpage), oldpage); ++ VM_BUG_ON_PAGE(!PageLocked(newpage), newpage); ++ VM_BUG_ON(newpage->mapping != oldpage->mapping); ++ ++ stable_node = page_stable_node(newpage); ++ if (stable_node) { ++ VM_BUG_ON(stable_node->kpfn != page_to_pfn(oldpage)); ++ stable_node->kpfn = page_to_pfn(newpage); ++ /* ++ * newpage->mapping was set in advance; now we need smp_wmb() ++ * to make sure that the new stable_node->kpfn is visible ++ * to get_ksm_page() before it can see that oldpage->mapping ++ * has gone stale (or that PageSwapCache has been cleared). ++ */ ++ smp_wmb(); ++ set_page_stable_node(oldpage, NULL); ++ } ++} ++#endif /* CONFIG_MIGRATION */ ++ ++#ifdef CONFIG_MEMORY_HOTREMOVE ++static struct stable_node *uksm_check_stable_tree(unsigned long start_pfn, ++ unsigned long end_pfn) ++{ ++ struct rb_node *node; ++ ++ for (node = rb_first(root_stable_treep); node; node = rb_next(node)) { ++ struct stable_node *stable_node; ++ ++ stable_node = rb_entry(node, struct stable_node, node); ++ if (stable_node->kpfn >= start_pfn && ++ stable_node->kpfn < end_pfn) ++ return stable_node; ++ } ++ return NULL; ++} ++ ++static int uksm_memory_callback(struct notifier_block *self, ++ unsigned long action, void *arg) ++{ ++ struct memory_notify *mn = arg; ++ struct stable_node *stable_node; ++ ++ switch (action) { ++ case MEM_GOING_OFFLINE: ++ /* ++ * Keep it very simple for now: just lock out ksmd and ++ * MADV_UNMERGEABLE while any memory is going offline. ++ * mutex_lock_nested() is necessary because lockdep was alarmed ++ * that here we take uksm_thread_mutex inside notifier chain ++ * mutex, and later take notifier chain mutex inside ++ * uksm_thread_mutex to unlock it. But that's safe because both ++ * are inside mem_hotplug_mutex. ++ */ ++ mutex_lock_nested(&uksm_thread_mutex, SINGLE_DEPTH_NESTING); ++ break; ++ ++ case MEM_OFFLINE: ++ /* ++ * Most of the work is done by page migration; but there might ++ * be a few stable_nodes left over, still pointing to struct ++ * pages which have been offlined: prune those from the tree. ++ */ ++ while ((stable_node = uksm_check_stable_tree(mn->start_pfn, ++ mn->start_pfn + mn->nr_pages)) != NULL) ++ remove_node_from_stable_tree(stable_node, 1, 1); ++ /* fallthrough */ ++ ++ case MEM_CANCEL_OFFLINE: ++ mutex_unlock(&uksm_thread_mutex); ++ break; ++ } ++ return NOTIFY_OK; ++} ++#endif /* CONFIG_MEMORY_HOTREMOVE */ ++ ++#ifdef CONFIG_SYSFS ++/* ++ * This all compiles without CONFIG_SYSFS, but is a waste of space. ++ */ ++ ++#define UKSM_ATTR_RO(_name) \ ++ static struct kobj_attribute _name##_attr = __ATTR_RO(_name) ++#define UKSM_ATTR(_name) \ ++ static struct kobj_attribute _name##_attr = \ ++ __ATTR(_name, 0644, _name##_show, _name##_store) ++ ++static ssize_t max_cpu_percentage_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return sprintf(buf, "%u\n", uksm_max_cpu_percentage); ++} ++ ++static ssize_t max_cpu_percentage_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t count) ++{ ++ unsigned long max_cpu_percentage; ++ int err; ++ ++ err = kstrtoul(buf, 10, &max_cpu_percentage); ++ if (err || max_cpu_percentage > 100) ++ return -EINVAL; ++ ++ if (max_cpu_percentage == 100) ++ max_cpu_percentage = 99; ++ else if (max_cpu_percentage < 10) ++ max_cpu_percentage = 10; ++ ++ uksm_max_cpu_percentage = max_cpu_percentage; ++ ++ return count; ++} ++UKSM_ATTR(max_cpu_percentage); ++ ++static ssize_t sleep_millisecs_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return sprintf(buf, "%u\n", jiffies_to_msecs(uksm_sleep_jiffies)); ++} ++ ++static ssize_t sleep_millisecs_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t count) ++{ ++ unsigned long msecs; ++ int err; ++ ++ err = kstrtoul(buf, 10, &msecs); ++ if (err || msecs > MSEC_PER_SEC) ++ return -EINVAL; ++ ++ uksm_sleep_jiffies = msecs_to_jiffies(msecs); ++ uksm_sleep_saved = uksm_sleep_jiffies; ++ ++ return count; ++} ++UKSM_ATTR(sleep_millisecs); ++ ++ ++static ssize_t cpu_governor_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ int n = sizeof(uksm_cpu_governor_str) / sizeof(char *); ++ int i; ++ ++ buf[0] = '\0'; ++ for (i = 0; i < n ; i++) { ++ if (uksm_cpu_governor == i) ++ strcat(buf, "["); ++ ++ strcat(buf, uksm_cpu_governor_str[i]); ++ ++ if (uksm_cpu_governor == i) ++ strcat(buf, "]"); ++ ++ strcat(buf, " "); ++ } ++ strcat(buf, "\n"); ++ ++ return strlen(buf); ++} ++ ++static inline void init_performance_values(void) ++{ ++ int i; ++ struct scan_rung *rung; ++ struct uksm_cpu_preset_s *preset = uksm_cpu_preset + uksm_cpu_governor; ++ ++ ++ for (i = 0; i < SCAN_LADDER_SIZE; i++) { ++ rung = uksm_scan_ladder + i; ++ rung->cpu_ratio = preset->cpu_ratio[i]; ++ rung->cover_msecs = preset->cover_msecs[i]; ++ } ++ ++ uksm_max_cpu_percentage = preset->max_cpu; ++} ++ ++static ssize_t cpu_governor_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int n = sizeof(uksm_cpu_governor_str) / sizeof(char *); ++ ++ for (n--; n >= 0 ; n--) { ++ if (!strncmp(buf, uksm_cpu_governor_str[n], ++ strlen(uksm_cpu_governor_str[n]))) ++ break; ++ } ++ ++ if (n < 0) ++ return -EINVAL; ++ else ++ uksm_cpu_governor = n; ++ ++ init_performance_values(); ++ ++ return count; ++} ++UKSM_ATTR(cpu_governor); ++ ++static ssize_t run_show(struct kobject *kobj, struct kobj_attribute *attr, ++ char *buf) ++{ ++ return sprintf(buf, "%u\n", uksm_run); ++} ++ ++static ssize_t run_store(struct kobject *kobj, struct kobj_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int err; ++ unsigned long flags; ++ ++ err = kstrtoul(buf, 10, &flags); ++ if (err || flags > UINT_MAX) ++ return -EINVAL; ++ if (flags > UKSM_RUN_MERGE) ++ return -EINVAL; ++ ++ mutex_lock(&uksm_thread_mutex); ++ if (uksm_run != flags) ++ uksm_run = flags; ++ mutex_unlock(&uksm_thread_mutex); ++ ++ if (flags & UKSM_RUN_MERGE) ++ wake_up_interruptible(&uksm_thread_wait); ++ ++ return count; ++} ++UKSM_ATTR(run); ++ ++static ssize_t abundant_threshold_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return sprintf(buf, "%u\n", uksm_abundant_threshold); ++} ++ ++static ssize_t abundant_threshold_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int err; ++ unsigned long flags; ++ ++ err = kstrtoul(buf, 10, &flags); ++ if (err || flags > 99) ++ return -EINVAL; ++ ++ uksm_abundant_threshold = flags; ++ ++ return count; ++} ++UKSM_ATTR(abundant_threshold); ++ ++static ssize_t thrash_threshold_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return sprintf(buf, "%u\n", uksm_thrash_threshold); ++} ++ ++static ssize_t thrash_threshold_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int err; ++ unsigned long flags; ++ ++ err = kstrtoul(buf, 10, &flags); ++ if (err || flags > 99) ++ return -EINVAL; ++ ++ uksm_thrash_threshold = flags; ++ ++ return count; ++} ++UKSM_ATTR(thrash_threshold); ++ ++static ssize_t cpu_ratios_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ int i, size; ++ struct scan_rung *rung; ++ char *p = buf; ++ ++ for (i = 0; i < SCAN_LADDER_SIZE; i++) { ++ rung = &uksm_scan_ladder[i]; ++ ++ if (rung->cpu_ratio > 0) ++ size = sprintf(p, "%d ", rung->cpu_ratio); ++ else ++ size = sprintf(p, "MAX/%d ", ++ TIME_RATIO_SCALE / -rung->cpu_ratio); ++ ++ p += size; ++ } ++ ++ *p++ = '\n'; ++ *p = '\0'; ++ ++ return p - buf; ++} ++ ++static ssize_t cpu_ratios_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int i, cpuratios[SCAN_LADDER_SIZE], err; ++ unsigned long value; ++ struct scan_rung *rung; ++ char *p, *end = NULL; ++ ++ p = kzalloc(count, GFP_KERNEL); ++ if (!p) ++ return -ENOMEM; ++ ++ memcpy(p, buf, count); ++ ++ for (i = 0; i < SCAN_LADDER_SIZE; i++) { ++ if (i != SCAN_LADDER_SIZE - 1) { ++ end = strchr(p, ' '); ++ if (!end) ++ return -EINVAL; ++ ++ *end = '\0'; ++ } ++ ++ if (strstr(p, "MAX/")) { ++ p = strchr(p, '/') + 1; ++ err = kstrtoul(p, 10, &value); ++ if (err || value > TIME_RATIO_SCALE || !value) ++ return -EINVAL; ++ ++ cpuratios[i] = -(int) (TIME_RATIO_SCALE / value); ++ } else { ++ err = kstrtoul(p, 10, &value); ++ if (err || value > TIME_RATIO_SCALE || !value) ++ return -EINVAL; ++ ++ cpuratios[i] = value; ++ } ++ ++ p = end + 1; ++ } ++ ++ for (i = 0; i < SCAN_LADDER_SIZE; i++) { ++ rung = &uksm_scan_ladder[i]; ++ ++ rung->cpu_ratio = cpuratios[i]; ++ } ++ ++ return count; ++} ++UKSM_ATTR(cpu_ratios); ++ ++static ssize_t eval_intervals_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ int i, size; ++ struct scan_rung *rung; ++ char *p = buf; ++ ++ for (i = 0; i < SCAN_LADDER_SIZE; i++) { ++ rung = &uksm_scan_ladder[i]; ++ size = sprintf(p, "%u ", rung->cover_msecs); ++ p += size; ++ } ++ ++ *p++ = '\n'; ++ *p = '\0'; ++ ++ return p - buf; ++} ++ ++static ssize_t eval_intervals_store(struct kobject *kobj, ++ struct kobj_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int i, err; ++ unsigned long values[SCAN_LADDER_SIZE]; ++ struct scan_rung *rung; ++ char *p, *end = NULL; ++ ssize_t ret = count; ++ ++ p = kzalloc(count + 2, GFP_KERNEL); ++ if (!p) ++ return -ENOMEM; ++ ++ memcpy(p, buf, count); ++ ++ for (i = 0; i < SCAN_LADDER_SIZE; i++) { ++ if (i != SCAN_LADDER_SIZE - 1) { ++ end = strchr(p, ' '); ++ if (!end) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ *end = '\0'; ++ } ++ ++ err = kstrtoul(p, 10, &values[i]); ++ if (err) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ p = end + 1; ++ } ++ ++ for (i = 0; i < SCAN_LADDER_SIZE; i++) { ++ rung = &uksm_scan_ladder[i]; ++ ++ rung->cover_msecs = values[i]; ++ } ++ ++out: ++ kfree(p); ++ return ret; ++} ++UKSM_ATTR(eval_intervals); ++ ++static ssize_t ema_per_page_time_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return sprintf(buf, "%lu\n", uksm_ema_page_time); ++} ++UKSM_ATTR_RO(ema_per_page_time); ++ ++static ssize_t pages_shared_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return sprintf(buf, "%lu\n", uksm_pages_shared); ++} ++UKSM_ATTR_RO(pages_shared); ++ ++static ssize_t pages_sharing_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return sprintf(buf, "%lu\n", uksm_pages_sharing); ++} ++UKSM_ATTR_RO(pages_sharing); ++ ++static ssize_t pages_unshared_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return sprintf(buf, "%lu\n", uksm_pages_unshared); ++} ++UKSM_ATTR_RO(pages_unshared); ++ ++static ssize_t full_scans_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return sprintf(buf, "%llu\n", fully_scanned_round); ++} ++UKSM_ATTR_RO(full_scans); ++ ++static ssize_t pages_scanned_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ unsigned long base = 0; ++ u64 delta, ret; ++ ++ if (pages_scanned_stored) { ++ base = pages_scanned_base; ++ ret = pages_scanned_stored; ++ delta = uksm_pages_scanned >> base; ++ if (CAN_OVERFLOW_U64(ret, delta)) { ++ ret >>= 1; ++ delta >>= 1; ++ base++; ++ ret += delta; ++ } ++ } else { ++ ret = uksm_pages_scanned; ++ } ++ ++ while (ret > ULONG_MAX) { ++ ret >>= 1; ++ base++; ++ } ++ ++ if (base) ++ return sprintf(buf, "%lu * 2^%lu\n", (unsigned long)ret, base); ++ else ++ return sprintf(buf, "%lu\n", (unsigned long)ret); ++} ++UKSM_ATTR_RO(pages_scanned); ++ ++static ssize_t hash_strength_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return sprintf(buf, "%lu\n", hash_strength); ++} ++UKSM_ATTR_RO(hash_strength); ++ ++static ssize_t sleep_times_show(struct kobject *kobj, ++ struct kobj_attribute *attr, char *buf) ++{ ++ return sprintf(buf, "%llu\n", uksm_sleep_times); ++} ++UKSM_ATTR_RO(sleep_times); ++ ++ ++static struct attribute *uksm_attrs[] = { ++ &max_cpu_percentage_attr.attr, ++ &sleep_millisecs_attr.attr, ++ &cpu_governor_attr.attr, ++ &run_attr.attr, ++ &ema_per_page_time_attr.attr, ++ &pages_shared_attr.attr, ++ &pages_sharing_attr.attr, ++ &pages_unshared_attr.attr, ++ &full_scans_attr.attr, ++ &pages_scanned_attr.attr, ++ &hash_strength_attr.attr, ++ &sleep_times_attr.attr, ++ &thrash_threshold_attr.attr, ++ &abundant_threshold_attr.attr, ++ &cpu_ratios_attr.attr, ++ &eval_intervals_attr.attr, ++ NULL, ++}; ++ ++static struct attribute_group uksm_attr_group = { ++ .attrs = uksm_attrs, ++ .name = "uksm", ++}; ++#endif /* CONFIG_SYSFS */ ++ ++static inline void init_scan_ladder(void) ++{ ++ int i; ++ struct scan_rung *rung; ++ ++ for (i = 0; i < SCAN_LADDER_SIZE; i++) { ++ rung = uksm_scan_ladder + i; ++ slot_tree_init_root(&rung->vma_root); ++ } ++ ++ init_performance_values(); ++ uksm_calc_scan_pages(); ++} ++ ++static inline int cal_positive_negative_costs(void) ++{ ++ struct page *p1, *p2; ++ unsigned char *addr1, *addr2; ++ unsigned long i, time_start, hash_cost; ++ unsigned long loopnum = 0; ++ ++ /*IMPORTANT: volatile is needed to prevent over-optimization by gcc. */ ++ volatile u32 hash; ++ volatile int ret; ++ ++ p1 = alloc_page(GFP_KERNEL); ++ if (!p1) ++ return -ENOMEM; ++ ++ p2 = alloc_page(GFP_KERNEL); ++ if (!p2) ++ return -ENOMEM; ++ ++ addr1 = kmap_atomic(p1); ++ addr2 = kmap_atomic(p2); ++ memset(addr1, prandom_u32(), PAGE_SIZE); ++ memcpy(addr2, addr1, PAGE_SIZE); ++ ++ /* make sure that the two pages differ in last byte */ ++ addr2[PAGE_SIZE-1] = ~addr2[PAGE_SIZE-1]; ++ kunmap_atomic(addr2); ++ kunmap_atomic(addr1); ++ ++ time_start = jiffies; ++ while (jiffies - time_start < 100) { ++ for (i = 0; i < 100; i++) ++ hash = page_hash(p1, HASH_STRENGTH_FULL, 0); ++ loopnum += 100; ++ } ++ hash_cost = (jiffies - time_start); ++ ++ time_start = jiffies; ++ for (i = 0; i < loopnum; i++) ++ ret = pages_identical_with_cost(p1, p2); ++ memcmp_cost = HASH_STRENGTH_FULL * (jiffies - time_start); ++ memcmp_cost /= hash_cost; ++ pr_info("UKSM: relative memcmp_cost = %lu " ++ "hash=%u cmp_ret=%d.\n", ++ memcmp_cost, hash, ret); ++ ++ __free_page(p1); ++ __free_page(p2); ++ return 0; ++} ++ ++static int init_zeropage_hash_table(void) ++{ ++ struct page *page; ++ char *addr; ++ int i; ++ ++ page = alloc_page(GFP_KERNEL); ++ if (!page) ++ return -ENOMEM; ++ ++ addr = kmap_atomic(page); ++ memset(addr, 0, PAGE_SIZE); ++ kunmap_atomic(addr); ++ ++ zero_hash_table = kmalloc_array(HASH_STRENGTH_MAX, sizeof(u32), ++ GFP_KERNEL); ++ if (!zero_hash_table) ++ return -ENOMEM; ++ ++ for (i = 0; i < HASH_STRENGTH_MAX; i++) ++ zero_hash_table[i] = page_hash(page, i, 0); ++ ++ __free_page(page); ++ ++ return 0; ++} ++ ++static inline int init_random_sampling(void) ++{ ++ unsigned long i; ++ ++ random_nums = kmalloc(PAGE_SIZE, GFP_KERNEL); ++ if (!random_nums) ++ return -ENOMEM; ++ ++ for (i = 0; i < HASH_STRENGTH_FULL; i++) ++ random_nums[i] = i; ++ ++ for (i = 0; i < HASH_STRENGTH_FULL; i++) { ++ unsigned long rand_range, swap_index, tmp; ++ ++ rand_range = HASH_STRENGTH_FULL - i; ++ swap_index = i + prandom_u32() % rand_range; ++ tmp = random_nums[i]; ++ random_nums[i] = random_nums[swap_index]; ++ random_nums[swap_index] = tmp; ++ } ++ ++ rshash_state.state = RSHASH_NEW; ++ rshash_state.below_count = 0; ++ rshash_state.lookup_window_index = 0; ++ ++ return cal_positive_negative_costs(); ++} ++ ++static int __init uksm_slab_init(void) ++{ ++ rmap_item_cache = UKSM_KMEM_CACHE(rmap_item, 0); ++ if (!rmap_item_cache) ++ goto out; ++ ++ stable_node_cache = UKSM_KMEM_CACHE(stable_node, 0); ++ if (!stable_node_cache) ++ goto out_free1; ++ ++ node_vma_cache = UKSM_KMEM_CACHE(node_vma, 0); ++ if (!node_vma_cache) ++ goto out_free2; ++ ++ vma_slot_cache = UKSM_KMEM_CACHE(vma_slot, 0); ++ if (!vma_slot_cache) ++ goto out_free3; ++ ++ tree_node_cache = UKSM_KMEM_CACHE(tree_node, 0); ++ if (!tree_node_cache) ++ goto out_free4; ++ ++ return 0; ++ ++out_free4: ++ kmem_cache_destroy(vma_slot_cache); ++out_free3: ++ kmem_cache_destroy(node_vma_cache); ++out_free2: ++ kmem_cache_destroy(stable_node_cache); ++out_free1: ++ kmem_cache_destroy(rmap_item_cache); ++out: ++ return -ENOMEM; ++} ++ ++static void __init uksm_slab_free(void) ++{ ++ kmem_cache_destroy(stable_node_cache); ++ kmem_cache_destroy(rmap_item_cache); ++ kmem_cache_destroy(node_vma_cache); ++ kmem_cache_destroy(vma_slot_cache); ++ kmem_cache_destroy(tree_node_cache); ++} ++ ++/* Common interface to ksm, different to it. */ ++int ksm_madvise(struct vm_area_struct *vma, unsigned long start, ++ unsigned long end, int advice, unsigned long *vm_flags) ++{ ++ int err; ++ ++ switch (advice) { ++ case MADV_MERGEABLE: ++ return 0; /* just ignore the advice */ ++ ++ case MADV_UNMERGEABLE: ++ if (!(*vm_flags & VM_MERGEABLE) || !uksm_flags_can_scan(*vm_flags)) ++ return 0; /* just ignore the advice */ ++ ++ if (vma->anon_vma) { ++ err = unmerge_uksm_pages(vma, start, end); ++ if (err) ++ return err; ++ } ++ ++ uksm_remove_vma(vma); ++ *vm_flags &= ~VM_MERGEABLE; ++ break; ++ } ++ ++ return 0; ++} ++ ++/* Common interface to ksm, actually the same. */ ++struct page *ksm_might_need_to_copy(struct page *page, ++ struct vm_area_struct *vma, unsigned long address) ++{ ++ struct anon_vma *anon_vma = page_anon_vma(page); ++ struct page *new_page; ++ ++ if (PageKsm(page)) { ++ if (page_stable_node(page)) ++ return page; /* no need to copy it */ ++ } else if (!anon_vma) { ++ return page; /* no need to copy it */ ++ } else if (anon_vma->root == vma->anon_vma->root && ++ page->index == linear_page_index(vma, address)) { ++ return page; /* still no need to copy it */ ++ } ++ if (!PageUptodate(page)) ++ return page; /* let do_swap_page report the error */ ++ ++ new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address); ++ if (new_page) { ++ copy_user_highpage(new_page, page, address, vma); ++ ++ SetPageDirty(new_page); ++ __SetPageUptodate(new_page); ++ __SetPageLocked(new_page); ++ } ++ ++ return new_page; ++} ++ ++/* Copied from mm/ksm.c and required from 5.1 */ ++bool reuse_ksm_page(struct page *page, ++ struct vm_area_struct *vma, ++ unsigned long address) ++{ ++#ifdef CONFIG_DEBUG_VM ++ if (WARN_ON(is_zero_pfn(page_to_pfn(page))) || ++ WARN_ON(!page_mapped(page)) || ++ WARN_ON(!PageLocked(page))) { ++ dump_page(page, "reuse_ksm_page"); ++ return false; ++ } ++#endif ++ ++ if (PageSwapCache(page) || !page_stable_node(page)) ++ return false; ++ /* Prohibit parallel get_ksm_page() */ ++ if (!page_ref_freeze(page, 1)) ++ return false; ++ ++ page_move_anon_rmap(page, vma); ++ page->index = linear_page_index(vma, address); ++ page_ref_unfreeze(page, 1); ++ ++ return true; ++} ++ ++static int __init uksm_init(void) ++{ ++ struct task_struct *uksm_thread; ++ int err; ++ ++ uksm_sleep_jiffies = msecs_to_jiffies(100); ++ uksm_sleep_saved = uksm_sleep_jiffies; ++ ++ slot_tree_init(); ++ init_scan_ladder(); ++ ++ ++ err = init_random_sampling(); ++ if (err) ++ goto out_free2; ++ ++ err = uksm_slab_init(); ++ if (err) ++ goto out_free1; ++ ++ err = init_zeropage_hash_table(); ++ if (err) ++ goto out_free0; ++ ++ uksm_thread = kthread_run(uksm_scan_thread, NULL, "uksmd"); ++ if (IS_ERR(uksm_thread)) { ++ pr_err("uksm: creating kthread failed\n"); ++ err = PTR_ERR(uksm_thread); ++ goto out_free; ++ } ++ ++#ifdef CONFIG_SYSFS ++ err = sysfs_create_group(mm_kobj, &uksm_attr_group); ++ if (err) { ++ pr_err("uksm: register sysfs failed\n"); ++ kthread_stop(uksm_thread); ++ goto out_free; ++ } ++#else ++ uksm_run = UKSM_RUN_MERGE; /* no way for user to start it */ ++ ++#endif /* CONFIG_SYSFS */ ++ ++#ifdef CONFIG_MEMORY_HOTREMOVE ++ /* ++ * Choose a high priority since the callback takes uksm_thread_mutex: ++ * later callbacks could only be taking locks which nest within that. ++ */ ++ hotplug_memory_notifier(uksm_memory_callback, 100); ++#endif ++ return 0; ++ ++out_free: ++ kfree(zero_hash_table); ++out_free0: ++ uksm_slab_free(); ++out_free1: ++ kfree(random_nums); ++out_free2: ++ kfree(uksm_scan_ladder); ++ return err; ++} ++ ++#ifdef MODULE ++subsys_initcall(ksm_init); ++#else ++late_initcall(uksm_init); ++#endif ++ +diff --git a/mm/vmstat.c b/mm/vmstat.c +index a8222041bd44..7058e8322cbd 100644 +--- a/mm/vmstat.c ++++ b/mm/vmstat.c +@@ -1168,6 +1168,9 @@ const char * const vmstat_text[] = { + "nr_written", + "nr_kernel_misc_reclaimable", + ++#ifdef CONFIG_UKSM ++ "nr_uksm_zero_pages", ++#endif + /* enum writeback_stat_item counters */ + "nr_dirty_threshold", + "nr_dirty_background_threshold", diff --git a/README.md b/README.md index 200d40975..0eb683747 100644 --- a/README.md +++ b/README.md @@ -22,26 +22,21 @@ ### 特性 - 基于原生 OpenWrt 21.02 编译,默认管理地址192.168.1.1 -- 同时支持 SFE/Software Offload (选则其一开启,默认开启SFE) +- 默认开启了 Software Offload - 内置升级功能可用,物理 Reset 按键可用 - 预配置了部分插件(包括但不限于 DNS 套娃,(注意,6月29日开始取消了dns套娃,使用dnsfilter作为广告过滤手段,使用dnsproxy作为dns分流措施,海外端口5335,国内端口6050。) -- 正式 Release 版本将具有可无脑 opkg kmod 的特性 +- 可无脑 opkg kmod - R2S核心频率1.6(交换了LAN WAN),R4S核心频率2.2/1.8(建议使用5v4a电源,死机大多数情况下,都是因为你用的电源过于垃圾,另外,你也可以选择使用自带的app限制最大频率,茄子🍆) -- O3 编译 -- 插件包含:SSRP,PassWall,OpenClash,AdguardHome,微信推送,网易云解锁,SQM,SmartDNS,ChinaDNS,网络唤醒,DDNS,迅雷快鸟,UPNP,FullCone(防火墙中开启,默认开启),流量分载,SFE流量分载,irq优化,京东签到,Zerotier,FRPC,FRPS,无线打印,流量监控,过滤军刀,R2S-OLED +- O3 编译,CFLAG优化 +- 插件包含:SSRP,PassWall,OpenClash,AdguardHome,微信推送,网易云解锁,SQM,DNSProxy,网络唤醒,DDNS,迅雷快鸟,UPNP,FullCone(防火墙中开启,默认开启),流量分载,irq优化,京东签到,Zerotier,FRPC,FRPS,无线打印,流量监控,过滤军刀,R2S-OLED - ss协议在armv8上实现了aes硬件加速(请仅使用aead加密的连接方式) +- 集成并默认启用了UKSM,BBRv2,以及CacULE Scheduler - 如有任何问题,请先尝试ssh进入后台,输入fuck后回车,等待机器重启后确认问题是否已经解决 ### 下载 - 选择自己设备对应的固件,并[下载](https://github.com/QiuSimons/R2S-R4S-OpenWrt/releases) -### 截图 - -| 组件 | 流量分载 | -| :----------------------------------------------------------: | :----------------------------------------------------------: | -| ![主页.png](https://raw.githubusercontent.com/QiuSimons/R4S-OpenWrt/master/PIC/app.png) | ![offload.png](https://raw.githubusercontent.com/QiuSimons/R4S-OpenWrt/master/PIC/offload.png) | - ### 鸣谢 | [CTCGFW](https://github.com/immortalwrt) | [coolsnowwolf](https://github.com/coolsnowwolf) | [Lienol](https://github.com/Lienol) | diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index c08657d52..934c8bae3 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -17,7 +17,7 @@ rm -rf ./scripts/download.pl rm -rf ./include/download.mk wget -P scripts/ https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/scripts/download.pl wget -P include/ https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/include/download.mk -wget -P include/ https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/include/package-immortalwrt.mk +#wget -P include/ https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/include/package-immortalwrt.mk sed -i '/unshift/d' scripts/download.pl sed -i '/mirror02/d' scripts/download.pl echo "net.netfilter.nf_conntrack_helper = 1" >> ./package/kernel/linux/files/sysctl-nf-conntrack.conf @@ -155,13 +155,13 @@ git clone -b luci --depth 1 https://github.com/pexcn/openwrt-chinadns-ng.git pac svn co https://github.com/xiaorouji/openwrt-passwall/trunk/chinadns-ng package/new/chinadns-ng # 内存压缩 #wget -O- https://patch-diff.githubusercontent.com/raw/openwrt/openwrt/pull/2840.patch | patch -p1 -wget -O- https://github.com/NoTengoBattery/openwrt/commit/40f1d5.patch | patch -p1 -wget -O- https://github.com/NoTengoBattery/openwrt/commit/a83a0b.patch | patch -p1 -wget -O- https://github.com/NoTengoBattery/openwrt/commit/6d5fb4.patch | patch -p1 -mkdir ./package/new -cp -rf ../NoTengoBattery/feeds/luci/applications/luci-app-compressed-memory ./package/new/luci-app-compressed-memory -sed -i 's,include ../..,include $(TOPDIR)/feeds/luci,g' ./package/new/luci-app-compressed-memory/Makefile -cp -rf ../NoTengoBattery/package/system/compressed-memory ./package/system/compressed-memory +#wget -O- https://github.com/NoTengoBattery/openwrt/commit/40f1d5.patch | patch -p1 +#wget -O- https://github.com/NoTengoBattery/openwrt/commit/a83a0b.patch | patch -p1 +#wget -O- https://github.com/NoTengoBattery/openwrt/commit/6d5fb4.patch | patch -p1 +#mkdir ./package/new +#cp -rf ../NoTengoBattery/feeds/luci/applications/luci-app-compressed-memory ./package/new/luci-app-compressed-memory +#sed -i 's,include ../..,include $(TOPDIR)/feeds/luci,g' ./package/new/luci-app-compressed-memory/Makefile +#cp -rf ../NoTengoBattery/package/system/compressed-memory ./package/system/compressed-memory # CPU 控制相关 svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-cpufreq feeds/luci/applications/luci-app-cpufreq ln -sf ../../../feeds/luci/applications/luci-app-cpufreq ./package/feeds/luci/luci-app-cpufreq @@ -176,11 +176,11 @@ ln -sf ../../../feeds/packages/utils/cpulimit ./package/feeds/packages/cpulimit #rm -rf ./feeds/luci/applications/luci-app-ddns #svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/ddns-scripts_aliyun package/lean/ddns-scripts_aliyun #svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/ddns-scripts_dnspod package/lean/ddns-scripts_dnspod +#svn co https://github.com/openwrt/packages/branches/openwrt-18.06/net/ddns-scripts feeds/packages/net/ddns-scripts +#svn co https://github.com/openwrt/luci/branches/openwrt-18.06/applications/luci-app-ddns feeds/luci/applications/luci-app-ddns git clone --depth 1 https://github.com/small-5/ddns-scripts-dnspod package/lean/ddns-scripts_dnspod git clone --depth 1 https://github.com/small-5/ddns-scripts-aliyun package/lean/ddns-scripts_aliyun -svn co https://github.com/openwrt/packages/branches/openwrt-18.06/net/ddns-scripts feeds/packages/net/ddns-scripts -svn co https://github.com/openwrt/luci/branches/openwrt-18.06/applications/luci-app-ddns feeds/luci/applications/luci-app-ddns -svn co https://github.com/QiuSimons/OpenWrt_luci-app/trunk/others/luci-app-tencentddns package/lean/luci-app-tencentddns +svn co https://github.com/QiuSimons/OpenWrt_luci-app/trunk/luci-app-tencentddns package/lean/luci-app-tencentddns svn co https://github.com/kenzok8/openwrt-packages/trunk/luci-app-aliddns feeds/luci/applications/luci-app-aliddns ln -sf ../../../feeds/luci/applications/luci-app-aliddns ./package/feeds/luci/luci-app-aliddns # Docker 容器(会导致 OpenWrt 出现 UDP 转发问题,慎用) @@ -208,13 +208,13 @@ svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-ipsec-vp svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/ipv6-helper package/lean/ipv6-helper # 京东签到 By Jerrykuku git clone --depth 1 https://github.com/jerrykuku/node-request.git package/new/node-request -svn co -r131 https://github.com/jerrykuku/luci-app-jd-dailybonus/trunk package/new/luci-app-jd-dailybonus -pushd package/new/luci-app-jd-dailybonus -sed -i 's,wget-ssl,wget,g' root/usr/share/jd-dailybonus/newapp.sh luasrc/controller/jd-dailybonus.lua -sed -i 's,* sh,*,g' root/usr/share/jd-dailybonus/newapp.sh -popd -rm -rf ./package/new/luci-app-jd-dailybonus/root/usr/share/jd-dailybonus/JD_DailyBonus.js -wget -P package/new/luci-app-jd-dailybonus/root/usr/share/jd-dailybonus/ https://github.com/NobyDa/Script/raw/master/JD-DailyBonus/JD_DailyBonus.js +git clone --depth 1 https://github.com/jerrykuku/luci-app-jd-dailybonus.git package/new/luci-app-jd-dailybonus +#pushd package/new/luci-app-jd-dailybonus +#sed -i 's,wget-ssl,wget,g' root/usr/share/jd-dailybonus/newapp.sh luasrc/controller/jd-dailybonus.lua +#sed -i 's,* sh,*,g' root/usr/share/jd-dailybonus/newapp.sh +#popd +#rm -rf ./package/new/luci-app-jd-dailybonus/root/usr/share/jd-dailybonus/JD_DailyBonus.js +#wget -P package/new/luci-app-jd-dailybonus/root/usr/share/jd-dailybonus/ https://github.com/NobyDa/Script/raw/master/JD-DailyBonus/JD_DailyBonus.js # 回滚通用即插即用 #rm -rf ./feeds/packages/net/miniupnpd #svn co https://github.com/coolsnowwolf/packages/trunk/net/miniupnpd feeds/packages/net/miniupnpd @@ -284,7 +284,6 @@ rm -rf ./feeds/luci/applications/luci-app-smartdns svn co https://github.com/immortalwrt/luci/branches/openwrt-18.06/applications/luci-app-smartdns feeds/luci/applications/luci-app-smartdns # ShadowsocksR Plus+ 依赖 rm -rf ./feeds/packages/net/kcptun -rm -rf ./feeds/packages/net/proxychains-ng rm -rf ./feeds/packages/net/shadowsocks-libev rm -rf ./feeds/packages/net/xray-core #svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/shadowsocksr-libev package/lean/shadowsocksr-libev @@ -295,7 +294,6 @@ svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/srelay package/le svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/microsocks package/lean/microsocks svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/dns2socks package/lean/dns2socks svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/redsocks2 package/lean/redsocks2 -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/proxychains-ng package/lean/proxychains-ng svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/ipt2socks package/lean/ipt2socks svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/simple-obfs package/lean/simple-obfs svn co https://github.com/coolsnowwolf/packages/trunk/net/shadowsocks-libev package/lean/shadowsocks-libev diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index a597c8dd7..20896c3bc 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -15,6 +15,12 @@ echo ' CONFIG_NR_CPUS=4 ' >> ./target/linux/rockchip/armv8/config-5.4 +# UKSM +echo ' +CONFIG_KSM=y +CONFIG_UKSM=y +' >> ./target/linux/rockchip/armv8/config-5.4 + # 配置 IRQ 并默认关闭 eth0 offloading rx/rx sed -i '/set_interface_core 4 "eth1"/a\set_interface_core 8 "ff160000" "ff160000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity sed -i '/set_interface_core 4 "eth1"/a\set_interface_core 1 "ff150000" "ff150000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index 440006295..01e686e04 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -10,20 +10,18 @@ sed -i 's,kmod-r8169,kmod-r8168,g' target/linux/rockchip/image/armv8.mk wget -P target/linux/rockchip/armv8/base-files/etc/init.d/ https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3399/base-files/etc/init.d/fa-rk3399-pwmfan wget -P target/linux/rockchip/armv8/base-files/usr/bin/ https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3399/base-files/usr/bin/start-rk3399-pwm-fan.sh -# 测试性功能 -sed -i '/CRYPTO_DEV_ROCKCHIP/d' ./target/linux/rockchip/armv8/config-5.4 -sed -i '/HW_RANDOM_ROCKCHIP/d' ./target/linux/rockchip/armv8/config-5.4 -echo ' -CONFIG_CRYPTO_DEV_ROCKCHIP=y -CONFIG_HW_RANDOM_ROCKCHIP=y -' >> ./target/linux/rockchip/armv8/config-5.4 - # CacULE sed -i '/CONFIG_NR_CPUS/d' ./target/linux/rockchip/armv8/config-5.4 echo ' CONFIG_NR_CPUS=6 ' >> ./target/linux/rockchip/armv8/config-5.4 +# UKSM +echo ' +CONFIG_KSM=y +CONFIG_UKSM=y +' >> ./target/linux/rockchip/armv8/config-5.4 + # IRQ 调优 sed -i '/set_interface_core 20 "eth1"/a\set_interface_core 8 "ff3c0000" "ff3c0000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity sed -i '/set_interface_core 20 "eth1"/a\ethtool -C eth0 rx-usecs 1000 rx-frames 25 tx-usecs 100 tx-frames 25' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity diff --git a/SCRIPTS/X86/02_target_only.sh b/SCRIPTS/X86/02_target_only.sh index 5c0ff3183..a513cfa69 100644 --- a/SCRIPTS/X86/02_target_only.sh +++ b/SCRIPTS/X86/02_target_only.sh @@ -10,6 +10,12 @@ echo ' CONFIG_CRYPTO_AES_NI_INTEL=y ' >> ./target/linux/x86/64/config-5.4 +# UKSM +echo ' +CONFIG_KSM=y +CONFIG_UKSM=y +' >> ./target/linux/x86/64/config-5.4 + #Vermagic latest_version="$(curl -s https://github.com/openwrt/openwrt/releases |grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" |sed -n '/21/p' |sed -n 1p |sed 's/v//g' |sed 's/.tar.gz//g')" wget https://downloads.openwrt.org/releases/${latest_version}/targets/x86/64/packages/Packages.gz diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index ee9213c24..8768f8415 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -13,6 +13,7 @@ CONFIG_NODEJS_14=y CONFIG_NODEJS_ICU_NONE=y CONFIG_DEVEL=y CONFIG_TOOLCHAINOPTS=y +CONFIG_GCC_USE_VERSION_7=y ### BASIC ### CONFIG_PACKAGE_r8169-firmware=y @@ -41,9 +42,6 @@ CONFIG_PACKAGE_kmod-ipt-nat6=y CONFIG_PACKAGE_kmod-tun=y #CONFIG_PACKAGE_kmod-shortcut-fe=y #CONFIG_PACKAGE_kmod-fast-classifier=y -CONFIG_PACKAGE_kmod-usb2=y -CONFIG_PACKAGE_kmod-usb2-pci=y -CONFIG_PACKAGE_kmod-usb3=y # CONFIG_PACKAGE_kmod-shortcut-fe-cm is not set CONFIG_PACKAGE_libiwinfo=y CONFIG_PACKAGE_libiwinfo-lua=y @@ -132,12 +130,6 @@ CONFIG_PACKAGE_subconverter=y CONFIG_PACKAGE_dnsproxy=y CONFIG_PACKAGE_luci-app-dnsfilter=y -### ZRAM ### -CONFIG_PACKAGE_luci-app-compressed-memory=y -CONFIG_PACKAGE_zram-swap=n -CONFIG_PACKAGE_block-mount=y -CONFIG_PACKAGE_swap-utils=y - ### THEME ### CONFIG_PACKAGE_luci-theme-argon=y CONFIG_PACKAGE_luci-theme-bootstrap=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index fe01cd954..e38091c00 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -13,6 +13,7 @@ CONFIG_NODEJS_14=y CONFIG_NODEJS_ICU_NONE=y CONFIG_DEVEL=y CONFIG_TOOLCHAINOPTS=y +CONFIG_GCC_USE_VERSION_7=y ### BASIC ### CONFIG_PACKAGE_r8169-firmware=y diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index 3c2c51f02..ec530887a 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -14,6 +14,7 @@ CONFIG_NODEJS_14=y CONFIG_NODEJS_ICU_NONE=y CONFIG_DEVEL=y CONFIG_TOOLCHAINOPTS=y +CONFIG_GCC_USE_VERSION_7=y ### BASIC ### CONFIG_PACKAGE_addition-trans-zh=y From 5f813331ca9b00a54351fd5fff4e1a414260cdec Mon Sep 17 00:00:00 2001 From: Topsy Chen <62056970+thomaswcy@users.noreply.github.com> Date: Thu, 19 Aug 2021 12:35:32 +0800 Subject: [PATCH 178/244] Add Support for NanoPi R2C (#220) --- .github/workflows/R2C-OpenWrt.yml | 147 ++++++++++++++ .github/workflows/R2S-OpenWrt.yml | 4 +- .github/workflows/R4S-OpenWrt.yml | 4 +- .github/workflows/X86-OpenWrt.yml | 4 +- ...U-temperature-for-thermal-throttling.patch | 4 +- README.md | 13 +- SCRIPTS/R2C/02_target_only.sh | 50 +++++ SEED/R2C/config.seed | 189 ++++++++++++++++++ 8 files changed, 401 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/R2C-OpenWrt.yml create mode 100644 SCRIPTS/R2C/02_target_only.sh create mode 100644 SEED/R2C/config.seed diff --git a/.github/workflows/R2C-OpenWrt.yml b/.github/workflows/R2C-OpenWrt.yml new file mode 100644 index 000000000..2c8e8c023 --- /dev/null +++ b/.github/workflows/R2C-OpenWrt.yml @@ -0,0 +1,147 @@ +name: R2C-OpenWrt + +on: +# schedule: +# - cron: 5 6 * * 0 + watch: + types: started + +jobs: + build: + runs-on: ubuntu-20.04 + if: github.event.repository.owner.id == github.event.sender.id + + steps: + - name: Checkout + uses: actions/checkout@main + - name: Show system + run: | + echo -e "Total CPU cores\t: $(nproc)" + cat /proc/cpuinfo | grep 'model name' + free -h + uname -a + [ -f /proc/version ] && cat /proc/version + [ -f /etc/issue.net ] && cat /etc/issue.net + [ -f /etc/issue ] && cat /etc/issue + ulimit -a + - name: Free disk space + run: | + sudo -E swapoff -a + sudo -E rm -f /swapfile + sudo -E docker image prune -a -f + sudo -E snap set system refresh.retain=2 + sudo -E apt-get -y purge azure* dotnet* firefox ghc* google* hhvm llvm* mono* mysql* openjdk* php* zulu* + sudo -E apt-get -y autoremove --purge + sudo -E apt-get clean + sudo -E rm -rf /usr/share/dotnet /usr/local/lib/android/sdk /etc/mysql /etc/php /usr/local/share/boost + [ -n "$AGENT_TOOLSDIRECTORY" ] && sudo rm -rf "$AGENT_TOOLSDIRECTORY" + df -h + - name: Init build dependencies + env: + DEBIAN_FRONTEND: noninteractive + run: | + sudo -E rm -rf /etc/apt/sources.list.d + sudo -E apt-get update -y + sudo -E apt-get install -y build-essential rsync asciidoc binutils bzip2 gawk gettext git libncurses5-dev libz-dev patch unzip zlib1g-dev lib32gcc1 libc6-dev-i386 subversion flex uglifyjs git-core p7zip p7zip-full msmtp libssl-dev texinfo libreadline-dev libglib2.0-dev xmlto qemu-utils upx libelf-dev autoconf automake libtool autopoint ccache curl wget vim nano python3 python3-pip python3-ply haveged lrzsz device-tree-compiler scons + wget -qO - https://raw.githubusercontent.com/friendlyarm/build-env-on-ubuntu-bionic/master/install.sh | sed 's/python-/python3-/g' | /bin/bash + sudo -E apt-get clean -y + git config --global user.name 'GitHub Actions' && git config --global user.email 'noreply@github.com' + df -h + - name: Prepare Mixedwrt + run: | + sudo chown -R runner:runner /home/runner/work/YAOF + cp -r ./SCRIPTS/R2C/. ./SCRIPTS/ + cp -r ./SCRIPTS/. ./ + /bin/bash 01_get_ready.sh + - name: Prepare Package + run: | + cd openwrt + rm -rf target/linux/rockchip + svn co https://github.com/immortalwrt/immortalwrt/branches/master/target/linux/rockchip target/linux/rockchip + rm -rf package/boot + svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/boot package/boot + cp -r ../SCRIPTS/. ./ + /bin/bash 02_prepare_package.sh + /bin/bash 02_target_only.sh + - name: Convert Translation + run: | + cd openwrt + /bin/bash 03_convert_translation.sh + - name: Add ACL + run: | + cd openwrt + /bin/bash 05_create_acl_for_luci.sh -a + - name: Make Config + run: | + cd openwrt + mv ../SEED/R2C/config.seed .config + make defconfig + - name: Smart chmod + run: | + MY_Filter=$(mktemp) + echo '/\.git' > ${MY_Filter} + echo '/\.svn' >> ${MY_Filter} + find ./ -maxdepth 1 | grep -v '\./$' | grep -v '/\.git' | xargs -s1024 chmod -R u=rwX,og=rX + find ./ -type f | grep -v -f ${MY_Filter} | xargs -s1024 file | grep 'executable\|ELF' | cut -d ':' -f1 | xargs -s1024 chmod 755 + rm -f ${MY_Filter} + unset MY_Filter + - name: Make Download + run: | + df -h + cd openwrt + make download -j50 + - name: Make Toolchain + run: | + df -h + cd openwrt + let make_process=$(nproc)+2 + make toolchain/install -j${make_process} || make toolchain/install -j${make_process} V=s + - name: Compile Openwrt + id: compileopenwrt + continue-on-error: true + run: | + df -h + cd openwrt + let Make_Process=$(nproc)+2 + make -j${Make_Process} || make -j${Make_Process} V=s + echo $? + - name: If Error + if: steps.compileopenwrt.outcome == 'failure' + run: | + cat openwrt/.config + echo '================================================================' + cd openwrt && make -j1 V=s + - name: Print Disk Space After + run: df -h + - name: Organize files + id: organize + run: | + rm -rf ./artifact/ + mkdir -p ./artifact/ + mv openwrt/bin/targets/rockchip/armv8/*sysupgrade.img* ./artifact/ + cd ./artifact/ + ls -Ahl + gzip -d *.gz && exit 0 + gzip --best *.img + ls -Ahl + sha256sum openwrt*r2s* | tee R2C-GC404-$(date +%Y-%m-%d)-21.02.sha256sum + zip R2C-GC404-$(date +%Y-%m-%d)-21.02-ext4.zip *r2s*ext4* + zip R2C-GC404-$(date +%Y-%m-%d)-21.02-sfs.zip *r2s*squashfs* + ls -Ahl + - name: Upload artifact + uses: actions/upload-artifact@main + with: + name: OpenWRT_21.02 + path: ./artifact/ + + - name: Create release + id: create_release + uses: ncipollo/release-action@v1.8.0 + with: + name: OpenWRT-21.02.0-RC4 + allowUpdates: true + tag: 21.02.0-rc4 + commit: master + replacesArtifacts: true + token: ${{ secrets.workflow_token }} + artifacts: ./artifact/*.zip diff --git a/.github/workflows/R2S-OpenWrt.yml b/.github/workflows/R2S-OpenWrt.yml index 683a7cd00..98db410fc 100644 --- a/.github/workflows/R2S-OpenWrt.yml +++ b/.github/workflows/R2S-OpenWrt.yml @@ -49,7 +49,7 @@ jobs: df -h - name: Prepare Mixedwrt run: | - sudo chown -R runner:runner /home/runner/work/R2S-R4S-X86-OpenWrt + sudo chown -R runner:runner /home/runner/work/YAOF cp -r ./SCRIPTS/R2S/. ./SCRIPTS/ cp -r ./SCRIPTS/. ./ /bin/bash 01_get_ready.sh @@ -136,7 +136,7 @@ jobs: id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-R2S-R4S-X86-21.02.0-RC4 + name: OpenWRT-21.02.0-RC4 allowUpdates: true tag: 21.02.0-rc4 commit: master diff --git a/.github/workflows/R4S-OpenWrt.yml b/.github/workflows/R4S-OpenWrt.yml index 23551c7c4..1973c97cf 100644 --- a/.github/workflows/R4S-OpenWrt.yml +++ b/.github/workflows/R4S-OpenWrt.yml @@ -49,7 +49,7 @@ jobs: df -h - name: Prepare Mixedwrt run: | - sudo chown -R runner:runner /home/runner/work/R2S-R4S-X86-OpenWrt + sudo chown -R runner:runner /home/runner/work/YAOF cp -r ./SCRIPTS/R4S/. ./SCRIPTS/ cp -r ./SCRIPTS/. ./ /bin/bash 01_get_ready.sh @@ -136,7 +136,7 @@ jobs: id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-R2S-R4S-X86-21.02.0-RC4 + name: OpenWRT-21.02.0-RC4 allowUpdates: true tag: 21.02.0-rc4 commit: master diff --git a/.github/workflows/X86-OpenWrt.yml b/.github/workflows/X86-OpenWrt.yml index 74bd3dab5..650a14652 100644 --- a/.github/workflows/X86-OpenWrt.yml +++ b/.github/workflows/X86-OpenWrt.yml @@ -49,7 +49,7 @@ jobs: df -h - name: Prepare Mixedwrt run: | - sudo chown -R runner:runner /home/runner/work/R2S-R4S-X86-OpenWrt + sudo chown -R runner:runner /home/runner/work/YAOF cp -r ./SCRIPTS/X86/. ./SCRIPTS/ cp -r ./SCRIPTS/. ./ /bin/bash 01_get_ready.sh @@ -136,7 +136,7 @@ jobs: id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-R2S-R4S-X86-21.02.0-RC4 + name: OpenWRT-21.02.0-RC4 allowUpdates: true tag: 21.02.0-rc4 commit: master diff --git a/PATCH/target_r4s/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch b/PATCH/target_r4s/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch index dca0a5d82..c4ba0dfed 100644 --- a/PATCH/target_r4s/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch +++ b/PATCH/target_r4s/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch @@ -16,13 +16,13 @@ index 2551b238b97c6..a53ff24d92bad 100644 trips { cpu_alert0: cpu_alert0 { - temperature = <70000>; -+ temperature = <80000>; ++ temperature = <75000>; hysteresis = <2000>; type = "passive"; }; cpu_alert1: cpu_alert1 { - temperature = <75000>; -+ temperature = <85000>; ++ temperature = <80000>; hysteresis = <2000>; type = "passive"; }; diff --git a/README.md b/README.md index 0eb683747..539b8e3d1 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,14 @@

-GitHub All Releases -GitHub +GitHub All Releases +GitHub

- - - + + + +

@@ -26,7 +27,7 @@ - 内置升级功能可用,物理 Reset 按键可用 - 预配置了部分插件(包括但不限于 DNS 套娃,(注意,6月29日开始取消了dns套娃,使用dnsfilter作为广告过滤手段,使用dnsproxy作为dns分流措施,海外端口5335,国内端口6050。) - 可无脑 opkg kmod -- R2S核心频率1.6(交换了LAN WAN),R4S核心频率2.2/1.8(建议使用5v4a电源,死机大多数情况下,都是因为你用的电源过于垃圾,另外,你也可以选择使用自带的app限制最大频率,茄子🍆) +- R2C/R2S核心频率1.6(交换了LAN WAN),R4S核心频率2.2/1.8(建议使用5v4a电源,死机大多数情况下,都是因为你用的电源过于垃圾,另外,你也可以选择使用自带的app限制最大频率,茄子🍆) - O3 编译,CFLAG优化 - 插件包含:SSRP,PassWall,OpenClash,AdguardHome,微信推送,网易云解锁,SQM,DNSProxy,网络唤醒,DDNS,迅雷快鸟,UPNP,FullCone(防火墙中开启,默认开启),流量分载,irq优化,京东签到,Zerotier,FRPC,FRPS,无线打印,流量监控,过滤军刀,R2S-OLED - ss协议在armv8上实现了aes硬件加速(请仅使用aead加密的连接方式) diff --git a/SCRIPTS/R2C/02_target_only.sh b/SCRIPTS/R2C/02_target_only.sh new file mode 100644 index 000000000..20896c3bc --- /dev/null +++ b/SCRIPTS/R2C/02_target_only.sh @@ -0,0 +1,50 @@ +#!/bin/bash +clear + +# 使用专属优化 +sed -i 's,-mcpu=generic,-mcpu=cortex-a53+crypto,g' include/target.mk +cp -f ../PATCH/mbedtls/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch ./package/libs/mbedtls/patches/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch + +#增加风扇调速(被动散热不香么? +wget -P target/linux/rockchip/armv8/base-files/etc/init.d/ https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3328/base-files/etc/init.d/fa-rk3328-pwmfan +wget -P target/linux/rockchip/armv8/base-files/usr/bin/ https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3328/base-files/usr/bin/start-rk3328-pwm-fan.sh + +# CacULE +sed -i '/CONFIG_NR_CPUS/d' ./target/linux/rockchip/armv8/config-5.4 +echo ' +CONFIG_NR_CPUS=4 +' >> ./target/linux/rockchip/armv8/config-5.4 + +# UKSM +echo ' +CONFIG_KSM=y +CONFIG_UKSM=y +' >> ./target/linux/rockchip/armv8/config-5.4 + +# 配置 IRQ 并默认关闭 eth0 offloading rx/rx +sed -i '/set_interface_core 4 "eth1"/a\set_interface_core 8 "ff160000" "ff160000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity +sed -i '/set_interface_core 4 "eth1"/a\set_interface_core 1 "ff150000" "ff150000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity +sed -i '/;;/i\ethtool -K eth0 rx off tx off && logger -t disable-offloading "disabed rk3328 ethernet tcp/udp offloading tx/rx"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity + +# 交换 LAN/WAN 口 +sed -i 's,"eth1" "eth0","eth0" "eth1",g' target/linux/rockchip/armv8/base-files/etc/board.d/02_network +sed -i "s,'eth1' 'eth0','eth0' 'eth1',g" target/linux/rockchip/armv8/base-files/etc/board.d/02_network + +# 添加 R2S GPU 驱动 +rm -rf ./package/kernel/linux/modules/video.mk +wget -P package/kernel/linux/modules/ https://github.com/immortalwrt/immortalwrt/raw/master/package/kernel/linux/modules/video.mk + +#Vermagic +latest_version="$(curl -s https://github.com/openwrt/openwrt/releases |grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" |sed -n '/21/p' |sed -n 1p |sed 's/v//g' |sed 's/.tar.gz//g')" +wget https://downloads.openwrt.org/releases/${latest_version}/targets/rockchip/armv8/packages/Packages.gz +zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' > .vermagic +sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic/' include/kernel-defaults.mk + +# 预配置一些插件 +cp -rf ../PATCH/files ./files + +chmod -R 755 ./ +find ./ -name *.orig | xargs rm -f +find ./ -name *.rej | xargs rm -f + +#exit 0 diff --git a/SEED/R2C/config.seed b/SEED/R2C/config.seed new file mode 100644 index 000000000..67d17824a --- /dev/null +++ b/SEED/R2C/config.seed @@ -0,0 +1,189 @@ +### INITIALIZATION ### +CONFIG_KERNEL_BUILD_DOMAIN="buildhost" +CONFIG_KERNEL_BUILD_USER="builder" +CONFIG_TARGET_rockchip=y +CONFIG_TARGET_rockchip_armv8=y +CONFIG_TARGET_rockchip_armv8_DEVICE_friendlyarm_nanopi-r2c=y +CONFIG_TARGET_ROOTFS_PARTSIZE=864 +# CONFIG_COLLECT_KERNEL_DEBUG is not set + +### AGGRESSIVE ### +CONFIG_PACKAGE_node=y +CONFIG_NODEJS_14=y +CONFIG_NODEJS_ICU_NONE=y +CONFIG_DEVEL=y +CONFIG_TOOLCHAINOPTS=y +CONFIG_GCC_USE_VERSION_7=y + +### BASIC ### +CONFIG_PACKAGE_r8169-firmware=y +CONFIG_PACKAGE_addition-trans-zh=y +CONFIG_PACKAGE_arm-trusted-firmware-rockchip=y +CONFIG_PACKAGE_autocore-arm=y +CONFIG_PACKAGE_ipv6helper=y +CONFIG_PACKAGE_cgi-io=y +CONFIG_PACKAGE_ethtool=y +CONFIG_PACKAGE_diffutils=y +CONFIG_PACKAGE_dnsmasq-full=y +CONFIG_PACKAGE_dnsmasq_full_auth=y +CONFIG_PACKAGE_dnsmasq_full_conntrack=y +CONFIG_PACKAGE_dnsmasq_full_dhcp=y +CONFIG_PACKAGE_dnsmasq_full_dhcpv6=y +CONFIG_PACKAGE_dnsmasq_full_dnssec=y +CONFIG_PACKAGE_dnsmasq_full_ipset=y +CONFIG_PACKAGE_dnsmasq_full_noid=y +CONFIG_PACKAGE_dnsmasq_full_tftp=y +# CONFIG_PACKAGE_dnsmasq is not set +CONFIG_PACKAGE_iptables-mod-fullconenat=y +CONFIG_PACKAGE_ip6tables-mod-fullconenat=y +CONFIG_PACKAGE_iptables-mod-nat-extra=y +CONFIG_PACKAGE_kmod-fs-f2fs=y +CONFIG_PACKAGE_kmod-ipt-nat6=y +CONFIG_PACKAGE_kmod-tun=y +#CONFIG_PACKAGE_kmod-shortcut-fe=y +#CONFIG_PACKAGE_kmod-fast-classifier=y +# CONFIG_PACKAGE_kmod-shortcut-fe-cm is not set +CONFIG_PACKAGE_libiwinfo=y +CONFIG_PACKAGE_libiwinfo-lua=y +CONFIG_PACKAGE_liblua=y +CONFIG_PACKAGE_liblucihttp=y +CONFIG_PACKAGE_liblucihttp-lua=y +CONFIG_PACKAGE_libubus-lua=y +CONFIG_PACKAGE_libustream-openssl=y +# CONFIG_PACKAGE_libustream-wolfssl is not set +CONFIG_PACKAGE_rpcd=y +CONFIG_PACKAGE_rpcd-mod-file=y +CONFIG_PACKAGE_rpcd-mod-iwinfo=y +CONFIG_PACKAGE_rpcd-mod-luci=y +CONFIG_PACKAGE_rpcd-mod-rrdns=y +CONFIG_PACKAGE_uhttpd=y +CONFIG_PACKAGE_wget-ssl=y +CONFIG_PACKAGE_lua=y +# CONFIG_PACKAGE_miniupnpd is not set +CONFIG_PACKAGE_miniupnpd-igdv1=y + +### LUCI ### +CONFIG_LUCI_LANG_zh_Hans=y +CONFIG_LUCI_LANG_en=y +# CONFIG_LUCI_CSSTIDY is not set +# CONFIG_LUCI_JSMIN is not set +CONFIG_PACKAGE_luci=y +CONFIG_PACKAGE_luci-app-firewall=y +CONFIG_PACKAGE_luci-base=y +CONFIG_PACKAGE_luci-compat=y +CONFIG_PACKAGE_luci-lib-ip=y +CONFIG_PACKAGE_luci-lib-ipkg=y +CONFIG_PACKAGE_luci-lib-jsonc=y +CONFIG_PACKAGE_luci-lib-nixio=y +CONFIG_PACKAGE_luci-mod-admin-full=y +CONFIG_PACKAGE_luci-mod-network=y +CONFIG_PACKAGE_luci-mod-status=y +CONFIG_PACKAGE_luci-mod-system=y +CONFIG_PACKAGE_luci-proto-ipv6=y +CONFIG_PACKAGE_luci-proto-ppp=y + +### APPLICATION ### +#CONFIG_PACKAGE_luci-app-adguardhome=y +#CONFIG_PACKAGE_adguardhome=y +CONFIG_PACKAGE_luci-app-wireguard=y +CONFIG_PACKAGE_luci-app-socat=y +CONFIG_PACKAGE_luci-app-argon-config=y +CONFIG_PACKAGE_luci-app-arpbind=y +CONFIG_PACKAGE_luci-app-autoreboot=y +CONFIG_PACKAGE_luci-app-boostupnp=y +CONFIG_PACKAGE_luci-app-control-weburl=y +CONFIG_PACKAGE_luci-app-cpufreq=y +CONFIG_PACKAGE_luci-app-cpulimit=y +CONFIG_PACKAGE_luci-app-ddns=y +CONFIG_PACKAGE_ddns-scripts-cloudflare=y +CONFIG_PACKAGE_ddns-scripts-dnspod=y +CONFIG_PACKAGE_ddns-scripts-aliyun=y +CONFIG_PACKAGE_luci-app-frpc=y +CONFIG_PACKAGE_frpc=y +CONFIG_PACKAGE_luci-app-frps=y +CONFIG_PACKAGE_frps=y +CONFIG_PACKAGE_luci-app-jd-dailybonus=y +CONFIG_PACKAGE_luci-app-dnsproxy=y +#CONFIG_PACKAGE_luci-app-oled=y +CONFIG_PACKAGE_luci-app-openclash=y +CONFIG_PACKAGE_luci-app-opkg=y +#CONFIG_PACKAGE_luci-app-qbittorrent=y +CONFIG_PACKAGE_luci-app-ramfree=y +CONFIG_PACKAGE_luci-app-serverchan=y +#CONFIG_PACKAGE_luci-app-smartdns=y +CONFIG_PACKAGE_luci-app-sqm=y +CONFIG_PACKAGE_luci-app-vlmcsd=y +CONFIG_PACKAGE_luci-app-vssr=y +CONFIG_PACKAGE_luci-app-ssr-plus=y +CONFIG_PACKAGE_luci-app-passwall=y +CONFIG_PACKAGE_luci-app-unblockneteasemusic=y +CONFIG_PACKAGE_luci-app-upnp=y +CONFIG_PACKAGE_luci-app-usb-printer=y +CONFIG_PACKAGE_luci-app-services-wolplus=y +CONFIG_PACKAGE_luci-app-wrtbwmon=y +CONFIG_PACKAGE_luci-app-xlnetacc=y +CONFIG_PACKAGE_luci-app-zerotier=y +CONFIG_PACKAGE_zerotier=y +CONFIG_PACKAGE_coremark=y +CONFIG_PACKAGE_htop=y +CONFIG_PACKAGE_subconverter=y +CONFIG_PACKAGE_dnsproxy=y +CONFIG_PACKAGE_luci-app-dnsfilter=y + +### THEME ### +CONFIG_PACKAGE_luci-theme-argon=y +CONFIG_PACKAGE_luci-theme-bootstrap=y + +### RESET ### +CONFIG_PACKAGE_kmod-gpio-button-hotplug=y + +### SHARE NETWORK ### +CONFIG_PACKAGE_usbmuxd=y +CONFIG_PACKAGE_kmod-usb-net-rndis=y +CONFIG_PACKAGE_kmod-usb-net-ipheth=y + +### BBRv2 ### +CONFIG_PACKAGE_kmod-tcp-bbr2=y + +### OPENSSL ### +CONFIG_OPENSSL_ENGINE=y +CONFIG_OPENSSL_OPTIMIZE_SPEED=y +CONFIG_OPENSSL_WITH_ASM=y +# CONFIG_OPENSSL_WITH_ERROR_MESSAGES is not set +CONFIG_PACKAGE_libopenssl-devcrypto=y +CONFIG_PACKAGE_libopenssl-conf=y +CONFIG_PACKAGE_openssl-util=y +CONFIG_PACKAGE_libcurl=y +CONFIG_LIBCURL_OPENSSL=y +# CONFIG_LIBCURL_MBEDTLS is not set +# CONFIG_LIBCURL_WOLFSSL is not set +# CONFIG_LIBCURL_GNUTLS is not set +# CONFIG_LIBCURL_NOSSL is not set + + +### DOCKER ###(实验性,有需要的删掉下面的注释) + +#CONFIG_PACKAGE_luci-app-dockerman=y +#CONFIG_DOCKER_KERNEL_OPTIONS=y +#CONFIG_DOCKER_NET_ENCRYPT=y +#CONFIG_DOCKER_NET_MACVLAN=y +#CONFIG_DOCKER_NET_OVERLAY=y +#CONFIG_DOCKER_NET_TFTP=y +#CONFIG_DOCKER_RES_SHAPE=y +#CONFIG_DOCKER_SECCOMP=y +#CONFIG_DOCKER_STO_BTRFS=y +#CONFIG_DOCKER_STO_EXT4=y + +### Video Support ### (实验性,有需要的删掉下面的注释) +#CONFIG_PACKAGE_kmod-backlight=y +#CONFIG_PACKAGE_kmod-drm=y +#CONFIG_PACKAGE_kmod-drm-kms-helper=y +#CONFIG_PACKAGE_kmod-drm-rockchip=y +#CONFIG_PACKAGE_kmod-fb=y +#CONFIG_PACKAGE_kmod-fb-cfb-copyarea=y +#CONFIG_PACKAGE_kmod-fb-cfb-fillrect=y +#CONFIG_PACKAGE_kmod-fb-cfb-imgblt=y +#CONFIG_PACKAGE_kmod-fb-sys-fops=y +#CONFIG_PACKAGE_kmod-fb-sys-ram=y +#CONFIG_PACKAGE_kmod-gpu-lima=y +#CONFIG_PACKAGE_kmod-multimedia-input=y From e2a2b4c89954e94bbec42cdd48433eec9a0196ad Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 19 Aug 2021 14:41:48 +0800 Subject: [PATCH 179/244] Strip Unnecessary Files --- .github/workflows/R2C-OpenWrt.yml | 8 ++--- SCRIPTS/02_prepare_package.sh | 1 + SCRIPTS/R2C/02_target_only.sh | 50 ------------------------------- 3 files changed, 5 insertions(+), 54 deletions(-) delete mode 100644 SCRIPTS/R2C/02_target_only.sh diff --git a/.github/workflows/R2C-OpenWrt.yml b/.github/workflows/R2C-OpenWrt.yml index 2c8e8c023..2aefd5a03 100644 --- a/.github/workflows/R2C-OpenWrt.yml +++ b/.github/workflows/R2C-OpenWrt.yml @@ -50,7 +50,7 @@ jobs: - name: Prepare Mixedwrt run: | sudo chown -R runner:runner /home/runner/work/YAOF - cp -r ./SCRIPTS/R2C/. ./SCRIPTS/ + cp -r ./SCRIPTS/R2S/. ./SCRIPTS/ cp -r ./SCRIPTS/. ./ /bin/bash 01_get_ready.sh - name: Prepare Package @@ -124,9 +124,9 @@ jobs: gzip -d *.gz && exit 0 gzip --best *.img ls -Ahl - sha256sum openwrt*r2s* | tee R2C-GC404-$(date +%Y-%m-%d)-21.02.sha256sum - zip R2C-GC404-$(date +%Y-%m-%d)-21.02-ext4.zip *r2s*ext4* - zip R2C-GC404-$(date +%Y-%m-%d)-21.02-sfs.zip *r2s*squashfs* + sha256sum openwrt*r2c* | tee R2C-GC404-$(date +%Y-%m-%d)-21.02.sha256sum + zip R2C-GC404-$(date +%Y-%m-%d)-21.02-ext4.zip *r2c*ext4* + zip R2C-GC404-$(date +%Y-%m-%d)-21.02-sfs.zip *r2c*squashfs* ls -Ahl - name: Upload artifact uses: actions/upload-artifact@main diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 934c8bae3..cafe45f6e 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -38,6 +38,7 @@ wget -qO - https://github.com/openwrt/openwrt/commit/cfaf039.patch | patch -p1 # CacULE wget -qO - https://github.com/QiuSimons/openwrt-NoTengoBattery/commit/7d44cab.patch | patch -p1 wget https://github.com/hamadmarri/cacule-cpu-scheduler/raw/master/patches/CacULE/v5.4/cacule-5.4.patch -O ./target/linux/generic/hack-5.4/694-cacule-5.4.patch +#wget https://github.com/hamadmarri/cacule-cpu-scheduler/raw/vR2.1/patches/CacULE/v5.4/cacule-5.4.patch -O ./target/linux/generic/hack-5.4/694-cacule-5.4.patch # UKSM cp -f ../PATCH/UKSM/695-uksm-5.4.patch ./target/linux/generic/hack-5.4/695-uksm-5.4.patch # Grub 2 diff --git a/SCRIPTS/R2C/02_target_only.sh b/SCRIPTS/R2C/02_target_only.sh deleted file mode 100644 index 20896c3bc..000000000 --- a/SCRIPTS/R2C/02_target_only.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash -clear - -# 使用专属优化 -sed -i 's,-mcpu=generic,-mcpu=cortex-a53+crypto,g' include/target.mk -cp -f ../PATCH/mbedtls/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch ./package/libs/mbedtls/patches/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch - -#增加风扇调速(被动散热不香么? -wget -P target/linux/rockchip/armv8/base-files/etc/init.d/ https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3328/base-files/etc/init.d/fa-rk3328-pwmfan -wget -P target/linux/rockchip/armv8/base-files/usr/bin/ https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3328/base-files/usr/bin/start-rk3328-pwm-fan.sh - -# CacULE -sed -i '/CONFIG_NR_CPUS/d' ./target/linux/rockchip/armv8/config-5.4 -echo ' -CONFIG_NR_CPUS=4 -' >> ./target/linux/rockchip/armv8/config-5.4 - -# UKSM -echo ' -CONFIG_KSM=y -CONFIG_UKSM=y -' >> ./target/linux/rockchip/armv8/config-5.4 - -# 配置 IRQ 并默认关闭 eth0 offloading rx/rx -sed -i '/set_interface_core 4 "eth1"/a\set_interface_core 8 "ff160000" "ff160000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity -sed -i '/set_interface_core 4 "eth1"/a\set_interface_core 1 "ff150000" "ff150000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity -sed -i '/;;/i\ethtool -K eth0 rx off tx off && logger -t disable-offloading "disabed rk3328 ethernet tcp/udp offloading tx/rx"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity - -# 交换 LAN/WAN 口 -sed -i 's,"eth1" "eth0","eth0" "eth1",g' target/linux/rockchip/armv8/base-files/etc/board.d/02_network -sed -i "s,'eth1' 'eth0','eth0' 'eth1',g" target/linux/rockchip/armv8/base-files/etc/board.d/02_network - -# 添加 R2S GPU 驱动 -rm -rf ./package/kernel/linux/modules/video.mk -wget -P package/kernel/linux/modules/ https://github.com/immortalwrt/immortalwrt/raw/master/package/kernel/linux/modules/video.mk - -#Vermagic -latest_version="$(curl -s https://github.com/openwrt/openwrt/releases |grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" |sed -n '/21/p' |sed -n 1p |sed 's/v//g' |sed 's/.tar.gz//g')" -wget https://downloads.openwrt.org/releases/${latest_version}/targets/rockchip/armv8/packages/Packages.gz -zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' > .vermagic -sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic/' include/kernel-defaults.mk - -# 预配置一些插件 -cp -rf ../PATCH/files ./files - -chmod -R 755 ./ -find ./ -name *.orig | xargs rm -f -find ./ -name *.rej | xargs rm -f - -#exit 0 From ff7d6e6dc21062b6ed7cad3f40d7fa7c4a7c4878 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 23 Aug 2021 17:05:12 +0800 Subject: [PATCH 180/244] Update dnsfilter --- PATCH/files/etc/config/dnsfilter | 5 ++--- SCRIPTS/02_prepare_package.sh | 3 +++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/PATCH/files/etc/config/dnsfilter b/PATCH/files/etc/config/dnsfilter index 0998cdd46..6fbc3f71d 100644 --- a/PATCH/files/etc/config/dnsfilter +++ b/PATCH/files/etc/config/dnsfilter @@ -4,7 +4,6 @@ config dnsfilter option time_update '6' option flash '0' option enable '1' - list url 'https://cdn.jsdelivr.net/gh/AdguardTeam/FiltersRegistry@master/filters/filter_2_English/filter.txt' - list url 'https://cdn.jsdelivr.net/gh/AdguardTeam/FiltersRegistry@master/filters/filter_224_Chinese/filter.txt' - list url 'https://cdn.jsdelivr.net/gh/AdguardTeam/FiltersRegistry@master/filters/filter_14_Annoyances/filter.txt' + list url 'https://cdn.jsdelivr.net/gh/AdguardTeam/AdGuardSDNSFilter@gh-pages/Filters/filter.txt' + list url 'https://cdn.jsdelivr.net/gh/easylist/easylistchina@master/easylistchina.txt' diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index cafe45f6e..95250684d 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -340,6 +340,9 @@ svn co https://github.com/immortalwrt/packages/trunk/libs/quickjspp feeds/packag ln -sf ../../../feeds/packages/libs/quickjspp ./package/feeds/packages/quickjspp # 网易云音乐解锁 git clone --depth 1 https://github.com/immortalwrt/luci-app-unblockneteasemusic.git package/new/UnblockNeteaseMusic +#pushd package/new/UnblockNeteaseMusic +#wget -qO - https://github.com/immortalwrt/luci-app-unblockneteasemusic/pull/78.patch | patch -p1 +#popd # USB 打印机 svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-usb-printer package/lean/luci-app-usb-printer # UU加速器 From 8a7c85ef702be80002c41c913fb42f29fb71224c Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 25 Aug 2021 18:11:56 +0800 Subject: [PATCH 181/244] Add LRNG Support --- PATCH/LRNG/696-01-v41-000001-sha1.patch | 17 + .../696-02-v41-000002-GRND_INSECURE.patch | 13 + .../696-03-v41-000003-jent-backport.patch | 80 + ...1-0001-Linux-Random-Number-Generator.patch | 4162 +++++++++++++++++ ...cate-one-DRNG-instance-per-NUMA-node.patch | 201 + ...0003-LRNG-sysctls-and-proc-interface.patch | 287 ++ ...004-LRNG-add-switchable-DRNG-support.patch | 326 ++ ...LRNG-add-common-generic-hash-support.patch | 198 + ...-externalize-DRBG-functions-for-LRNG.patch | 139 + ...07-LRNG-add-SP800-90A-DRBG-extension.patch | 278 ++ ...add-kernel-crypto-API-PRNG-extension.patch | 307 ++ ...de-access-to-a-static-Jitter-RNG-sta.patch | 148 + ...RNG-add-Jitter-RNG-fast-noise-source.patch | 174 + ...add-SP800-90B-compliant-health-tests.patch | 623 +++ ...terface-for-gathering-of-raw-entropy.patch | 956 ++++ ...-add-power-on-and-runtime-self-tests.patch | 494 ++ .../696-17-v41-01-remove_compat_ioctl.patch | 18 + ...-v41-02-jitterentropy_remove_RCT_APT.patch | 15 + .../696-19-v41-03-arch_random_early.patch | 13 + PATCH/LRNG/696-20-v41-04-net_rand_state.patch | 10 + PATCH/LRNG/696-21-v41-05-kzfree.patch | 44 + PATCH/LRNG/696-22-v41-06-sha-includes.patch | 32 + SCRIPTS/02_prepare_package.sh | 6 + 23 files changed, 8541 insertions(+) create mode 100644 PATCH/LRNG/696-01-v41-000001-sha1.patch create mode 100644 PATCH/LRNG/696-02-v41-000002-GRND_INSECURE.patch create mode 100644 PATCH/LRNG/696-03-v41-000003-jent-backport.patch create mode 100644 PATCH/LRNG/696-04-v41-0001-Linux-Random-Number-Generator.patch create mode 100644 PATCH/LRNG/696-05-v41-0002-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch create mode 100644 PATCH/LRNG/696-06-v41-0003-LRNG-sysctls-and-proc-interface.patch create mode 100644 PATCH/LRNG/696-07-v41-0004-LRNG-add-switchable-DRNG-support.patch create mode 100644 PATCH/LRNG/696-08-v41-0005-LRNG-add-common-generic-hash-support.patch create mode 100644 PATCH/LRNG/696-09-v41-0006-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch create mode 100644 PATCH/LRNG/696-10-v41-0007-LRNG-add-SP800-90A-DRBG-extension.patch create mode 100644 PATCH/LRNG/696-11-v41-0008-LRNG-add-kernel-crypto-API-PRNG-extension.patch create mode 100644 PATCH/LRNG/696-12-v41-0009-crypto-provide-access-to-a-static-Jitter-RNG-sta.patch create mode 100644 PATCH/LRNG/696-13-v41-0010-LRNG-add-Jitter-RNG-fast-noise-source.patch create mode 100644 PATCH/LRNG/696-14-v41-0011-LRNG-add-SP800-90B-compliant-health-tests.patch create mode 100644 PATCH/LRNG/696-15-v41-0012-LRNG-add-interface-for-gathering-of-raw-entropy.patch create mode 100644 PATCH/LRNG/696-16-v41-0013-LRNG-add-power-on-and-runtime-self-tests.patch create mode 100644 PATCH/LRNG/696-17-v41-01-remove_compat_ioctl.patch create mode 100644 PATCH/LRNG/696-18-v41-02-jitterentropy_remove_RCT_APT.patch create mode 100644 PATCH/LRNG/696-19-v41-03-arch_random_early.patch create mode 100644 PATCH/LRNG/696-20-v41-04-net_rand_state.patch create mode 100644 PATCH/LRNG/696-21-v41-05-kzfree.patch create mode 100644 PATCH/LRNG/696-22-v41-06-sha-includes.patch diff --git a/PATCH/LRNG/696-01-v41-000001-sha1.patch b/PATCH/LRNG/696-01-v41-000001-sha1.patch new file mode 100644 index 000000000..f4f5010e4 --- /dev/null +++ b/PATCH/LRNG/696-01-v41-000001-sha1.patch @@ -0,0 +1,17 @@ +--- a/include/crypto/sha.h ++++ b/include/crypto/sha.h +@@ -159,4 +159,14 @@ extern int sha224_update(struct sha256_s + unsigned int length); + extern int sha224_final(struct sha256_state *sctx, u8 *hash); + ++/* ++ * An implementation of SHA-1's compression function. Don't use in new code! ++ * You shouldn't be using SHA-1, and even if you *have* to use SHA-1, this isn't ++ * the correct way to hash something with SHA-1 (use crypto_shash instead). ++ */ ++#define SHA1_DIGEST_WORDS (SHA1_DIGEST_SIZE / 4) ++#define SHA1_WORKSPACE_WORDS 16 ++void sha_init(__u32 *buf); ++void sha_transform(__u32 *digest, const char *data, __u32 *W); ++ + #endif diff --git a/PATCH/LRNG/696-02-v41-000002-GRND_INSECURE.patch b/PATCH/LRNG/696-02-v41-000002-GRND_INSECURE.patch new file mode 100644 index 000000000..268235d11 --- /dev/null +++ b/PATCH/LRNG/696-02-v41-000002-GRND_INSECURE.patch @@ -0,0 +1,13 @@ +--- a/include/uapi/linux/random.h ++++ b/include/uapi/linux/random.h +@@ -49,8 +49,10 @@ struct rand_pool_info { + * + * GRND_NONBLOCK Don't block and return EAGAIN instead + * GRND_RANDOM Use the /dev/random pool instead of /dev/urandom ++ * GRND_INSECURE Return non-cryptographic random bytes + */ + #define GRND_NONBLOCK 0x0001 + #define GRND_RANDOM 0x0002 ++#define GRND_INSECURE 0x0004 + + #endif /* _UAPI_LINUX_RANDOM_H */ diff --git a/PATCH/LRNG/696-03-v41-000003-jent-backport.patch b/PATCH/LRNG/696-03-v41-000003-jent-backport.patch new file mode 100644 index 000000000..0feef6dfe --- /dev/null +++ b/PATCH/LRNG/696-03-v41-000003-jent-backport.patch @@ -0,0 +1,80 @@ +commit 965d7286d871b622dcaaafd2e2346b11631584ff +Author: Ben Dooks +Date: Wed Oct 9 10:12:56 2019 +0100 + + crypto: jitter - add header to fix buildwarnings + + Fix the following build warnings by adding a header for + the definitions shared between jitterentropy.c and + jitterentropy-kcapi.c. Fixes the following: + + crypto/jitterentropy.c:445:5: warning: symbol 'jent_read_entropy' was not declared. Should it be static? + crypto/jitterentropy.c:475:18: warning: symbol 'jent_entropy_collector_alloc' was not declared. Should it be static? + crypto/jitterentropy.c:509:6: warning: symbol 'jent_entropy_collector_free' was not declared. Should it be static? + crypto/jitterentropy.c:516:5: warning: symbol 'jent_entropy_init' was not declared. Should it be static? + crypto/jitterentropy-kcapi.c:59:6: warning: symbol 'jent_zalloc' was not declared. Should it be static? + crypto/jitterentropy-kcapi.c:64:6: warning: symbol 'jent_zfree' was not declared. Should it be static? + crypto/jitterentropy-kcapi.c:69:5: warning: symbol 'jent_fips_enabled' was not declared. Should it be static? + crypto/jitterentropy-kcapi.c:74:6: warning: symbol 'jent_panic' was not declared. Should it be static? + crypto/jitterentropy-kcapi.c:79:6: warning: symbol 'jent_memcpy' was not declared. Should it be static? + crypto/jitterentropy-kcapi.c:93:6: warning: symbol 'jent_get_nstime' was not declared. Should it be static? + + Signed-off-by: Ben Dooks + Reviewed-by: Stephan Mueller + +--- a/crypto/jitterentropy-kcapi.c ++++ b/crypto/jitterentropy-kcapi.c +@@ -44,13 +44,7 @@ + #include + #include + +-struct rand_data; +-int jent_read_entropy(struct rand_data *ec, unsigned char *data, +- unsigned int len); +-int jent_entropy_init(void); +-struct rand_data *jent_entropy_collector_alloc(unsigned int osr, +- unsigned int flags); +-void jent_entropy_collector_free(struct rand_data *entropy_collector); ++#include "jitterentropy.h" + + /*************************************************************************** + * Helper function +--- a/crypto/jitterentropy.c ++++ b/crypto/jitterentropy.c +@@ -103,12 +103,7 @@ struct rand_data { + * Helper functions + ***************************************************************************/ + +-void jent_get_nstime(__u64 *out); +-void *jent_zalloc(unsigned int len); +-void jent_zfree(void *ptr); +-int jent_fips_enabled(void); +-void jent_panic(char *s); +-void jent_memcpy(void *dest, const void *src, unsigned int n); ++#include "jitterentropy.h" + + /** + * Update of the loop count used for the next round of +--- /dev/null ++++ b/crypto/jitterentropy.h +@@ -0,0 +1,19 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++ ++typedef unsigned long long __u64; ++ ++extern void *jent_zalloc(unsigned int len); ++extern void jent_zfree(void *ptr); ++extern int jent_fips_enabled(void); ++extern void jent_panic(char *s); ++extern void jent_memcpy(void *dest, const void *src, unsigned int n); ++extern void jent_get_nstime(__u64 *out); ++ ++struct rand_data; ++extern int jent_entropy_init(void); ++extern int jent_read_entropy(struct rand_data *ec, unsigned char *data, ++ unsigned int len); ++ ++extern struct rand_data *jent_entropy_collector_alloc(unsigned int osr, ++ unsigned int flags); ++extern void jent_entropy_collector_free(struct rand_data *entropy_collector); diff --git a/PATCH/LRNG/696-04-v41-0001-Linux-Random-Number-Generator.patch b/PATCH/LRNG/696-04-v41-0001-Linux-Random-Number-Generator.patch new file mode 100644 index 000000000..3fa0088a8 --- /dev/null +++ b/PATCH/LRNG/696-04-v41-0001-Linux-Random-Number-Generator.patch @@ -0,0 +1,4162 @@ +From 13918cf8b7d4f1383ff2a61687d45441b03b3b74 Mon Sep 17 00:00:00 2001 +From: Stephan Mueller +Date: Wed, 23 Jun 2021 18:42:39 +0200 +Subject: [PATCH v41 01/13] Linux Random Number Generator +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In an effort to provide a flexible implementation for a random number +generator that also delivers entropy during early boot time, allows +replacement of the deterministic random number generation mechanism, +implement the various components in separate code for easier +maintenance, and provide compliance to SP800-90[A|B|C], introduce +the Linux Random Number Generator (LRNG) framework. + +The general design is as follows. Additional implementation details +are given in [1]. The LRNG consists of the following components: + +1. The LRNG implements a DRNG. The DRNG always generates the +requested amount of output. When using the SP800-90A terminology +it operates without prediction resistance. The secondary DRNG +maintains a counter of how many bytes were generated since last +re-seed and a timer of the elapsed time since last re-seed. If either +the counter or the timer reaches a threshold, the secondary DRNG is +seeded from the entropy pool. + +In case the Linux kernel detects a NUMA system, one secondary DRNG +instance per NUMA node is maintained. + +2. The DRNG is seeded by concatenating the data from the +following sources: + +(a) the output of the entropy pool, + +(b) the Jitter RNG if available and enabled, and + +(c) the CPU-based noise source such as Intel RDRAND if available and +enabled. + +The entropy estimate of the data of all noise sources are added to +form the entropy estimate of the data used to seed the DRNG with. +The LRNG ensures, however, that the DRNG after seeding is at +maximum the security strength of the DRNG. + +The LRNG is designed such that none of these noise sources can dominate +the other noise sources to provide seed data to the DRNG during due to +the following: + +(a) During boot time, the amount of received interrupts are the trigger +points to (re)seed the DRNG. + +(b) At runtime, the available entropy from the slow noise source is +concatenated with a pre-defined amount of data from the fast noise +sources. In addition, each DRNG reseed operation triggers external +noise source providers to deliver one block of data. + +3. The entropy pool accumulates entropy obtained from certain events, +which will henceforth be collectively called "slow noise sources". +The entropy pool collects noise data from slow noise sources. Any data +received by the LRNG from the slow noise sources is inserted into a +per-CPU entropy pool using a hash operation that can be changed during +runtime. Per default, SHA-256 is used. + + (a) When an interrupt occurs, the high-resolution time stamp is mixed +into the per-CPU entropy pool. This time stamp is credited with +heuristically implied entropy. + + (b) HID event data like the key stroke or the mouse coordinates are +mixed into the per-CPU entropy pool. This data is not credited with +entropy by the LRNG. + + (c) Device drivers may provide data that is mixed into an auxiliary +pool using the same hash that is used to process the per-CPU entropy +pool. This data is not credited with entropy by the LRNG. + +Any data provided from user space by either writing to /dev/random, +/dev/urandom or the IOCTL of RNDADDENTROPY on both device files +are always injected into the auxiliary pool. + +In addition, when a hardware random number generator covered by the +Linux kernel HW generator framework wants to deliver random numbers, +it is injected into the auxiliary pool as well. HW generator noise source +is handled separately from the other noise source due to the fact that +the HW generator framework may decide by itself when to deliver data +whereas the other noise sources always requested for data driven by the +LRNG operation. Similarly any user space provided data is inserted into +the entropy pool. + +When seed data for the DRNG is to be generated, all per-CPU +entropy pools and the auxiliary pool are hashed. The message digest +forms the new auxiliary pool state. At the same time, this data +is used for seeding the DRNG. + +To speed up the interrupt handling code of the LRNG, the time stamp +collected for an interrupt event is truncated to the 8 least +significant bits. 64 truncated time stamps are concatenated and then +jointly inserted into the per-CPU entropy pool. During boot time, +until the fully seeded stage is reached, each time stamp with its +32 least significant bits is are concatenated. When 16 such events +are received, they are injected into the per-CPU entropy pool. + +The LRNG allows the DRNG mechanism to be changed at runtime. Per default, +a ChaCha20-based DRNG is used. The ChaCha20-DRNG implemented for the +LRNG is also provided as a stand-alone user space deterministic random +number generator. The LRNG also offers an SP800-90A DRBG based on the +Linux kernel crypto API DRBG implementation. + +The processing of entropic data from the noise source before injecting +them into the DRNG is performed with the following mathematical +operations: + +1. Truncation: The received time stamps are truncated to 8 least +significant bits (or 32 least significant bits during boot time) + +2. Concatenation: The received and truncated time stamps as well as +auxiliary 32 bit words are concatenated to fill the per-CPU data +array that is capable of holding 64 8-bit words. + +3. Hashing: A set of concatenated time stamp data received from the +interrupts are hashed together with the current existing per-CPU +entropy pool state. The resulting message digest is the new per-CPU +entropy pool state. + +4. Hashing: When new data is added to the auxiliary pool, the data +is hashed together with the auxiliary pool to form a new auxiliary +pool state. + +5. Hashing: A message digest of all per-CPU entropy pools and the +auxiliary pool is calculated which forms the new auxiliary pool +state. At the same time, this message digest is used to fill the +slow noise source output buffer discussed in the following. + +6. Truncation: The most-significant bits (MSB) defined by the +requested number of bits (commonly equal to the security strength +of the DRBG) or the entropy available transported with the buffer +(which is the minimum of the message digest size and the available +entropy in all entropy pools and the auxiliary pool), whatever is +smaller, are obtained from the slow noise source output buffer. + +7. Concatenation: The temporary seed buffer used to seed the DRNG +is a concatenation of the slow noise source buffer, the Jitter RNG +output, the CPU noise source output, and the current time. + +The DRNG always tries to seed itself with 256 bits of entropy, except +during boot. In any case, if the noise sources cannot deliver that +amount, the available entropy is used and the DRNG keeps track on how +much entropy it was seeded with. The entropy implied by the LRNG +available in the entropy pool may be too conservative. To ensure +that during boot time all available entropy from the entropy pool is +transferred to the DRNG, the hash_df function always generates 256 +data bits during boot to seed the DRNG. During boot, the DRNG is +seeded as follows: + +1. The DRNG is reseeded from the entropy pool and potentially the fast +noise sources if the entropy pool has collected at least 32 bits of +entropy from the interrupt noise source. The goal of this step is to +ensure that the DRNG receives some initial entropy as early as +possible. In addition it receives the entropy available from +the fast noise sources. + +2. The DRNG is reseeded from the entropy pool and potentially the fast +noise sources if all noise sources collectively can provide at least +128 bits of entropy. + +3. The DRNG is reseeded from the entropy pool and potentially the fast +noise sources if all noise sources collectivel can provide at least 256 +bits. + +At the time of the reseeding steps, the DRNG requests as much entropy as +is available in order to skip certain steps and reach the seeding level +of 256 bits. This may imply that one or more of the aforementioned steps +are skipped. + +In all listed steps, the DRNG is (re)seeded with a number of random +bytes from the entropy pool that is at most the amount of entropy +present in the entropy pool. This means that when the entropy pool +contains 128 or 256 bits of entropy, the DRNG is seeded with that +amount of entropy as well. + +Before the DRNG is seeded with 256 bits of entropy in step 3, +requests of random data from /dev/random and the getrandom system +call are not processed. + +The hash operation providing random data from the entropy pools will +always require that all entropy sources collectively can deliver at +least 128 entropy bits. + +The DRNG operates as deterministic random number generator with the +following properties: + +* The maximum number of random bytes that can be generated with one +DRNG generate operation is limited to 4096 bytes. When longer random +numbers are requested, multiple DRNG generate operations are performed. +The ChaCha20 DRNG as well as the SP800-90A DRBGs implement an update of +their state after completing a generate request for backtracking +resistance. + +* The secondary DRNG is reseeded with whatever entropy is available – +in the worst case where no additional entropy can be provided by the +noise sources, the DRNG is not re-seeded and continues its operation +to try to reseed again after again the expiry of one of these thresholds: + + - If the last reseeding of the secondary DRNG is more than 600 seconds + ago, or + + - 2^20 DRNG generate operations are performed, whatever comes first, or + + - the secondary DRNG is forced to reseed before the next generation of + random numbers if data has been injected into the LRNG by writing data + into /dev/random or /dev/urandom. + +The chosen values prevent high-volume requests from user space to cause +frequent reseeding operations which drag down the performance of the +DRNG. + +With the automatic reseeding after 600 seconds, the LRNG is triggered +to reseed itself before the first request after a suspend that put the +hardware to sleep for longer than 600 seconds. + +To support smaller devices including IoT environments, this patch +allows reducing the runtime memory footprint of the LRNG at compile +time by selecting smaller collection data sizes. + +When selecting the compilation of a kernel for a small environment, +prevent the allocation of a buffer up to 4096 bytes to serve user space +requests. In this case, the stack variable of 64 bytes is used to serve +all user space requests. + +The LRNG has the following properties: + +* internal noise source: interrupts timing with fast boot time seeding + +* high performance of interrupt handling code: The LRNG impact on the +interrupt handling has been reduced to a minimum. On one example +system, the LRNG interrupt handling code in its fastest configuration +executes within an average 55 cycles whereas the existing +/dev/random on the same device takes about 97 cycles when measuring +the execution time of add_interrupt_randomness(). + +* use of almost never contended lock for hashing operation to collect + raw entropy supporting concurrency-free use of massive parallel + systems - worst case rate of contention is the number of DRNG + reseeds, usually: number of NUMA nodes contentions per 5 minutes. + +* use of standalone ChaCha20 based RNG with the option to use a + different DRNG selectable at compile time + +* instantiate one DRNG per NUMA node + +* support for runtime switchable output DRNGs + +* use of runtime-switchable hash for conditioning implementation +following widely accepted approach + +* compile-time selectable collection size + +* support of small systems by allowing the reduction of the +runtime memory needs + +Further details including the rationale for the design choices and +properties of the LRNG together with testing is provided at [1]. +In addition, the documentation explains the conducted regression +tests to verify that the LRNG is API and ABI compatible with the +existing /dev/random implementation. + +[1] https://www.chronox.de/lrng.html + +CC: Torsten Duwe +CC: "Eric W. Biederman" +CC: "Alexander E. Patrakov" +CC: "Ahmed S. Darwish" +CC: "Theodore Y. Ts'o" +CC: Willy Tarreau +CC: Matthew Garrett +CC: Vito Caputo +CC: Andreas Dilger +CC: Jan Kara +CC: Ray Strode +CC: William Jon McCann +CC: zhangjs +CC: Andy Lutomirski +CC: Florian Weimer +CC: Lennart Poettering +CC: Nicolai Stange +CC: Alexander Lobakin +Mathematical aspects Reviewed-by: "Peter, Matthias" +Reviewed-by: Marcelo Henrique Cerri +Reviewed-by: Roman Drahtmueller +Tested-by: Marcelo Henrique Cerri +Tested-by: Neil Horman +Signed-off-by: Stephan Mueller +--- + MAINTAINERS | 7 + + drivers/char/Kconfig | 2 + + drivers/char/Makefile | 9 +- + drivers/char/lrng/Kconfig | 205 ++++++++ + drivers/char/lrng/Makefile | 9 + + drivers/char/lrng/lrng_archrandom.c | 91 ++++ + drivers/char/lrng/lrng_aux.c | 136 ++++++ + drivers/char/lrng/lrng_chacha20.c | 321 +++++++++++++ + drivers/char/lrng/lrng_chacha20.h | 29 ++ + drivers/char/lrng/lrng_drng.c | 422 +++++++++++++++++ + drivers/char/lrng/lrng_interfaces.c | 650 ++++++++++++++++++++++++++ + drivers/char/lrng/lrng_internal.h | 416 +++++++++++++++++ + drivers/char/lrng/lrng_pool.c | 622 ++++++++++++++++++++++++ + drivers/char/lrng/lrng_sw_noise.c | 702 ++++++++++++++++++++++++++++ + drivers/char/lrng/lrng_sw_noise.h | 71 +++ + include/linux/lrng.h | 81 ++++ + 16 files changed, 3772 insertions(+), 1 deletion(-) + create mode 100644 drivers/char/lrng/Kconfig + create mode 100644 drivers/char/lrng/Makefile + create mode 100644 drivers/char/lrng/lrng_archrandom.c + create mode 100644 drivers/char/lrng/lrng_aux.c + create mode 100644 drivers/char/lrng/lrng_chacha20.c + create mode 100644 drivers/char/lrng/lrng_chacha20.h + create mode 100644 drivers/char/lrng/lrng_drng.c + create mode 100644 drivers/char/lrng/lrng_interfaces.c + create mode 100644 drivers/char/lrng/lrng_internal.h + create mode 100644 drivers/char/lrng/lrng_pool.c + create mode 100644 drivers/char/lrng/lrng_sw_noise.c + create mode 100644 drivers/char/lrng/lrng_sw_noise.h + create mode 100644 include/linux/lrng.h + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -9494,6 +9494,13 @@ F: Documentation/core-api/atomic_ops.rst + F: Documentation/core-api/refcount-vs-atomic.rst + F: Documentation/memory-barriers.txt + ++LINUX RANDOM NUMBER GENERATOR (LRNG) DRIVER ++M: Stephan Mueller ++S: Maintained ++W: https://www.chronox.de/lrng.html ++F: drivers/char/lrng/* ++F: include/linux/lrng.h ++ + LIS3LV02D ACCELEROMETER DRIVER + M: Eric Piel + S: Maintained +--- a/drivers/char/Kconfig ++++ b/drivers/char/Kconfig +@@ -535,6 +535,8 @@ config ADI + and SSM (Silicon Secured Memory). Intended consumers of this + driver include crash and makedumpfile. + ++source "drivers/char/lrng/Kconfig" ++ + endmenu + + config RANDOM_TRUST_CPU +--- a/drivers/char/Makefile ++++ b/drivers/char/Makefile +@@ -3,7 +3,14 @@ + # Makefile for the kernel character device drivers. + # + +-obj-y += mem.o random.o ++obj-y += mem.o ++ ++ifeq ($(CONFIG_LRNG),y) ++ obj-y += lrng/ ++else ++ obj-y += random.o ++endif ++ + obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o + obj-y += misc.o + obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o +--- /dev/null ++++ b/drivers/char/lrng/Kconfig +@@ -0,0 +1,205 @@ ++# SPDX-License-Identifier: GPL-2.0 ++# ++# Linux Random Number Generator configuration ++# ++ ++menuconfig LRNG ++ bool "Linux Random Number Generator" ++ select CRYPTO_LIB_SHA256 if CRYPTO ++ help ++ The Linux Random Number Generator (LRNG) is the replacement ++ of the existing /dev/random provided with drivers/char/random.c. ++ It generates entropy from different noise sources and ++ delivers significant entropy during boot. ++ ++if LRNG ++ ++menu "Specific DRNG seeding strategies" ++ ++config LRNG_OVERSAMPLE_ENTROPY_SOURCES ++ bool "Oversample entropy sources" ++ default n ++ help ++ When enabling this option, the entropy sources are ++ over-sampled with the following approach: First, the ++ the entropy sources are requested to provide 64 bits more ++ entropy than the size of the entropy buffer. For example, ++ if the entropy buffer is 256 bits, 320 bits of entropy ++ is requested to fill that buffer. ++ ++ Second, the seed operation of the deterministic RNG ++ requests 128 bits more data from each entropy source than ++ the security strength of the DRNG during initialization. ++ A prerequisite for this operation is that the digest size ++ of the used hash must be at least equally large to generate ++ that buffer. If the prerequisite is not met, this ++ oversampling is not applied. ++ ++ This strategy is intended to offset the asymptotic entropy ++ increase to reach full entropy in a buffer. ++ ++ The strategy is consistent with the requirements in ++ NIST SP800-90C and is only enforced with fips=1. ++ ++ If unsure, say N. ++ ++config LRNG_OVERSAMPLE_ES_BITS ++ int ++ default 0 if !LRNG_OVERSAMPLE_ENTROPY_SOURCES ++ default 64 if LRNG_OVERSAMPLE_ENTROPY_SOURCES ++ ++config LRNG_SEED_BUFFER_INIT_ADD_BITS ++ int ++ default 0 if !LRNG_OVERSAMPLE_ENTROPY_SOURCES ++ default 128 if LRNG_OVERSAMPLE_ENTROPY_SOURCES ++ ++endmenu # "Specific DRNG seeding strategies" ++ ++menu "Entropy Source Configuration" ++ ++comment "Interrupt Entropy Source" ++ ++choice ++ prompt "Continuous entropy compression boot time setting" ++ default LRNG_CONTINUOUS_COMPRESSION_ENABLED ++ help ++ Select the default behavior of the interrupt entropy source ++ continuous compression operation. ++ ++ The Linux RNG collects entropy data during each interrupt. ++ For performance reasons, a amount of entropy data defined by ++ the LRNG entropy collection pool size is concatenated into ++ an array. When that array is filled up, a hash is calculated ++ to compress the entropy. That hash is calculated in ++ interrupt context. ++ ++ In case such hash calculation in interrupt context is deemed ++ too time-consuming, the continuous compression operation ++ can be disabled. If disabled, the collection of entropy will ++ not trigger a hash compression operation in interrupt context. ++ The compression happens only when the DRNG is reseeded which is ++ in process context. This implies that old entropy data ++ collected after the last DRNG-reseed is overwritten with newer ++ entropy data once the collection pool is full instead of ++ retaining its entropy with the compression operation. ++ ++ config LRNG_CONTINUOUS_COMPRESSION_ENABLED ++ bool "Enable continuous compression (default)" ++ ++ config LRNG_CONTINUOUS_COMPRESSION_DISABLED ++ bool "Disable continuous compression" ++endchoice ++ ++config LRNG_ENABLE_CONTINUOUS_COMPRESSION ++ bool ++ default y if LRNG_CONTINUOUS_COMPRESSION_ENABLED ++ default n if LRNG_CONTINUOUS_COMPRESSION_DISABLED ++ ++config LRNG_SWITCHABLE_CONTINUOUS_COMPRESSION ++ bool "Runtime-switchable continuous entropy compression" ++ help ++ Per default, the interrupt entropy source continuous ++ compression operation behavior is hard-wired into the kernel. ++ Enable this option to allow it to be configurable at boot time. ++ ++ To modify the default behavior of the continuous ++ compression operation, use the kernel command line option ++ of lrng_sw_noise.lrng_pcpu_continuous_compression. ++ ++ If unsure, say N. ++ ++choice ++ prompt "LRNG Entropy Collection Pool Size" ++ default LRNG_COLLECTION_SIZE_1024 ++ help ++ Select the size of the LRNG entropy collection pool ++ storing data for the interrupt entropy source without ++ performing a compression operation. The larger the ++ collection size is, the faster the average interrupt ++ handling will be. The collection size represents the ++ number of bytes of the per-CPU memory used to batch ++ up entropy event data. ++ ++ The default value is good for regular operations. Choose ++ larger sizes for servers that have no memory limitations. ++ If runtime memory is precious, choose a smaller size. ++ ++ The collection size is unrelated to the entropy rate ++ or the amount of entropy the LRNG can process. ++ ++ config LRNG_COLLECTION_SIZE_32 ++ depends on LRNG_CONTINUOUS_COMPRESSION_ENABLED ++ depends on !LRNG_SWITCHABLE_CONTINUOUS_COMPRESSION ++ depends on !LRNG_OVERSAMPLE_ENTROPY_SOURCES ++ bool "32 interrupt events" ++ ++ config LRNG_COLLECTION_SIZE_256 ++ depends on !LRNG_OVERSAMPLE_ENTROPY_SOURCES ++ bool "256 interrupt events" ++ ++ config LRNG_COLLECTION_SIZE_512 ++ bool "512 interrupt events" ++ ++ config LRNG_COLLECTION_SIZE_1024 ++ bool "1024 interrupt events (default)" ++ ++ config LRNG_COLLECTION_SIZE_2048 ++ bool "2048 interrupt events" ++ ++ config LRNG_COLLECTION_SIZE_4096 ++ bool "4096 interrupt events" ++ ++ config LRNG_COLLECTION_SIZE_8192 ++ bool "8192 interrupt events" ++ ++endchoice ++ ++config LRNG_COLLECTION_SIZE ++ int ++ default 32 if LRNG_COLLECTION_SIZE_32 ++ default 256 if LRNG_COLLECTION_SIZE_256 ++ default 512 if LRNG_COLLECTION_SIZE_512 ++ default 1024 if LRNG_COLLECTION_SIZE_1024 ++ default 2048 if LRNG_COLLECTION_SIZE_2048 ++ default 4096 if LRNG_COLLECTION_SIZE_4096 ++ default 8192 if LRNG_COLLECTION_SIZE_8192 ++ ++config LRNG_IRQ_ENTROPY_RATE ++ int "Interrupt Entropy Source Entropy Rate" ++ range 256 4294967295 ++ default 256 ++ help ++ The LRNG will collect the configured number of interrupts to ++ obtain 256 bits of entropy. This value can be set to any between ++ 256 and 4294967295. The LRNG guarantees that this value is not ++ lower than 256. This lower limit implies that one interrupt event ++ is credited with one bit of entropy. This value is subject to the ++ increase by the oversampling factor, if no high-resolution timer ++ is found. ++ ++ In order to effectively disable the interrupt entropy source, ++ the option has to be set to 4294967295. In this case, the ++ interrupt entropy source will still deliver data but without ++ being credited with entropy. ++ ++comment "CPU Entropy Source" ++ ++config LRNG_CPU_ENTROPY_RATE ++ int "CPU Entropy Source Entropy Rate" ++ range 0 256 ++ default 8 ++ help ++ The option defines the amount of entropy the LRNG applies to 256 ++ bits of data obtained from the CPU entropy source. The LRNG ++ enforces the limit that this value must be in the range between ++ 0 and 256. ++ ++ In order to disable the CPU entropy source, the option has to ++ be set to 0. ++ ++ Note, this option is overwritten when the option ++ CONFIG_RANDOM_TRUST_CPU is set. ++ ++endmenu # "Entropy Source Configuration" ++ ++endif # LRNG +--- /dev/null ++++ b/drivers/char/lrng/Makefile +@@ -0,0 +1,9 @@ ++# SPDX-License-Identifier: GPL-2.0 ++# ++# Makefile for the Linux Random Number Generator. ++# ++ ++obj-y += lrng_pool.o lrng_aux.o \ ++ lrng_sw_noise.o lrng_archrandom.o \ ++ lrng_drng.o lrng_chacha20.o \ ++ lrng_interfaces.o +--- /dev/null ++++ b/drivers/char/lrng/lrng_archrandom.c +@@ -0,0 +1,91 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause ++/* ++ * LRNG Fast Entropy Source: CPU-based entropy source ++ * ++ * Copyright (C) 2016 - 2021, Stephan Mueller ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++ ++#include "lrng_internal.h" ++ ++/* ++ * Estimated entropy of data is a 32th of LRNG_DRNG_SECURITY_STRENGTH_BITS. ++ * As we have no ability to review the implementation of those noise sources, ++ * it is prudent to have a conservative estimate here. ++ */ ++#define LRNG_ARCHRANDOM_DEFAULT_STRENGTH CONFIG_LRNG_CPU_ENTROPY_RATE ++#define LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH LRNG_DRNG_SECURITY_STRENGTH_BITS ++#ifdef CONFIG_RANDOM_TRUST_CPU ++static u32 archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH; ++#else ++static u32 archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH; ++#endif ++#ifdef CONFIG_LRNG_RUNTIME_ES_CONFIG ++module_param(archrandom, uint, 0644); ++MODULE_PARM_DESC(archrandom, "Entropy in bits of 256 data bits from CPU noise source (e.g. RDRAND)"); ++#endif ++ ++static int __init lrng_parse_trust_cpu(char *arg) ++{ ++ int ret; ++ bool trust_cpu = false; ++ ++ ret = kstrtobool(arg, &trust_cpu); ++ if (ret) ++ return ret; ++ ++ if (trust_cpu) { ++ archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH; ++ lrng_pool_add_entropy(); ++ } else { ++ archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH; ++ } ++ ++ return 0; ++} ++early_param("random.trust_cpu", lrng_parse_trust_cpu); ++ ++u32 lrng_archrandom_entropylevel(u32 requested_bits) ++{ ++ return lrng_fast_noise_entropylevel(archrandom, requested_bits); ++} ++ ++/** ++ * lrng_get_arch() - Get CPU noise source entropy ++ * ++ * @outbuf: buffer to store entropy of size LRNG_DRNG_SECURITY_STRENGTH_BYTES ++ * ++ * Return: ++ * * > 0 on success where value provides the added entropy in bits ++ * * 0 if no fast source was available ++ */ ++u32 lrng_get_arch(u8 *outbuf, u32 requested_bits) ++{ ++ u32 i, ent_bits = lrng_archrandom_entropylevel(requested_bits); ++ ++ /* operate on full blocks */ ++ BUILD_BUG_ON(LRNG_DRNG_SECURITY_STRENGTH_BYTES % sizeof(unsigned long)); ++ BUILD_BUG_ON(CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS % ++ sizeof(unsigned long)); ++ /* ensure we have aligned buffers */ ++ BUILD_BUG_ON(LRNG_KCAPI_ALIGN % sizeof(unsigned long)); ++ ++ if (!ent_bits) ++ return 0; ++ ++ for (i = 0; i < (requested_bits >> 3); ++ i += sizeof(unsigned long)) { ++ if (!arch_get_random_seed_long((unsigned long *)(outbuf + i)) && ++ !arch_get_random_long((unsigned long *)(outbuf + i))) { ++ archrandom = 0; ++ return 0; ++ } ++ } ++ ++ pr_debug("obtained %u bits of entropy from CPU RNG noise source\n", ++ ent_bits); ++ return ent_bits; ++} +--- /dev/null ++++ b/drivers/char/lrng/lrng_aux.c +@@ -0,0 +1,136 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause ++/* ++ * LRNG auxiliary interfaces ++ * ++ * Copyright (C) 2019 - 2021 Stephan Mueller ++ * Copyright (C) 2017 Jason A. Donenfeld . All ++ * Rights Reserved. ++ * Copyright (C) 2016 Jason Cooper ++ */ ++ ++#include ++#include ++ ++#include "lrng_internal.h" ++ ++struct batched_entropy { ++ union { ++ u64 entropy_u64[LRNG_DRNG_BLOCKSIZE / sizeof(u64)]; ++ u32 entropy_u32[LRNG_DRNG_BLOCKSIZE / sizeof(u32)]; ++ }; ++ unsigned int position; ++ spinlock_t batch_lock; ++}; ++ ++/* ++ * Get a random word for internal kernel use only. The quality of the random ++ * number is as good as /dev/urandom, but there is no backtrack protection, ++ * with the goal of being quite fast and not depleting entropy. ++ */ ++static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64) = { ++ .batch_lock = __SPIN_LOCK_UNLOCKED(batched_entropy_u64.lock), ++}; ++ ++u64 get_random_u64(void) ++{ ++ u64 ret; ++ unsigned long flags; ++ struct batched_entropy *batch; ++ ++ lrng_debug_report_seedlevel("get_random_u64"); ++ ++ batch = raw_cpu_ptr(&batched_entropy_u64); ++ spin_lock_irqsave(&batch->batch_lock, flags); ++ if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) { ++ lrng_drng_get_atomic((u8 *)batch->entropy_u64, ++ LRNG_DRNG_BLOCKSIZE); ++ batch->position = 0; ++ } ++ ret = batch->entropy_u64[batch->position++]; ++ spin_unlock_irqrestore(&batch->batch_lock, flags); ++ return ret; ++} ++EXPORT_SYMBOL(get_random_u64); ++ ++static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u32) = { ++ .batch_lock = __SPIN_LOCK_UNLOCKED(batched_entropy_u32.lock), ++}; ++ ++u32 get_random_u32(void) ++{ ++ u32 ret; ++ unsigned long flags; ++ struct batched_entropy *batch; ++ ++ lrng_debug_report_seedlevel("get_random_u32"); ++ ++ batch = raw_cpu_ptr(&batched_entropy_u32); ++ spin_lock_irqsave(&batch->batch_lock, flags); ++ if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) { ++ lrng_drng_get_atomic((u8 *)batch->entropy_u32, ++ LRNG_DRNG_BLOCKSIZE); ++ batch->position = 0; ++ } ++ ret = batch->entropy_u32[batch->position++]; ++ spin_unlock_irqrestore(&batch->batch_lock, flags); ++ return ret; ++} ++EXPORT_SYMBOL(get_random_u32); ++ ++/* ++ * It's important to invalidate all potential batched entropy that might ++ * be stored before the crng is initialized, which we can do lazily by ++ * simply resetting the counter to zero so that it's re-extracted on the ++ * next usage. ++ */ ++void invalidate_batched_entropy(void) ++{ ++ int cpu; ++ unsigned long flags; ++ ++ for_each_possible_cpu(cpu) { ++ struct batched_entropy *batched_entropy; ++ ++ batched_entropy = per_cpu_ptr(&batched_entropy_u32, cpu); ++ spin_lock_irqsave(&batched_entropy->batch_lock, flags); ++ batched_entropy->position = 0; ++ spin_unlock(&batched_entropy->batch_lock); ++ ++ batched_entropy = per_cpu_ptr(&batched_entropy_u64, cpu); ++ spin_lock(&batched_entropy->batch_lock); ++ batched_entropy->position = 0; ++ spin_unlock_irqrestore(&batched_entropy->batch_lock, flags); ++ } ++} ++ ++/** ++ * randomize_page - Generate a random, page aligned address ++ * @start: The smallest acceptable address the caller will take. ++ * @range: The size of the area, starting at @start, within which the ++ * random address must fall. ++ * ++ * If @start + @range would overflow, @range is capped. ++ * ++ * NOTE: Historical use of randomize_range, which this replaces, presumed that ++ * @start was already page aligned. We now align it regardless. ++ * ++ * Return: A page aligned address within [start, start + range). On error, ++ * @start is returned. ++ */ ++unsigned long randomize_page(unsigned long start, unsigned long range) ++{ ++ if (!PAGE_ALIGNED(start)) { ++ range -= PAGE_ALIGN(start) - start; ++ start = PAGE_ALIGN(start); ++ } ++ ++ if (start > ULONG_MAX - range) ++ range = ULONG_MAX - start; ++ ++ range >>= PAGE_SHIFT; ++ ++ if (range == 0) ++ return start; ++ ++ return start + (get_random_long() % range << PAGE_SHIFT); ++} +--- /dev/null ++++ b/drivers/char/lrng/lrng_chacha20.c +@@ -0,0 +1,321 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause ++/* ++ * Backend for the LRNG providing the cryptographic primitives using ++ * ChaCha20 cipher implementations. ++ * ++ * Copyright (C) 2016 - 2021, Stephan Mueller ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++ ++#include "lrng_chacha20.h" ++#include "lrng_internal.h" ++ ++/******************************* ChaCha20 DRNG *******************************/ ++ ++#define CHACHA_BLOCK_WORDS (CHACHA_BLOCK_SIZE / sizeof(u32)) ++ ++struct chacha20_state { ++ struct chacha20_block block; ++}; ++ ++/* ++ * Have a static memory blocks for the ChaCha20 DRNG instance to avoid calling ++ * kmalloc too early in the boot cycle. For subsequent allocation requests, ++ * such as per-NUMA-node DRNG instances, kmalloc will be used. ++ */ ++struct chacha20_state chacha20 __latent_entropy; ++ ++/** ++ * Update of the ChaCha20 state by either using an unused buffer part or by ++ * generating one ChaCha20 block which is half of the state of the ChaCha20. ++ * The block is XORed into the key part of the state. This shall ensure ++ * backtracking resistance as well as a proper mix of the ChaCha20 state once ++ * the key is injected. ++ */ ++static void lrng_chacha20_update(struct chacha20_state *chacha20_state, ++ __le32 *buf, u32 used_words) ++{ ++ struct chacha20_block *chacha20 = &chacha20_state->block; ++ u32 i; ++ __le32 tmp[CHACHA_BLOCK_WORDS]; ++ ++ BUILD_BUG_ON(sizeof(struct chacha20_block) != CHACHA_BLOCK_SIZE); ++ BUILD_BUG_ON(CHACHA_BLOCK_SIZE != 2 * CHACHA_KEY_SIZE); ++ ++ if (used_words > CHACHA_KEY_SIZE_WORDS) { ++ chacha20_block(&chacha20->constants[0], (u8 *)tmp); ++ for (i = 0; i < CHACHA_KEY_SIZE_WORDS; i++) ++ chacha20->key.u[i] ^= le32_to_cpu(tmp[i]); ++ memzero_explicit(tmp, sizeof(tmp)); ++ } else { ++ for (i = 0; i < CHACHA_KEY_SIZE_WORDS; i++) ++ chacha20->key.u[i] ^= le32_to_cpu(buf[i + used_words]); ++ } ++ ++ /* Deterministic increment of nonce as required in RFC 7539 chapter 4 */ ++ chacha20->nonce[0]++; ++ if (chacha20->nonce[0] == 0) { ++ chacha20->nonce[1]++; ++ if (chacha20->nonce[1] == 0) ++ chacha20->nonce[2]++; ++ } ++ ++ /* Leave counter untouched as it is start value is undefined in RFC */ ++} ++ ++/* ++ * Seed the ChaCha20 DRNG by injecting the input data into the key part of ++ * the ChaCha20 state. If the input data is longer than the ChaCha20 key size, ++ * perform a ChaCha20 operation after processing of key size input data. ++ * This operation shall spread out the entropy into the ChaCha20 state before ++ * new entropy is injected into the key part. ++ */ ++static int lrng_cc20_drng_seed_helper(void *drng, const u8 *inbuf, u32 inbuflen) ++{ ++ struct chacha20_state *chacha20_state = (struct chacha20_state *)drng; ++ struct chacha20_block *chacha20 = &chacha20_state->block; ++ ++ while (inbuflen) { ++ u32 i, todo = min_t(u32, inbuflen, CHACHA_KEY_SIZE); ++ ++ for (i = 0; i < todo; i++) ++ chacha20->key.b[i] ^= inbuf[i]; ++ ++ /* Break potential dependencies between the inbuf key blocks */ ++ lrng_chacha20_update(chacha20_state, NULL, ++ CHACHA_BLOCK_WORDS); ++ inbuf += todo; ++ inbuflen -= todo; ++ } ++ ++ return 0; ++} ++ ++/* ++ * Chacha20 DRNG generation of random numbers: the stream output of ChaCha20 ++ * is the random number. After the completion of the generation of the ++ * stream, the entire ChaCha20 state is updated. ++ * ++ * Note, as the ChaCha20 implements a 32 bit counter, we must ensure ++ * that this function is only invoked for at most 2^32 - 1 ChaCha20 blocks ++ * before a reseed or an update happens. This is ensured by the variable ++ * outbuflen which is a 32 bit integer defining the number of bytes to be ++ * generated by the ChaCha20 DRNG. At the end of this function, an update ++ * operation is invoked which implies that the 32 bit counter will never be ++ * overflown in this implementation. ++ */ ++static int lrng_cc20_drng_generate_helper(void *drng, u8 *outbuf, u32 outbuflen) ++{ ++ struct chacha20_state *chacha20_state = (struct chacha20_state *)drng; ++ struct chacha20_block *chacha20 = &chacha20_state->block; ++ __le32 aligned_buf[CHACHA_BLOCK_WORDS]; ++ u32 ret = outbuflen, used = CHACHA_BLOCK_WORDS; ++ int zeroize_buf = 0; ++ ++ while (outbuflen >= CHACHA_BLOCK_SIZE) { ++ chacha20_block(&chacha20->constants[0], outbuf); ++ outbuf += CHACHA_BLOCK_SIZE; ++ outbuflen -= CHACHA_BLOCK_SIZE; ++ } ++ ++ if (outbuflen) { ++ chacha20_block(&chacha20->constants[0], (u8 *)aligned_buf); ++ memcpy(outbuf, aligned_buf, outbuflen); ++ used = ((outbuflen + sizeof(aligned_buf[0]) - 1) / ++ sizeof(aligned_buf[0])); ++ zeroize_buf = 1; ++ } ++ ++ lrng_chacha20_update(chacha20_state, aligned_buf, used); ++ ++ if (zeroize_buf) ++ memzero_explicit(aligned_buf, sizeof(aligned_buf)); ++ ++ return ret; ++} ++ ++void lrng_cc20_init_state(struct chacha20_state *state) ++{ ++ lrng_cc20_init_rfc7539(&state->block); ++} ++ ++/* ++ * Allocation of the DRNG state ++ */ ++static void *lrng_cc20_drng_alloc(u32 sec_strength) ++{ ++ struct chacha20_state *state = NULL; ++ ++ if (sec_strength > CHACHA_KEY_SIZE) { ++ pr_err("Security strength of ChaCha20 DRNG (%u bits) lower than requested by LRNG (%u bits)\n", ++ CHACHA_KEY_SIZE * 8, sec_strength * 8); ++ return ERR_PTR(-EINVAL); ++ } ++ if (sec_strength < CHACHA_KEY_SIZE) ++ pr_warn("Security strength of ChaCha20 DRNG (%u bits) higher than requested by LRNG (%u bits)\n", ++ CHACHA_KEY_SIZE * 8, sec_strength * 8); ++ ++ state = kmalloc(sizeof(struct chacha20_state), GFP_KERNEL); ++ if (!state) ++ return ERR_PTR(-ENOMEM); ++ pr_debug("memory for ChaCha20 core allocated\n"); ++ ++ lrng_cc20_init_state(state); ++ ++ return state; ++} ++ ++static void lrng_cc20_drng_dealloc(void *drng) ++{ ++ struct chacha20_state *chacha20_state = (struct chacha20_state *)drng; ++ ++ if (drng == &chacha20) { ++ memzero_explicit(chacha20_state, sizeof(*chacha20_state)); ++ pr_debug("static ChaCha20 core zeroized\n"); ++ return; ++ } ++ ++ pr_debug("ChaCha20 core zeroized and freed\n"); ++ kfree_sensitive(chacha20_state); ++} ++ ++/******************************* Hash Operation *******************************/ ++ ++#ifdef CONFIG_CRYPTO_LIB_SHA256 ++ ++#include ++ ++static u32 lrng_cc20_hash_digestsize(void *hash) ++{ ++ return SHA256_DIGEST_SIZE; ++} ++ ++static int lrng_cc20_hash_init(struct shash_desc *shash, void *hash) ++{ ++ /* ++ * We do not need a TFM - we only need sufficient space for ++ * struct sha256_state on the stack. ++ */ ++ sha256_init(shash_desc_ctx(shash)); ++ return 0; ++} ++ ++static int lrng_cc20_hash_update(struct shash_desc *shash, ++ const u8 *inbuf, u32 inbuflen) ++{ ++ sha256_update(shash_desc_ctx(shash), inbuf, inbuflen); ++ return 0; ++} ++ ++static int lrng_cc20_hash_final(struct shash_desc *shash, u8 *digest) ++{ ++ sha256_final(shash_desc_ctx(shash), digest); ++ return 0; ++} ++ ++static const char *lrng_cc20_hash_name(void) ++{ ++ return "SHA-256"; ++} ++ ++static void lrng_cc20_hash_desc_zero(struct shash_desc *shash) ++{ ++ memzero_explicit(shash_desc_ctx(shash), sizeof(struct sha256_state)); ++} ++ ++#else /* CONFIG_CRYPTO_LIB_SHA256 */ ++ ++#include ++#include ++ ++/* ++ * If the SHA-256 support is not compiled, we fall back to SHA-1 that is always ++ * compiled and present in the kernel. ++ */ ++static u32 lrng_cc20_hash_digestsize(void *hash) ++{ ++ return SHA1_DIGEST_SIZE; ++} ++ ++static void lrng_sha1_block_fn(struct sha1_state *sctx, const u8 *src, ++ int blocks) ++{ ++ u32 temp[SHA1_WORKSPACE_WORDS]; ++ ++ while (blocks--) { ++ sha1_transform(sctx->state, src, temp); ++ src += SHA1_BLOCK_SIZE; ++ } ++ memzero_explicit(temp, sizeof(temp)); ++} ++ ++static int lrng_cc20_hash_init(struct shash_desc *shash, void *hash) ++{ ++ /* ++ * We do not need a TFM - we only need sufficient space for ++ * struct sha1_state on the stack. ++ */ ++ sha1_base_init(shash); ++ return 0; ++} ++ ++static int lrng_cc20_hash_update(struct shash_desc *shash, ++ const u8 *inbuf, u32 inbuflen) ++{ ++ return sha1_base_do_update(shash, inbuf, inbuflen, lrng_sha1_block_fn); ++} ++ ++static int lrng_cc20_hash_final(struct shash_desc *shash, u8 *digest) ++{ ++ return sha1_base_do_finalize(shash, lrng_sha1_block_fn) ?: ++ sha1_base_finish(shash, digest); ++} ++ ++static const char *lrng_cc20_hash_name(void) ++{ ++ return "SHA-1"; ++} ++ ++static void lrng_cc20_hash_desc_zero(struct shash_desc *shash) ++{ ++ memzero_explicit(shash_desc_ctx(shash), sizeof(struct sha1_state)); ++} ++ ++#endif /* CONFIG_CRYPTO_LIB_SHA256 */ ++ ++static void *lrng_cc20_hash_alloc(void) ++{ ++ pr_info("Hash %s allocated\n", lrng_cc20_hash_name()); ++ return NULL; ++} ++ ++static void lrng_cc20_hash_dealloc(void *hash) ++{ ++} ++ ++static const char *lrng_cc20_drng_name(void) ++{ ++ return "ChaCha20 DRNG"; ++} ++ ++const struct lrng_crypto_cb lrng_cc20_crypto_cb = { ++ .lrng_drng_name = lrng_cc20_drng_name, ++ .lrng_hash_name = lrng_cc20_hash_name, ++ .lrng_drng_alloc = lrng_cc20_drng_alloc, ++ .lrng_drng_dealloc = lrng_cc20_drng_dealloc, ++ .lrng_drng_seed_helper = lrng_cc20_drng_seed_helper, ++ .lrng_drng_generate_helper = lrng_cc20_drng_generate_helper, ++ .lrng_hash_alloc = lrng_cc20_hash_alloc, ++ .lrng_hash_dealloc = lrng_cc20_hash_dealloc, ++ .lrng_hash_digestsize = lrng_cc20_hash_digestsize, ++ .lrng_hash_init = lrng_cc20_hash_init, ++ .lrng_hash_update = lrng_cc20_hash_update, ++ .lrng_hash_final = lrng_cc20_hash_final, ++ .lrng_hash_desc_zero = lrng_cc20_hash_desc_zero, ++}; +--- /dev/null ++++ b/drivers/char/lrng/lrng_chacha20.h +@@ -0,0 +1,29 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ ++/* ++ * LRNG ChaCha20 definitions ++ * ++ * Copyright (C) 2016 - 2021, Stephan Mueller ++ */ ++ ++#include ++ ++/* State according to RFC 7539 section 2.3 */ ++struct chacha20_block { ++ u32 constants[4]; ++ union { ++#define CHACHA_KEY_SIZE_WORDS (CHACHA_KEY_SIZE / sizeof(u32)) ++ u32 u[CHACHA_KEY_SIZE_WORDS]; ++ u8 b[CHACHA_KEY_SIZE]; ++ } key; ++ u32 counter; ++ u32 nonce[3]; ++}; ++ ++static inline void lrng_cc20_init_rfc7539(struct chacha20_block *chacha20) ++{ ++ /* String "expand 32-byte k" */ ++ chacha20->constants[0] = 0x61707865; ++ chacha20->constants[1] = 0x3320646e; ++ chacha20->constants[2] = 0x79622d32; ++ chacha20->constants[3] = 0x6b206574; ++} +--- /dev/null ++++ b/drivers/char/lrng/lrng_drng.c +@@ -0,0 +1,422 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause ++/* ++ * LRNG DRNG processing ++ * ++ * Copyright (C) 2016 - 2021, Stephan Mueller ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++ ++#include "lrng_internal.h" ++ ++/* ++ * Maximum number of seconds between DRNG reseed intervals of the DRNG. Note, ++ * this is enforced with the next request of random numbers from the ++ * DRNG. Setting this value to zero implies a reseeding attempt before every ++ * generated random number. ++ */ ++int lrng_drng_reseed_max_time = 600; ++ ++static atomic_t lrng_avail = ATOMIC_INIT(0); ++ ++DEFINE_MUTEX(lrng_crypto_cb_update); ++ ++/* DRNG for /dev/urandom, getrandom(2), get_random_bytes */ ++static struct lrng_drng lrng_drng_init = { ++ .drng = &chacha20, ++ .crypto_cb = &lrng_cc20_crypto_cb, ++ .lock = __MUTEX_INITIALIZER(lrng_drng_init.lock), ++ .spin_lock = __SPIN_LOCK_UNLOCKED(lrng_drng_init.spin_lock), ++ .hash_lock = __RW_LOCK_UNLOCKED(lrng_drng_init.hash_lock) ++}; ++ ++/* ++ * DRNG for get_random_bytes when called in atomic context. This ++ * DRNG will always use the ChaCha20 DRNG. It will never benefit from a ++ * DRNG switch like the "regular" DRNG. If there was no DRNG switch, the atomic ++ * DRNG is identical to the "regular" DRNG. ++ * ++ * The reason for having this is due to the fact that DRNGs other than ++ * the ChaCha20 DRNG may sleep. ++ */ ++static struct lrng_drng lrng_drng_atomic = { ++ .drng = &chacha20, ++ .crypto_cb = &lrng_cc20_crypto_cb, ++ .spin_lock = __SPIN_LOCK_UNLOCKED(lrng_drng_atomic.spin_lock), ++ .hash_lock = __RW_LOCK_UNLOCKED(lrng_drng_atomic.hash_lock) ++}; ++ ++/********************************** Helper ************************************/ ++ ++bool lrng_get_available(void) ++{ ++ return likely(atomic_read(&lrng_avail)); ++} ++ ++void lrng_set_available(void) ++{ ++ atomic_set(&lrng_avail, 1); ++} ++ ++struct lrng_drng *lrng_drng_init_instance(void) ++{ ++ return &lrng_drng_init; ++} ++ ++struct lrng_drng *lrng_drng_atomic_instance(void) ++{ ++ return &lrng_drng_atomic; ++} ++ ++void lrng_drng_reset(struct lrng_drng *drng) ++{ ++ atomic_set(&drng->requests, LRNG_DRNG_RESEED_THRESH); ++ drng->last_seeded = jiffies; ++ drng->fully_seeded = false; ++ drng->force_reseed = true; ++ pr_debug("reset DRNG\n"); ++} ++ ++/* Initialize the default DRNG during boot */ ++static void lrng_drng_seed(struct lrng_drng *drng); ++void lrng_drngs_init_cc20(bool force_seed) ++{ ++ unsigned long flags = 0; ++ ++ if (lrng_get_available()) ++ return; ++ ++ lrng_drng_lock(&lrng_drng_init, &flags); ++ if (lrng_get_available()) { ++ lrng_drng_unlock(&lrng_drng_init, &flags); ++ if (force_seed) ++ goto seed; ++ return; ++ } ++ ++ lrng_drng_reset(&lrng_drng_init); ++ lrng_cc20_init_state(&chacha20); ++ lrng_drng_unlock(&lrng_drng_init, &flags); ++ ++ lrng_drng_lock(&lrng_drng_atomic, &flags); ++ lrng_drng_reset(&lrng_drng_atomic); ++ /* ++ * We do not initialize the state of the atomic DRNG as it is identical ++ * to the DRNG at this point. ++ */ ++ lrng_drng_unlock(&lrng_drng_atomic, &flags); ++ ++ lrng_set_available(); ++ ++seed: ++ /* Seed the DRNG with any entropy available */ ++ if (!lrng_pool_trylock()) { ++ lrng_drng_seed(&lrng_drng_init); ++ pr_info("ChaCha20 core initialized with first seeding\n"); ++ lrng_pool_unlock(); ++ } else { ++ pr_info("ChaCha20 core initialized without seeding\n"); ++ } ++} ++ ++bool lrng_sp80090c_compliant(void) ++{ ++ if (!IS_ENABLED(CONFIG_LRNG_OVERSAMPLE_ENTROPY_SOURCES)) ++ return false; ++ ++ /* Entropy source hash must be capable of transporting enough entropy */ ++ if (lrng_get_digestsize() < ++ (lrng_security_strength() + CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS)) ++ return false; ++ ++ /* SP800-90C only requested in FIPS mode */ ++ return fips_enabled; ++} ++ ++/************************* Random Number Generation ***************************/ ++ ++/* Inject a data buffer into the DRNG */ ++static void lrng_drng_inject(struct lrng_drng *drng, ++ const u8 *inbuf, u32 inbuflen) ++{ ++ const char *drng_type = unlikely(drng == &lrng_drng_atomic) ? ++ "atomic" : "regular"; ++ unsigned long flags = 0; ++ ++ BUILD_BUG_ON(LRNG_DRNG_RESEED_THRESH > INT_MAX); ++ pr_debug("seeding %s DRNG with %u bytes\n", drng_type, inbuflen); ++ lrng_drng_lock(drng, &flags); ++ if (drng->crypto_cb->lrng_drng_seed_helper(drng->drng, ++ inbuf, inbuflen) < 0) { ++ pr_warn("seeding of %s DRNG failed\n", drng_type); ++ atomic_set(&drng->requests, 1); ++ } else { ++ pr_debug("%s DRNG stats since last seeding: %lu secs; generate calls: %d\n", ++ drng_type, ++ (time_after(jiffies, drng->last_seeded) ? ++ (jiffies - drng->last_seeded) : 0) / HZ, ++ (LRNG_DRNG_RESEED_THRESH - ++ atomic_read(&drng->requests))); ++ drng->last_seeded = jiffies; ++ atomic_set(&drng->requests, LRNG_DRNG_RESEED_THRESH); ++ drng->force_reseed = false; ++ ++ if (drng->drng == lrng_drng_atomic.drng) { ++ lrng_drng_atomic.last_seeded = jiffies; ++ atomic_set(&lrng_drng_atomic.requests, ++ LRNG_DRNG_RESEED_THRESH); ++ lrng_drng_atomic.force_reseed = false; ++ } ++ } ++ lrng_drng_unlock(drng, &flags); ++} ++ ++/* ++ * Perform the seeding of the DRNG with data from noise source ++ */ ++static inline void _lrng_drng_seed(struct lrng_drng *drng) ++{ ++ struct entropy_buf seedbuf __aligned(LRNG_KCAPI_ALIGN); ++ ++ lrng_fill_seed_buffer(&seedbuf, lrng_get_seed_entropy_osr()); ++ lrng_init_ops(&seedbuf); ++ lrng_drng_inject(drng, (u8 *)&seedbuf, sizeof(seedbuf)); ++ ++ if (!drng->fully_seeded) { ++ drng->fully_seeded = lrng_fully_seeded(&seedbuf); ++ if (drng->fully_seeded) ++ pr_debug("DRNG fully seeded\n"); ++ } ++ memzero_explicit(&seedbuf, sizeof(seedbuf)); ++} ++ ++static int lrng_drng_get(struct lrng_drng *drng, u8 *outbuf, u32 outbuflen); ++static void lrng_drng_seed(struct lrng_drng *drng) ++{ ++ _lrng_drng_seed(drng); ++ ++ BUILD_BUG_ON(LRNG_MIN_SEED_ENTROPY_BITS > ++ LRNG_DRNG_SECURITY_STRENGTH_BITS); ++ ++ /* ++ * Reseed atomic DRNG from current DRNG, ++ * ++ * We can obtain random numbers from DRNG as the lock type ++ * chosen by lrng_drng_get is usable with the current caller. ++ */ ++ if ((drng->drng != lrng_drng_atomic.drng) && ++ (lrng_drng_atomic.force_reseed || ++ atomic_read(&lrng_drng_atomic.requests) <= 0 || ++ time_after(jiffies, lrng_drng_atomic.last_seeded + ++ lrng_drng_reseed_max_time * HZ))) { ++ u8 seedbuf[LRNG_DRNG_SECURITY_STRENGTH_BYTES] ++ __aligned(LRNG_KCAPI_ALIGN); ++ int ret = lrng_drng_get(drng, seedbuf, sizeof(seedbuf)); ++ ++ if (ret < 0) { ++ pr_warn("Error generating random numbers for atomic DRNG: %d\n", ++ ret); ++ } else { ++ lrng_drng_inject(&lrng_drng_atomic, seedbuf, ret); ++ } ++ memzero_explicit(&seedbuf, sizeof(seedbuf)); ++ } ++} ++ ++static inline void _lrng_drng_seed_work(struct lrng_drng *drng, u32 node) ++{ ++ pr_debug("reseed triggered by interrupt noise source for DRNG on NUMA node %d\n", ++ node); ++ lrng_drng_seed(drng); ++ if (drng->fully_seeded) { ++ /* Prevent reseed storm */ ++ drng->last_seeded += node * 100 * HZ; ++ /* Prevent draining of pool on idle systems */ ++ lrng_drng_reseed_max_time += 100; ++ } ++} ++ ++/* ++ * DRNG reseed trigger: Kernel thread handler triggered by the schedule_work() ++ */ ++void lrng_drng_seed_work(struct work_struct *dummy) ++{ ++ struct lrng_drng **lrng_drng = lrng_drng_instances(); ++ u32 node; ++ ++ if (lrng_drng) { ++ for_each_online_node(node) { ++ struct lrng_drng *drng = lrng_drng[node]; ++ ++ if (drng && !drng->fully_seeded) { ++ _lrng_drng_seed_work(drng, node); ++ goto out; ++ } ++ } ++ } else { ++ if (!lrng_drng_init.fully_seeded) { ++ _lrng_drng_seed_work(&lrng_drng_init, 0); ++ goto out; ++ } ++ } ++ ++ lrng_pool_all_numa_nodes_seeded(true); ++ ++out: ++ /* Allow the seeding operation to be called again */ ++ lrng_pool_unlock(); ++} ++ ++/* Force all DRNGs to reseed before next generation */ ++void lrng_drng_force_reseed(void) ++{ ++ struct lrng_drng **lrng_drng = lrng_drng_instances(); ++ u32 node; ++ ++ if (!lrng_drng) { ++ lrng_drng_init.force_reseed = lrng_drng_init.fully_seeded; ++ pr_debug("force reseed of initial DRNG\n"); ++ return; ++ } ++ for_each_online_node(node) { ++ struct lrng_drng *drng = lrng_drng[node]; ++ ++ if (!drng) ++ continue; ++ ++ drng->force_reseed = drng->fully_seeded; ++ pr_debug("force reseed of DRNG on node %u\n", node); ++ } ++ lrng_drng_atomic.force_reseed = lrng_drng_atomic.fully_seeded; ++} ++ ++/** ++ * lrng_drng_get() - Get random data out of the DRNG which is reseeded ++ * frequently. ++ * ++ * @outbuf: buffer for storing random data ++ * @outbuflen: length of outbuf ++ * ++ * Return: ++ * * < 0 in error case (DRNG generation or update failed) ++ * * >=0 returning the returned number of bytes ++ */ ++static int lrng_drng_get(struct lrng_drng *drng, u8 *outbuf, u32 outbuflen) ++{ ++ unsigned long flags = 0; ++ u32 processed = 0; ++ ++ if (!outbuf || !outbuflen) ++ return 0; ++ ++ outbuflen = min_t(size_t, outbuflen, INT_MAX); ++ ++ lrng_drngs_init_cc20(false); ++ ++ while (outbuflen) { ++ u32 todo = min_t(u32, outbuflen, LRNG_DRNG_MAX_REQSIZE); ++ int ret; ++ ++ /* All but the atomic DRNG are seeded during generation */ ++ if (atomic_dec_and_test(&drng->requests) || ++ drng->force_reseed || ++ time_after(jiffies, drng->last_seeded + ++ lrng_drng_reseed_max_time * HZ)) { ++ if (likely(drng != &lrng_drng_atomic)) { ++ if (lrng_pool_trylock()) { ++ atomic_set(&drng->requests, 1); ++ } else { ++ lrng_drng_seed(drng); ++ lrng_pool_unlock(); ++ } ++ } ++ } ++ ++ lrng_drng_lock(drng, &flags); ++ ret = drng->crypto_cb->lrng_drng_generate_helper( ++ drng->drng, outbuf + processed, todo); ++ lrng_drng_unlock(drng, &flags); ++ if (ret <= 0) { ++ pr_warn("getting random data from DRNG failed (%d)\n", ++ ret); ++ return -EFAULT; ++ } ++ processed += ret; ++ outbuflen -= ret; ++ } ++ ++ return processed; ++} ++ ++int lrng_drng_get_atomic(u8 *outbuf, u32 outbuflen) ++{ ++ return lrng_drng_get(&lrng_drng_atomic, outbuf, outbuflen); ++} ++ ++int lrng_drng_get_sleep(u8 *outbuf, u32 outbuflen) ++{ ++ struct lrng_drng **lrng_drng = lrng_drng_instances(); ++ struct lrng_drng *drng = &lrng_drng_init; ++ int node = numa_node_id(); ++ ++ might_sleep(); ++ ++ if (lrng_drng && lrng_drng[node] && lrng_drng[node]->fully_seeded) ++ drng = lrng_drng[node]; ++ ++ return lrng_drng_get(drng, outbuf, outbuflen); ++} ++ ++/* Reset LRNG such that all existing entropy is gone */ ++static void _lrng_reset(struct work_struct *work) ++{ ++ struct lrng_drng **lrng_drng = lrng_drng_instances(); ++ unsigned long flags = 0; ++ ++ if (!lrng_drng) { ++ lrng_drng_lock(&lrng_drng_init, &flags); ++ lrng_drng_reset(&lrng_drng_init); ++ lrng_drng_unlock(&lrng_drng_init, &flags); ++ } else { ++ u32 node; ++ ++ for_each_online_node(node) { ++ struct lrng_drng *drng = lrng_drng[node]; ++ ++ if (!drng) ++ continue; ++ lrng_drng_lock(drng, &flags); ++ lrng_drng_reset(drng); ++ lrng_drng_unlock(drng, &flags); ++ } ++ } ++ lrng_set_entropy_thresh(LRNG_INIT_ENTROPY_BITS); ++ ++ lrng_reset_state(); ++} ++ ++static DECLARE_WORK(lrng_reset_work, _lrng_reset); ++ ++void lrng_reset(void) ++{ ++ schedule_work(&lrng_reset_work); ++} ++ ++/***************************** Initialize LRNG *******************************/ ++ ++static int __init lrng_init(void) ++{ ++ lrng_drngs_init_cc20(false); ++ ++ lrng_drngs_numa_alloc(); ++ return 0; ++} ++ ++late_initcall(lrng_init); ++ ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_AUTHOR("Stephan Mueller "); ++MODULE_DESCRIPTION("Linux Random Number Generator"); +--- /dev/null ++++ b/drivers/char/lrng/lrng_interfaces.c +@@ -0,0 +1,650 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause ++/* ++ * LRNG User and kernel space interfaces ++ * ++ * Copyright (C) 2016 - 2021, Stephan Mueller ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define CREATE_TRACE_POINTS ++#include ++ ++#include "lrng_internal.h" ++ ++/* ++ * If the entropy count falls under this number of bits, then we ++ * should wake up processes which are selecting or polling on write ++ * access to /dev/random. ++ */ ++u32 lrng_write_wakeup_bits = LRNG_WRITE_WAKEUP_ENTROPY; ++ ++static LIST_HEAD(lrng_ready_list); ++static DEFINE_SPINLOCK(lrng_ready_list_lock); ++ ++static DECLARE_WAIT_QUEUE_HEAD(lrng_write_wait); ++static DECLARE_WAIT_QUEUE_HEAD(lrng_init_wait); ++static struct fasync_struct *fasync; ++ ++struct ctl_table random_table[]; ++ ++/********************************** Helper ***********************************/ ++ ++/* Is the DRNG seed level too low? */ ++static inline bool lrng_need_entropy(void) ++{ ++ return (lrng_avail_aux_entropy() < lrng_write_wakeup_bits); ++} ++ ++void lrng_writer_wakeup(void) ++{ ++ if (lrng_need_entropy() && wq_has_sleeper(&lrng_write_wait)) { ++ wake_up_interruptible(&lrng_write_wait); ++ kill_fasync(&fasync, SIGIO, POLL_OUT); ++ } ++} ++ ++void lrng_init_wakeup(void) ++{ ++ wake_up_all(&lrng_init_wait); ++ kill_fasync(&fasync, SIGIO, POLL_IN); ++} ++ ++/** ++ * lrng_process_ready_list() - Ping all kernel internal callers waiting until ++ * the DRNG is completely initialized to inform that the DRNG reached that ++ * seed level. ++ * ++ * When the SP800-90B testing is enabled, the ping only happens if the SP800-90B ++ * startup health tests are completed. This implies that kernel internal ++ * callers always have an SP800-90B compliant noise source when being ++ * pinged. ++ */ ++void lrng_process_ready_list(void) ++{ ++ unsigned long flags; ++ struct random_ready_callback *rdy, *tmp; ++ ++ if (!lrng_state_operational()) ++ return; ++ ++ spin_lock_irqsave(&lrng_ready_list_lock, flags); ++ list_for_each_entry_safe(rdy, tmp, &lrng_ready_list, list) { ++ struct module *owner = rdy->owner; ++ ++ list_del_init(&rdy->list); ++ rdy->func(rdy); ++ module_put(owner); ++ } ++ spin_unlock_irqrestore(&lrng_ready_list_lock, flags); ++} ++ ++void lrng_debug_report_seedlevel(const char *name) ++{ ++#ifdef CONFIG_WARN_ALL_UNSEEDED_RANDOM ++ static void *previous = NULL; ++ void *caller = (void *) _RET_IP_; ++ ++ if (READ_ONCE(previous) == caller) ++ return; ++ ++ if (!lrng_state_min_seeded()) ++ pr_notice("%pS %s called without reaching minimally seeded level (available entropy %u)\n", ++ caller, name, lrng_avail_entropy()); ++ ++ WRITE_ONCE(previous, caller); ++#endif ++} ++ ++/************************ LRNG kernel input interfaces ************************/ ++ ++/** ++ * add_hwgenerator_randomness() - Interface for in-kernel drivers of true ++ * hardware RNGs. ++ * ++ * Those devices may produce endless random bits and will be throttled ++ * when our pool is full. ++ * ++ * @buffer: buffer holding the entropic data from HW noise sources to be used to ++ * insert into entropy pool. ++ * @count: length of buffer ++ * @entropy_bits: amount of entropy in buffer (value is in bits) ++ */ ++void add_hwgenerator_randomness(const char *buffer, size_t count, ++ size_t entropy_bits) ++{ ++ /* ++ * Suspend writing if we are fully loaded with entropy. ++ * We'll be woken up again once below lrng_write_wakeup_thresh, ++ * or when the calling thread is about to terminate. ++ */ ++ wait_event_interruptible(lrng_write_wait, ++ lrng_need_entropy() || ++ lrng_state_exseed_allow(lrng_noise_source_hw) || ++ kthread_should_stop()); ++ lrng_state_exseed_set(lrng_noise_source_hw, false); ++ lrng_pool_insert_aux(buffer, count, entropy_bits); ++} ++EXPORT_SYMBOL_GPL(add_hwgenerator_randomness); ++ ++/** ++ * add_bootloader_randomness() - Handle random seed passed by bootloader. ++ * ++ * If the seed is trustworthy, it would be regarded as hardware RNGs. Otherwise ++ * it would be regarded as device data. ++ * The decision is controlled by CONFIG_RANDOM_TRUST_BOOTLOADER. ++ * ++ * @buf: buffer holding the entropic data from HW noise sources to be used to ++ * insert into entropy pool. ++ * @size: length of buffer ++ */ ++void add_bootloader_randomness(const void *buf, unsigned int size) ++{ ++ lrng_pool_insert_aux(buf, size, ++ IS_ENABLED(CONFIG_RANDOM_TRUST_BOOTLOADER) ? ++ size * 8 : 0); ++} ++EXPORT_SYMBOL_GPL(add_bootloader_randomness); ++ ++/* ++ * Callback for HID layer -- use the HID event values to stir the entropy pool ++ */ ++void add_input_randomness(unsigned int type, unsigned int code, ++ unsigned int value) ++{ ++ static unsigned char last_value; ++ ++ /* ignore autorepeat and the like */ ++ if (value == last_value) ++ return; ++ ++ last_value = value; ++ ++ lrng_pcpu_array_add_u32((type << 4) ^ code ^ (code >> 4) ^ value); ++} ++EXPORT_SYMBOL_GPL(add_input_randomness); ++ ++/** ++ * add_device_randomness() - Add device- or boot-specific data to the entropy ++ * pool to help initialize it. ++ * ++ * None of this adds any entropy; it is meant to avoid the problem of ++ * the entropy pool having similar initial state across largely ++ * identical devices. ++ * ++ * @buf: buffer holding the entropic data from HW noise sources to be used to ++ * insert into entropy pool. ++ * @size: length of buffer ++ */ ++void add_device_randomness(const void *buf, unsigned int size) ++{ ++ lrng_pool_insert_aux((u8 *)buf, size, 0); ++} ++EXPORT_SYMBOL(add_device_randomness); ++ ++#ifdef CONFIG_BLOCK ++void rand_initialize_disk(struct gendisk *disk) { } ++void add_disk_randomness(struct gendisk *disk) { } ++EXPORT_SYMBOL(add_disk_randomness); ++#endif ++ ++/** ++ * del_random_ready_callback() - Delete a previously registered readiness ++ * callback function. ++ * ++ * @rdy: callback definition that was registered initially ++ */ ++void del_random_ready_callback(struct random_ready_callback *rdy) ++{ ++ unsigned long flags; ++ struct module *owner = NULL; ++ ++ spin_lock_irqsave(&lrng_ready_list_lock, flags); ++ if (!list_empty(&rdy->list)) { ++ list_del_init(&rdy->list); ++ owner = rdy->owner; ++ } ++ spin_unlock_irqrestore(&lrng_ready_list_lock, flags); ++ ++ module_put(owner); ++} ++EXPORT_SYMBOL(del_random_ready_callback); ++ ++/** ++ * add_random_ready_callback() - Add a callback function that will be invoked ++ * when the DRNG is fully initialized and seeded. ++ * ++ * @rdy: callback definition to be invoked when the LRNG is seeded ++ * ++ * Return: ++ * * 0 if callback is successfully added ++ * * -EALREADY if pool is already initialised (callback not called) ++ * * -ENOENT if module for callback is not alive ++ */ ++int add_random_ready_callback(struct random_ready_callback *rdy) ++{ ++ struct module *owner; ++ unsigned long flags; ++ int err = -EALREADY; ++ ++ if (likely(lrng_state_operational())) ++ return err; ++ ++ owner = rdy->owner; ++ if (!try_module_get(owner)) ++ return -ENOENT; ++ ++ spin_lock_irqsave(&lrng_ready_list_lock, flags); ++ if (lrng_state_operational()) ++ goto out; ++ ++ owner = NULL; ++ ++ list_add(&rdy->list, &lrng_ready_list); ++ err = 0; ++ ++out: ++ spin_unlock_irqrestore(&lrng_ready_list_lock, flags); ++ ++ module_put(owner); ++ ++ return err; ++} ++EXPORT_SYMBOL(add_random_ready_callback); ++ ++/*********************** LRNG kernel output interfaces ************************/ ++ ++/** ++ * get_random_bytes() - Provider of cryptographic strong random numbers for ++ * kernel-internal usage. ++ * ++ * This function is appropriate for all in-kernel use cases. However, ++ * it will always use the ChaCha20 DRNG. ++ * ++ * @buf: buffer to store the random bytes ++ * @nbytes: size of the buffer ++ */ ++void get_random_bytes(void *buf, int nbytes) ++{ ++ lrng_drng_get_atomic((u8 *)buf, (u32)nbytes); ++ lrng_debug_report_seedlevel("get_random_bytes"); ++} ++EXPORT_SYMBOL(get_random_bytes); ++ ++/** ++ * get_random_bytes_full() - Provider of cryptographic strong random numbers ++ * for kernel-internal usage. ++ * ++ * This function is appropriate only for non-atomic use cases as this ++ * function may sleep. Though, it provides access to the full functionality ++ * of LRNG including the switchable DRNG support, that may support other ++ * DRNGs such as the SP800-90A DRBG. ++ * ++ * @buf: buffer to store the random bytes ++ * @nbytes: size of the buffer ++ */ ++void get_random_bytes_full(void *buf, int nbytes) ++{ ++ lrng_drng_get_sleep((u8 *)buf, (u32)nbytes); ++ lrng_debug_report_seedlevel("get_random_bytes_full"); ++} ++EXPORT_SYMBOL(get_random_bytes_full); ++ ++/** ++ * wait_for_random_bytes() - Wait for the LRNG to be seeded and thus ++ * guaranteed to supply cryptographically secure random numbers. ++ * ++ * This applies to: the /dev/urandom device, the get_random_bytes function, ++ * and the get_random_{u32,u64,int,long} family of functions. Using any of ++ * these functions without first calling this function forfeits the guarantee ++ * of security. ++ * ++ * Return: ++ * * 0 if the LRNG has been seeded. ++ * * -ERESTARTSYS if the function was interrupted by a signal. ++ */ ++int wait_for_random_bytes(void) ++{ ++ if (likely(lrng_state_min_seeded())) ++ return 0; ++ return wait_event_interruptible(lrng_init_wait, ++ lrng_state_min_seeded()); ++} ++EXPORT_SYMBOL(wait_for_random_bytes); ++ ++/** ++ * get_random_bytes_arch() - This function will use the architecture-specific ++ * hardware random number generator if it is available. ++ * ++ * The arch-specific hw RNG will almost certainly be faster than what we can ++ * do in software, but it is impossible to verify that it is implemented ++ * securely (as opposed, to, say, the AES encryption of a sequence number using ++ * a key known by the NSA). So it's useful if we need the speed, but only if ++ * we're willing to trust the hardware manufacturer not to have put in a back ++ * door. ++ * ++ * @buf: buffer allocated by caller to store the random data in ++ * @nbytes: length of outbuf ++ * ++ * Return: number of bytes filled in. ++ */ ++int __must_check get_random_bytes_arch(void *buf, int nbytes) ++{ ++ u8 *p = buf; ++ ++ while (nbytes) { ++ unsigned long v; ++ int chunk = min_t(int, nbytes, sizeof(unsigned long)); ++ ++ if (!arch_get_random_long(&v)) ++ break; ++ ++ memcpy(p, &v, chunk); ++ p += chunk; ++ nbytes -= chunk; ++ } ++ ++ if (nbytes) ++ lrng_drng_get_atomic((u8 *)p, (u32)nbytes); ++ ++ return nbytes; ++} ++EXPORT_SYMBOL(get_random_bytes_arch); ++ ++/* ++ * Returns whether or not the LRNG has been seeded. ++ * ++ * Returns: true if the urandom pool has been seeded. ++ * false if the urandom pool has not been seeded. ++ */ ++bool rng_is_initialized(void) ++{ ++ return lrng_state_operational(); ++} ++EXPORT_SYMBOL(rng_is_initialized); ++ ++/************************ LRNG user output interfaces *************************/ ++ ++static ssize_t lrng_read_common(char __user *buf, size_t nbytes) ++{ ++ ssize_t ret = 0; ++ u8 tmpbuf[LRNG_DRNG_BLOCKSIZE] __aligned(LRNG_KCAPI_ALIGN); ++ u8 *tmp_large = NULL, *tmp = tmpbuf; ++ u32 tmplen = sizeof(tmpbuf); ++ ++ if (nbytes == 0) ++ return 0; ++ ++ /* ++ * Satisfy large read requests -- as the common case are smaller ++ * request sizes, such as 16 or 32 bytes, avoid a kmalloc overhead for ++ * those by using the stack variable of tmpbuf. ++ */ ++ if (!CONFIG_BASE_SMALL && (nbytes > sizeof(tmpbuf))) { ++ tmplen = min_t(u32, nbytes, LRNG_DRNG_MAX_REQSIZE); ++ tmp_large = kmalloc(tmplen + LRNG_KCAPI_ALIGN, GFP_KERNEL); ++ if (!tmp_large) ++ tmplen = sizeof(tmpbuf); ++ else ++ tmp = PTR_ALIGN(tmp_large, LRNG_KCAPI_ALIGN); ++ } ++ ++ while (nbytes) { ++ u32 todo = min_t(u32, nbytes, tmplen); ++ int rc = 0; ++ ++ /* Reschedule if we received a large request. */ ++ if ((tmp_large) && need_resched()) { ++ if (signal_pending(current)) { ++ if (ret == 0) ++ ret = -ERESTARTSYS; ++ break; ++ } ++ schedule(); ++ } ++ ++ rc = lrng_drng_get_sleep(tmp, todo); ++ if (rc <= 0) { ++ if (rc < 0) ++ ret = rc; ++ break; ++ } ++ if (copy_to_user(buf, tmp, rc)) { ++ ret = -EFAULT; ++ break; ++ } ++ ++ nbytes -= rc; ++ buf += rc; ++ ret += rc; ++ } ++ ++ /* Wipe data just returned from memory */ ++ if (tmp_large) ++ kfree_sensitive(tmp_large); ++ else ++ memzero_explicit(tmpbuf, sizeof(tmpbuf)); ++ ++ return ret; ++} ++ ++static ssize_t ++lrng_read_common_block(int nonblock, char __user *buf, size_t nbytes) ++{ ++ if (nbytes == 0) ++ return 0; ++ ++ if (unlikely(!lrng_state_operational())) { ++ int ret; ++ ++ if (nonblock) ++ return -EAGAIN; ++ ++ ret = wait_event_interruptible(lrng_init_wait, ++ lrng_state_operational()); ++ if (unlikely(ret)) ++ return ret; ++ } ++ ++ return lrng_read_common(buf, nbytes); ++} ++ ++static ssize_t lrng_drng_read_block(struct file *file, char __user *buf, ++ size_t nbytes, loff_t *ppos) ++{ ++ return lrng_read_common_block(file->f_flags & O_NONBLOCK, buf, nbytes); ++} ++ ++static __poll_t lrng_random_poll(struct file *file, poll_table *wait) ++{ ++ __poll_t mask; ++ ++ poll_wait(file, &lrng_init_wait, wait); ++ poll_wait(file, &lrng_write_wait, wait); ++ mask = 0; ++ if (lrng_state_operational()) ++ mask |= EPOLLIN | EPOLLRDNORM; ++ if (lrng_need_entropy() || ++ lrng_state_exseed_allow(lrng_noise_source_user)) ++ mask |= EPOLLOUT | EPOLLWRNORM; ++ return mask; ++} ++ ++static ssize_t lrng_drng_write_common(const char __user *buffer, size_t count, ++ u32 entropy_bits) ++{ ++ ssize_t ret = 0; ++ u8 buf[64] __aligned(LRNG_KCAPI_ALIGN); ++ const char __user *p = buffer; ++ u32 orig_entropy_bits = entropy_bits; ++ ++ if (!lrng_get_available()) ++ return -EAGAIN; ++ ++ count = min_t(size_t, count, INT_MAX); ++ while (count > 0) { ++ size_t bytes = min_t(size_t, count, sizeof(buf)); ++ u32 ent = min_t(u32, bytes<<3, entropy_bits); ++ ++ if (copy_from_user(&buf, p, bytes)) ++ return -EFAULT; ++ /* Inject data into entropy pool */ ++ lrng_pool_insert_aux(buf, bytes, ent); ++ ++ count -= bytes; ++ p += bytes; ++ ret += bytes; ++ entropy_bits -= ent; ++ ++ cond_resched(); ++ } ++ ++ /* Force reseed of DRNG during next data request. */ ++ if (!orig_entropy_bits) ++ lrng_drng_force_reseed(); ++ ++ return ret; ++} ++ ++static ssize_t lrng_drng_read(struct file *file, char __user *buf, ++ size_t nbytes, loff_t *ppos) ++{ ++ if (!lrng_state_min_seeded()) ++ pr_notice_ratelimited("%s - use of insufficiently seeded DRNG (%zu bytes read)\n", ++ current->comm, nbytes); ++ else if (!lrng_state_operational()) ++ pr_debug_ratelimited("%s - use of not fully seeded DRNG (%zu bytes read)\n", ++ current->comm, nbytes); ++ ++ return lrng_read_common(buf, nbytes); ++} ++ ++static ssize_t lrng_drng_write(struct file *file, const char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ return lrng_drng_write_common(buffer, count, 0); ++} ++ ++static long lrng_ioctl(struct file *f, unsigned int cmd, unsigned long arg) ++{ ++ u32 digestsize_bits; ++ int size, ent_count_bits; ++ int __user *p = (int __user *)arg; ++ ++ switch (cmd) { ++ case RNDGETENTCNT: ++ ent_count_bits = lrng_avail_entropy(); ++ if (put_user(ent_count_bits, p)) ++ return -EFAULT; ++ return 0; ++ case RNDADDTOENTCNT: ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ if (get_user(ent_count_bits, p)) ++ return -EFAULT; ++ ent_count_bits = (int)lrng_avail_aux_entropy() + ent_count_bits; ++ if (ent_count_bits < 0) ++ ent_count_bits = 0; ++ digestsize_bits = lrng_get_digestsize(); ++ if (ent_count_bits > digestsize_bits) ++ ent_count_bits = digestsize_bits; ++ lrng_pool_set_entropy(ent_count_bits); ++ return 0; ++ case RNDADDENTROPY: ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ if (get_user(ent_count_bits, p++)) ++ return -EFAULT; ++ if (ent_count_bits < 0) ++ return -EINVAL; ++ if (get_user(size, p++)) ++ return -EFAULT; ++ if (size < 0) ++ return -EINVAL; ++ lrng_state_exseed_set(lrng_noise_source_user, false); ++ /* there cannot be more entropy than data */ ++ ent_count_bits = min(ent_count_bits, size<<3); ++ return lrng_drng_write_common((const char __user *)p, size, ++ ent_count_bits); ++ case RNDZAPENTCNT: ++ case RNDCLEARPOOL: ++ /* Clear the entropy pool counter. */ ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ lrng_pool_set_entropy(0); ++ return 0; ++ case RNDRESEEDCRNG: ++ /* ++ * We leave the capability check here since it is present ++ * in the upstream's RNG implementation. Yet, user space ++ * can trigger a reseed as easy as writing into /dev/random ++ * or /dev/urandom where no privilege is needed. ++ */ ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ /* Force a reseed of all DRNGs */ ++ lrng_drng_force_reseed(); ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int lrng_fasync(int fd, struct file *filp, int on) ++{ ++ return fasync_helper(fd, filp, on, &fasync); ++} ++ ++const struct file_operations random_fops = { ++ .read = lrng_drng_read_block, ++ .write = lrng_drng_write, ++ .poll = lrng_random_poll, ++ .unlocked_ioctl = lrng_ioctl, ++ .compat_ioctl = compat_ptr_ioctl, ++ .fasync = lrng_fasync, ++ .llseek = noop_llseek, ++}; ++ ++const struct file_operations urandom_fops = { ++ .read = lrng_drng_read, ++ .write = lrng_drng_write, ++ .unlocked_ioctl = lrng_ioctl, ++ .compat_ioctl = compat_ptr_ioctl, ++ .fasync = lrng_fasync, ++ .llseek = noop_llseek, ++}; ++ ++SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count, ++ unsigned int, flags) ++{ ++ if (flags & ~(GRND_NONBLOCK|GRND_RANDOM|GRND_INSECURE)) ++ return -EINVAL; ++ ++ /* ++ * Requesting insecure and blocking randomness at the same time makes ++ * no sense. ++ */ ++ if ((flags & ++ (GRND_INSECURE|GRND_RANDOM)) == (GRND_INSECURE|GRND_RANDOM)) ++ return -EINVAL; ++ ++ if (count > INT_MAX) ++ count = INT_MAX; ++ ++ if (flags & GRND_INSECURE) ++ return lrng_drng_read(NULL, buf, count, NULL); ++ ++ return lrng_read_common_block(flags & GRND_NONBLOCK, buf, count); ++} +--- /dev/null ++++ b/drivers/char/lrng/lrng_internal.h +@@ -0,0 +1,416 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ ++/* ++ * Copyright (C) 2018 - 2021, Stephan Mueller ++ */ ++ ++#ifndef _LRNG_INTERNAL_H ++#define _LRNG_INTERNAL_H ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/*************************** General LRNG parameter ***************************/ ++ ++/* Security strength of LRNG -- this must match DRNG security strength */ ++#define LRNG_DRNG_SECURITY_STRENGTH_BYTES 32 ++#define LRNG_DRNG_SECURITY_STRENGTH_BITS (LRNG_DRNG_SECURITY_STRENGTH_BYTES * 8) ++#define LRNG_DRNG_BLOCKSIZE 64 /* Maximum of DRNG block sizes */ ++ ++/* ++ * SP800-90A defines a maximum request size of 1<<16 bytes. The given value is ++ * considered a safer margin. ++ * ++ * This value is allowed to be changed. ++ */ ++#define LRNG_DRNG_MAX_REQSIZE (1<<12) ++ ++/* ++ * SP800-90A defines a maximum number of requests between reseeds of 2^48. ++ * The given value is considered a much safer margin, balancing requests for ++ * frequent reseeds with the need to conserve entropy. This value MUST NOT be ++ * larger than INT_MAX because it is used in an atomic_t. ++ * ++ * This value is allowed to be changed. ++ */ ++#define LRNG_DRNG_RESEED_THRESH (1<<20) ++ ++/* ++ * Number of interrupts to be recorded to assume that DRNG security strength ++ * bits of entropy are received. ++ * Note: a value below the DRNG security strength should not be defined as this ++ * may imply the DRNG can never be fully seeded in case other noise ++ * sources are unavailable. ++ * ++ * This value is allowed to be changed. ++ */ ++#define LRNG_IRQ_ENTROPY_BITS CONFIG_LRNG_IRQ_ENTROPY_RATE ++ ++/* ++ * Min required seed entropy is 128 bits covering the minimum entropy ++ * requirement of SP800-131A and the German BSI's TR02102. ++ * ++ * This value is allowed to be changed. ++ */ ++#define LRNG_FULL_SEED_ENTROPY_BITS LRNG_DRNG_SECURITY_STRENGTH_BITS ++#define LRNG_MIN_SEED_ENTROPY_BITS 128 ++#define LRNG_INIT_ENTROPY_BITS 32 ++ ++/* ++ * Wakeup value ++ * ++ * This value is allowed to be changed but must not be larger than the ++ * digest size of the hash operation used update the aux_pool. ++ */ ++#ifdef CONFIG_CRYPTO_LIB_SHA256 ++# define LRNG_ATOMIC_DIGEST_SIZE SHA256_DIGEST_SIZE ++#else ++# define LRNG_ATOMIC_DIGEST_SIZE SHA1_DIGEST_SIZE ++#endif ++#define LRNG_WRITE_WAKEUP_ENTROPY LRNG_ATOMIC_DIGEST_SIZE ++ ++/* ++ * If the switching support is configured, we must provide support up to ++ * the largest digest size. Without switching support, we know it is only ++ * the built-in digest size. ++ */ ++#ifdef CONFIG_LRNG_DRNG_SWITCH ++# define LRNG_MAX_DIGESTSIZE 64 ++#else ++# define LRNG_MAX_DIGESTSIZE LRNG_ATOMIC_DIGEST_SIZE ++#endif ++ ++/* ++ * Oversampling factor of IRQ events to obtain ++ * LRNG_DRNG_SECURITY_STRENGTH_BYTES. This factor is used when a ++ * high-resolution time stamp is not available. In this case, jiffies and ++ * register contents are used to fill the entropy pool. These noise sources ++ * are much less entropic than the high-resolution timer. The entropy content ++ * is the entropy content assumed with LRNG_IRQ_ENTROPY_BITS divided by ++ * LRNG_IRQ_OVERSAMPLING_FACTOR. ++ * ++ * This value is allowed to be changed. ++ */ ++#define LRNG_IRQ_OVERSAMPLING_FACTOR 10 ++ ++/* Alignmask that is intended to be identical to CRYPTO_MINALIGN */ ++#define LRNG_KCAPI_ALIGN ARCH_KMALLOC_MINALIGN ++ ++/* ++ * This definition must provide a buffer that is equal to SHASH_DESC_ON_STACK ++ * as it will be casted into a struct shash_desc. ++ */ ++#define LRNG_POOL_SIZE (sizeof(struct shash_desc) + HASH_MAX_DESCSIZE) ++ ++/************************ Default DRNG implementation *************************/ ++ ++extern struct chacha20_state chacha20; ++extern const struct lrng_crypto_cb lrng_cc20_crypto_cb; ++void lrng_cc20_init_state(struct chacha20_state *state); ++ ++/********************************** /proc *************************************/ ++ ++static inline void lrng_pool_inc_numa_node(void) { } ++ ++/****************************** LRNG interfaces *******************************/ ++ ++extern u32 lrng_write_wakeup_bits; ++extern int lrng_drng_reseed_max_time; ++ ++void lrng_writer_wakeup(void); ++void lrng_init_wakeup(void); ++void lrng_debug_report_seedlevel(const char *name); ++void lrng_process_ready_list(void); ++ ++/* External interface to use of the switchable DRBG inside the kernel */ ++void get_random_bytes_full(void *buf, int nbytes); ++ ++/************************* Jitter RNG Entropy Source **************************/ ++ ++#ifdef CONFIG_LRNG_JENT ++u32 lrng_get_jent(u8 *outbuf, u32 requested_bits); ++u32 lrng_jent_entropylevel(u32 requested_bits); ++#else /* CONFIG_CRYPTO_JITTERENTROPY */ ++static inline u32 lrng_get_jent(u8 *outbuf, u32 requested_bits) { return 0; } ++static inline u32 lrng_jent_entropylevel(u32 requested_bits) { return 0; } ++#endif /* CONFIG_CRYPTO_JITTERENTROPY */ ++ ++/************************** CPU-based Entropy Source **************************/ ++ ++static inline u32 lrng_fast_noise_entropylevel(u32 ent_bits, u32 requested_bits) ++{ ++ /* Obtain entropy statement */ ++ ent_bits = ent_bits * requested_bits / LRNG_DRNG_SECURITY_STRENGTH_BITS; ++ /* Cap entropy to buffer size in bits */ ++ ent_bits = min_t(u32, ent_bits, requested_bits); ++ return ent_bits; ++} ++ ++u32 lrng_get_arch(u8 *outbuf, u32 requested_bits); ++u32 lrng_archrandom_entropylevel(u32 requested_bits); ++ ++/************************** Interrupt Entropy Source **************************/ ++ ++bool lrng_pcpu_continuous_compression_state(void); ++void lrng_pcpu_reset(void); ++u32 lrng_pcpu_avail_pool_size(void); ++u32 lrng_pcpu_avail_entropy(void); ++int lrng_pcpu_switch_hash(int node, ++ const struct lrng_crypto_cb *new_cb, void *new_hash, ++ const struct lrng_crypto_cb *old_cb); ++u32 lrng_pcpu_pool_hash(u8 *outbuf, u32 requested_bits, bool fully_seeded); ++void lrng_pcpu_array_add_u32(u32 data); ++ ++/****************************** DRNG processing *******************************/ ++ ++/* DRNG state handle */ ++struct lrng_drng { ++ void *drng; /* DRNG handle */ ++ void *hash; /* Hash handle */ ++ const struct lrng_crypto_cb *crypto_cb; /* Crypto callbacks */ ++ atomic_t requests; /* Number of DRNG requests */ ++ unsigned long last_seeded; /* Last time it was seeded */ ++ bool fully_seeded; /* Is DRNG fully seeded? */ ++ bool force_reseed; /* Force a reseed */ ++ ++ /* Lock write operations on DRNG state, DRNG replacement of crypto_cb */ ++ struct mutex lock; ++ spinlock_t spin_lock; ++ /* Lock *hash replacement - always take before DRNG lock */ ++ rwlock_t hash_lock; ++}; ++ ++extern struct mutex lrng_crypto_cb_update; ++ ++struct lrng_drng *lrng_drng_init_instance(void); ++struct lrng_drng *lrng_drng_atomic_instance(void); ++ ++static __always_inline bool lrng_drng_is_atomic(struct lrng_drng *drng) ++{ ++ return (drng->drng == lrng_drng_atomic_instance()->drng); ++} ++ ++/* Lock the DRNG */ ++static __always_inline void lrng_drng_lock(struct lrng_drng *drng, ++ unsigned long *flags) ++ __acquires(&drng->spin_lock) ++{ ++ /* Use spin lock in case the atomic DRNG context is used */ ++ if (lrng_drng_is_atomic(drng)) { ++ spin_lock_irqsave(&drng->spin_lock, *flags); ++ ++ /* ++ * In case a lock transition happened while we were spinning, ++ * catch this case and use the new lock type. ++ */ ++ if (!lrng_drng_is_atomic(drng)) { ++ spin_unlock_irqrestore(&drng->spin_lock, *flags); ++ __acquire(&drng->spin_lock); ++ mutex_lock(&drng->lock); ++ } ++ } else { ++ __acquire(&drng->spin_lock); ++ mutex_lock(&drng->lock); ++ } ++} ++ ++/* Unlock the DRNG */ ++static __always_inline void lrng_drng_unlock(struct lrng_drng *drng, ++ unsigned long *flags) ++ __releases(&drng->spin_lock) ++{ ++ if (lrng_drng_is_atomic(drng)) { ++ spin_unlock_irqrestore(&drng->spin_lock, *flags); ++ } else { ++ mutex_unlock(&drng->lock); ++ __release(&drng->spin_lock); ++ } ++} ++ ++void lrng_reset(void); ++void lrng_drngs_init_cc20(bool force_seed); ++bool lrng_sp80090c_compliant(void); ++ ++static inline u32 lrng_compress_osr(void) ++{ ++ return lrng_sp80090c_compliant() ? CONFIG_LRNG_OVERSAMPLE_ES_BITS : 0; ++} ++ ++static inline u32 lrng_reduce_by_osr(u32 entropy_bits) ++{ ++ u32 osr_bits = lrng_compress_osr(); ++ return (entropy_bits >= osr_bits) ? (entropy_bits - osr_bits) : 0; ++} ++ ++bool lrng_get_available(void); ++void lrng_set_available(void); ++void lrng_drng_reset(struct lrng_drng *drng); ++int lrng_drng_get_atomic(u8 *outbuf, u32 outbuflen); ++int lrng_drng_get_sleep(u8 *outbuf, u32 outbuflen); ++void lrng_drng_force_reseed(void); ++void lrng_drng_seed_work(struct work_struct *dummy); ++ ++static inline struct lrng_drng **lrng_drng_instances(void) { return NULL; } ++static inline void lrng_drngs_numa_alloc(void) { return; } ++ ++/************************* Entropy sources management *************************/ ++ ++enum lrng_external_noise_source { ++ lrng_noise_source_hw, ++ lrng_noise_source_user ++}; ++ ++u32 lrng_avail_aux_entropy(void); ++u32 lrng_get_digestsize(void); ++ ++/* Obtain the security strength of the LRNG in bits */ ++static inline u32 lrng_security_strength(void) ++{ ++ /* ++ * We use a hash to read the entropy in the entropy pool. According to ++ * SP800-90B table 1, the entropy can be at most the digest size. ++ * Considering this together with the last sentence in section 3.1.5.1.2 ++ * the security strength of a (approved) hash is equal to its output ++ * size. On the other hand the entropy cannot be larger than the ++ * security strength of the used DRBG. ++ */ ++ return min_t(u32, LRNG_FULL_SEED_ENTROPY_BITS, lrng_get_digestsize()); ++} ++ ++static inline u32 lrng_get_seed_entropy_osr(void) ++{ ++ u32 requested_bits = lrng_security_strength(); ++ ++ /* Apply oversampling during initialization according to SP800-90C */ ++ if (lrng_sp80090c_compliant()) ++ requested_bits += CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS; ++ return requested_bits; ++} ++ ++void lrng_set_entropy_thresh(u32 new); ++u32 lrng_avail_entropy(void); ++void lrng_reset_state(void); ++ ++bool lrng_state_exseed_allow(enum lrng_external_noise_source source); ++void lrng_state_exseed_set(enum lrng_external_noise_source source, bool type); ++bool lrng_state_min_seeded(void); ++bool lrng_state_fully_seeded(void); ++bool lrng_state_operational(void); ++ ++int lrng_pool_trylock(void); ++void lrng_pool_unlock(void); ++void lrng_pool_all_numa_nodes_seeded(bool set); ++bool lrng_pool_highres_timer(void); ++void lrng_pool_set_entropy(u32 entropy_bits); ++int lrng_aux_switch_hash(const struct lrng_crypto_cb *new_cb, void *new_hash, ++ const struct lrng_crypto_cb *old_cb); ++int lrng_pool_insert_aux(const u8 *inbuf, u32 inbuflen, u32 entropy_bits); ++void lrng_pool_add_entropy(void); ++ ++struct entropy_buf { ++ u8 a[LRNG_DRNG_SECURITY_STRENGTH_BYTES + ++ (CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS >> 3)]; ++ u8 b[LRNG_DRNG_SECURITY_STRENGTH_BYTES + ++ (CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS >> 3)]; ++ u8 c[LRNG_DRNG_SECURITY_STRENGTH_BYTES + ++ (CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS >> 3)]; ++ u8 d[LRNG_DRNG_SECURITY_STRENGTH_BYTES + ++ (CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS >> 3)]; ++ u32 now, a_bits, b_bits, c_bits, d_bits; ++}; ++ ++bool lrng_fully_seeded(struct entropy_buf *eb); ++void lrng_unset_operational(void); ++void lrng_fill_seed_buffer(struct entropy_buf *entropy_buf, u32 requested_bits); ++void lrng_init_ops(struct entropy_buf *eb); ++ ++/************************** Health Test linking code **************************/ ++ ++enum lrng_health_res { ++ lrng_health_pass, /* Health test passes on time stamp */ ++ lrng_health_fail_use, /* Time stamp unhealthy, but mix in */ ++ lrng_health_fail_drop /* Time stamp unhealthy, drop it */ ++}; ++ ++#ifdef CONFIG_LRNG_HEALTH_TESTS ++bool lrng_sp80090b_startup_complete(void); ++bool lrng_sp80090b_compliant(void); ++ ++enum lrng_health_res lrng_health_test(u32 now_time); ++void lrng_health_disable(void); ++ ++#else /* CONFIG_LRNG_HEALTH_TESTS */ ++static inline bool lrng_sp80090b_startup_complete(void) { return true; } ++static inline bool lrng_sp80090b_compliant(void) { return false; } ++ ++static inline enum lrng_health_res ++lrng_health_test(u32 now_time) { return lrng_health_pass; } ++static inline void lrng_health_disable(void) { } ++#endif /* CONFIG_LRNG_HEALTH_TESTS */ ++ ++/****************************** Helper code ***********************************/ ++ ++static inline u32 atomic_read_u32(atomic_t *v) ++{ ++ return (u32)atomic_read(v); ++} ++ ++/*************************** Auxiliary functions ******************************/ ++ ++void invalidate_batched_entropy(void); ++ ++/***************************** Testing code ***********************************/ ++ ++#ifdef CONFIG_LRNG_RAW_HIRES_ENTROPY ++bool lrng_raw_hires_entropy_store(u32 value); ++#else /* CONFIG_LRNG_RAW_HIRES_ENTROPY */ ++static inline bool lrng_raw_hires_entropy_store(u32 value) { return false; } ++#endif /* CONFIG_LRNG_RAW_HIRES_ENTROPY */ ++ ++#ifdef CONFIG_LRNG_RAW_JIFFIES_ENTROPY ++bool lrng_raw_jiffies_entropy_store(u32 value); ++#else /* CONFIG_LRNG_RAW_JIFFIES_ENTROPY */ ++static inline bool lrng_raw_jiffies_entropy_store(u32 value) { return false; } ++#endif /* CONFIG_LRNG_RAW_JIFFIES_ENTROPY */ ++ ++#ifdef CONFIG_LRNG_RAW_IRQ_ENTROPY ++bool lrng_raw_irq_entropy_store(u32 value); ++#else /* CONFIG_LRNG_RAW_IRQ_ENTROPY */ ++static inline bool lrng_raw_irq_entropy_store(u32 value) { return false; } ++#endif /* CONFIG_LRNG_RAW_IRQ_ENTROPY */ ++ ++#ifdef CONFIG_LRNG_RAW_IRQFLAGS_ENTROPY ++bool lrng_raw_irqflags_entropy_store(u32 value); ++#else /* CONFIG_LRNG_RAW_IRQFLAGS_ENTROPY */ ++static inline bool lrng_raw_irqflags_entropy_store(u32 value) { return false; } ++#endif /* CONFIG_LRNG_RAW_IRQFLAGS_ENTROPY */ ++ ++#ifdef CONFIG_LRNG_RAW_RETIP_ENTROPY ++bool lrng_raw_retip_entropy_store(u32 value); ++#else /* CONFIG_LRNG_RAW_RETIP_ENTROPY */ ++static inline bool lrng_raw_retip_entropy_store(u32 value) { return false; } ++#endif /* CONFIG_LRNG_RAW_RETIP_ENTROPY */ ++ ++#ifdef CONFIG_LRNG_RAW_REGS_ENTROPY ++bool lrng_raw_regs_entropy_store(u32 value); ++#else /* CONFIG_LRNG_RAW_REGS_ENTROPY */ ++static inline bool lrng_raw_regs_entropy_store(u32 value) { return false; } ++#endif /* CONFIG_LRNG_RAW_REGS_ENTROPY */ ++ ++#ifdef CONFIG_LRNG_RAW_ARRAY ++bool lrng_raw_array_entropy_store(u32 value); ++#else /* CONFIG_LRNG_RAW_ARRAY */ ++static inline bool lrng_raw_array_entropy_store(u32 value) { return false; } ++#endif /* CONFIG_LRNG_RAW_ARRAY */ ++ ++#ifdef CONFIG_LRNG_IRQ_PERF ++bool lrng_perf_time(u32 start); ++#else /* CONFIG_LRNG_IRQ_PERF */ ++static inline bool lrng_perf_time(u32 start) { return false; } ++#endif /*CONFIG_LRNG_IRQ_PERF */ ++ ++#endif /* _LRNG_INTERNAL_H */ +--- /dev/null ++++ b/drivers/char/lrng/lrng_pool.c +@@ -0,0 +1,622 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause ++/* ++ * LRNG Entropy sources management ++ * LRNG Slow Entropy Source: Auxiliary entropy pool ++ * ++ * Copyright (C) 2016 - 2021, Stephan Mueller ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "lrng_internal.h" ++#include "lrng_sw_noise.h" ++ ++struct lrng_state { ++ bool can_invalidate; /* Can invalidate batched entropy? */ ++ bool perform_seedwork; /* Can seed work be performed? */ ++ bool lrng_operational; /* Is DRNG operational? */ ++ bool lrng_fully_seeded; /* Is DRNG fully seeded? */ ++ bool lrng_min_seeded; /* Is DRNG minimally seeded? */ ++ bool all_online_numa_node_seeded;/* All NUMA DRNGs seeded? */ ++ ++ /* ++ * To ensure that external entropy providers cannot dominate the ++ * internal noise sources but yet cannot be dominated by internal ++ * noise sources, the following booleans are intended to allow ++ * external to provide seed once when a DRNG reseed occurs. This ++ * triggering of external noise source is performed even when the ++ * entropy pool has sufficient entropy. ++ */ ++ bool lrng_seed_hw; /* Allow HW to provide seed */ ++ bool lrng_seed_user; /* Allow user space to provide seed */ ++ ++ atomic_t boot_entropy_thresh; /* Reseed threshold */ ++ atomic_t reseed_in_progress; /* Flag for on executing reseed */ ++ struct work_struct lrng_seed_work; /* (re)seed work queue */ ++}; ++ ++/* ++ * This is the auxiliary pool ++ * ++ * The aux pool array is aligned to 8 bytes to comfort the kernel crypto API ++ * cipher implementations of the hash functions used to read the pool: for some ++ * accelerated implementations, we need an alignment to avoid a realignment ++ * which involves memcpy(). The alignment to 8 bytes should satisfy all crypto ++ * implementations. ++ */ ++struct lrng_pool { ++ u8 aux_pool[LRNG_POOL_SIZE]; /* Aux pool: digest state */ ++ atomic_t aux_entropy_bits; ++ atomic_t digestsize; /* Digest size of used hash */ ++ bool initialized; /* Aux pool initialized? */ ++ ++ /* Serialize read of entropy pool and update of aux pool */ ++ spinlock_t lock; ++}; ++ ++static struct lrng_pool lrng_pool __aligned(LRNG_KCAPI_ALIGN) = { ++ .aux_entropy_bits = ATOMIC_INIT(0), ++ .digestsize = ATOMIC_INIT(LRNG_ATOMIC_DIGEST_SIZE), ++ .initialized = false, ++ .lock = __SPIN_LOCK_UNLOCKED(lrng_pool.lock) ++}; ++ ++static struct lrng_state lrng_state = { ++ false, false, false, false, false, false, true, true, ++ .boot_entropy_thresh = ATOMIC_INIT(LRNG_INIT_ENTROPY_BITS), ++ .reseed_in_progress = ATOMIC_INIT(0), ++}; ++ ++/********************************** Helper ***********************************/ ++ ++/* External entropy provider is allowed to provide seed data */ ++bool lrng_state_exseed_allow(enum lrng_external_noise_source source) ++{ ++ if (source == lrng_noise_source_hw) ++ return lrng_state.lrng_seed_hw; ++ return lrng_state.lrng_seed_user; ++} ++ ++/* Enable / disable external entropy provider to furnish seed */ ++void lrng_state_exseed_set(enum lrng_external_noise_source source, bool type) ++{ ++ if (source == lrng_noise_source_hw) ++ lrng_state.lrng_seed_hw = type; ++ else ++ lrng_state.lrng_seed_user = type; ++} ++ ++static inline void lrng_state_exseed_allow_all(void) ++{ ++ lrng_state_exseed_set(lrng_noise_source_hw, true); ++ lrng_state_exseed_set(lrng_noise_source_user, true); ++} ++ ++/* Entropy in bits present in aux pool */ ++u32 lrng_avail_aux_entropy(void) ++{ ++ /* Cap available entropy with max entropy */ ++ u32 avail_bits = min_t(u32, lrng_get_digestsize(), ++ atomic_read_u32(&lrng_pool.aux_entropy_bits)); ++ ++ /* Consider oversampling rate due to aux pool conditioning */ ++ return lrng_reduce_by_osr(avail_bits); ++} ++ ++/* Set the digest size of the used hash in bytes */ ++static inline void lrng_set_digestsize(u32 digestsize) ++{ ++ struct lrng_pool *pool = &lrng_pool; ++ u32 ent_bits = atomic_xchg_relaxed(&pool->aux_entropy_bits, 0), ++ old_digestsize = lrng_get_digestsize(); ++ ++ atomic_set(&lrng_pool.digestsize, digestsize); ++ ++ /* ++ * In case the new digest is larger than the old one, cap the available ++ * entropy to the old message digest used to process the existing data. ++ */ ++ ent_bits = min_t(u32, ent_bits, old_digestsize); ++ atomic_add(ent_bits, &pool->aux_entropy_bits); ++} ++ ++/* Obtain the digest size provided by the used hash in bits */ ++u32 lrng_get_digestsize(void) ++{ ++ return atomic_read_u32(&lrng_pool.digestsize) << 3; ++} ++ ++/* ++ * Reading of the LRNG pool is only allowed by one caller. The reading is ++ * only performed to (re)seed DRNGs. Thus, if this "lock" is already taken, ++ * the reseeding operation is in progress. The caller is not intended to wait ++ * but continue with its other operation. ++ */ ++int lrng_pool_trylock(void) ++{ ++ return atomic_cmpxchg(&lrng_state.reseed_in_progress, 0, 1); ++} ++ ++void lrng_pool_unlock(void) ++{ ++ atomic_set(&lrng_state.reseed_in_progress, 0); ++} ++ ++/* Set new entropy threshold for reseeding during boot */ ++void lrng_set_entropy_thresh(u32 new_entropy_bits) ++{ ++ atomic_set(&lrng_state.boot_entropy_thresh, new_entropy_bits); ++} ++ ++/* ++ * Reset LRNG state - the entropy counters are reset, but the data that may ++ * or may not have entropy remains in the pools as this data will not hurt. ++ */ ++void lrng_reset_state(void) ++{ ++ atomic_set(&lrng_pool.aux_entropy_bits, 0); ++ lrng_pcpu_reset(); ++ lrng_state.lrng_operational = false; ++ lrng_state.lrng_fully_seeded = false; ++ lrng_state.lrng_min_seeded = false; ++ lrng_state.all_online_numa_node_seeded = false; ++ pr_debug("reset LRNG\n"); ++} ++ ++/* Set flag that all DRNGs are fully seeded */ ++void lrng_pool_all_numa_nodes_seeded(bool set) ++{ ++ lrng_state.all_online_numa_node_seeded = set; ++} ++ ++/* Return boolean whether LRNG reached minimally seed level */ ++bool lrng_state_min_seeded(void) ++{ ++ return lrng_state.lrng_min_seeded; ++} ++ ++/* Return boolean whether LRNG reached fully seed level */ ++bool lrng_state_fully_seeded(void) ++{ ++ return lrng_state.lrng_fully_seeded; ++} ++ ++/* Return boolean whether LRNG is considered fully operational */ ++bool lrng_state_operational(void) ++{ ++ return lrng_state.lrng_operational; ++} ++ ++/* Policy to check whether entropy buffer contains full seeded entropy */ ++bool lrng_fully_seeded(struct entropy_buf *eb) ++{ ++ return ((eb->a_bits + eb->b_bits + eb->c_bits + eb->d_bits) >= ++ lrng_get_seed_entropy_osr()); ++} ++ ++/* Disable the fully seeded and operational mode */ ++void lrng_unset_operational(void) ++{ ++ lrng_pool_all_numa_nodes_seeded(false); ++ lrng_state.lrng_operational = false; ++ lrng_state.lrng_fully_seeded = false; ++} ++ ++/* Policy to enable LRNG operational mode */ ++static inline void lrng_set_operational(u32 external_es) ++{ ++ if (lrng_state.lrng_fully_seeded && ++ (lrng_sp80090b_startup_complete() || ++ (lrng_get_seed_entropy_osr() <= external_es))) { ++ lrng_state.lrng_operational = true; ++ lrng_process_ready_list(); ++ lrng_init_wakeup(); ++ pr_info("LRNG fully operational\n"); ++ } ++} ++ ++/* Set entropy content in user-space controllable aux pool */ ++void lrng_pool_set_entropy(u32 entropy_bits) ++{ ++ atomic_set(&lrng_pool.aux_entropy_bits, entropy_bits); ++} ++ ++/* Available entropy in the entire LRNG considering all entropy sources */ ++u32 lrng_avail_entropy(void) ++{ ++ u32 ent_thresh = lrng_security_strength(); ++ ++ /* ++ * Apply oversampling during initialization according to SP800-90C as ++ * we request a larger buffer from the ES. ++ */ ++ if (lrng_sp80090c_compliant() && ++ !lrng_state.all_online_numa_node_seeded) ++ ent_thresh += CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS; ++ ++ return lrng_pcpu_avail_entropy() + lrng_avail_aux_entropy() + ++ lrng_archrandom_entropylevel(ent_thresh) + ++ lrng_jent_entropylevel(ent_thresh); ++} ++ ++/** ++ * lrng_init_ops() - Set seed stages of LRNG ++ * ++ * Set the slow noise source reseed trigger threshold. The initial threshold ++ * is set to the minimum data size that can be read from the pool: a word. Upon ++ * reaching this value, the next seed threshold of 128 bits is set followed ++ * by 256 bits. ++ * ++ * @eb: buffer containing the size of entropy currently injected into DRNG ++ */ ++void lrng_init_ops(struct entropy_buf *eb) ++{ ++ struct lrng_state *state = &lrng_state; ++ u32 requested_bits, seed_bits, external_es; ++ ++ if (state->lrng_operational) ++ return; ++ ++ requested_bits = lrng_get_seed_entropy_osr(); ++ ++ /* ++ * Entropy provided by external entropy sources - if they provide ++ * the requested amount of entropy, unblock the interface. ++ */ ++ external_es = eb->a_bits + eb->c_bits + eb->d_bits; ++ seed_bits = external_es + eb->b_bits; ++ ++ /* DRNG is seeded with full security strength */ ++ if (state->lrng_fully_seeded) { ++ lrng_set_operational(external_es); ++ lrng_set_entropy_thresh(requested_bits); ++ } else if (lrng_fully_seeded(eb)) { ++ if (state->can_invalidate) ++ invalidate_batched_entropy(); ++ ++ state->lrng_fully_seeded = true; ++ lrng_set_operational(external_es); ++ state->lrng_min_seeded = true; ++ pr_info("LRNG fully seeded with %u bits of entropy\n", ++ seed_bits); ++ lrng_set_entropy_thresh(requested_bits); ++ } else if (!state->lrng_min_seeded) { ++ ++ /* DRNG is seeded with at least 128 bits of entropy */ ++ if (seed_bits >= LRNG_MIN_SEED_ENTROPY_BITS) { ++ if (state->can_invalidate) ++ invalidate_batched_entropy(); ++ ++ state->lrng_min_seeded = true; ++ pr_info("LRNG minimally seeded with %u bits of entropy\n", ++ seed_bits); ++ lrng_set_entropy_thresh(requested_bits); ++ lrng_init_wakeup(); ++ ++ /* DRNG is seeded with at least LRNG_INIT_ENTROPY_BITS bits */ ++ } else if (seed_bits >= LRNG_INIT_ENTROPY_BITS) { ++ pr_info("LRNG initial entropy level %u bits of entropy\n", ++ seed_bits); ++ lrng_set_entropy_thresh(LRNG_MIN_SEED_ENTROPY_BITS); ++ } ++ } ++} ++ ++int __init rand_initialize(void) ++{ ++ struct seed { ++ ktime_t time; ++ unsigned long data[(LRNG_MAX_DIGESTSIZE / ++ sizeof(unsigned long))]; ++ struct new_utsname utsname; ++ } seed __aligned(LRNG_KCAPI_ALIGN); ++ unsigned int i; ++ ++ BUILD_BUG_ON(LRNG_MAX_DIGESTSIZE % sizeof(unsigned long)); ++ ++ seed.time = ktime_get_real(); ++ ++ for (i = 0; i < ARRAY_SIZE(seed.data); i++) { ++ if (!arch_get_random_seed_long_early(&(seed.data[i])) && ++ !arch_get_random_long_early(&seed.data[i])) ++ seed.data[i] = random_get_entropy(); ++ } ++ memcpy(&seed.utsname, utsname(), sizeof(*(utsname()))); ++ ++ lrng_pool_insert_aux((u8 *)&seed, sizeof(seed), 0); ++ memzero_explicit(&seed, sizeof(seed)); ++ ++ /* Initialize the seed work queue */ ++ INIT_WORK(&lrng_state.lrng_seed_work, lrng_drng_seed_work); ++ lrng_state.perform_seedwork = true; ++ ++ lrng_drngs_init_cc20(true); ++ invalidate_batched_entropy(); ++ ++ lrng_state.can_invalidate = true; ++ ++ return 0; ++} ++ ++/* ++ * Replace old with new hash for auxiliary pool handling ++ * ++ * Assumption: the caller must guarantee that the new_cb is available during the ++ * entire operation (e.g. it must hold the write lock against pointer updating). ++ */ ++int lrng_aux_switch_hash(const struct lrng_crypto_cb *new_cb, void *new_hash, ++ const struct lrng_crypto_cb *old_cb) ++{ ++ struct lrng_pool *pool = &lrng_pool; ++ struct shash_desc *shash = (struct shash_desc *)pool->aux_pool; ++ u8 digest[LRNG_MAX_DIGESTSIZE]; ++ int ret; ++ ++ if (!IS_ENABLED(CONFIG_LRNG_DRNG_SWITCH)) ++ return -EOPNOTSUPP; ++ ++ if (unlikely(!pool->initialized)) ++ return 0; ++ ++ /* Get the aux pool hash with old digest ... */ ++ ret = old_cb->lrng_hash_final(shash, digest) ?: ++ /* ... re-initialize the hash with the new digest ... */ ++ new_cb->lrng_hash_init(shash, new_hash) ?: ++ /* ++ * ... feed the old hash into the new state. We may feed ++ * uninitialized memory into the new state, but this is ++ * considered no issue and even good as we have some more ++ * uncertainty here. ++ */ ++ new_cb->lrng_hash_update(shash, digest, sizeof(digest)); ++ if (!ret) { ++ lrng_set_digestsize(new_cb->lrng_hash_digestsize(new_hash)); ++ pr_debug("Re-initialize aux entropy pool with hash %s\n", ++ new_cb->lrng_hash_name()); ++ } ++ ++ memzero_explicit(digest, sizeof(digest)); ++ return ret; ++} ++ ++/* ++ * Insert data into auxiliary pool by hashing the input data together with ++ * the auxiliary pool. The message digest is the new state of the auxiliary ++ * pool. ++ */ ++static int ++lrng_pool_insert_aux_locked(const u8 *inbuf, u32 inbuflen, u32 entropy_bits) ++{ ++ struct lrng_pool *pool = &lrng_pool; ++ struct shash_desc *shash = (struct shash_desc *)pool->aux_pool; ++ struct lrng_drng *drng = lrng_drng_init_instance(); ++ const struct lrng_crypto_cb *crypto_cb; ++ unsigned long flags; ++ void *hash; ++ int ret; ++ ++ entropy_bits = min_t(u32, entropy_bits, inbuflen << 3); ++ ++ read_lock_irqsave(&drng->hash_lock, flags); ++ ++ crypto_cb = drng->crypto_cb; ++ hash = drng->hash; ++ ++ if (unlikely(!pool->initialized)) { ++ ret = crypto_cb->lrng_hash_init(shash, hash); ++ if (ret) ++ goto out; ++ pool->initialized = true; ++ } ++ ++ ret = crypto_cb->lrng_hash_update(shash, inbuf, inbuflen); ++ if (ret) ++ goto out; ++ ++ /* ++ * Cap the available entropy to the hash output size compliant to ++ * SP800-90B section 3.1.5.1 table 1. ++ */ ++ entropy_bits += atomic_read_u32(&pool->aux_entropy_bits); ++ atomic_set(&pool->aux_entropy_bits, ++ min_t(u32, entropy_bits, ++ crypto_cb->lrng_hash_digestsize(hash) << 3)); ++ ++out: ++ read_unlock_irqrestore(&drng->hash_lock, flags); ++ return ret; ++} ++ ++int lrng_pool_insert_aux(const u8 *inbuf, u32 inbuflen, u32 entropy_bits) ++{ ++ struct lrng_pool *pool = &lrng_pool; ++ unsigned long flags; ++ int ret; ++ ++ spin_lock_irqsave(&pool->lock, flags); ++ ret = lrng_pool_insert_aux_locked(inbuf, inbuflen, entropy_bits); ++ spin_unlock_irqrestore(&pool->lock, flags); ++ ++ lrng_pool_add_entropy(); ++ ++ return ret; ++} ++ ++/* Hot code path during boot - mix data into entropy pool during boot */ ++void lrng_pool_add_entropy(void) ++{ ++ /* ++ * Once all DRNGs are fully seeded, the interrupt noise ++ * sources will not trigger any reseeding any more. ++ */ ++ if (likely(lrng_state.all_online_numa_node_seeded)) ++ return; ++ ++ /* Only try to reseed if the DRNG is alive. */ ++ if (!lrng_get_available()) ++ return; ++ ++ /* Only trigger the DRNG reseed if we have collected entropy. */ ++ if (lrng_avail_entropy() < ++ atomic_read_u32(&lrng_state.boot_entropy_thresh)) ++ return; ++ ++ /* Ensure that the seeding only occurs once at any given time. */ ++ if (lrng_pool_trylock()) ++ return; ++ ++ /* Seed the DRNG with IRQ noise. */ ++ if (lrng_state.perform_seedwork) ++ schedule_work(&lrng_state.lrng_seed_work); ++ else ++ lrng_drng_seed_work(NULL); ++} ++ ++/************************* Get data from entropy pool *************************/ ++ ++/** ++ * Get auxiliary entropy pool and its entropy content for seed buffer. ++ * Caller must hold lrng_pool.pool->lock. ++ * @outbuf: buffer to store data in with size requested_bits ++ * @requested_bits: Requested amount of entropy ++ * @return: amount of entropy in outbuf in bits. ++ */ ++static inline u32 lrng_get_aux_pool(u8 *outbuf, u32 requested_bits) ++{ ++ struct lrng_pool *pool = &lrng_pool; ++ struct shash_desc *shash = (struct shash_desc *)pool->aux_pool; ++ struct lrng_drng *drng = lrng_drng_init_instance(); ++ const struct lrng_crypto_cb *crypto_cb; ++ unsigned long flags; ++ void *hash; ++ u32 collected_ent_bits, returned_ent_bits, unused_bits = 0, ++ digestsize; ++ u8 aux_output[LRNG_MAX_DIGESTSIZE]; ++ ++ if (unlikely(!pool->initialized)) ++ return 0; ++ ++ read_lock_irqsave(&drng->hash_lock, flags); ++ ++ crypto_cb = drng->crypto_cb; ++ hash = drng->hash; ++ digestsize = crypto_cb->lrng_hash_digestsize(hash); ++ ++ /* Ensure that no more than the size of aux_pool can be requested */ ++ requested_bits = min_t(u32, requested_bits, (LRNG_MAX_DIGESTSIZE << 3)); ++ ++ /* Cap entropy with entropy counter from aux pool and the used digest */ ++ collected_ent_bits = min_t(u32, digestsize << 3, ++ atomic_xchg_relaxed(&pool->aux_entropy_bits, 0)); ++ ++ /* We collected too much entropy and put the overflow back */ ++ if (collected_ent_bits > (requested_bits + lrng_compress_osr())) { ++ /* Amount of bits we collected too much */ ++ unused_bits = collected_ent_bits - requested_bits; ++ /* Put entropy back */ ++ atomic_add(unused_bits, &pool->aux_entropy_bits); ++ /* Fix collected entropy */ ++ collected_ent_bits = requested_bits; ++ } ++ ++ /* Apply oversampling: discount requested oversampling rate */ ++ returned_ent_bits = lrng_reduce_by_osr(collected_ent_bits); ++ ++ pr_debug("obtained %u bits by collecting %u bits of entropy from aux pool, %u bits of entropy remaining\n", ++ returned_ent_bits, collected_ent_bits, unused_bits); ++ ++ /* Get the digest for the aux pool to be returned to the caller ... */ ++ if (crypto_cb->lrng_hash_final(shash, aux_output) || ++ /* ++ * ... and re-initialize the aux state. Do not add the aux pool ++ * digest for backward secrecy as it will be added with the ++ * insertion of the complete seed buffer after it has been filled. ++ */ ++ crypto_cb->lrng_hash_init(shash, hash)) { ++ returned_ent_bits = 0; ++ } else { ++ /* ++ * Do not truncate the output size exactly to collected_ent_bits ++ * as the aux pool may contain data that is not credited with ++ * entropy, but we want to use them to stir the DRNG state. ++ */ ++ memcpy(outbuf, aux_output, requested_bits >> 3); ++ } ++ ++ read_unlock_irqrestore(&drng->hash_lock, flags); ++ memzero_explicit(aux_output, digestsize); ++ return returned_ent_bits; ++} ++ ++/* Fill the seed buffer with data from the noise sources */ ++void lrng_fill_seed_buffer(struct entropy_buf *entropy_buf, u32 requested_bits) ++{ ++ struct lrng_pool *pool = &lrng_pool; ++ struct lrng_state *state = &lrng_state; ++ unsigned long flags; ++ u32 pcpu_request, req_ent = lrng_sp80090c_compliant() ? ++ lrng_security_strength() : LRNG_MIN_SEED_ENTROPY_BITS; ++ ++ /* Guarantee that requested bits is a multiple of bytes */ ++ BUILD_BUG_ON(LRNG_DRNG_SECURITY_STRENGTH_BITS % 8); ++ ++ /* always reseed the DRNG with the current time stamp */ ++ entropy_buf->now = random_get_entropy(); ++ ++ /* ++ * Require at least 128 bits of entropy for any reseed. If the LRNG is ++ * operated SP800-90C compliant we want to comply with SP800-90A section ++ * 9.2 mandating that DRNG is reseeded with the security strength. ++ */ ++ if (state->lrng_fully_seeded && (lrng_avail_entropy() < req_ent)) { ++ entropy_buf->a_bits = entropy_buf->b_bits = 0; ++ entropy_buf->c_bits = entropy_buf->d_bits = 0; ++ goto wakeup; ++ } ++ ++ /* Ensure aux pool extraction and backtracking op are atomic */ ++ spin_lock_irqsave(&pool->lock, flags); ++ ++ /* Concatenate the output of the entropy sources. */ ++ entropy_buf->a_bits = lrng_get_aux_pool(entropy_buf->a, requested_bits); ++ ++ /* ++ * If the aux pool returned entropy, pull respective less from per-CPU ++ * pool, but attempt to at least get LRNG_MIN_SEED_ENTROPY_BITS entropy. ++ */ ++ pcpu_request = max_t(u32, requested_bits - entropy_buf->a_bits, ++ LRNG_MIN_SEED_ENTROPY_BITS); ++ entropy_buf->b_bits = lrng_pcpu_pool_hash(entropy_buf->b, pcpu_request, ++ state->lrng_fully_seeded); ++ ++ entropy_buf->c_bits = lrng_get_arch(entropy_buf->c, requested_bits); ++ entropy_buf->d_bits = lrng_get_jent(entropy_buf->d, requested_bits); ++ ++ /* Mix the extracted data back into pool for backtracking resistance */ ++ if (lrng_pool_insert_aux_locked((u8 *)entropy_buf, ++ sizeof(struct entropy_buf), 0)) ++ pr_warn("Backtracking resistance operation failed\n"); ++ ++ spin_unlock_irqrestore(&pool->lock, flags); ++ ++ /* allow external entropy provider to provide seed */ ++ lrng_state_exseed_allow_all(); ++ ++wakeup: ++ /* ++ * Shall we wake up user space writers? This location covers ++ * ensures that the user space provider does not dominate the internal ++ * noise sources since in case the first call of this function finds ++ * sufficient entropy in the entropy pool, it will not trigger the ++ * wakeup. This implies that when the next /dev/urandom read happens, ++ * the entropy pool is drained. ++ */ ++ lrng_writer_wakeup(); ++} +--- /dev/null ++++ b/drivers/char/lrng/lrng_sw_noise.c +@@ -0,0 +1,702 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause ++/* ++ * LRNG Slow Entropy Source: Interrupt data collection ++ * ++ * Copyright (C) 2016 - 2021, Stephan Mueller ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "lrng_internal.h" ++#include "lrng_sw_noise.h" ++ ++/* Number of interrupts required for LRNG_DRNG_SECURITY_STRENGTH_BITS entropy */ ++static u32 lrng_irq_entropy_bits = LRNG_IRQ_ENTROPY_BITS; ++/* Is high-resolution timer present? */ ++static bool lrng_irq_highres_timer = false; ++ ++static u32 irq_entropy __read_mostly = LRNG_IRQ_ENTROPY_BITS; ++#ifdef CONFIG_LRNG_RUNTIME_ES_CONFIG ++module_param(irq_entropy, uint, 0444); ++MODULE_PARM_DESC(irq_entropy, ++ "How many interrupts must be collected for obtaining 256 bits of entropy\n"); ++#endif ++ ++/* Per-CPU array holding concatenated entropy events */ ++static DEFINE_PER_CPU(u32 [LRNG_DATA_ARRAY_SIZE], lrng_pcpu_array) ++ __aligned(LRNG_KCAPI_ALIGN); ++static DEFINE_PER_CPU(u32, lrng_pcpu_array_ptr) = 0; ++static DEFINE_PER_CPU(atomic_t, lrng_pcpu_array_irqs) = ATOMIC_INIT(0); ++ ++/* ++ * The entropy collection is performed by executing the following steps: ++ * 1. fill up the per-CPU array holding the time stamps ++ * 2. once the per-CPU array is full, a compression of the data into ++ * the entropy pool is performed - this happens in interrupt context ++ * ++ * If step 2 is not desired in interrupt context, the following boolean ++ * needs to be set to false. This implies that old entropy data in the ++ * per-CPU array collected since the last DRNG reseed is overwritten with ++ * new entropy data instead of retaining the entropy with the compression ++ * operation. ++ * ++ * Impact on entropy: ++ * ++ * If continuous compression is enabled, the maximum entropy that is collected ++ * per CPU between DRNG reseeds is equal to the digest size of the used hash. ++ * ++ * If continuous compression is disabled, the maximum number of entropy events ++ * that can be collected per CPU is equal to LRNG_DATA_ARRAY_SIZE. This amount ++ * of events is converted into an entropy statement which then represents the ++ * maximum amount of entropy collectible per CPU between DRNG reseeds. ++ */ ++static bool lrng_pcpu_continuous_compression __read_mostly = ++ IS_ENABLED(CONFIG_LRNG_ENABLE_CONTINUOUS_COMPRESSION); ++ ++#ifdef CONFIG_LRNG_SWITCHABLE_CONTINUOUS_COMPRESSION ++module_param(lrng_pcpu_continuous_compression, bool, 0444); ++MODULE_PARM_DESC(lrng_pcpu_continuous_compression, ++ "Perform entropy compression if per-CPU entropy data array is full\n"); ++#endif ++ ++/* ++ * Per-CPU entropy pool with compressed entropy event ++ * ++ * The per-CPU entropy pool is defined as the hash state. New data is simply ++ * inserted into the entropy pool by performing a hash update operation. ++ * To read the entropy pool, a hash final must be invoked. However, before ++ * the entropy pool is released again after a hash final, the hash init must ++ * be performed. ++ */ ++static DEFINE_PER_CPU(u8 [LRNG_POOL_SIZE], lrng_pcpu_pool) ++ __aligned(LRNG_KCAPI_ALIGN); ++/* ++ * Lock to allow other CPUs to read the pool - as this is only done during ++ * reseed which is infrequent, this lock is hardly contended. ++ */ ++static DEFINE_PER_CPU(spinlock_t, lrng_pcpu_lock); ++static DEFINE_PER_CPU(bool, lrng_pcpu_lock_init) = false; ++ ++/* Return boolean whether LRNG identified presence of high-resolution timer */ ++bool lrng_pool_highres_timer(void) ++{ ++ return lrng_irq_highres_timer; ++} ++ ++/* Convert entropy in bits into number of IRQs with the same entropy content. */ ++static inline u32 lrng_entropy_to_data(u32 entropy_bits) ++{ ++ return ((entropy_bits * lrng_irq_entropy_bits) / ++ LRNG_DRNG_SECURITY_STRENGTH_BITS); ++} ++ ++/* Convert number of IRQs into entropy value. */ ++static inline u32 lrng_data_to_entropy(u32 irqnum) ++{ ++ return ((irqnum * LRNG_DRNG_SECURITY_STRENGTH_BITS) / ++ lrng_irq_entropy_bits); ++} ++ ++static inline bool lrng_pcpu_pool_online(int cpu) ++{ ++ return per_cpu(lrng_pcpu_lock_init, cpu); ++} ++ ++bool lrng_pcpu_continuous_compression_state(void) ++{ ++ return lrng_pcpu_continuous_compression; ++} ++ ++static void lrng_pcpu_check_compression_state(void) ++{ ++ /* One pool must hold sufficient entropy for disabled compression */ ++ if (!lrng_pcpu_continuous_compression) { ++ u32 max_ent = min_t(u32, lrng_get_digestsize(), ++ lrng_data_to_entropy(LRNG_DATA_NUM_VALUES)); ++ if (max_ent < lrng_security_strength()) { ++ pr_warn("Force continuous compression operation to ensure LRNG can hold enough entropy\n"); ++ lrng_pcpu_continuous_compression = true; ++ } ++ } ++} ++ ++static int __init lrng_init_time_source(void) ++{ ++ /* Set a minimum number of interrupts that must be collected */ ++ irq_entropy = max_t(u32, LRNG_IRQ_ENTROPY_BITS, irq_entropy); ++ ++ if ((random_get_entropy() & LRNG_DATA_SLOTSIZE_MASK) || ++ (random_get_entropy() & LRNG_DATA_SLOTSIZE_MASK)) { ++ /* ++ * As the highres timer is identified here, previous interrupts ++ * obtained during boot time are treated like a lowres-timer ++ * would have been present. ++ */ ++ lrng_irq_highres_timer = true; ++ lrng_irq_entropy_bits = irq_entropy; ++ } else { ++ lrng_health_disable(); ++ lrng_irq_highres_timer = false; ++ lrng_irq_entropy_bits = irq_entropy * ++ LRNG_IRQ_OVERSAMPLING_FACTOR; ++ pr_warn("operating without high-resolution timer and applying IRQ oversampling factor %u\n", ++ LRNG_IRQ_OVERSAMPLING_FACTOR); ++ lrng_pcpu_check_compression_state(); ++ } ++ ++ return 0; ++} ++core_initcall(lrng_init_time_source); ++ ++/* ++ * Reset all per-CPU pools - reset entropy estimator but leave the pool data ++ * that may or may not have entropy unchanged. ++ */ ++void lrng_pcpu_reset(void) ++{ ++ int cpu; ++ ++ for_each_online_cpu(cpu) ++ atomic_set(per_cpu_ptr(&lrng_pcpu_array_irqs, cpu), 0); ++} ++ ++u32 lrng_pcpu_avail_pool_size(void) ++{ ++ u32 max_size = 0, max_pool = lrng_get_digestsize(); ++ int cpu; ++ ++ if (!lrng_pcpu_continuous_compression) ++ max_pool = min_t(u32, max_pool, LRNG_DATA_NUM_VALUES); ++ ++ for_each_online_cpu(cpu) { ++ if (lrng_pcpu_pool_online(cpu)) ++ max_size += max_pool; ++ } ++ ++ return max_size; ++} ++ ++/* Return entropy of unused IRQs present in all per-CPU pools. */ ++u32 lrng_pcpu_avail_entropy(void) ++{ ++ u32 digestsize_irqs, irq = 0; ++ int cpu; ++ ++ /* Obtain the cap of maximum numbers of IRQs we count */ ++ digestsize_irqs = lrng_entropy_to_data(lrng_get_digestsize()); ++ if (!lrng_pcpu_continuous_compression) { ++ /* Cap to max. number of IRQs the array can hold */ ++ digestsize_irqs = min_t(u32, digestsize_irqs, ++ LRNG_DATA_NUM_VALUES); ++ } ++ ++ for_each_online_cpu(cpu) { ++ if (!lrng_pcpu_pool_online(cpu)) ++ continue; ++ irq += min_t(u32, digestsize_irqs, ++ atomic_read_u32(per_cpu_ptr(&lrng_pcpu_array_irqs, ++ cpu))); ++ } ++ ++ /* Consider oversampling rate */ ++ return lrng_reduce_by_osr(lrng_data_to_entropy(irq)); ++} ++ ++/** ++ * Trigger a switch of the hash implementation for the per-CPU pool. ++ * ++ * For each per-CPU pool, obtain the message digest with the old hash ++ * implementation, initialize the per-CPU pool again with the new hash ++ * implementation and inject the message digest into the new state. ++ * ++ * Assumption: the caller must guarantee that the new_cb is available during the ++ * entire operation (e.g. it must hold the lock against pointer updating). ++ */ ++int lrng_pcpu_switch_hash(int node, ++ const struct lrng_crypto_cb *new_cb, void *new_hash, ++ const struct lrng_crypto_cb *old_cb) ++{ ++ u8 digest[LRNG_MAX_DIGESTSIZE]; ++ u32 digestsize_irqs, found_irqs; ++ int ret = 0, cpu; ++ ++ if (!IS_ENABLED(CONFIG_LRNG_DRNG_SWITCH)) ++ return -EOPNOTSUPP; ++ ++ for_each_online_cpu(cpu) { ++ struct shash_desc *pcpu_shash; ++ ++ /* ++ * Only switch the per-CPU pools for the current node because ++ * the crypto_cb only applies NUMA-node-wide. ++ */ ++ if (cpu_to_node(cpu) != node || !lrng_pcpu_pool_online(cpu)) ++ continue; ++ ++ pcpu_shash = (struct shash_desc *)per_cpu_ptr(lrng_pcpu_pool, ++ cpu); ++ ++ digestsize_irqs = old_cb->lrng_hash_digestsize(pcpu_shash); ++ digestsize_irqs = lrng_entropy_to_data(digestsize_irqs << 3); ++ ++ if (pcpu_shash->tfm == new_hash) ++ continue; ++ ++ /* Get the per-CPU pool hash with old digest ... */ ++ ret = old_cb->lrng_hash_final(pcpu_shash, digest) ?: ++ /* ... re-initialize the hash with the new digest ... */ ++ new_cb->lrng_hash_init(pcpu_shash, new_hash) ?: ++ /* ++ * ... feed the old hash into the new state. We may feed ++ * uninitialized memory into the new state, but this is ++ * considered no issue and even good as we have some more ++ * uncertainty here. ++ */ ++ new_cb->lrng_hash_update(pcpu_shash, digest, ++ sizeof(digest)); ++ if (ret) ++ goto out; ++ ++ /* ++ * In case the new digest is larger than the old one, cap ++ * the available entropy to the old message digest used to ++ * process the existing data. ++ */ ++ found_irqs = atomic_xchg_relaxed( ++ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu), 0); ++ found_irqs = min_t(u32, found_irqs, digestsize_irqs); ++ atomic_add_return_relaxed(found_irqs, ++ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu)); ++ ++ pr_debug("Re-initialize per-CPU entropy pool for CPU %d on NUMA node %d with hash %s\n", ++ cpu, node, new_cb->lrng_hash_name()); ++ } ++ ++out: ++ memzero_explicit(digest, sizeof(digest)); ++ return ret; ++} ++ ++/* ++ * When reading the per-CPU message digest, make sure we use the crypto ++ * callbacks defined for the NUMA node the per-CPU pool is defined for because ++ * the LRNG crypto switch support is only atomic per NUMA node. ++ */ ++static inline u32 ++lrng_pcpu_pool_hash_one(const struct lrng_crypto_cb *pcpu_crypto_cb, ++ void *pcpu_hash, int cpu, u8 *digest, u32 *digestsize) ++{ ++ struct shash_desc *pcpu_shash = ++ (struct shash_desc *)per_cpu_ptr(lrng_pcpu_pool, cpu); ++ spinlock_t *lock = per_cpu_ptr(&lrng_pcpu_lock, cpu); ++ unsigned long flags; ++ u32 digestsize_irqs, found_irqs; ++ ++ /* Lock guarding against reading / writing to per-CPU pool */ ++ spin_lock_irqsave(lock, flags); ++ ++ *digestsize = pcpu_crypto_cb->lrng_hash_digestsize(pcpu_hash); ++ digestsize_irqs = lrng_entropy_to_data(*digestsize << 3); ++ ++ /* Obtain entropy statement like for the entropy pool */ ++ found_irqs = atomic_xchg_relaxed( ++ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu), 0); ++ /* Cap to maximum amount of data we can hold in hash */ ++ found_irqs = min_t(u32, found_irqs, digestsize_irqs); ++ ++ /* Cap to maximum amount of data we can hold in array */ ++ if (!lrng_pcpu_continuous_compression) ++ found_irqs = min_t(u32, found_irqs, LRNG_DATA_NUM_VALUES); ++ ++ /* Store all not-yet compressed data in data array into hash, ... */ ++ if (pcpu_crypto_cb->lrng_hash_update(pcpu_shash, ++ (u8 *)per_cpu_ptr(lrng_pcpu_array, cpu), ++ LRNG_DATA_ARRAY_SIZE * sizeof(u32)) ?: ++ /* ... get the per-CPU pool digest, ... */ ++ pcpu_crypto_cb->lrng_hash_final(pcpu_shash, digest) ?: ++ /* ... re-initialize the hash, ... */ ++ pcpu_crypto_cb->lrng_hash_init(pcpu_shash, pcpu_hash) ?: ++ /* ... feed the old hash into the new state. */ ++ pcpu_crypto_cb->lrng_hash_update(pcpu_shash, digest, *digestsize)) ++ found_irqs = 0; ++ ++ spin_unlock_irqrestore(lock, flags); ++ return found_irqs; ++} ++ ++/** ++ * Hash all per-CPU pools and return the digest to be used as seed data for ++ * seeding a DRNG. The caller must guarantee backtracking resistance. ++ * The function will only copy as much data as entropy is available into the ++ * caller-provided output buffer. ++ * ++ * This function handles the translation from the number of received interrupts ++ * into an entropy statement. The conversion depends on LRNG_IRQ_ENTROPY_BITS ++ * which defines how many interrupts must be received to obtain 256 bits of ++ * entropy. With this value, the function lrng_data_to_entropy converts a given ++ * data size (received interrupts, requested amount of data, etc.) into an ++ * entropy statement. lrng_entropy_to_data does the reverse. ++ * ++ * @outbuf: buffer to store data in with size requested_bits ++ * @requested_bits: Requested amount of entropy ++ * @fully_seeded: indicator whether LRNG is fully seeded ++ * @return: amount of entropy in outbuf in bits. ++ */ ++u32 lrng_pcpu_pool_hash(u8 *outbuf, u32 requested_bits, bool fully_seeded) ++{ ++ SHASH_DESC_ON_STACK(shash, NULL); ++ const struct lrng_crypto_cb *crypto_cb; ++ struct lrng_drng **lrng_drng = lrng_drng_instances(); ++ struct lrng_drng *drng = lrng_drng_init_instance(); ++ u8 digest[LRNG_MAX_DIGESTSIZE]; ++ unsigned long flags, flags2; ++ u32 found_irqs, collected_irqs = 0, collected_ent_bits, requested_irqs, ++ returned_ent_bits; ++ int ret, cpu; ++ void *hash; ++ ++ /* Lock guarding replacement of per-NUMA hash */ ++ read_lock_irqsave(&drng->hash_lock, flags); ++ ++ crypto_cb = drng->crypto_cb; ++ hash = drng->hash; ++ ++ /* The hash state of filled with all per-CPU pool hashes. */ ++ ret = crypto_cb->lrng_hash_init(shash, hash); ++ if (ret) ++ goto err; ++ ++ requested_irqs = lrng_entropy_to_data(requested_bits) + ++ lrng_compress_osr(); ++ ++ /* ++ * Harvest entropy from each per-CPU hash state - even though we may ++ * have collected sufficient entropy, we will hash all per-CPU pools. ++ */ ++ for_each_online_cpu(cpu) { ++ struct lrng_drng *pcpu_drng = drng; ++ u32 digestsize, pcpu_unused_irqs = 0; ++ int node = cpu_to_node(cpu); ++ ++ /* If pool is not online, then no entropy is present. */ ++ if (!lrng_pcpu_pool_online(cpu)) ++ continue; ++ ++ if (lrng_drng && lrng_drng[node]) ++ pcpu_drng = lrng_drng[node]; ++ ++ if (pcpu_drng == drng) { ++ found_irqs = lrng_pcpu_pool_hash_one(crypto_cb, hash, ++ cpu, digest, ++ &digestsize); ++ } else { ++ read_lock_irqsave(&pcpu_drng->hash_lock, flags2); ++ found_irqs = ++ lrng_pcpu_pool_hash_one(pcpu_drng->crypto_cb, ++ pcpu_drng->hash, cpu, ++ digest, &digestsize); ++ read_unlock_irqrestore(&pcpu_drng->hash_lock, flags2); ++ } ++ ++ /* Inject the digest into the state of all per-CPU pools */ ++ ret = crypto_cb->lrng_hash_update(shash, digest, digestsize); ++ if (ret) ++ goto err; ++ ++ collected_irqs += found_irqs; ++ if (collected_irqs > requested_irqs) { ++ pcpu_unused_irqs = collected_irqs - requested_irqs; ++ atomic_add_return_relaxed(pcpu_unused_irqs, ++ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu)); ++ collected_irqs = requested_irqs; ++ } ++ pr_debug("%u interrupts used from entropy pool of CPU %d, %u interrupts remain unused\n", ++ found_irqs - pcpu_unused_irqs, cpu, pcpu_unused_irqs); ++ } ++ ++ ret = crypto_cb->lrng_hash_final(shash, digest); ++ if (ret) ++ goto err; ++ ++ collected_ent_bits = lrng_data_to_entropy(collected_irqs); ++ /* Cap to maximum entropy that can ever be generated with given hash */ ++ collected_ent_bits = min_t(u32, collected_ent_bits, ++ crypto_cb->lrng_hash_digestsize(hash) << 3); ++ /* Apply oversampling: discount requested oversampling rate */ ++ returned_ent_bits = lrng_reduce_by_osr(collected_ent_bits); ++ ++ pr_debug("obtained %u bits by collecting %u bits of entropy from entropy pool noise source\n", ++ returned_ent_bits, collected_ent_bits); ++ ++ /* ++ * Truncate to available entropy as implicitly allowed by SP800-90B ++ * section 3.1.5.1.1 table 1 which awards truncated hashes full ++ * entropy. ++ * ++ * During boot time, we read requested_bits data with ++ * returned_ent_bits entropy. In case our conservative entropy ++ * estimate underestimates the available entropy we can transport as ++ * much available entropy as possible. ++ */ ++ memcpy(outbuf, digest, fully_seeded ? returned_ent_bits >> 3 : ++ requested_bits >> 3); ++ ++out: ++ crypto_cb->lrng_hash_desc_zero(shash); ++ read_unlock_irqrestore(&drng->hash_lock, flags); ++ memzero_explicit(digest, sizeof(digest)); ++ return returned_ent_bits; ++ ++err: ++ returned_ent_bits = 0; ++ goto out; ++} ++ ++/* Compress the lrng_pcpu_array array into lrng_pcpu_pool */ ++static inline void lrng_pcpu_array_compress(void) ++{ ++ struct shash_desc *shash = ++ (struct shash_desc *)this_cpu_ptr(lrng_pcpu_pool); ++ struct lrng_drng **lrng_drng = lrng_drng_instances(); ++ struct lrng_drng *drng = lrng_drng_init_instance(); ++ const struct lrng_crypto_cb *crypto_cb; ++ spinlock_t *lock = this_cpu_ptr(&lrng_pcpu_lock); ++ unsigned long flags, flags2; ++ int node = numa_node_id(); ++ void *hash; ++ bool init = false; ++ ++ /* Get NUMA-node local hash instance */ ++ if (lrng_drng && lrng_drng[node]) ++ drng = lrng_drng[node]; ++ ++ read_lock_irqsave(&drng->hash_lock, flags); ++ crypto_cb = drng->crypto_cb; ++ hash = drng->hash; ++ ++ if (unlikely(!this_cpu_read(lrng_pcpu_lock_init))) { ++ init = true; ++ spin_lock_init(lock); ++ this_cpu_write(lrng_pcpu_lock_init, true); ++ pr_debug("Initializing per-CPU entropy pool for CPU %d on NUMA node %d with hash %s\n", ++ raw_smp_processor_id(), node, ++ crypto_cb->lrng_hash_name()); ++ } ++ ++ spin_lock_irqsave(lock, flags2); ++ ++ if (unlikely(init) && crypto_cb->lrng_hash_init(shash, hash)) { ++ this_cpu_write(lrng_pcpu_lock_init, false); ++ pr_warn("Initialization of hash failed\n"); ++ } else if (lrng_pcpu_continuous_compression) { ++ /* Add entire per-CPU data array content into entropy pool. */ ++ if (crypto_cb->lrng_hash_update(shash, ++ (u8 *)this_cpu_ptr(lrng_pcpu_array), ++ LRNG_DATA_ARRAY_SIZE * sizeof(u32))) ++ pr_warn_ratelimited("Hashing of entropy data failed\n"); ++ } ++ ++ spin_unlock_irqrestore(lock, flags2); ++ read_unlock_irqrestore(&drng->hash_lock, flags); ++} ++ ++/* Compress data array into hash */ ++static inline void lrng_pcpu_array_to_hash(u32 ptr) ++{ ++ u32 *array = this_cpu_ptr(lrng_pcpu_array); ++ ++ /* ++ * During boot time the hash operation is triggered more often than ++ * during regular operation. ++ */ ++ if (unlikely(!lrng_state_fully_seeded())) { ++ if ((ptr & 31) && (ptr < LRNG_DATA_WORD_MASK)) ++ return; ++ } else if (ptr < LRNG_DATA_WORD_MASK) { ++ return; ++ } ++ ++ if (lrng_raw_array_entropy_store(*array)) { ++ u32 i; ++ ++ /* ++ * If we fed even a part of the array to external analysis, we ++ * mark that the entire array and the per-CPU pool to have no ++ * entropy. This is due to the non-IID property of the data as ++ * we do not fully know whether the existing dependencies ++ * diminish the entropy beyond to what we expect it has. ++ */ ++ atomic_set(this_cpu_ptr(&lrng_pcpu_array_irqs), 0); ++ ++ for (i = 1; i < LRNG_DATA_ARRAY_SIZE; i++) ++ lrng_raw_array_entropy_store(*(array + i)); ++ } else { ++ lrng_pcpu_array_compress(); ++ /* Ping pool handler about received entropy */ ++ lrng_pool_add_entropy(); ++ } ++} ++ ++/* ++ * Concatenate full 32 bit word at the end of time array even when current ++ * ptr is not aligned to sizeof(data). ++ */ ++static inline void _lrng_pcpu_array_add_u32(u32 data) ++{ ++ /* Increment pointer by number of slots taken for input value */ ++ u32 pre_ptr, mask, ptr = this_cpu_add_return(lrng_pcpu_array_ptr, ++ LRNG_DATA_SLOTS_PER_UINT); ++ unsigned int pre_array; ++ ++ /* ++ * This function injects a unit into the array - guarantee that ++ * array unit size is equal to data type of input data. ++ */ ++ BUILD_BUG_ON(LRNG_DATA_ARRAY_MEMBER_BITS != (sizeof(data) << 3)); ++ ++ /* ++ * The following logic requires at least two units holding ++ * the data as otherwise the pointer would immediately wrap when ++ * injection an u32 word. ++ */ ++ BUILD_BUG_ON(LRNG_DATA_NUM_VALUES <= LRNG_DATA_SLOTS_PER_UINT); ++ ++ lrng_pcpu_split_u32(&ptr, &pre_ptr, &mask); ++ ++ /* MSB of data go into previous unit */ ++ pre_array = lrng_data_idx2array(pre_ptr); ++ /* zeroization of slot to ensure the following OR adds the data */ ++ this_cpu_and(lrng_pcpu_array[pre_array], ~(0xffffffff &~ mask)); ++ this_cpu_or(lrng_pcpu_array[pre_array], data & ~mask); ++ ++ /* Invoke compression as we just filled data array completely */ ++ if (unlikely(pre_ptr > ptr)) ++ lrng_pcpu_array_to_hash(LRNG_DATA_WORD_MASK); ++ ++ /* LSB of data go into current unit */ ++ this_cpu_write(lrng_pcpu_array[lrng_data_idx2array(ptr)], ++ data & mask); ++ ++ if (likely(pre_ptr <= ptr)) ++ lrng_pcpu_array_to_hash(ptr); ++} ++ ++/* Concatenate a 32-bit word at the end of the per-CPU array */ ++void lrng_pcpu_array_add_u32(u32 data) ++{ ++ /* ++ * Disregard entropy-less data without continuous compression to ++ * avoid it overwriting data with entropy when array ptr wraps. ++ */ ++ if (lrng_pcpu_continuous_compression) ++ _lrng_pcpu_array_add_u32(data); ++} ++ ++/* Concatenate data of max LRNG_DATA_SLOTSIZE_MASK at the end of time array */ ++static inline void lrng_pcpu_array_add_slot(u32 data) ++{ ++ /* Get slot */ ++ u32 ptr = this_cpu_inc_return(lrng_pcpu_array_ptr) & ++ LRNG_DATA_WORD_MASK; ++ unsigned int array = lrng_data_idx2array(ptr); ++ unsigned int slot = lrng_data_idx2slot(ptr); ++ ++ BUILD_BUG_ON(LRNG_DATA_ARRAY_MEMBER_BITS % LRNG_DATA_SLOTSIZE_BITS); ++ /* Ensure consistency of values */ ++ BUILD_BUG_ON(LRNG_DATA_ARRAY_MEMBER_BITS != ++ sizeof(lrng_pcpu_array[0]) << 3); ++ ++ /* zeroization of slot to ensure the following OR adds the data */ ++ this_cpu_and(lrng_pcpu_array[array], ++ ~(lrng_data_slot_val(0xffffffff & LRNG_DATA_SLOTSIZE_MASK, ++ slot))); ++ /* Store data into slot */ ++ this_cpu_or(lrng_pcpu_array[array], lrng_data_slot_val(data, slot)); ++ ++ lrng_pcpu_array_to_hash(ptr); ++} ++ ++static inline void ++lrng_time_process_common(u32 time, void(*add_time)(u32 data)) ++{ ++ enum lrng_health_res health_test; ++ ++ if (lrng_raw_hires_entropy_store(time)) ++ return; ++ ++ health_test = lrng_health_test(time); ++ if (health_test > lrng_health_fail_use) ++ return; ++ ++ if (health_test == lrng_health_pass) ++ atomic_inc_return(this_cpu_ptr(&lrng_pcpu_array_irqs)); ++ ++ add_time(time); ++} ++ ++/* ++ * Batching up of entropy in per-CPU array before injecting into entropy pool. ++ */ ++static inline void lrng_time_process(void) ++{ ++ u32 now_time = random_get_entropy(); ++ ++ if (unlikely(!lrng_state_fully_seeded())) { ++ /* During boot time, we process the full time stamp */ ++ lrng_time_process_common(now_time, _lrng_pcpu_array_add_u32); ++ } else { ++ /* Runtime operation */ ++ lrng_time_process_common(now_time & LRNG_DATA_SLOTSIZE_MASK, ++ lrng_pcpu_array_add_slot); ++ } ++ ++ lrng_perf_time(now_time); ++} ++ ++/* Hot code path - Callback for interrupt handler */ ++void add_interrupt_randomness(int irq, int irq_flg) ++{ ++ if (lrng_pool_highres_timer()) { ++ lrng_time_process(); ++ } else { ++ struct pt_regs *regs = get_irq_regs(); ++ static atomic_t reg_idx = ATOMIC_INIT(0); ++ u64 ip; ++ u32 tmp; ++ ++ if (regs) { ++ u32 *ptr = (u32 *)regs; ++ int reg_ptr = atomic_add_return_relaxed(1, ®_idx); ++ size_t n = (sizeof(struct pt_regs) / sizeof(u32)); ++ ++ ip = instruction_pointer(regs); ++ tmp = *(ptr + (reg_ptr % n)); ++ tmp = lrng_raw_regs_entropy_store(tmp) ? 0 : tmp; ++ _lrng_pcpu_array_add_u32(tmp); ++ } else { ++ ip = _RET_IP_; ++ } ++ ++ lrng_time_process(); ++ ++ /* ++ * The XOR operation combining the different values is not ++ * considered to destroy entropy since the entirety of all ++ * processed values delivers the entropy (and not each ++ * value separately of the other values). ++ */ ++ tmp = lrng_raw_jiffies_entropy_store(jiffies) ? 0 : jiffies; ++ tmp ^= lrng_raw_irq_entropy_store(irq) ? 0 : irq; ++ tmp ^= lrng_raw_irqflags_entropy_store(irq_flg) ? 0 : irq_flg; ++ tmp ^= lrng_raw_retip_entropy_store(ip) ? 0 : ip; ++ tmp ^= ip >> 32; ++ _lrng_pcpu_array_add_u32(tmp); ++ } ++} ++EXPORT_SYMBOL(add_interrupt_randomness); +--- /dev/null ++++ b/drivers/char/lrng/lrng_sw_noise.h +@@ -0,0 +1,71 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ ++/* ++ * LRNG Slow Noise Source: Time stamp array handling ++ * ++ * Copyright (C) 2016 - 2021, Stephan Mueller ++ */ ++ ++/* ++ * To limit the impact on the interrupt handling, the LRNG concatenates ++ * entropic LSB parts of the time stamps in a per-CPU array and only ++ * injects them into the entropy pool when the array is full. ++ */ ++ ++/* Store multiple integers in one u32 */ ++#define LRNG_DATA_SLOTSIZE_BITS (8) ++#define LRNG_DATA_SLOTSIZE_MASK ((1 << LRNG_DATA_SLOTSIZE_BITS) - 1) ++#define LRNG_DATA_ARRAY_MEMBER_BITS (4 << 3) /* ((sizeof(u32)) << 3) */ ++#define LRNG_DATA_SLOTS_PER_UINT (LRNG_DATA_ARRAY_MEMBER_BITS / \ ++ LRNG_DATA_SLOTSIZE_BITS) ++ ++/* ++ * Number of time values to store in the array - in small environments ++ * only one atomic_t variable per CPU is used. ++ */ ++#define LRNG_DATA_NUM_VALUES (CONFIG_LRNG_COLLECTION_SIZE) ++/* Mask of LSB of time stamp to store */ ++#define LRNG_DATA_WORD_MASK (LRNG_DATA_NUM_VALUES - 1) ++ ++#define LRNG_DATA_SLOTS_MASK (LRNG_DATA_SLOTS_PER_UINT - 1) ++#define LRNG_DATA_ARRAY_SIZE (LRNG_DATA_NUM_VALUES / \ ++ LRNG_DATA_SLOTS_PER_UINT) ++ ++/* Starting bit index of slot */ ++static inline unsigned int lrng_data_slot2bitindex(unsigned int slot) ++{ ++ return (LRNG_DATA_SLOTSIZE_BITS * slot); ++} ++ ++/* Convert index into the array index */ ++static inline unsigned int lrng_data_idx2array(unsigned int idx) ++{ ++ return idx / LRNG_DATA_SLOTS_PER_UINT; ++} ++ ++/* Convert index into the slot of a given array index */ ++static inline unsigned int lrng_data_idx2slot(unsigned int idx) ++{ ++ return idx & LRNG_DATA_SLOTS_MASK; ++} ++ ++/* Convert value into slot value */ ++static inline unsigned int lrng_data_slot_val(unsigned int val, ++ unsigned int slot) ++{ ++ return val << lrng_data_slot2bitindex(slot); ++} ++ ++/* ++ * Return the pointers for the previous and current units to inject a u32 into. ++ * Also return the mask which the u32 word is to be processed. ++ */ ++static inline void lrng_pcpu_split_u32(u32 *ptr, u32 *pre_ptr, u32 *mask) ++{ ++ /* ptr to previous unit */ ++ *pre_ptr = (*ptr - LRNG_DATA_SLOTS_PER_UINT) & LRNG_DATA_WORD_MASK; ++ *ptr &= LRNG_DATA_WORD_MASK; ++ ++ /* mask to split data into the two parts for the two units */ ++ *mask = ((1 << (*pre_ptr & (LRNG_DATA_SLOTS_PER_UINT - 1)) * ++ LRNG_DATA_SLOTSIZE_BITS)) - 1; ++} +--- /dev/null ++++ b/include/linux/lrng.h +@@ -0,0 +1,81 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ ++/* ++ * Copyright (C) 2018 - 2021, Stephan Mueller ++ */ ++ ++#ifndef _LRNG_H ++#define _LRNG_H ++ ++#include ++#include ++#include ++ ++/** ++ * struct lrng_crypto_cb - cryptographic callback functions ++ * @lrng_drng_name Name of DRNG ++ * @lrng_hash_name Name of Hash used for reading entropy pool ++ * @lrng_drng_alloc: Allocate DRNG -- the provided integer should be ++ * used for sanity checks. ++ * return: allocated data structure or PTR_ERR on ++ * error ++ * @lrng_drng_dealloc: Deallocate DRNG ++ * @lrng_drng_seed_helper: Seed the DRNG with data of arbitrary length ++ * drng: is pointer to data structure allocated ++ * with lrng_drng_alloc ++ * return: >= 0 on success, < 0 on error ++ * @lrng_drng_generate_helper: Generate random numbers from the DRNG with ++ * arbitrary length ++ * @lrng_hash_alloc: Allocate the hash for reading the entropy pool ++ * return: allocated data structure (NULL is ++ * success too) or ERR_PTR on error ++ * @lrng_hash_dealloc: Deallocate Hash ++ * @lrng_hash_digestsize: Return the digestsize for the used hash to read ++ * out entropy pool ++ * hash: is pointer to data structure allocated ++ * with lrng_hash_alloc ++ * return: size of digest of hash in bytes ++ * @lrng_hash_init: Initialize hash ++ * hash: is pointer to data structure allocated ++ * with lrng_hash_alloc ++ * return: 0 on success, < 0 on error ++ * @lrng_hash_update: Update hash operation ++ * hash: is pointer to data structure allocated ++ * with lrng_hash_alloc ++ * return: 0 on success, < 0 on error ++ * @lrng_hash_final Final hash operation ++ * hash: is pointer to data structure allocated ++ * with lrng_hash_alloc ++ * return: 0 on success, < 0 on error ++ * @lrng_hash_desc_zero Zeroization of hash state buffer ++ * ++ * Assumptions: ++ * ++ * 1. Hash operation will not sleep ++ * 2. The hash' volatile state information is provided with *shash by caller. ++ */ ++struct lrng_crypto_cb { ++ const char *(*lrng_drng_name)(void); ++ const char *(*lrng_hash_name)(void); ++ void *(*lrng_drng_alloc)(u32 sec_strength); ++ void (*lrng_drng_dealloc)(void *drng); ++ int (*lrng_drng_seed_helper)(void *drng, const u8 *inbuf, u32 inbuflen); ++ int (*lrng_drng_generate_helper)(void *drng, u8 *outbuf, u32 outbuflen); ++ void *(*lrng_hash_alloc)(void); ++ void (*lrng_hash_dealloc)(void *hash); ++ u32 (*lrng_hash_digestsize)(void *hash); ++ int (*lrng_hash_init)(struct shash_desc *shash, void *hash); ++ int (*lrng_hash_update)(struct shash_desc *shash, const u8 *inbuf, ++ u32 inbuflen); ++ int (*lrng_hash_final)(struct shash_desc *shash, u8 *digest); ++ void (*lrng_hash_desc_zero)(struct shash_desc *shash); ++}; ++ ++/* Register cryptographic backend */ ++#ifdef CONFIG_LRNG_DRNG_SWITCH ++int lrng_set_drng_cb(const struct lrng_crypto_cb *cb); ++#else /* CONFIG_LRNG_DRNG_SWITCH */ ++static inline int ++lrng_set_drng_cb(const struct lrng_crypto_cb *cb) { return -EOPNOTSUPP; } ++#endif /* CONFIG_LRNG_DRNG_SWITCH */ ++ ++#endif /* _LRNG_H */ diff --git a/PATCH/LRNG/696-05-v41-0002-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch b/PATCH/LRNG/696-05-v41-0002-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch new file mode 100644 index 000000000..9cf20b6b5 --- /dev/null +++ b/PATCH/LRNG/696-05-v41-0002-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch @@ -0,0 +1,201 @@ +From 0a73760d76194fd8fa2aa039d121b28c9d9e200a Mon Sep 17 00:00:00 2001 +From: Stephan Mueller +Date: Fri, 18 Jun 2021 08:03:15 +0200 +Subject: [PATCH v41 02/13] LRNG - allocate one DRNG instance per NUMA node + +In order to improve NUMA-locality when serving getrandom(2) requests, +allocate one DRNG instance per node. + +The DRNG instance that is present right from the start of the kernel is +reused as the first per-NUMA-node DRNG. For all remaining online NUMA +nodes a new DRNG instance is allocated. + +During boot time, the multiple DRNG instances are seeded sequentially. +With this, the first DRNG instance (referenced as the initial DRNG +in the code) is completely seeded with 256 bits of entropy before the +next DRNG instance is completely seeded. + +When random numbers are requested, the NUMA-node-local DRNG is checked +whether it has been already fully seeded. If this is not the case, the +initial DRNG is used to serve the request. + +CC: Torsten Duwe +CC: "Eric W. Biederman" +CC: "Alexander E. Patrakov" +CC: "Ahmed S. Darwish" +CC: "Theodore Y. Ts'o" +CC: Willy Tarreau +CC: Matthew Garrett +CC: Vito Caputo +CC: Andreas Dilger +CC: Jan Kara +CC: Ray Strode +CC: William Jon McCann +CC: zhangjs +CC: Andy Lutomirski +CC: Florian Weimer +CC: Lennart Poettering +CC: Nicolai Stange +CC: Eric Biggers +CC: Alexander Lobakin +Reviewed-by: Marcelo Henrique Cerri +Reviewed-by: Roman Drahtmueller +Tested-by: Marcelo Henrique Cerri +Tested-by: Neil Horman +Signed-off-by: Stephan Mueller +--- + drivers/char/lrng/Makefile | 2 + + drivers/char/lrng/lrng_internal.h | 5 ++ + drivers/char/lrng/lrng_numa.c | 122 ++++++++++++++++++++++++++++++ + 3 files changed, 129 insertions(+) + create mode 100644 drivers/char/lrng/lrng_numa.c + +--- a/drivers/char/lrng/Makefile ++++ b/drivers/char/lrng/Makefile +@@ -7,3 +7,5 @@ obj-y += lrng_pool.o lrng_aux.o \ + lrng_sw_noise.o lrng_archrandom.o \ + lrng_drng.o lrng_chacha20.o \ + lrng_interfaces.o ++ ++obj-$(CONFIG_NUMA) += lrng_numa.o +--- a/drivers/char/lrng/lrng_internal.h ++++ b/drivers/char/lrng/lrng_internal.h +@@ -254,8 +254,13 @@ int lrng_drng_get_sleep(u8 *outbuf, u32 + void lrng_drng_force_reseed(void); + void lrng_drng_seed_work(struct work_struct *dummy); + ++#ifdef CONFIG_NUMA ++struct lrng_drng **lrng_drng_instances(void); ++void lrng_drngs_numa_alloc(void); ++#else /* CONFIG_NUMA */ + static inline struct lrng_drng **lrng_drng_instances(void) { return NULL; } + static inline void lrng_drngs_numa_alloc(void) { return; } ++#endif /* CONFIG_NUMA */ + + /************************* Entropy sources management *************************/ + +--- /dev/null ++++ b/drivers/char/lrng/lrng_numa.c +@@ -0,0 +1,122 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause ++/* ++ * LRNG NUMA support ++ * ++ * Copyright (C) 2016 - 2021, Stephan Mueller ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++ ++#include "lrng_internal.h" ++ ++static struct lrng_drng **lrng_drng __read_mostly = NULL; ++ ++struct lrng_drng **lrng_drng_instances(void) ++{ ++ return smp_load_acquire(&lrng_drng); ++} ++ ++/* Allocate the data structures for the per-NUMA node DRNGs */ ++static void _lrng_drngs_numa_alloc(struct work_struct *work) ++{ ++ struct lrng_drng **drngs; ++ struct lrng_drng *lrng_drng_init = lrng_drng_init_instance(); ++ u32 node; ++ bool init_drng_used = false; ++ ++ mutex_lock(&lrng_crypto_cb_update); ++ ++ /* per-NUMA-node DRNGs are already present */ ++ if (lrng_drng) ++ goto unlock; ++ ++ drngs = kcalloc(nr_node_ids, sizeof(void *), GFP_KERNEL|__GFP_NOFAIL); ++ for_each_online_node(node) { ++ struct lrng_drng *drng; ++ ++ if (!init_drng_used) { ++ drngs[node] = lrng_drng_init; ++ init_drng_used = true; ++ continue; ++ } ++ ++ drng = kmalloc_node(sizeof(struct lrng_drng), ++ GFP_KERNEL|__GFP_NOFAIL, node); ++ memset(drng, 0, sizeof(lrng_drng)); ++ ++ drng->crypto_cb = lrng_drng_init->crypto_cb; ++ drng->drng = drng->crypto_cb->lrng_drng_alloc( ++ LRNG_DRNG_SECURITY_STRENGTH_BYTES); ++ if (IS_ERR(drng->drng)) { ++ kfree(drng); ++ goto err; ++ } ++ ++ drng->hash = drng->crypto_cb->lrng_hash_alloc(); ++ if (IS_ERR(drng->hash)) { ++ drng->crypto_cb->lrng_drng_dealloc(drng->drng); ++ kfree(drng); ++ goto err; ++ } ++ ++ mutex_init(&drng->lock); ++ spin_lock_init(&drng->spin_lock); ++ rwlock_init(&drng->hash_lock); ++ ++ /* ++ * Switch the hash used by the per-CPU pool. ++ * We do not need to lock the new hash as it is not usable yet ++ * due to **drngs not yet being initialized. ++ */ ++ if (lrng_pcpu_switch_hash(node, drng->crypto_cb, drng->hash, ++ &lrng_cc20_crypto_cb)) ++ goto err; ++ ++ /* ++ * No reseeding of NUMA DRNGs from previous DRNGs as this ++ * would complicate the code. Let it simply reseed. ++ */ ++ lrng_drng_reset(drng); ++ drngs[node] = drng; ++ ++ lrng_pool_inc_numa_node(); ++ pr_info("DRNG and entropy pool read hash for NUMA node %d allocated\n", ++ node); ++ } ++ ++ /* counterpart to smp_load_acquire in lrng_drng_instances */ ++ if (!cmpxchg_release(&lrng_drng, NULL, drngs)) { ++ lrng_pool_all_numa_nodes_seeded(false); ++ goto unlock; ++ } ++ ++err: ++ for_each_online_node(node) { ++ struct lrng_drng *drng = drngs[node]; ++ ++ if (drng == lrng_drng_init) ++ continue; ++ ++ if (drng) { ++ lrng_pcpu_switch_hash(node, &lrng_cc20_crypto_cb, NULL, ++ drng->crypto_cb); ++ drng->crypto_cb->lrng_hash_dealloc(drng->hash); ++ drng->crypto_cb->lrng_drng_dealloc(drng->drng); ++ kfree(drng); ++ } ++ } ++ kfree(drngs); ++ ++unlock: ++ mutex_unlock(&lrng_crypto_cb_update); ++} ++ ++static DECLARE_WORK(lrng_drngs_numa_alloc_work, _lrng_drngs_numa_alloc); ++ ++void lrng_drngs_numa_alloc(void) ++{ ++ schedule_work(&lrng_drngs_numa_alloc_work); ++} diff --git a/PATCH/LRNG/696-06-v41-0003-LRNG-sysctls-and-proc-interface.patch b/PATCH/LRNG/696-06-v41-0003-LRNG-sysctls-and-proc-interface.patch new file mode 100644 index 000000000..f517737f6 --- /dev/null +++ b/PATCH/LRNG/696-06-v41-0003-LRNG-sysctls-and-proc-interface.patch @@ -0,0 +1,287 @@ +From 28ba413daaf3dc24f8efb15335a8da82201e42d7 Mon Sep 17 00:00:00 2001 +From: Stephan Mueller +Date: Wed, 23 Jun 2021 18:44:26 +0200 +Subject: [PATCH v41 03/13] LRNG - sysctls and /proc interface + +The LRNG sysctl interface provides the same controls as the existing +/dev/random implementation. These sysctls behave identically and are +implemented identically. The goal is to allow a possible merge of the +existing /dev/random implementation with this implementation which +implies that this patch tries have a very close similarity. Yet, all +sysctls are documented at [1]. + +In addition, it provides the file lrng_type which provides details about +the LRNG: + +- the name of the DRNG that produces the random numbers for /dev/random, +/dev/urandom, getrandom(2) + +- the hash used to produce random numbers from the entropy pool + +- the number of secondary DRNG instances + +- indicator whether the LRNG operates SP800-90B compliant + +- indicator whether a high-resolution timer is identified - only with a +high-resolution timer the interrupt noise source will deliver sufficient +entropy + +- indicator whether the LRNG has been minimally seeded (i.e. is the +secondary DRNG seeded with at least 128 bits of entropy) + +- indicator whether the LRNG has been fully seeded (i.e. is the +secondary DRNG seeded with at least 256 bits of entropy) + +[1] https://www.chronox.de/lrng.html + +CC: Torsten Duwe +CC: "Eric W. Biederman" +CC: "Alexander E. Patrakov" +CC: "Ahmed S. Darwish" +CC: "Theodore Y. Ts'o" +CC: Willy Tarreau +CC: Matthew Garrett +CC: Vito Caputo +CC: Andreas Dilger +CC: Jan Kara +CC: Ray Strode +CC: William Jon McCann +CC: zhangjs +CC: Andy Lutomirski +CC: Florian Weimer +CC: Lennart Poettering +CC: Nicolai Stange +CC: Alexander Lobakin +Reviewed-by: Marcelo Henrique Cerri +Reviewed-by: Roman Drahtmueller +Tested-by: Marcelo Henrique Cerri +Tested-by: Neil Horman +Signed-off-by: Stephan Mueller +--- + drivers/char/lrng/Makefile | 1 + + drivers/char/lrng/lrng_interfaces.c | 2 - + drivers/char/lrng/lrng_internal.h | 4 + + drivers/char/lrng/lrng_proc.c | 185 ++++++++++++++++++++++++++++ + 4 files changed, 190 insertions(+), 2 deletions(-) + create mode 100644 drivers/char/lrng/lrng_proc.c + +--- a/drivers/char/lrng/Makefile ++++ b/drivers/char/lrng/Makefile +@@ -9,3 +9,4 @@ obj-y += lrng_pool.o lrng_aux.o \ + lrng_interfaces.o + + obj-$(CONFIG_NUMA) += lrng_numa.o ++obj-$(CONFIG_SYSCTL) += lrng_proc.o +--- a/drivers/char/lrng/lrng_interfaces.c ++++ b/drivers/char/lrng/lrng_interfaces.c +@@ -38,8 +38,6 @@ static DECLARE_WAIT_QUEUE_HEAD(lrng_writ + static DECLARE_WAIT_QUEUE_HEAD(lrng_init_wait); + static struct fasync_struct *fasync; + +-struct ctl_table random_table[]; +- + /********************************** Helper ***********************************/ + + /* Is the DRNG seed level too low? */ +--- a/drivers/char/lrng/lrng_internal.h ++++ b/drivers/char/lrng/lrng_internal.h +@@ -114,7 +114,11 @@ void lrng_cc20_init_state(struct chacha2 + + /********************************** /proc *************************************/ + ++#ifdef CONFIG_SYSCTL ++void lrng_pool_inc_numa_node(void); ++#else + static inline void lrng_pool_inc_numa_node(void) { } ++#endif + + /****************************** LRNG interfaces *******************************/ + +--- /dev/null ++++ b/drivers/char/lrng/lrng_proc.c +@@ -0,0 +1,185 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause ++/* ++ * LRNG proc and sysctl interfaces ++ * ++ * Copyright (C) 2016 - 2021, Stephan Mueller ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "lrng_internal.h" ++#include "lrng_sw_noise.h" ++ ++/* ++ * This function is used to return both the bootid UUID, and random ++ * UUID. The difference is in whether table->data is NULL; if it is, ++ * then a new UUID is generated and returned to the user. ++ * ++ * If the user accesses this via the proc interface, the UUID will be ++ * returned as an ASCII string in the standard UUID format; if via the ++ * sysctl system call, as 16 bytes of binary data. ++ */ ++static int lrng_proc_do_uuid(struct ctl_table *table, int write, ++ void *buffer, size_t *lenp, loff_t *ppos) ++{ ++ struct ctl_table fake_table; ++ unsigned char buf[64], tmp_uuid[16], *uuid; ++ ++ uuid = table->data; ++ if (!uuid) { ++ uuid = tmp_uuid; ++ generate_random_uuid(uuid); ++ } else { ++ static DEFINE_SPINLOCK(bootid_spinlock); ++ ++ spin_lock(&bootid_spinlock); ++ if (!uuid[8]) ++ generate_random_uuid(uuid); ++ spin_unlock(&bootid_spinlock); ++ } ++ ++ sprintf(buf, "%pU", uuid); ++ ++ fake_table.data = buf; ++ fake_table.maxlen = sizeof(buf); ++ ++ return proc_dostring(&fake_table, write, buffer, lenp, ppos); ++} ++ ++static int lrng_proc_do_entropy(struct ctl_table *table, int write, ++ void *buffer, size_t *lenp, loff_t *ppos) ++{ ++ struct ctl_table fake_table; ++ int entropy_count; ++ ++ entropy_count = lrng_avail_entropy(); ++ ++ fake_table.data = &entropy_count; ++ fake_table.maxlen = sizeof(entropy_count); ++ ++ return proc_dointvec(&fake_table, write, buffer, lenp, ppos); ++} ++ ++static int lrng_proc_do_poolsize(struct ctl_table *table, int write, ++ void *buffer, size_t *lenp, loff_t *ppos) ++{ ++ struct ctl_table fake_table; ++ int entropy_count; ++ ++ /* LRNG can at most retain entropy in per-CPU pools and aux pool */ ++ entropy_count = lrng_get_digestsize() + lrng_pcpu_avail_pool_size(); ++ ++ fake_table.data = &entropy_count; ++ fake_table.maxlen = sizeof(entropy_count); ++ ++ return proc_dointvec(&fake_table, write, buffer, lenp, ppos); ++} ++ ++static int lrng_min_write_thresh; ++static int lrng_max_write_thresh = LRNG_MAX_DIGESTSIZE; ++static char lrng_sysctl_bootid[16]; ++static int lrng_drng_reseed_max_min; ++ ++struct ctl_table random_table[] = { ++ { ++ .procname = "poolsize", ++ .maxlen = sizeof(int), ++ .mode = 0444, ++ .proc_handler = lrng_proc_do_poolsize, ++ }, ++ { ++ .procname = "entropy_avail", ++ .maxlen = sizeof(int), ++ .mode = 0444, ++ .proc_handler = lrng_proc_do_entropy, ++ }, ++ { ++ .procname = "write_wakeup_threshold", ++ .data = &lrng_write_wakeup_bits, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec_minmax, ++ .extra1 = &lrng_min_write_thresh, ++ .extra2 = &lrng_max_write_thresh, ++ }, ++ { ++ .procname = "boot_id", ++ .data = &lrng_sysctl_bootid, ++ .maxlen = 16, ++ .mode = 0444, ++ .proc_handler = lrng_proc_do_uuid, ++ }, ++ { ++ .procname = "uuid", ++ .maxlen = 16, ++ .mode = 0444, ++ .proc_handler = lrng_proc_do_uuid, ++ }, ++ { ++ .procname = "urandom_min_reseed_secs", ++ .data = &lrng_drng_reseed_max_time, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec, ++ .extra1 = &lrng_drng_reseed_max_min, ++ }, ++ { } ++}; ++ ++/* Number of online DRNGs */ ++static u32 numa_drngs = 1; ++ ++void lrng_pool_inc_numa_node(void) ++{ ++ numa_drngs++; ++} ++ ++static int lrng_proc_type_show(struct seq_file *m, void *v) ++{ ++ struct lrng_drng *lrng_drng_init = lrng_drng_init_instance(); ++ unsigned long flags = 0; ++ unsigned char buf[390]; ++ ++ lrng_drng_lock(lrng_drng_init, &flags); ++ snprintf(buf, sizeof(buf), ++ "DRNG name: %s\n" ++ "Hash for reading entropy pool: %s\n" ++ "Hash for operating aux entropy pool: %s\n" ++ "LRNG security strength in bits: %d\n" ++ "per-CPU interrupt collection size: %u\n" ++ "number of DRNG instances: %u\n" ++ "Standards compliance: %s%s\n" ++ "High-resolution timer: %s\n" ++ "LRNG minimally seeded: %s\n" ++ "LRNG fully seeded: %s\n" ++ "Continuous compression: %s\n", ++ lrng_drng_init->crypto_cb->lrng_drng_name(), ++ lrng_drng_init->crypto_cb->lrng_hash_name(), ++ lrng_drng_init->crypto_cb->lrng_hash_name(), ++ lrng_security_strength(), ++ LRNG_DATA_NUM_VALUES, ++ numa_drngs, ++ lrng_sp80090b_compliant() ? "SP800-90B " : "", ++ lrng_sp80090c_compliant() ? "SP800-90C " : "", ++ lrng_pool_highres_timer() ? "true" : "false", ++ lrng_state_min_seeded() ? "true" : "false", ++ lrng_state_fully_seeded() ? "true" : "false", ++ lrng_pcpu_continuous_compression_state() ? "true" : "false"); ++ lrng_drng_unlock(lrng_drng_init, &flags); ++ ++ seq_write(m, buf, strlen(buf)); ++ ++ return 0; ++} ++ ++static int __init lrng_proc_type_init(void) ++{ ++ proc_create_single("lrng_type", 0444, NULL, &lrng_proc_type_show); ++ return 0; ++} ++ ++module_init(lrng_proc_type_init); diff --git a/PATCH/LRNG/696-07-v41-0004-LRNG-add-switchable-DRNG-support.patch b/PATCH/LRNG/696-07-v41-0004-LRNG-add-switchable-DRNG-support.patch new file mode 100644 index 000000000..975c74cf0 --- /dev/null +++ b/PATCH/LRNG/696-07-v41-0004-LRNG-add-switchable-DRNG-support.patch @@ -0,0 +1,326 @@ +From 2ea9e51004f8a85964977ec7cd26f9f5a294295a Mon Sep 17 00:00:00 2001 +From: Stephan Mueller +Date: Fri, 18 Jun 2021 08:06:39 +0200 +Subject: [PATCH v41 04/13] LRNG - add switchable DRNG support + +The DRNG switch support allows replacing the DRNG mechanism of the +LRNG. The switching support rests on the interface definition of +include/linux/lrng.h. A new DRNG is implemented by filling in the +interface defined in this header file. + +In addition to the DRNG, the extension also has to provide a hash +implementation that is used to hash the entropy pool for random number +extraction. + +Note: It is permissible to implement a DRNG whose operations may sleep. +However, the hash function must not sleep. + +The switchable DRNG support allows replacing the DRNG at runtime. +However, only one DRNG extension is allowed to be loaded at any given +time. Before replacing it with another DRNG implementation, the possibly +existing DRNG extension must be unloaded. + +The switchable DRNG extension activates the new DRNG during load time. +It is expected, however, that such a DRNG switch would be done only once +by an administrator to load the intended DRNG implementation. + +It is permissible to compile DRNG extensions either as kernel modules or +statically. The initialization of the DRNG extension should be performed +with a late_initcall to ensure the extension is available when user +space starts but after all other initialization completed. +The initialization is performed by registering the function call data +structure with the lrng_set_drng_cb function. In order to unload the +DRNG extension, lrng_set_drng_cb must be invoked with the NULL +parameter. + +The DRNG extension should always provide a security strength that is at +least as strong as LRNG_DRNG_SECURITY_STRENGTH_BITS. + +The hash extension must not sleep and must not maintain a separate +state. + +CC: Torsten Duwe +CC: "Eric W. Biederman" +CC: "Alexander E. Patrakov" +CC: "Ahmed S. Darwish" +CC: "Theodore Y. Ts'o" +CC: Willy Tarreau +CC: Matthew Garrett +CC: Vito Caputo +CC: Andreas Dilger +CC: Jan Kara +CC: Ray Strode +CC: William Jon McCann +CC: zhangjs +CC: Andy Lutomirski +CC: Florian Weimer +CC: Lennart Poettering +CC: Nicolai Stange +CC: Alexander Lobakin +Reviewed-by: Marcelo Henrique Cerri +Reviewed-by: Roman Drahtmueller +Tested-by: Marcelo Henrique Cerri +Tested-by: Neil Horman +Signed-off-by: Stephan Mueller +--- + drivers/char/lrng/Kconfig | 7 + + drivers/char/lrng/Makefile | 1 + + drivers/char/lrng/lrng_switch.c | 231 ++++++++++++++++++++++++++++++++ + 3 files changed, 239 insertions(+) + create mode 100644 drivers/char/lrng/lrng_switch.c + +--- a/drivers/char/lrng/Kconfig ++++ b/drivers/char/lrng/Kconfig +@@ -202,4 +202,11 @@ config LRNG_CPU_ENTROPY_RATE + + endmenu # "Entropy Source Configuration" + ++menuconfig LRNG_DRNG_SWITCH ++ bool "Support DRNG runtime switching" ++ help ++ The Linux RNG per default uses a ChaCha20 DRNG that is ++ accessible via the external interfaces. With this configuration ++ option other DRNGs can be selected and loaded at runtime. ++ + endif # LRNG +--- a/drivers/char/lrng/Makefile ++++ b/drivers/char/lrng/Makefile +@@ -10,3 +10,4 @@ obj-y += lrng_pool.o lrng_aux.o \ + + obj-$(CONFIG_NUMA) += lrng_numa.o + obj-$(CONFIG_SYSCTL) += lrng_proc.o ++obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_switch.o +--- /dev/null ++++ b/drivers/char/lrng/lrng_switch.c +@@ -0,0 +1,231 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause ++/* ++ * LRNG DRNG switching support ++ * ++ * Copyright (C) 2016 - 2021, Stephan Mueller ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++ ++#include "lrng_internal.h" ++ ++static int lrng_drng_switch(struct lrng_drng *drng_store, ++ const struct lrng_crypto_cb *cb, int node) ++{ ++ const struct lrng_crypto_cb *old_cb; ++ unsigned long flags = 0, flags2 = 0; ++ int ret; ++ u8 seed[LRNG_DRNG_SECURITY_STRENGTH_BYTES]; ++ void *new_drng = cb->lrng_drng_alloc(LRNG_DRNG_SECURITY_STRENGTH_BYTES); ++ void *old_drng, *new_hash, *old_hash; ++ u32 current_security_strength; ++ bool sl = false, reset_drng = !lrng_get_available(); ++ ++ if (IS_ERR(new_drng)) { ++ pr_warn("could not allocate new DRNG for NUMA node %d (%ld)\n", ++ node, PTR_ERR(new_drng)); ++ return PTR_ERR(new_drng); ++ } ++ ++ new_hash = cb->lrng_hash_alloc(); ++ if (IS_ERR(new_hash)) { ++ pr_warn("could not allocate new LRNG pool hash (%ld)\n", ++ PTR_ERR(new_hash)); ++ cb->lrng_drng_dealloc(new_drng); ++ return PTR_ERR(new_hash); ++ } ++ ++ if (cb->lrng_hash_digestsize(new_hash) > LRNG_MAX_DIGESTSIZE) { ++ pr_warn("digest size of newly requested hash too large\n"); ++ cb->lrng_hash_dealloc(new_hash); ++ cb->lrng_drng_dealloc(new_drng); ++ return -EINVAL; ++ } ++ ++ current_security_strength = lrng_security_strength(); ++ lrng_drng_lock(drng_store, &flags); ++ ++ /* ++ * Pull from existing DRNG to seed new DRNG regardless of seed status ++ * of old DRNG -- the entropy state for the DRNG is left unchanged which ++ * implies that als the new DRNG is reseeded when deemed necessary. This ++ * seeding of the new DRNG shall only ensure that the new DRNG has the ++ * same entropy as the old DRNG. ++ */ ++ ret = drng_store->crypto_cb->lrng_drng_generate_helper( ++ drng_store->drng, seed, sizeof(seed)); ++ lrng_drng_unlock(drng_store, &flags); ++ ++ if (ret < 0) { ++ reset_drng = true; ++ pr_warn("getting random data from DRNG failed for NUMA node %d (%d)\n", ++ node, ret); ++ } else { ++ /* seed new DRNG with data */ ++ ret = cb->lrng_drng_seed_helper(new_drng, seed, ret); ++ memzero_explicit(seed, sizeof(seed)); ++ if (ret < 0) { ++ reset_drng = true; ++ pr_warn("seeding of new DRNG failed for NUMA node %d (%d)\n", ++ node, ret); ++ } else { ++ pr_debug("seeded new DRNG of NUMA node %d instance from old DRNG instance\n", ++ node); ++ } ++ } ++ ++ mutex_lock(&drng_store->lock); ++ write_lock_irqsave(&drng_store->hash_lock, flags2); ++ /* ++ * If we switch the DRNG from the initial ChaCha20 DRNG to something ++ * else, there is a lock transition from spin lock to mutex (see ++ * lrng_drng_is_atomic and how the lock is taken in lrng_drng_lock). ++ * Thus, we need to take both locks during the transition phase. ++ */ ++ if (lrng_drng_is_atomic(drng_store)) { ++ spin_lock_irqsave(&drng_store->spin_lock, flags); ++ sl = true; ++ } else { ++ __acquire(&drng_store->spin_lock); ++ } ++ ++ /* Trigger the switch of the aux entropy pool for current node. */ ++ if (drng_store == lrng_drng_init_instance()) { ++ ret = lrng_aux_switch_hash(cb, new_hash, drng_store->crypto_cb); ++ if (ret) ++ goto err; ++ } ++ ++ /* Trigger the switch of the per-CPU entropy pools for current node. */ ++ ret = lrng_pcpu_switch_hash(node, cb, new_hash, drng_store->crypto_cb); ++ if (ret) { ++ /* Switch the crypto operation back to be consistent */ ++ WARN_ON(lrng_aux_switch_hash(drng_store->crypto_cb, ++ drng_store->hash, cb)); ++ } else { ++ if (reset_drng) ++ lrng_drng_reset(drng_store); ++ ++ old_drng = drng_store->drng; ++ old_cb = drng_store->crypto_cb; ++ drng_store->drng = new_drng; ++ drng_store->crypto_cb = cb; ++ ++ old_hash = drng_store->hash; ++ drng_store->hash = new_hash; ++ pr_info("Entropy pool read-hash allocated for DRNG for NUMA node %d\n", ++ node); ++ ++ if (lrng_state_min_seeded()) ++ lrng_set_entropy_thresh(lrng_get_seed_entropy_osr()); ++ ++ /* Reseed if previous LRNG security strength was insufficient */ ++ if (current_security_strength < lrng_security_strength()) ++ drng_store->force_reseed = true; ++ ++ /* Force oversampling seeding as we initialize DRNG */ ++ if (IS_ENABLED(CONFIG_LRNG_OVERSAMPLE_ENTROPY_SOURCES)) { ++ drng_store->force_reseed = true; ++ drng_store->fully_seeded = false; ++ ++ /* Block output interfaces until again fully seeded */ ++ if (drng_store == lrng_drng_init_instance()) ++ lrng_unset_operational(); ++ } ++ ++ /* ChaCha20 serves as atomic instance left untouched. */ ++ if (old_drng != &chacha20) { ++ old_cb->lrng_drng_dealloc(old_drng); ++ old_cb->lrng_hash_dealloc(old_hash); ++ } ++ ++ pr_info("DRNG of NUMA node %d switched\n", node); ++ } ++ ++err: ++ if (sl) ++ spin_unlock_irqrestore(&drng_store->spin_lock, flags); ++ else ++ __release(&drng_store->spin_lock); ++ write_unlock_irqrestore(&drng_store->hash_lock, flags2); ++ mutex_unlock(&drng_store->lock); ++ ++ return ret; ++} ++ ++/* ++ * Switch the existing DRNG instances with new using the new crypto callbacks. ++ * The caller must hold the lrng_crypto_cb_update lock. ++ */ ++static int lrng_drngs_switch(const struct lrng_crypto_cb *cb) ++{ ++ struct lrng_drng **lrng_drng = lrng_drng_instances(); ++ struct lrng_drng *lrng_drng_init = lrng_drng_init_instance(); ++ int ret = 0; ++ ++ /* Update DRNG */ ++ if (lrng_drng) { ++ u32 node; ++ ++ for_each_online_node(node) { ++ if (lrng_drng[node]) ++ ret = lrng_drng_switch(lrng_drng[node], cb, ++ node); ++ } ++ } else { ++ ret = lrng_drng_switch(lrng_drng_init, cb, 0); ++ } ++ ++ if (!ret) ++ lrng_set_available(); ++ ++ return 0; ++} ++ ++/** ++ * lrng_set_drng_cb - Register new cryptographic callback functions for DRNG ++ * The registering implies that all old DRNG states are replaced with new ++ * DRNG states. ++ * ++ * @cb: Callback functions to be registered -- if NULL, use the default ++ * callbacks pointing to the ChaCha20 DRNG. ++ * ++ * Return: ++ * * 0 on success ++ * * < 0 on error ++ */ ++int lrng_set_drng_cb(const struct lrng_crypto_cb *cb) ++{ ++ struct lrng_drng *lrng_drng_init = lrng_drng_init_instance(); ++ int ret; ++ ++ if (!cb) ++ cb = &lrng_cc20_crypto_cb; ++ ++ mutex_lock(&lrng_crypto_cb_update); ++ ++ /* ++ * If a callback other than the default is set, allow it only to be ++ * set back to the default callback. This ensures that multiple ++ * different callbacks can be registered at the same time. If a ++ * callback different from the current callback and the default ++ * callback shall be set, the current callback must be deregistered ++ * (e.g. the kernel module providing it must be unloaded) and the new ++ * implementation can be registered. ++ */ ++ if ((cb != &lrng_cc20_crypto_cb) && ++ (lrng_drng_init->crypto_cb != &lrng_cc20_crypto_cb)) { ++ pr_warn("disallow setting new cipher callbacks, unload the old callbacks first!\n"); ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ ret = lrng_drngs_switch(cb); ++ ++out: ++ mutex_unlock(&lrng_crypto_cb_update); ++ return ret; ++} ++EXPORT_SYMBOL(lrng_set_drng_cb); diff --git a/PATCH/LRNG/696-08-v41-0005-LRNG-add-common-generic-hash-support.patch b/PATCH/LRNG/696-08-v41-0005-LRNG-add-common-generic-hash-support.patch new file mode 100644 index 000000000..ea5685b89 --- /dev/null +++ b/PATCH/LRNG/696-08-v41-0005-LRNG-add-common-generic-hash-support.patch @@ -0,0 +1,198 @@ +From 2ca28b8684c0673b2e0363cc109479ecf1cae641 Mon Sep 17 00:00:00 2001 +From: Stephan Mueller +Date: Fri, 18 Jun 2021 08:08:20 +0200 +Subject: [PATCH v41 05/13] LRNG - add common generic hash support + +The LRNG switchable DRNG support also allows the replacement of the hash +implementation used as conditioning component. The common generic hash +support code provides the required callbacks using the synchronous hash +implementations of the kernel crypto API. + +All synchronous hash implementations supported by the kernel crypto API +can be used as part of the LRNG with this generic support. + +The generic support is intended to be configured by separate switchable +DRNG backends. + +CC: Torsten Duwe +CC: "Eric W. Biederman" +CC: "Alexander E. Patrakov" +CC: "Ahmed S. Darwish" +CC: "Theodore Y. Ts'o" +CC: Willy Tarreau +CC: Matthew Garrett +CC: Vito Caputo +CC: Andreas Dilger +CC: Jan Kara +CC: Ray Strode +CC: William Jon McCann +CC: zhangjs +CC: Andy Lutomirski +CC: Florian Weimer +CC: Lennart Poettering +CC: Nicolai Stange +CC: Alexander Lobakin +CC: "Peter, Matthias" +CC: Marcelo Henrique Cerri +CC: Neil Horman +Signed-off-by: Stephan Mueller +--- + drivers/char/lrng/Kconfig | 8 +++ + drivers/char/lrng/Makefile | 1 + + drivers/char/lrng/lrng_kcapi_hash.c | 103 ++++++++++++++++++++++++++++ + drivers/char/lrng/lrng_kcapi_hash.h | 20 ++++++ + 4 files changed, 132 insertions(+) + create mode 100644 drivers/char/lrng/lrng_kcapi_hash.c + create mode 100644 drivers/char/lrng/lrng_kcapi_hash.h + +--- a/drivers/char/lrng/Kconfig ++++ b/drivers/char/lrng/Kconfig +@@ -209,4 +209,12 @@ menuconfig LRNG_DRNG_SWITCH + accessible via the external interfaces. With this configuration + option other DRNGs can be selected and loaded at runtime. + ++if LRNG_DRNG_SWITCH ++ ++config LRNG_KCAPI_HASH ++ bool ++ select CRYPTO_HASH ++ ++endif # LRNG_DRNG_SWITCH ++ + endif # LRNG +--- a/drivers/char/lrng/Makefile ++++ b/drivers/char/lrng/Makefile +@@ -11,3 +11,4 @@ obj-y += lrng_pool.o lrng_aux.o \ + obj-$(CONFIG_NUMA) += lrng_numa.o + obj-$(CONFIG_SYSCTL) += lrng_proc.o + obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_switch.o ++obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.o +--- /dev/null ++++ b/drivers/char/lrng/lrng_kcapi_hash.c +@@ -0,0 +1,103 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause ++/* ++ * Backend for providing the hash primitive using the kernel crypto API. ++ * ++ * Copyright (C) 2021, Stephan Mueller ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++ ++#include "lrng_kcapi_hash.h" ++ ++struct lrng_hash_info { ++ struct crypto_shash *tfm; ++}; ++ ++static inline void _lrng_kcapi_hash_free(struct lrng_hash_info *lrng_hash) ++{ ++ struct crypto_shash *tfm = lrng_hash->tfm; ++ ++ crypto_free_shash(tfm); ++ kfree(lrng_hash); ++} ++ ++void *lrng_kcapi_hash_alloc(const char *name) ++{ ++ struct lrng_hash_info *lrng_hash; ++ struct crypto_shash *tfm; ++ int ret; ++ ++ if (!name) { ++ pr_err("Hash name missing\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ tfm = crypto_alloc_shash(name, 0, 0); ++ if (IS_ERR(tfm)) { ++ pr_err("could not allocate hash %s\n", name); ++ return ERR_CAST(tfm); ++ } ++ ++ ret = sizeof(struct lrng_hash_info); ++ lrng_hash = kmalloc(ret, GFP_KERNEL); ++ if (!lrng_hash) { ++ crypto_free_shash(tfm); ++ return ERR_PTR(-ENOMEM); ++ } ++ ++ lrng_hash->tfm = tfm; ++ ++ pr_info("Hash %s allocated\n", name); ++ ++ return lrng_hash; ++} ++EXPORT_SYMBOL(lrng_kcapi_hash_alloc); ++ ++u32 lrng_kcapi_hash_digestsize(void *hash) ++{ ++ struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash; ++ struct crypto_shash *tfm = lrng_hash->tfm; ++ ++ return crypto_shash_digestsize(tfm); ++} ++EXPORT_SYMBOL(lrng_kcapi_hash_digestsize); ++ ++void lrng_kcapi_hash_dealloc(void *hash) ++{ ++ struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash; ++ ++ _lrng_kcapi_hash_free(lrng_hash); ++ pr_info("Hash deallocated\n"); ++} ++EXPORT_SYMBOL(lrng_kcapi_hash_dealloc); ++ ++int lrng_kcapi_hash_init(struct shash_desc *shash, void *hash) ++{ ++ struct lrng_hash_info *lrng_hash = (struct lrng_hash_info *)hash; ++ struct crypto_shash *tfm = lrng_hash->tfm; ++ ++ shash->tfm = tfm; ++ return crypto_shash_init(shash); ++} ++EXPORT_SYMBOL(lrng_kcapi_hash_init); ++ ++int lrng_kcapi_hash_update(struct shash_desc *shash, const u8 *inbuf, ++ u32 inbuflen) ++{ ++ return crypto_shash_update(shash, inbuf, inbuflen); ++} ++EXPORT_SYMBOL(lrng_kcapi_hash_update); ++ ++int lrng_kcapi_hash_final(struct shash_desc *shash, u8 *digest) ++{ ++ return crypto_shash_final(shash, digest); ++} ++EXPORT_SYMBOL(lrng_kcapi_hash_final); ++ ++void lrng_kcapi_hash_zero(struct shash_desc *shash) ++{ ++ shash_desc_zero(shash); ++} ++EXPORT_SYMBOL(lrng_kcapi_hash_zero); +--- /dev/null ++++ b/drivers/char/lrng/lrng_kcapi_hash.h +@@ -0,0 +1,20 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ ++/* ++ * Copyright (C) 2020 - 2021, Stephan Mueller ++ */ ++ ++#ifndef _LRNG_KCAPI_HASH_H ++#define _LRNG_KCAPI_HASH_H ++ ++#include ++ ++void *lrng_kcapi_hash_alloc(const char *name); ++u32 lrng_kcapi_hash_digestsize(void *hash); ++void lrng_kcapi_hash_dealloc(void *hash); ++int lrng_kcapi_hash_init(struct shash_desc *shash, void *hash); ++int lrng_kcapi_hash_update(struct shash_desc *shash, const u8 *inbuf, ++ u32 inbuflen); ++int lrng_kcapi_hash_final(struct shash_desc *shash, u8 *digest); ++void lrng_kcapi_hash_zero(struct shash_desc *shash); ++ ++#endif /* _LRNG_KCAPI_HASH_H */ diff --git a/PATCH/LRNG/696-09-v41-0006-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch b/PATCH/LRNG/696-09-v41-0006-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch new file mode 100644 index 000000000..30f827960 --- /dev/null +++ b/PATCH/LRNG/696-09-v41-0006-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch @@ -0,0 +1,139 @@ +From f83f3fc4de379c8be7b382277c4ac3d2b491d3c1 Mon Sep 17 00:00:00 2001 +From: Stephan Mueller +Date: Tue, 15 Sep 2020 22:17:43 +0200 +Subject: [PATCH v41 06/13] crypto: DRBG - externalize DRBG functions for LRNG +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch allows several DRBG functions to be called by the LRNG kernel +code paths outside the drbg.c file. + +CC: Torsten Duwe +CC: "Eric W. Biederman" +CC: "Alexander E. Patrakov" +CC: "Ahmed S. Darwish" +CC: "Theodore Y. Ts'o" +CC: Willy Tarreau +CC: Matthew Garrett +CC: Vito Caputo +CC: Andreas Dilger +CC: Jan Kara +CC: Ray Strode +CC: William Jon McCann +CC: zhangjs +CC: Andy Lutomirski +CC: Florian Weimer +CC: Lennart Poettering +CC: Nicolai Stange +CC: Alexander Lobakin +Reviewed-by: Roman Drahtmueller +Tested-by: Roman Drahtmüller +Tested-by: Marcelo Henrique Cerri +Tested-by: Neil Horman +Signed-off-by: Stephan Mueller +--- + crypto/drbg.c | 16 ++++++++++------ + include/crypto/drbg.h | 7 +++++++ + 2 files changed, 17 insertions(+), 6 deletions(-) + +--- a/crypto/drbg.c ++++ b/crypto/drbg.c +@@ -113,7 +113,7 @@ + * the SHA256 / AES 256 over other ciphers. Thus, the favored + * DRBGs are the latest entries in this array. + */ +-static const struct drbg_core drbg_cores[] = { ++const struct drbg_core drbg_cores[] = { + #ifdef CONFIG_CRYPTO_DRBG_CTR + { + .flags = DRBG_CTR | DRBG_STRENGTH128, +@@ -190,6 +190,7 @@ static const struct drbg_core drbg_cores + }, + #endif /* CONFIG_CRYPTO_DRBG_HMAC */ + }; ++EXPORT_SYMBOL(drbg_cores); + + static int drbg_uninstantiate(struct drbg_state *drbg); + +@@ -205,7 +206,7 @@ static int drbg_uninstantiate(struct drb + * Return: normalized strength in *bytes* value or 32 as default + * to counter programming errors + */ +-static inline unsigned short drbg_sec_strength(drbg_flag_t flags) ++unsigned short drbg_sec_strength(drbg_flag_t flags) + { + switch (flags & DRBG_STRENGTH_MASK) { + case DRBG_STRENGTH128: +@@ -218,6 +219,7 @@ static inline unsigned short drbg_sec_st + return 32; + } + } ++EXPORT_SYMBOL(drbg_sec_strength); + + /* + * FIPS 140-2 continuous self test for the noise source +@@ -1202,7 +1204,7 @@ out: + } + + /* Free all substructures in a DRBG state without the DRBG state structure */ +-static inline void drbg_dealloc_state(struct drbg_state *drbg) ++void drbg_dealloc_state(struct drbg_state *drbg) + { + if (!drbg) + return; +@@ -1223,12 +1225,13 @@ static inline void drbg_dealloc_state(st + drbg->fips_primed = false; + } + } ++EXPORT_SYMBOL(drbg_dealloc_state); + + /* + * Allocate all sub-structures for a DRBG state. + * The DRBG state structure must already be allocated. + */ +-static inline int drbg_alloc_state(struct drbg_state *drbg) ++int drbg_alloc_state(struct drbg_state *drbg) + { + int ret = -ENOMEM; + unsigned int sb_size = 0; +@@ -1309,6 +1312,7 @@ err: + drbg_dealloc_state(drbg); + return ret; + } ++EXPORT_SYMBOL(drbg_alloc_state); + + /************************************************************************* + * DRBG interface functions +@@ -1876,8 +1880,7 @@ out: + * + * return: flags + */ +-static inline void drbg_convert_tfm_core(const char *cra_driver_name, +- int *coreref, bool *pr) ++void drbg_convert_tfm_core(const char *cra_driver_name, int *coreref, bool *pr) + { + int i = 0; + size_t start = 0; +@@ -1904,6 +1907,7 @@ static inline void drbg_convert_tfm_core + } + } + } ++EXPORT_SYMBOL(drbg_convert_tfm_core); + + static int drbg_kcapi_init(struct crypto_tfm *tfm) + { +--- a/include/crypto/drbg.h ++++ b/include/crypto/drbg.h +@@ -282,4 +282,11 @@ enum drbg_prefixes { + DRBG_PREFIX3 + }; + ++extern int drbg_alloc_state(struct drbg_state *drbg); ++extern void drbg_dealloc_state(struct drbg_state *drbg); ++extern void drbg_convert_tfm_core(const char *cra_driver_name, int *coreref, ++ bool *pr); ++extern const struct drbg_core drbg_cores[]; ++extern unsigned short drbg_sec_strength(drbg_flag_t flags); ++ + #endif /* _DRBG_H */ diff --git a/PATCH/LRNG/696-10-v41-0007-LRNG-add-SP800-90A-DRBG-extension.patch b/PATCH/LRNG/696-10-v41-0007-LRNG-add-SP800-90A-DRBG-extension.patch new file mode 100644 index 000000000..235965811 --- /dev/null +++ b/PATCH/LRNG/696-10-v41-0007-LRNG-add-SP800-90A-DRBG-extension.patch @@ -0,0 +1,278 @@ +From 288d9cf9f2e949fb6c7dc3cf623186d07d4173fd Mon Sep 17 00:00:00 2001 +From: Stephan Mueller +Date: Fri, 18 Jun 2021 08:09:59 +0200 +Subject: [PATCH v41 07/13] LRNG - add SP800-90A DRBG extension + +Using the LRNG switchable DRNG support, the SP800-90A DRBG extension is +implemented. + +The DRBG uses the kernel crypto API DRBG implementation. In addition, it +uses the kernel crypto API SHASH support to provide the hashing +operation. + +The DRBG supports the choice of either a CTR DRBG using AES-256, HMAC +DRBG with SHA-512 core or Hash DRBG with SHA-512 core. The used core can +be selected with the module parameter lrng_drbg_type. The default is the +CTR DRBG. + +When compiling the DRBG extension statically, the DRBG is loaded at +late_initcall stage which implies that with the start of user space, the +user space interfaces of getrandom(2), /dev/random and /dev/urandom +provide random data produced by an SP800-90A DRBG. + +CC: Torsten Duwe +CC: "Eric W. Biederman" +CC: "Alexander E. Patrakov" +CC: "Ahmed S. Darwish" +CC: "Theodore Y. Ts'o" +CC: Willy Tarreau +CC: Matthew Garrett +CC: Vito Caputo +CC: Andreas Dilger +CC: Jan Kara +CC: Ray Strode +CC: William Jon McCann +CC: zhangjs +CC: Andy Lutomirski +CC: Florian Weimer +CC: Lennart Poettering +CC: Nicolai Stange +CC: Alexander Lobakin +Reviewed-by: Roman Drahtmueller +Tested-by: Marcelo Henrique Cerri +Tested-by: Neil Horman +Signed-off-by: Stephan Mueller +--- + drivers/char/lrng/Kconfig | 10 ++ + drivers/char/lrng/Makefile | 1 + + drivers/char/lrng/lrng_drbg.c | 198 ++++++++++++++++++++++++++++++++++ + 3 files changed, 209 insertions(+) + create mode 100644 drivers/char/lrng/lrng_drbg.c + +--- a/drivers/char/lrng/Kconfig ++++ b/drivers/char/lrng/Kconfig +@@ -215,6 +215,16 @@ config LRNG_KCAPI_HASH + bool + select CRYPTO_HASH + ++config LRNG_DRBG ++ tristate "SP800-90A support for the LRNG" ++ depends on CRYPTO ++ select CRYPTO_DRBG_MENU ++ select CRYPTO_SHA512 ++ select LRNG_KCAPI_HASH ++ help ++ Enable the SP800-90A DRBG support for the LRNG. Once the ++ module is loaded, output from /dev/random, /dev/urandom, ++ getrandom(2), or get_random_bytes_full is provided by a DRBG. + endif # LRNG_DRNG_SWITCH + + endif # LRNG +--- a/drivers/char/lrng/Makefile ++++ b/drivers/char/lrng/Makefile +@@ -12,3 +12,4 @@ obj-$(CONFIG_NUMA) += lrng_numa.o + obj-$(CONFIG_SYSCTL) += lrng_proc.o + obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_switch.o + obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.o ++obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o +--- /dev/null ++++ b/drivers/char/lrng/lrng_drbg.c +@@ -0,0 +1,198 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause ++/* ++ * Backend for the LRNG providing the cryptographic primitives using the ++ * kernel crypto API and its DRBG. ++ * ++ * Copyright (C) 2016 - 2021, Stephan Mueller ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++ ++#include "lrng_kcapi_hash.h" ++ ++/* ++ * Define a DRBG plus a hash / MAC used to extract data from the entropy pool. ++ * For LRNG_HASH_NAME you can use a hash or a MAC (HMAC or CMAC) of your choice ++ * (Note, you should use the suggested selections below -- using SHA-1 or MD5 ++ * is not wise). The idea is that the used cipher primitive can be selected to ++ * be the same as used for the DRBG. I.e. the LRNG only uses one cipher ++ * primitive using the same cipher implementation with the options offered in ++ * the following. This means, if the CTR DRBG is selected and AES-NI is present, ++ * both the CTR DRBG and the selected cmac(aes) use AES-NI. ++ * ++ * The security strengths of the DRBGs are all 256 bits according to ++ * SP800-57 section 5.6.1. ++ * ++ * This definition is allowed to be changed. ++ */ ++#ifdef CONFIG_CRYPTO_DRBG_CTR ++static unsigned int lrng_drbg_type = 0; ++#elif defined CONFIG_CRYPTO_DRBG_HMAC ++static unsigned int lrng_drbg_type = 1; ++#elif defined CONFIG_CRYPTO_DRBG_HASH ++static unsigned int lrng_drbg_type = 2; ++#else ++#error "Unknown DRBG in use" ++#endif ++ ++/* The parameter must be r/o in sysfs as otherwise races appear. */ ++module_param(lrng_drbg_type, uint, 0444); ++MODULE_PARM_DESC(lrng_drbg_type, "DRBG type used for LRNG (0->CTR_DRBG, 1->HMAC_DRBG, 2->Hash_DRBG)"); ++ ++struct lrng_drbg { ++ const char *hash_name; ++ const char *drbg_core; ++}; ++ ++static const struct lrng_drbg lrng_drbg_types[] = { ++ { /* CTR_DRBG with AES-256 using derivation function */ ++ .hash_name = "sha512", ++ .drbg_core = "drbg_nopr_ctr_aes256", ++ }, { /* HMAC_DRBG with SHA-512 */ ++ .hash_name = "sha512", ++ .drbg_core = "drbg_nopr_hmac_sha512", ++ }, { /* Hash_DRBG with SHA-512 using derivation function */ ++ .hash_name = "sha512", ++ .drbg_core = "drbg_nopr_sha512" ++ } ++}; ++ ++static int lrng_drbg_drng_seed_helper(void *drng, const u8 *inbuf, u32 inbuflen) ++{ ++ struct drbg_state *drbg = (struct drbg_state *)drng; ++ LIST_HEAD(seedlist); ++ struct drbg_string data; ++ int ret; ++ ++ drbg_string_fill(&data, inbuf, inbuflen); ++ list_add_tail(&data.list, &seedlist); ++ ret = drbg->d_ops->update(drbg, &seedlist, drbg->seeded); ++ ++ if (ret >= 0) ++ drbg->seeded = true; ++ ++ return ret; ++} ++ ++static int lrng_drbg_drng_generate_helper(void *drng, u8 *outbuf, u32 outbuflen) ++{ ++ struct drbg_state *drbg = (struct drbg_state *)drng; ++ ++ return drbg->d_ops->generate(drbg, outbuf, outbuflen, NULL); ++} ++ ++static void *lrng_drbg_drng_alloc(u32 sec_strength) ++{ ++ struct drbg_state *drbg; ++ int coreref = -1; ++ bool pr = false; ++ int ret; ++ ++ drbg_convert_tfm_core(lrng_drbg_types[lrng_drbg_type].drbg_core, ++ &coreref, &pr); ++ if (coreref < 0) ++ return ERR_PTR(-EFAULT); ++ ++ drbg = kzalloc(sizeof(struct drbg_state), GFP_KERNEL); ++ if (!drbg) ++ return ERR_PTR(-ENOMEM); ++ ++ drbg->core = &drbg_cores[coreref]; ++ drbg->seeded = false; ++ ret = drbg_alloc_state(drbg); ++ if (ret) ++ goto err; ++ ++ if (sec_strength > drbg_sec_strength(drbg->core->flags)) { ++ pr_err("Security strength of DRBG (%u bits) lower than requested by LRNG (%u bits)\n", ++ drbg_sec_strength(drbg->core->flags) * 8, ++ sec_strength * 8); ++ goto dealloc; ++ } ++ ++ if (sec_strength < drbg_sec_strength(drbg->core->flags)) ++ pr_warn("Security strength of DRBG (%u bits) higher than requested by LRNG (%u bits)\n", ++ drbg_sec_strength(drbg->core->flags) * 8, ++ sec_strength * 8); ++ ++ pr_info("DRBG with %s core allocated\n", drbg->core->backend_cra_name); ++ ++ return drbg; ++ ++dealloc: ++ if (drbg->d_ops) ++ drbg->d_ops->crypto_fini(drbg); ++ drbg_dealloc_state(drbg); ++err: ++ kfree(drbg); ++ return ERR_PTR(-EINVAL); ++} ++ ++static void lrng_drbg_drng_dealloc(void *drng) ++{ ++ struct drbg_state *drbg = (struct drbg_state *)drng; ++ ++ if (drbg && drbg->d_ops) ++ drbg->d_ops->crypto_fini(drbg); ++ drbg_dealloc_state(drbg); ++ kfree_sensitive(drbg); ++ pr_info("DRBG deallocated\n"); ++} ++ ++static void *lrng_drbg_hash_alloc(void) ++{ ++ return lrng_kcapi_hash_alloc(lrng_drbg_types[lrng_drbg_type].hash_name); ++} ++ ++static const char *lrng_drbg_name(void) ++{ ++ return lrng_drbg_types[lrng_drbg_type].drbg_core; ++} ++ ++static const char *lrng_hash_name(void) ++{ ++ return lrng_drbg_types[lrng_drbg_type].hash_name; ++} ++ ++static const struct lrng_crypto_cb lrng_drbg_crypto_cb = { ++ .lrng_drng_name = lrng_drbg_name, ++ .lrng_hash_name = lrng_hash_name, ++ .lrng_drng_alloc = lrng_drbg_drng_alloc, ++ .lrng_drng_dealloc = lrng_drbg_drng_dealloc, ++ .lrng_drng_seed_helper = lrng_drbg_drng_seed_helper, ++ .lrng_drng_generate_helper = lrng_drbg_drng_generate_helper, ++ .lrng_hash_alloc = lrng_drbg_hash_alloc, ++ .lrng_hash_dealloc = lrng_kcapi_hash_dealloc, ++ .lrng_hash_digestsize = lrng_kcapi_hash_digestsize, ++ .lrng_hash_init = lrng_kcapi_hash_init, ++ .lrng_hash_update = lrng_kcapi_hash_update, ++ .lrng_hash_final = lrng_kcapi_hash_final, ++ .lrng_hash_desc_zero = lrng_kcapi_hash_zero, ++}; ++ ++static int __init lrng_drbg_init(void) ++{ ++ if (lrng_drbg_type >= ARRAY_SIZE(lrng_drbg_types)) { ++ pr_err("lrng_drbg_type parameter too large (given %u - max: %lu)", ++ lrng_drbg_type, ++ (unsigned long)ARRAY_SIZE(lrng_drbg_types) - 1); ++ return -EAGAIN; ++ } ++ return lrng_set_drng_cb(&lrng_drbg_crypto_cb); ++} ++ ++static void __exit lrng_drbg_exit(void) ++{ ++ lrng_set_drng_cb(NULL); ++} ++ ++late_initcall(lrng_drbg_init); ++module_exit(lrng_drbg_exit); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_AUTHOR("Stephan Mueller "); ++MODULE_DESCRIPTION("Linux Random Number Generator - SP800-90A DRBG backend"); diff --git a/PATCH/LRNG/696-11-v41-0008-LRNG-add-kernel-crypto-API-PRNG-extension.patch b/PATCH/LRNG/696-11-v41-0008-LRNG-add-kernel-crypto-API-PRNG-extension.patch new file mode 100644 index 000000000..59f2a0349 --- /dev/null +++ b/PATCH/LRNG/696-11-v41-0008-LRNG-add-kernel-crypto-API-PRNG-extension.patch @@ -0,0 +1,307 @@ +From 570409d073bb1d6645214532a431d5bc45454c0f Mon Sep 17 00:00:00 2001 +From: Stephan Mueller +Date: Fri, 18 Jun 2021 08:10:53 +0200 +Subject: [PATCH v41 08/13] LRNG - add kernel crypto API PRNG extension + +Add runtime-pluggable support for all PRNGs that are accessible via +the kernel crypto API, including hardware PRNGs. The PRNG is selected +with the module parameter drng_name where the name must be one that the +kernel crypto API can resolve into an RNG. + +This allows using of the kernel crypto API PRNG implementations that +provide an interface to hardware PRNGs. Using this extension, +the LRNG uses the hardware PRNGs to generate random numbers. An +example is the S390 CPACF support providing such a PRNG. + +The hash is provided by a kernel crypto API SHASH whose digest size +complies with the seedsize of the PRNG. + +CC: Torsten Duwe +CC: "Eric W. Biederman" +CC: "Alexander E. Patrakov" +CC: "Ahmed S. Darwish" +CC: "Theodore Y. Ts'o" +CC: Willy Tarreau +CC: Matthew Garrett +CC: Vito Caputo +CC: Andreas Dilger +CC: Jan Kara +CC: Ray Strode +CC: William Jon McCann +CC: zhangjs +CC: Andy Lutomirski +CC: Florian Weimer +CC: Lennart Poettering +CC: Nicolai Stange +CC: Alexander Lobakin +Reviewed-by: Marcelo Henrique Cerri +Reviewed-by: Roman Drahtmueller +Tested-by: Marcelo Henrique Cerri +Tested-by: Neil Horman +Signed-off-by: Stephan Mueller +--- + drivers/char/lrng/Kconfig | 13 ++ + drivers/char/lrng/Makefile | 1 + + drivers/char/lrng/lrng_kcapi.c | 227 +++++++++++++++++++++++++++++++++ + 3 files changed, 241 insertions(+) + create mode 100644 drivers/char/lrng/lrng_kcapi.c + +--- a/drivers/char/lrng/Kconfig ++++ b/drivers/char/lrng/Kconfig +@@ -225,6 +225,19 @@ config LRNG_DRBG + Enable the SP800-90A DRBG support for the LRNG. Once the + module is loaded, output from /dev/random, /dev/urandom, + getrandom(2), or get_random_bytes_full is provided by a DRBG. ++ ++config LRNG_KCAPI ++ tristate "Kernel Crypto API support for the LRNG" ++ depends on CRYPTO ++ depends on !LRNG_DRBG ++ select CRYPTO_RNG ++ select LRNG_KCAPI_HASH ++ help ++ Enable the support for generic pseudo-random number ++ generators offered by the kernel crypto API with the ++ LRNG. Once the module is loaded, output from /dev/random, ++ /dev/urandom, getrandom(2), or get_random_bytes is ++ provided by the selected kernel crypto API RNG. + endif # LRNG_DRNG_SWITCH + + endif # LRNG +--- a/drivers/char/lrng/Makefile ++++ b/drivers/char/lrng/Makefile +@@ -13,3 +13,4 @@ obj-$(CONFIG_SYSCTL) += lrng_proc.o + obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_switch.o + obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.o + obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o ++obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o +--- /dev/null ++++ b/drivers/char/lrng/lrng_kcapi.c +@@ -0,0 +1,227 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause ++/* ++ * Backend for the LRNG providing the cryptographic primitives using the ++ * kernel crypto API. ++ * ++ * Copyright (C) 2018 - 2021, Stephan Mueller ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "lrng_kcapi_hash.h" ++ ++static char *drng_name = NULL; ++module_param(drng_name, charp, 0444); ++MODULE_PARM_DESC(drng_name, "Kernel crypto API name of DRNG"); ++ ++static char *pool_hash = "sha512"; ++module_param(pool_hash, charp, 0444); ++MODULE_PARM_DESC(pool_hash, ++ "Kernel crypto API name of hash or keyed message digest to read the entropy pool"); ++ ++static char *seed_hash = NULL; ++module_param(seed_hash, charp, 0444); ++MODULE_PARM_DESC(seed_hash, ++ "Kernel crypto API name of hash with output size equal to seedsize of DRNG to bring seed string to the size required by the DRNG"); ++ ++struct lrng_drng_info { ++ struct crypto_rng *kcapi_rng; ++ void *lrng_hash; ++}; ++ ++static void *lrng_kcapi_drng_hash_alloc(void) ++{ ++ return lrng_kcapi_hash_alloc(pool_hash); ++} ++ ++static int lrng_kcapi_drng_seed_helper(void *drng, const u8 *inbuf, ++ u32 inbuflen) ++{ ++ SHASH_DESC_ON_STACK(shash, NULL); ++ struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng; ++ struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng; ++ void *hash = lrng_drng_info->lrng_hash; ++ u32 digestsize = lrng_kcapi_hash_digestsize(hash); ++ u8 digest[64] __aligned(8); ++ int ret; ++ ++ if (!hash) ++ return crypto_rng_reset(kcapi_rng, inbuf, inbuflen); ++ ++ BUG_ON(digestsize > sizeof(digest)); ++ ++ ret = lrng_kcapi_hash_init(shash, hash) ?: ++ lrng_kcapi_hash_update(shash, inbuf, inbuflen) ?: ++ lrng_kcapi_hash_final(shash, digest); ++ lrng_kcapi_hash_zero(shash); ++ if (ret) ++ return ret; ++ ++ ret = crypto_rng_reset(kcapi_rng, digest, digestsize); ++ if (ret) ++ return ret; ++ ++ memzero_explicit(digest, digestsize); ++ return 0; ++} ++ ++static int lrng_kcapi_drng_generate_helper(void *drng, u8 *outbuf, ++ u32 outbuflen) ++{ ++ struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng; ++ struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng; ++ int ret = crypto_rng_get_bytes(kcapi_rng, outbuf, outbuflen); ++ ++ if (ret < 0) ++ return ret; ++ ++ return outbuflen; ++} ++ ++static void *lrng_kcapi_drng_alloc(u32 sec_strength) ++{ ++ struct lrng_drng_info *lrng_drng_info; ++ struct crypto_rng *kcapi_rng; ++ int seedsize; ++ void *ret = ERR_PTR(-ENOMEM); ++ ++ if (!drng_name) { ++ pr_err("DRNG name missing\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ if (!memcmp(drng_name, "drbg", 4) || ++ !memcmp(drng_name, "stdrng", 6) || ++ !memcmp(drng_name, "jitterentropy_rng", 17)) { ++ pr_err("Refusing to load the requested random number generator\n"); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ lrng_drng_info = kmalloc(sizeof(*lrng_drng_info), GFP_KERNEL); ++ if (!lrng_drng_info) ++ return ERR_PTR(-ENOMEM); ++ ++ kcapi_rng = crypto_alloc_rng(drng_name, 0, 0); ++ if (IS_ERR(kcapi_rng)) { ++ pr_err("DRNG %s cannot be allocated\n", drng_name); ++ ret = ERR_CAST(kcapi_rng); ++ goto free; ++ } ++ lrng_drng_info->kcapi_rng = kcapi_rng; ++ ++ seedsize = crypto_rng_seedsize(kcapi_rng); ++ ++ if (sec_strength > seedsize) ++ pr_info("Seedsize DRNG (%u bits) lower than security strength of LRNG noise source (%u bits)\n", ++ crypto_rng_seedsize(kcapi_rng) * 8, sec_strength * 8); ++ ++ if (seedsize) { ++ void *lrng_hash; ++ ++ if (!seed_hash) { ++ switch (seedsize) { ++ case 32: ++ seed_hash = "sha256"; ++ break; ++ case 48: ++ seed_hash = "sha384"; ++ break; ++ case 64: ++ seed_hash = "sha512"; ++ break; ++ default: ++ pr_err("Seed size %d cannot be processed\n", ++ seedsize); ++ goto dealloc; ++ } ++ } ++ ++ lrng_hash = lrng_kcapi_hash_alloc(seed_hash); ++ if (IS_ERR(lrng_hash)) { ++ ret = ERR_CAST(lrng_hash); ++ goto dealloc; ++ } ++ ++ if (seedsize != lrng_kcapi_hash_digestsize(lrng_hash)) { ++ pr_err("Seed hash output size not equal to DRNG seed size\n"); ++ lrng_kcapi_hash_dealloc(lrng_hash); ++ ret = ERR_PTR(-EINVAL); ++ goto dealloc; ++ } ++ ++ lrng_drng_info->lrng_hash = lrng_hash; ++ ++ pr_info("Seed hash %s allocated\n", seed_hash); ++ } else { ++ lrng_drng_info->lrng_hash = NULL; ++ } ++ ++ pr_info("Kernel crypto API DRNG %s allocated\n", drng_name); ++ ++ return lrng_drng_info; ++ ++dealloc: ++ crypto_free_rng(kcapi_rng); ++free: ++ kfree(lrng_drng_info); ++ return ret; ++} ++ ++static void lrng_kcapi_drng_dealloc(void *drng) ++{ ++ struct lrng_drng_info *lrng_drng_info = (struct lrng_drng_info *)drng; ++ struct crypto_rng *kcapi_rng = lrng_drng_info->kcapi_rng; ++ ++ crypto_free_rng(kcapi_rng); ++ if (lrng_drng_info->lrng_hash) ++ lrng_kcapi_hash_dealloc(lrng_drng_info->lrng_hash); ++ kfree(lrng_drng_info); ++ pr_info("DRNG %s deallocated\n", drng_name); ++} ++ ++static const char *lrng_kcapi_drng_name(void) ++{ ++ return drng_name; ++} ++ ++static const char *lrng_kcapi_pool_hash(void) ++{ ++ return pool_hash; ++} ++ ++static const struct lrng_crypto_cb lrng_kcapi_crypto_cb = { ++ .lrng_drng_name = lrng_kcapi_drng_name, ++ .lrng_hash_name = lrng_kcapi_pool_hash, ++ .lrng_drng_alloc = lrng_kcapi_drng_alloc, ++ .lrng_drng_dealloc = lrng_kcapi_drng_dealloc, ++ .lrng_drng_seed_helper = lrng_kcapi_drng_seed_helper, ++ .lrng_drng_generate_helper = lrng_kcapi_drng_generate_helper, ++ .lrng_hash_alloc = lrng_kcapi_drng_hash_alloc, ++ .lrng_hash_dealloc = lrng_kcapi_hash_dealloc, ++ .lrng_hash_digestsize = lrng_kcapi_hash_digestsize, ++ .lrng_hash_init = lrng_kcapi_hash_init, ++ .lrng_hash_update = lrng_kcapi_hash_update, ++ .lrng_hash_final = lrng_kcapi_hash_final, ++ .lrng_hash_desc_zero = lrng_kcapi_hash_zero, ++}; ++ ++static int __init lrng_kcapi_init(void) ++{ ++ return lrng_set_drng_cb(&lrng_kcapi_crypto_cb); ++} ++static void __exit lrng_kcapi_exit(void) ++{ ++ lrng_set_drng_cb(NULL); ++} ++ ++late_initcall(lrng_kcapi_init); ++module_exit(lrng_kcapi_exit); ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_AUTHOR("Stephan Mueller "); ++MODULE_DESCRIPTION("Linux Random Number Generator - kernel crypto API DRNG backend"); diff --git a/PATCH/LRNG/696-12-v41-0009-crypto-provide-access-to-a-static-Jitter-RNG-sta.patch b/PATCH/LRNG/696-12-v41-0009-crypto-provide-access-to-a-static-Jitter-RNG-sta.patch new file mode 100644 index 000000000..6d98d1c94 --- /dev/null +++ b/PATCH/LRNG/696-12-v41-0009-crypto-provide-access-to-a-static-Jitter-RNG-sta.patch @@ -0,0 +1,148 @@ +From 927d21648cb471466dc4ee32e1de9964b74d8b95 Mon Sep 17 00:00:00 2001 +From: Stephan Mueller +Date: Wed, 16 Sep 2020 09:50:27 +0200 +Subject: [PATCH v41 09/13] crypto: provide access to a static Jitter RNG state +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +To support the LRNG operation which uses the Jitter RNG separately +from the kernel crypto API, at a time where potentially the regular +memory management is not yet initialized, the Jitter RNG needs to +provide a state whose memory is defined at compile time. As only once +instance will ever be needed by the LRNG, define once static memory +block which is solely to be used by the LRNG. + +CC: Torsten Duwe +CC: "Eric W. Biederman" +CC: "Alexander E. Patrakov" +CC: "Ahmed S. Darwish" +CC: "Theodore Y. Ts'o" +CC: Willy Tarreau +CC: Matthew Garrett +CC: Vito Caputo +CC: Andreas Dilger +CC: Jan Kara +CC: Ray Strode +CC: William Jon McCann +CC: zhangjs +CC: Andy Lutomirski +CC: Florian Weimer +CC: Lennart Poettering +CC: Nicolai Stange +CC: Alexander Lobakin +Reviewed-by: Roman Drahtmueller +Tested-by: Roman Drahtmüller +Tested-by: Marcelo Henrique Cerri +Tested-by: Neil Horman +Signed-off-by: Stephan Mueller +--- + crypto/jitterentropy-kcapi.c | 3 +- + crypto/jitterentropy.c | 31 ++++++++++++++++++- + .../crypto/internal}/jitterentropy.h | 3 ++ + 3 files changed, 34 insertions(+), 3 deletions(-) + rename {crypto => include/crypto/internal}/jitterentropy.h (84%) + +--- a/crypto/jitterentropy-kcapi.c ++++ b/crypto/jitterentropy-kcapi.c +@@ -43,8 +43,7 @@ + #include + #include + #include +- +-#include "jitterentropy.h" ++#include + + /*************************************************************************** + * Helper function +--- a/crypto/jitterentropy.c ++++ b/crypto/jitterentropy.c +@@ -103,7 +103,7 @@ struct rand_data { + * Helper functions + ***************************************************************************/ + +-#include "jitterentropy.h" ++#include + + /** + * Update of the loop count used for the next round of +@@ -639,3 +639,32 @@ int jent_entropy_init(void) + + return 0; + } ++ ++struct rand_data *jent_lrng_entropy_collector(void) ++{ ++ static unsigned char lrng_jent_mem[JENT_MEMORY_SIZE]; ++ static struct rand_data lrng_jent_state = { ++ .data = 0, ++ .old_data = 0, ++ .prev_time = 0, ++ .last_delta = 0, ++ .last_delta2 = 0, ++ .osr = 1, ++ .mem = lrng_jent_mem, ++ .memlocation = 0, ++ .memblocks = JENT_MEMORY_BLOCKSIZE, ++ .memblocksize = JENT_MEMORY_BLOCKS, ++ .memaccessloops = JENT_MEMORY_ACCESSLOOPS, ++ .rct_count = 0, ++ .apt_observations = 0, ++ .apt_count = 0, ++ .apt_base = 0, ++ .apt_base_set = 0, ++ .health_failure = 0 ++ }; ++ ++ if (jent_entropy_init()) ++ return NULL; ++ ++ return &lrng_jent_state; ++} +--- a/crypto/jitterentropy.h ++++ /dev/null +@@ -1,19 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-or-later +- +-typedef unsigned long long __u64; +- +-extern void *jent_zalloc(unsigned int len); +-extern void jent_zfree(void *ptr); +-extern int jent_fips_enabled(void); +-extern void jent_panic(char *s); +-extern void jent_memcpy(void *dest, const void *src, unsigned int n); +-extern void jent_get_nstime(__u64 *out); +- +-struct rand_data; +-extern int jent_entropy_init(void); +-extern int jent_read_entropy(struct rand_data *ec, unsigned char *data, +- unsigned int len); +- +-extern struct rand_data *jent_entropy_collector_alloc(unsigned int osr, +- unsigned int flags); +-extern void jent_entropy_collector_free(struct rand_data *entropy_collector); +--- /dev/null ++++ b/include/crypto/internal/jitterentropy.h +@@ -0,0 +1,22 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++ ++typedef unsigned long long __u64; ++ ++extern void *jent_zalloc(unsigned int len); ++extern void jent_zfree(void *ptr); ++extern int jent_fips_enabled(void); ++extern void jent_panic(char *s); ++extern void jent_memcpy(void *dest, const void *src, unsigned int n); ++extern void jent_get_nstime(__u64 *out); ++ ++struct rand_data; ++extern int jent_entropy_init(void); ++extern int jent_read_entropy(struct rand_data *ec, unsigned char *data, ++ unsigned int len); ++ ++extern struct rand_data *jent_entropy_collector_alloc(unsigned int osr, ++ unsigned int flags); ++extern void jent_entropy_collector_free(struct rand_data *entropy_collector); ++ ++/* Access to statically allocated Jitter RNG instance */ ++extern struct rand_data *jent_lrng_entropy_collector(void); diff --git a/PATCH/LRNG/696-13-v41-0010-LRNG-add-Jitter-RNG-fast-noise-source.patch b/PATCH/LRNG/696-13-v41-0010-LRNG-add-Jitter-RNG-fast-noise-source.patch new file mode 100644 index 000000000..f64d5f717 --- /dev/null +++ b/PATCH/LRNG/696-13-v41-0010-LRNG-add-Jitter-RNG-fast-noise-source.patch @@ -0,0 +1,174 @@ +From 44305098f785b82a20285ad47668bacd2a2ee4a8 Mon Sep 17 00:00:00 2001 +From: Stephan Mueller +Date: Fri, 18 Jun 2021 08:13:57 +0200 +Subject: [PATCH v41 10/13] LRNG - add Jitter RNG fast noise source + +The Jitter RNG fast noise source implemented as part of the kernel +crypto API is queried for 256 bits of entropy at the time the seed +buffer managed by the LRNG is about to be filled. + +CC: Torsten Duwe +CC: "Eric W. Biederman" +CC: "Alexander E. Patrakov" +CC: "Ahmed S. Darwish" +CC: "Theodore Y. Ts'o" +CC: Willy Tarreau +CC: Matthew Garrett +CC: Vito Caputo +CC: Andreas Dilger +CC: Jan Kara +CC: Ray Strode +CC: William Jon McCann +CC: zhangjs +CC: Andy Lutomirski +CC: Florian Weimer +CC: Lennart Poettering +CC: Nicolai Stange +CC: Alexander Lobakin +Reviewed-by: Marcelo Henrique Cerri +Tested-by: Marcelo Henrique Cerri +Tested-by: Neil Horman +Signed-off-by: Stephan Mueller +--- + drivers/char/lrng/Kconfig | 27 +++++++++++ + drivers/char/lrng/Makefile | 1 + + drivers/char/lrng/lrng_jent.c | 90 +++++++++++++++++++++++++++++++++++ + 3 files changed, 118 insertions(+) + create mode 100644 drivers/char/lrng/lrng_jent.c + +--- a/drivers/char/lrng/Kconfig ++++ b/drivers/char/lrng/Kconfig +@@ -182,6 +182,33 @@ config LRNG_IRQ_ENTROPY_RATE + interrupt entropy source will still deliver data but without + being credited with entropy. + ++comment "Jitter RNG Entropy Source" ++ ++config LRNG_JENT ++ bool "Enable Jitter RNG as LRNG Seed Source" ++ depends on CRYPTO ++ select CRYPTO_JITTERENTROPY ++ help ++ The Linux RNG may use the Jitter RNG as noise source. Enabling ++ this option enables the use of the Jitter RNG. Its default ++ entropy level is 16 bits of entropy per 256 data bits delivered ++ by the Jitter RNG. This entropy level can be changed at boot ++ time or at runtime with the lrng_base.jitterrng configuration ++ variable. ++ ++config LRNG_JENT_ENTROPY_RATE ++ int "Jitter RNG Entropy Source Entropy Rate" ++ range 0 256 ++ default 16 ++ help ++ The option defines the amount of entropy the LRNG applies to 256 ++ bits of data obtained from the Jitter RNG entropy source. The ++ LRNG enforces the limit that this value must be in the range ++ between 0 and 256. ++ ++ In order to disable the Jitter RNG entropy source, the option ++ has to be set to 0. ++ + comment "CPU Entropy Source" + + config LRNG_CPU_ENTROPY_RATE +--- a/drivers/char/lrng/Makefile ++++ b/drivers/char/lrng/Makefile +@@ -14,3 +14,4 @@ obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_s + obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.o + obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o + obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o ++obj-$(CONFIG_LRNG_JENT) += lrng_jent.o +--- /dev/null ++++ b/drivers/char/lrng/lrng_jent.c +@@ -0,0 +1,90 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause ++/* ++ * LRNG Fast Entropy Source: Jitter RNG ++ * ++ * Copyright (C) 2016 - 2021, Stephan Mueller ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++ ++#include "lrng_internal.h" ++ ++/* ++ * Estimated entropy of data is a 16th of LRNG_DRNG_SECURITY_STRENGTH_BITS. ++ * Albeit a full entropy assessment is provided for the noise source indicating ++ * that it provides high entropy rates and considering that it deactivates ++ * when it detects insufficient hardware, the chosen under estimation of ++ * entropy is considered to be acceptable to all reviewers. ++ */ ++static u32 jitterrng = CONFIG_LRNG_JENT_ENTROPY_RATE; ++#ifdef CONFIG_LRNG_RUNTIME_ES_CONFIG ++module_param(jitterrng, uint, 0644); ++MODULE_PARM_DESC(jitterrng, "Entropy in bits of 256 data bits from Jitter RNG noise source"); ++#endif ++ ++static bool lrng_jent_initialized = false; ++static struct rand_data *lrng_jent_state; ++ ++static int __init lrng_jent_initialize(void) ++{ ++ /* Initialize the Jitter RNG after the clocksources are initialized. */ ++ lrng_jent_state = jent_lrng_entropy_collector(); ++ if (!lrng_jent_state) { ++ jitterrng = 0; ++ pr_info("Jitter RNG unusable on current system\n"); ++ return 0; ++ } ++ lrng_jent_initialized = true; ++ lrng_pool_add_entropy(); ++ pr_debug("Jitter RNG working on current system\n"); ++ ++ return 0; ++} ++device_initcall(lrng_jent_initialize); ++ ++/** ++ * lrng_get_jent() - Get Jitter RNG entropy ++ * ++ * @outbuf: buffer to store entropy ++ * @outbuflen: length of buffer ++ * ++ * Return: ++ * * > 0 on success where value provides the added entropy in bits ++ * * 0 if no fast source was available ++ */ ++u32 lrng_get_jent(u8 *outbuf, u32 requested_bits) ++{ ++ int ret; ++ u32 ent_bits = lrng_jent_entropylevel(requested_bits); ++ unsigned long flags; ++ static DEFINE_SPINLOCK(lrng_jent_lock); ++ ++ spin_lock_irqsave(&lrng_jent_lock, flags); ++ ++ if (!ent_bits || !lrng_jent_initialized) { ++ spin_unlock_irqrestore(&lrng_jent_lock, flags); ++ return 0; ++ } ++ ++ ret = jent_read_entropy(lrng_jent_state, outbuf, requested_bits >> 3); ++ spin_unlock_irqrestore(&lrng_jent_lock, flags); ++ ++ if (ret) { ++ pr_debug("Jitter RNG failed with %d\n", ret); ++ return 0; ++ } ++ ++ pr_debug("obtained %u bits of entropy from Jitter RNG noise source\n", ++ ent_bits); ++ ++ return ent_bits; ++} ++ ++u32 lrng_jent_entropylevel(u32 requested_bits) ++{ ++ return lrng_fast_noise_entropylevel((lrng_jent_initialized) ? ++ jitterrng : 0, requested_bits); ++} diff --git a/PATCH/LRNG/696-14-v41-0011-LRNG-add-SP800-90B-compliant-health-tests.patch b/PATCH/LRNG/696-14-v41-0011-LRNG-add-SP800-90B-compliant-health-tests.patch new file mode 100644 index 000000000..951cc6d1b --- /dev/null +++ b/PATCH/LRNG/696-14-v41-0011-LRNG-add-SP800-90B-compliant-health-tests.patch @@ -0,0 +1,623 @@ +From 928e83bd2eb312c68d2e1bbaadd96a5e841eadff Mon Sep 17 00:00:00 2001 +From: Stephan Mueller +Date: Fri, 18 Jun 2021 08:17:40 +0200 +Subject: [PATCH v41 11/13] LRNG - add SP800-90B compliant health tests +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Implement health tests for LRNG's slow noise sources as mandated by +SP-800-90B The file contains the following health tests: + +- stuck test: The stuck test calculates the first, second and third + discrete derivative of the time stamp to be processed by the hash + for the per-CPU entropy pool. Only if all three values are non-zero, + the received time delta is considered to be non-stuck. + +- SP800-90B Repetition Count Test (RCT): The LRNG uses an enhanced + version of the RCT specified in SP800-90B section 4.4.1. Instead of + counting identical back-to-back values, the input to the RCT is the + counting of the stuck values during the processing of received + interrupt events. The RCT is applied with alpha=2^-30 compliant to + the recommendation of FIPS 140-2 IG 9.8. During the counting operation, + the LRNG always calculates the RCT cut-off value of C. If that value + exceeds the allowed cut-off value, the LRNG will trigger the health + test failure discussed below. An error is logged to the kernel log + that such RCT failure occurred. This test is only applied and + enforced in FIPS mode, i.e. when the kernel compiled with + CONFIG_CONFIG_FIPS is started with fips=1. + +- SP800-90B Adaptive Proportion Test (APT): The LRNG implements the + APT as defined in SP800-90B section 4.4.2. The applied significance + level again is alpha=2^-30 compliant to the recommendation of FIPS + 140-2 IG 9.8. + +The aforementioned health tests are applied to the first 1,024 time stamps +obtained from interrupt events. In case one error is identified for either +the RCT, or the APT, the collected entropy is invalidated and the +SP800-90B startup health test is restarted. + +As long as the SP800-90B startup health test is not completed, all LRNG +random number output interfaces that may block will block and not generate +any data. This implies that only those potentially blocking interfaces are +defined to provide random numbers that are seeded with the interrupt noise +source being SP800-90B compliant. All other output interfaces will not be +affected by the SP800-90B startup test and thus are not considered +SP800-90B compliant. + +At runtime, the SP800-90B APT and RCT are applied to each time stamp +generated for a received interrupt. When either the APT and RCT indicates +a noise source failure, the LRNG is reset to a state it has immediately +after boot: + +- all entropy counters are set to zero + +- the SP800-90B startup tests are re-performed which implies that +getrandom(2) would block again until new entropy was collected + +To summarize, the following rules apply: + +• SP800-90B compliant output interfaces + + - /dev/random + + - getrandom(2) system call + + - get_random_bytes kernel-internal interface when being triggered by + the callback registered with add_random_ready_callback + +• SP800-90B non-compliant output interfaces + + - /dev/urandom + + - get_random_bytes kernel-internal interface called directly + + - randomize_page kernel-internal interface + + - get_random_u32 and get_random_u64 kernel-internal interfaces + + - get_random_u32_wait, get_random_u64_wait, get_random_int_wait, and + get_random_long_wait kernel-internal interfaces + +If either the RCT, or the APT health test fails irrespective whether +during initialization or runtime, the following actions occur: + + 1. The entropy of the entire entropy pool is invalidated. + + 2. All DRNGs are reset which imply that they are treated as being + not seeded and require a reseed during next invocation. + + 3. The SP800-90B startup health test are initiated with all + implications of the startup tests. That implies that from that point + on, new events must be observed and its entropy must be inserted into + the entropy pool before random numbers are calculated from the + entropy pool. + +Further details on the SP800-90B compliance and the availability of all +test tools required to perform all tests mandated by SP800-90B are +provided at [1]. + +The entire health testing code is compile-time configurable. + +The patch provides a CONFIG_BROKEN configuration of the APT / RCT cutoff +values which have a high likelihood to trigger the health test failure. +The BROKEN APT cutoff is set to the exact mean of the expected value if +the time stamps are equally distributed (512 time stamps divided by 16 +possible values due to using the 4 LSB of the time stamp). The BROKEN +RCT cutoff value is set to 1 which is likely to be triggered during +regular operation. + +CC: Torsten Duwe +CC: "Eric W. Biederman" +CC: "Alexander E. Patrakov" +CC: "Ahmed S. Darwish" +CC: "Theodore Y. Ts'o" +CC: Willy Tarreau +CC: Matthew Garrett +CC: Vito Caputo +CC: Andreas Dilger +CC: Jan Kara +CC: Ray Strode +CC: William Jon McCann +CC: zhangjs +CC: Andy Lutomirski +CC: Florian Weimer +CC: Lennart Poettering +CC: Nicolai Stange +CC: Alexander Lobakin +Reviewed-by: Roman Drahtmueller +Tested-by: Marcelo Henrique Cerri +Tested-by: Neil Horman +Signed-off-by: Stephan Mueller +--- + drivers/char/lrng/Kconfig | 56 +++++ + drivers/char/lrng/Makefile | 1 + + drivers/char/lrng/lrng_health.c | 410 ++++++++++++++++++++++++++++++++ + 3 files changed, 467 insertions(+) + create mode 100644 drivers/char/lrng/lrng_health.c + +--- a/drivers/char/lrng/Kconfig ++++ b/drivers/char/lrng/Kconfig +@@ -164,6 +164,62 @@ config LRNG_COLLECTION_SIZE + default 4096 if LRNG_COLLECTION_SIZE_4096 + default 8192 if LRNG_COLLECTION_SIZE_8192 + ++config LRNG_HEALTH_TESTS ++ bool "Enable noise source online health tests" ++ help ++ The online health tests validate the noise source at ++ runtime for fatal errors. These tests include SP800-90B ++ compliant tests which are invoked if the system is booted ++ with fips=1. In case of fatal errors during active ++ SP800-90B tests, the issue is logged and the noise ++ data is discarded. These tests are required for full ++ compliance with SP800-90B. ++ ++ If unsure, say Y. ++ ++config LRNG_RCT_BROKEN ++ bool "SP800-90B RCT with dangerous low cutoff value" ++ depends on LRNG_HEALTH_TESTS ++ depends on BROKEN ++ default n ++ help ++ This option enables a dangerously low SP800-90B repetitive ++ count test (RCT) cutoff value which makes it very likely ++ that the RCT is triggered to raise a self test failure. ++ ++ This option is ONLY intended for developers wanting to ++ test the effectiveness of the SP800-90B RCT health test. ++ ++ If unsure, say N. ++ ++config LRNG_APT_BROKEN ++ bool "SP800-90B APT with dangerous low cutoff value" ++ depends on LRNG_HEALTH_TESTS ++ depends on BROKEN ++ default n ++ help ++ This option enables a dangerously low SP800-90B adaptive ++ proportion test (APT) cutoff value which makes it very ++ likely that the APT is triggered to raise a self test ++ failure. ++ ++ This option is ONLY intended for developers wanting to ++ test the effectiveness of the SP800-90B APT health test. ++ ++ If unsure, say N. ++ ++# Default taken from SP800-90B sec 4.4.1 - significance level 2^-30 ++config LRNG_RCT_CUTOFF ++ int ++ default 31 if !LRNG_RCT_BROKEN ++ default 1 if LRNG_RCT_BROKEN ++ ++# Default taken from SP800-90B sec 4.4.2 - significance level 2^-30 ++config LRNG_APT_CUTOFF ++ int ++ default 325 if !LRNG_APT_BROKEN ++ default 32 if LRNG_APT_BROKEN ++ + config LRNG_IRQ_ENTROPY_RATE + int "Interrupt Entropy Source Entropy Rate" + range 256 4294967295 +--- a/drivers/char/lrng/Makefile ++++ b/drivers/char/lrng/Makefile +@@ -15,3 +15,4 @@ obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kc + obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o + obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o + obj-$(CONFIG_LRNG_JENT) += lrng_jent.o ++obj-$(CONFIG_LRNG_HEALTH_TESTS) += lrng_health.o +--- /dev/null ++++ b/drivers/char/lrng/lrng_health.c +@@ -0,0 +1,410 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause ++/* ++ * Linux Random Number Generator (LRNG) Health Testing ++ * ++ * Copyright (C) 2019 - 2021, Stephan Mueller ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++ ++#include "lrng_internal.h" ++ ++/* Stuck Test */ ++struct lrng_stuck_test { ++ u32 last_time; /* Stuck test: time of previous IRQ */ ++ u32 last_delta; /* Stuck test: delta of previous IRQ */ ++ u32 last_delta2; /* Stuck test: 2. time derivation of prev IRQ */ ++}; ++ ++/* Repetition Count Test */ ++struct lrng_rct { ++ atomic_t rct_count; /* Number of stuck values */ ++}; ++ ++/* Adaptive Proportion Test */ ++struct lrng_apt { ++ /* Data window size */ ++#define LRNG_APT_WINDOW_SIZE 512 ++ /* LSB of time stamp to process */ ++#define LRNG_APT_LSB 16 ++#define LRNG_APT_WORD_MASK (LRNG_APT_LSB - 1) ++ atomic_t apt_count; /* APT counter */ ++ atomic_t apt_base; /* APT base reference */ ++ ++ atomic_t apt_trigger; ++ bool apt_base_set; /* Is APT base set? */ ++}; ++ ++/* The health test code must operate lock-less */ ++struct lrng_health { ++ struct lrng_rct rct; ++ struct lrng_apt apt; ++ ++ bool health_test_enabled; ++ ++ /* SP800-90B startup health tests */ ++#define LRNG_SP80090B_STARTUP_SAMPLES 1024 ++#define LRNG_SP80090B_STARTUP_BLOCKS ((LRNG_SP80090B_STARTUP_SAMPLES + \ ++ LRNG_APT_WINDOW_SIZE - 1) / \ ++ LRNG_APT_WINDOW_SIZE) ++ bool sp80090b_startup_done; ++ atomic_t sp80090b_startup_blocks; ++}; ++ ++static struct lrng_health lrng_health = { ++ .rct.rct_count = ATOMIC_INIT(0), ++ ++ .apt.apt_count = ATOMIC_INIT(0), ++ .apt.apt_base = ATOMIC_INIT(-1), ++ .apt.apt_trigger = ATOMIC_INIT(LRNG_APT_WINDOW_SIZE), ++ .apt.apt_base_set = false, ++ ++ .health_test_enabled = true, ++ ++ .sp80090b_startup_blocks = ATOMIC_INIT(LRNG_SP80090B_STARTUP_BLOCKS), ++ .sp80090b_startup_done = false, ++}; ++ ++static DEFINE_PER_CPU(struct lrng_stuck_test, lrng_stuck_test); ++ ++static inline bool lrng_sp80090b_health_requested(void) ++{ ++ /* Health tests are only requested in FIPS mode */ ++ return fips_enabled; ++} ++ ++static inline bool lrng_sp80090b_health_enabled(void) ++{ ++ struct lrng_health *health = &lrng_health; ++ ++ return lrng_sp80090b_health_requested() && health->health_test_enabled; ++} ++ ++/*************************************************************************** ++ * SP800-90B Compliance ++ * ++ * If the Linux-RNG is booted into FIPS mode, the following interfaces ++ * provide an SP800-90B compliant noise source: ++ * ++ * * /dev/random ++ * * getrandom(2) ++ * * get_random_bytes when using it in conjunction with ++ * add_random_ready_callback ++ * ++ * All other interfaces, including /dev/urandom or get_random_bytes without ++ * the add_random_ready_callback cannot claim to use an SP800-90B compliant ++ * noise source. ++ ***************************************************************************/ ++ ++/* ++ * Perform SP800-90B startup testing ++ */ ++static inline void lrng_sp80090b_startup(struct lrng_health *health) ++{ ++ if (!health->sp80090b_startup_done && ++ atomic_dec_and_test(&health->sp80090b_startup_blocks)) { ++ struct entropy_buf eb; ++ ++ health->sp80090b_startup_done = true; ++ pr_info("SP800-90B startup health tests completed\n"); ++ memset(&eb, 0, sizeof(eb)); ++ lrng_init_ops(&eb); ++ ++ /* ++ * Force a reseed of DRNGs to ensure they are seeded with ++ * entropy that passed the SP800-90B health tests. ++ * As the DRNG always will reseed before generating ++ * random numbers, it does not need a reseed trigger. ++ */ ++ lrng_drng_force_reseed(); ++ } ++} ++ ++/* ++ * Handle failure of SP800-90B startup testing ++ */ ++static inline void lrng_sp80090b_startup_failure(struct lrng_health *health) ++{ ++ /* Reset of LRNG and its entropy - NOTE: we are in atomic context */ ++ lrng_reset(); ++ ++ /* ++ * Reset the SP800-90B startup test. ++ * ++ * NOTE SP800-90B section 4.3 bullet 4 does not specify what ++ * exactly is to be done in case of failure! Thus, we do what ++ * makes sense, i.e. restarting the health test and thus gating ++ * the output function of /dev/random and getrandom(2). ++ */ ++ atomic_set(&health->sp80090b_startup_blocks, ++ LRNG_SP80090B_STARTUP_BLOCKS); ++} ++ ++/* ++ * Handle failure of SP800-90B runtime testing ++ */ ++static inline void lrng_sp80090b_runtime_failure(struct lrng_health *health) ++{ ++ lrng_sp80090b_startup_failure(health); ++ health->sp80090b_startup_done = false; ++} ++ ++static inline void lrng_sp80090b_failure(struct lrng_health *health) ++{ ++ if (health->sp80090b_startup_done) { ++ pr_err("SP800-90B runtime health test failure - invalidating all existing entropy and initiate SP800-90B startup\n"); ++ lrng_sp80090b_runtime_failure(health); ++ } else { ++ pr_err("SP800-90B startup test failure - resetting\n"); ++ lrng_sp80090b_startup_failure(health); ++ } ++} ++ ++/* ++ * Is the SP800-90B startup testing complete? ++ * ++ * This function is called by the LRNG to determine whether to unblock ++ * a certain user interface. Therefore, only the potentially blocking ++ * user interfaces are considered SP800-90B compliant. ++ */ ++bool lrng_sp80090b_startup_complete(void) ++{ ++ struct lrng_health *health = &lrng_health; ++ ++ return (lrng_sp80090b_health_enabled()) ? health->sp80090b_startup_done: ++ true; ++} ++ ++bool lrng_sp80090b_compliant(void) ++{ ++ struct lrng_health *health = &lrng_health; ++ ++ return lrng_sp80090b_health_enabled() && health->sp80090b_startup_done; ++} ++ ++/*************************************************************************** ++ * Adaptive Proportion Test ++ * ++ * This test complies with SP800-90B section 4.4.2. ++ ***************************************************************************/ ++ ++/* ++ * Reset the APT counter ++ * ++ * @health [in] Reference to health state ++ */ ++static inline void lrng_apt_reset(struct lrng_health *health, ++ unsigned int time_masked) ++{ ++ struct lrng_apt *apt = &health->apt; ++ ++ pr_debug("APT value %d for base %d\n", ++ atomic_read(&apt->apt_count), atomic_read(&apt->apt_base)); ++ ++ /* Reset APT */ ++ atomic_set(&apt->apt_count, 0); ++ atomic_set(&apt->apt_base, time_masked); ++} ++ ++static inline void lrng_apt_restart(struct lrng_health *health) ++{ ++ struct lrng_apt *apt = &health->apt; ++ ++ atomic_set(&apt->apt_trigger, LRNG_APT_WINDOW_SIZE); ++} ++ ++/* ++ * Insert a new entropy event into APT ++ * ++ * This function does is void as it does not decide about the fate of a time ++ * stamp. An APT failure can only happen at the same time of a stuck test ++ * failure. Thus, the stuck failure will already decide how the time stamp ++ * is handled. ++ * ++ * @health [in] Reference to health state ++ * @now_time [in] Time stamp to process ++ */ ++static inline void lrng_apt_insert(struct lrng_health *health, ++ unsigned int now_time) ++{ ++ struct lrng_apt *apt = &health->apt; ++ ++ if (!lrng_sp80090b_health_requested()) ++ return; ++ ++ now_time &= LRNG_APT_WORD_MASK; ++ ++ /* Initialization of APT */ ++ if (!apt->apt_base_set) { ++ atomic_set(&apt->apt_base, now_time); ++ apt->apt_base_set = true; ++ return; ++ } ++ ++ if (now_time == (unsigned int)atomic_read(&apt->apt_base)) { ++ u32 apt_val = (u32)atomic_inc_return_relaxed(&apt->apt_count); ++ ++ if (apt_val >= CONFIG_LRNG_APT_CUTOFF) ++ lrng_sp80090b_failure(health); ++ } ++ ++ if (atomic_dec_and_test(&apt->apt_trigger)) { ++ lrng_apt_restart(health); ++ lrng_apt_reset(health, now_time); ++ lrng_sp80090b_startup(health); ++ } ++} ++ ++/*************************************************************************** ++ * Repetition Count Test ++ * ++ * The LRNG uses an enhanced version of the Repetition Count Test ++ * (RCT) specified in SP800-90B section 4.4.1. Instead of counting identical ++ * back-to-back values, the input to the RCT is the counting of the stuck ++ * values while filling the entropy pool. ++ * ++ * The RCT is applied with an alpha of 2^-30 compliant to FIPS 140-2 IG 9.8. ++ * ++ * During the counting operation, the LRNG always calculates the RCT ++ * cut-off value of C. If that value exceeds the allowed cut-off value, ++ * the LRNG will invalidate all entropy for the entropy pool which implies ++ * that no data can be extracted from the entropy pool unless new entropy ++ * is received. ++ ***************************************************************************/ ++ ++/* ++ * Hot code path - Insert data for Repetition Count Test ++ * ++ * @health: Reference to health information ++ * @stuck: Decision of stuck test ++ */ ++static inline void lrng_rct(struct lrng_health *health, int stuck) ++{ ++ struct lrng_rct *rct = &health->rct; ++ ++ if (!lrng_sp80090b_health_requested()) ++ return; ++ ++ if (stuck) { ++ u32 rct_count = atomic_add_return_relaxed(1, &rct->rct_count); ++ ++ pr_debug("RCT count: %u\n", rct_count); ++ ++ /* ++ * The cutoff value is based on the following consideration: ++ * alpha = 2^-30 as recommended in FIPS 140-2 IG 9.8. ++ * In addition, we imply an entropy value H of 1 bit as this ++ * is the minimum entropy required to provide full entropy. ++ * ++ * Note, rct_count (which equals to value B in the ++ * pseudo code of SP800-90B section 4.4.1) starts with zero. ++ * Hence we need to subtract one from the cutoff value as ++ * calculated following SP800-90B. ++ */ ++ if (rct_count >= CONFIG_LRNG_RCT_CUTOFF) { ++ atomic_set(&rct->rct_count, 0); ++ ++ /* ++ * APT must start anew as we consider all previously ++ * recorded data to contain no entropy. ++ */ ++ lrng_apt_restart(health); ++ ++ lrng_sp80090b_failure(health); ++ } ++ } else { ++ atomic_set(&rct->rct_count, 0); ++ } ++} ++ ++/*************************************************************************** ++ * Stuck Test ++ * ++ * Checking the: ++ * 1st derivative of the event occurrence (time delta) ++ * 2nd derivative of the event occurrence (delta of time deltas) ++ * 3rd derivative of the event occurrence (delta of delta of time deltas) ++ * ++ * All values must always be non-zero. The stuck test is only valid disabled if ++ * high-resolution time stamps are identified after initialization. ++ ***************************************************************************/ ++ ++static inline u32 lrng_delta(u32 prev, u32 next) ++{ ++ /* ++ * Note that this (unsigned) subtraction does yield the correct value ++ * in the wraparound-case, i.e. when next < prev. ++ */ ++ return (next - prev); ++} ++ ++/* ++ * Hot code path ++ * ++ * @health: Reference to health information ++ * @now: Event time ++ * @return: 0 event occurrence not stuck (good time stamp) ++ * != 0 event occurrence stuck (reject time stamp) ++ */ ++static inline int lrng_irq_stuck(struct lrng_stuck_test *stuck, u32 now_time) ++{ ++ u32 delta = lrng_delta(stuck->last_time, now_time); ++ u32 delta2 = lrng_delta(stuck->last_delta, delta); ++ u32 delta3 = lrng_delta(stuck->last_delta2, delta2); ++ ++ stuck->last_time = now_time; ++ stuck->last_delta = delta; ++ stuck->last_delta2 = delta2; ++ ++ if (!delta || !delta2 || !delta3) ++ return 1; ++ ++ return 0; ++} ++ ++/*************************************************************************** ++ * Health test interfaces ++ ***************************************************************************/ ++ ++/* ++ * Disable all health tests ++ */ ++void lrng_health_disable(void) ++{ ++ struct lrng_health *health = &lrng_health; ++ ++ health->health_test_enabled = false; ++ ++ if (lrng_sp80090b_health_requested()) ++ pr_warn("SP800-90B compliance requested but the Linux RNG is NOT SP800-90B compliant\n"); ++} ++ ++/* ++ * Hot code path - Perform health test on time stamp received from an event ++ * ++ * @now_time Time stamp ++ */ ++enum lrng_health_res lrng_health_test(u32 now_time) ++{ ++ struct lrng_health *health = &lrng_health; ++ struct lrng_stuck_test *stuck_test = this_cpu_ptr(&lrng_stuck_test); ++ int stuck; ++ ++ if (!health->health_test_enabled) ++ return lrng_health_pass; ++ ++ lrng_apt_insert(health, now_time); ++ ++ stuck = lrng_irq_stuck(stuck_test, now_time); ++ lrng_rct(health, stuck); ++ if (stuck) { ++ /* SP800-90B disallows using a failing health test time stamp */ ++ return lrng_sp80090b_health_requested() ? ++ lrng_health_fail_drop : lrng_health_fail_use; ++ } ++ ++ return lrng_health_pass; ++} diff --git a/PATCH/LRNG/696-15-v41-0012-LRNG-add-interface-for-gathering-of-raw-entropy.patch b/PATCH/LRNG/696-15-v41-0012-LRNG-add-interface-for-gathering-of-raw-entropy.patch new file mode 100644 index 000000000..f4bf5c423 --- /dev/null +++ b/PATCH/LRNG/696-15-v41-0012-LRNG-add-interface-for-gathering-of-raw-entropy.patch @@ -0,0 +1,956 @@ +From 95f1ae07c94a30f083eb24c57bf15b3f0fff12c2 Mon Sep 17 00:00:00 2001 +From: Stephan Mueller +Date: Fri, 18 Jun 2021 08:23:31 +0200 +Subject: [PATCH v41 12/13] LRNG - add interface for gathering of raw entropy + +The test interface allows a privileged process to capture the raw +unconditioned noise that is collected by the LRNG for statistical +analysis. Such testing allows the analysis how much entropy +the interrupt noise source provides on a given platform. +Extracted noise data is not used to seed the LRNG. This +is a test interface and not appropriate for production systems. +Yet, the interface is considered to be sufficiently secured for +production systems. + +Access to the data is given through the lrng_raw debugfs file. The +data buffer should be multiples of sizeof(u32) to fill the entire +buffer. Using the option lrng_testing.boot_test=1 the raw noise of +the first 1000 entropy events since boot can be sampled. + +This test interface allows generating the data required for +analysis whether the LRNG is in compliance with SP800-90B +sections 3.1.3 and 3.1.4. + +In addition, the test interface allows gathering of the concatenated raw +entropy data to verify that the concatenation works appropriately. +This includes sampling of the following raw data: + +* high-resolution time stamp + +* Jiffies + +* IRQ number + +* IRQ flags + +* return instruction pointer + +* interrupt register state + +* array logic batching the high-resolution time stamp + +* enabling the runtime configuration of entropy source entropy rates + +Also, a testing interface to support ACVT of the hash implementation +is provided. The reason why only hash testing is supported (as +opposed to also provide testing for the DRNG) is the fact that the +LRNG software hash implementation contains glue code that may +warrant testing in addition to the testing of the software ciphers +via the kernel crypto API. Also, for testing the CTR-DRBG, the +underlying AES implementation would need to be tested. However, +such AES test interface cannot be provided by the LRNG as it has no +means to access the AES operation. + +Finally, the execution duration for processing a time stamp can be +obtained with the LRNG raw entropy interface. + +If a test interface is not compiled, its code is a noop which has no +impact on the performance. + +CC: Torsten Duwe +CC: "Eric W. Biederman" +CC: "Alexander E. Patrakov" +CC: "Ahmed S. Darwish" +CC: "Theodore Y. Ts'o" +CC: Willy Tarreau +CC: Matthew Garrett +CC: Vito Caputo +CC: Andreas Dilger +CC: Jan Kara +CC: Ray Strode +CC: William Jon McCann +CC: zhangjs +CC: Andy Lutomirski +CC: Florian Weimer +CC: Lennart Poettering +CC: Nicolai Stange +CC: Alexander Lobakin +Reviewed-by: Roman Drahtmueller +Tested-by: Marcelo Henrique Cerri +Tested-by: Neil Horman +Signed-off-by: Stephan Mueller +--- + drivers/char/lrng/Kconfig | 162 ++++++++ + drivers/char/lrng/Makefile | 1 + + drivers/char/lrng/lrng_testing.c | 689 +++++++++++++++++++++++++++++++ + 3 files changed, 852 insertions(+) + create mode 100644 drivers/char/lrng/lrng_testing.c + +--- a/drivers/char/lrng/Kconfig ++++ b/drivers/char/lrng/Kconfig +@@ -323,4 +323,166 @@ config LRNG_KCAPI + provided by the selected kernel crypto API RNG. + endif # LRNG_DRNG_SWITCH + ++menuconfig LRNG_TESTING_MENU ++ bool "LRNG testing interfaces" ++ depends on DEBUG_FS ++ help ++ Enable one or more of the following test interfaces. ++ ++ If unsure, say N. ++ ++if LRNG_TESTING_MENU ++ ++config LRNG_RAW_HIRES_ENTROPY ++ bool "Enable entropy test interface to hires timer noise source" ++ default y ++ help ++ The test interface allows a privileged process to capture ++ the raw unconditioned high resolution time stamp noise that ++ is collected by the LRNG for statistical analysis. Extracted ++ noise data is not used to seed the LRNG. ++ ++ The raw noise data can be obtained using the lrng_raw_hires ++ debugfs file. Using the option lrng_testing.boot_raw_hires_test=1 ++ the raw noise of the first 1000 entropy events since boot ++ can be sampled. ++ ++config LRNG_RAW_JIFFIES_ENTROPY ++ bool "Enable entropy test interface to Jiffies noise source" ++ help ++ The test interface allows a privileged process to capture ++ the raw unconditioned Jiffies that is collected by ++ the LRNG for statistical analysis. This data is used for ++ seeding the LRNG if a high-resolution time stamp is not ++ available. If a high-resolution time stamp is detected, ++ the Jiffies value is not collected by the LRNG and no ++ data is provided via the test interface. Extracted noise ++ data is not used to seed the random number generator. ++ ++ The raw noise data can be obtained using the lrng_raw_jiffies ++ debugfs file. Using the option lrng_testing.boot_raw_jiffies_test=1 ++ the raw noise of the first 1000 entropy events since boot ++ can be sampled. ++ ++config LRNG_RAW_IRQ_ENTROPY ++ bool "Enable entropy test interface to IRQ number noise source" ++ help ++ The test interface allows a privileged process to capture ++ the raw unconditioned interrupt number that is collected by ++ the LRNG for statistical analysis. This data is used for ++ seeding the random32 PRNG external to the LRNG if a ++ high-resolution time stamp is available or it will be used to ++ seed the LRNG otherwise. Extracted noise data is not used to ++ seed the random number generator. ++ ++ The raw noise data can be obtained using the lrng_raw_irq ++ debugfs file. Using the option lrng_testing.boot_raw_irq_test=1 ++ the raw noise of the first 1000 entropy events since boot ++ can be sampled. ++ ++config LRNG_RAW_IRQFLAGS_ENTROPY ++ bool "Enable entropy test interface to IRQ flags noise source" ++ help ++ The test interface allows a privileged process to capture ++ the raw unconditioned interrupt flags that is collected by ++ the LRNG for statistical analysis. This data is used for ++ seeding the random32 PRNG external to the LRNG if a ++ high-resolution time stamp is available or it will be used to ++ seed the LRNG otherwise. Extracted noise data is not used to ++ seed the random number generator. ++ ++ The raw noise data can be obtained using the lrng_raw_irqflags ++ debugfs file. Using the option lrng_testing.boot_raw_irqflags_test=1 ++ the raw noise of the first 1000 entropy events since boot ++ can be sampled. ++ ++config LRNG_RAW_RETIP_ENTROPY ++ bool "Enable entropy test interface to RETIP value noise source" ++ help ++ The test interface allows a privileged process to capture ++ the raw unconditioned return instruction pointer value ++ that is collected by the LRNG for statistical analysis. ++ This data is used for seeding the random32 PRNG external ++ to the LRNG if a high-resolution time stamp is available or ++ it will be used to seed the LRNG otherwise. Extracted noise ++ data is not used to seed the random number generator. ++ ++ The raw noise data can be obtained using the lrng_raw_retip ++ debugfs file. Using the option lrng_testing.boot_raw_retip_test=1 ++ the raw noise of the first 1000 entropy events since boot ++ can be sampled. ++ ++config LRNG_RAW_REGS_ENTROPY ++ bool "Enable entropy test interface to IRQ register value noise source" ++ help ++ The test interface allows a privileged process to capture ++ the raw unconditioned interrupt register value that is ++ collected by the LRNG for statistical analysis. Extracted noise ++ data is not used to seed the random number generator. ++ ++ The raw noise data can be obtained using the lrng_raw_regs ++ debugfs file. Using the option lrng_testing.boot_raw_regs_test=1 ++ the raw noise of the first 1000 entropy events since boot ++ can be sampled. ++ ++config LRNG_RAW_ARRAY ++ bool "Enable test interface to LRNG raw entropy storage array" ++ help ++ The test interface allows a privileged process to capture ++ the raw noise data that is collected by the LRNG ++ in the per-CPU array for statistical analysis. The purpose ++ of this interface is to verify that the array handling code ++ truly only concatenates data and provides the same entropy ++ rate as the raw unconditioned noise source when assessing ++ the collected data byte-wise. ++ ++ The data can be obtained using the lrng_raw_array debugfs ++ file. Using the option lrng_testing.boot_raw_array=1 ++ the raw noise of the first 1000 entropy events since boot ++ can be sampled. ++ ++config LRNG_IRQ_PERF ++ bool "Enable LRNG interrupt performance monitor" ++ help ++ With this option, the performance monitor of the LRNG ++ interrupt handling code is enabled. The file provides ++ the execution time of the interrupt handler in ++ cycles. ++ ++ The interrupt performance data can be obtained using ++ the lrng_irq_perf debugfs file. Using the option ++ lrng_testing.boot_irq_perf=1 the performance data of ++ the first 1000 entropy events since boot can be sampled. ++ ++config LRNG_ACVT_HASH ++ bool "Enable LRNG ACVT Hash interface" ++ help ++ With this option, the LRNG built-in hash function used for ++ auxiliary pool management and prior to switching the ++ cryptographic backends is made available for ACVT. The ++ interface allows writing of the data to be hashed ++ into the interface. The read operation triggers the hash ++ operation to generate message digest. ++ ++ The ACVT interface is available with the lrng_acvt_hash ++ debugfs file. ++ ++config LRNG_RUNTIME_ES_CONFIG ++ bool "Enable runtime configuration of entropy sources" ++ help ++ When enabling this option, the LRNG provides the mechanism ++ allowing to alter the entropy rate of each entropy source ++ during boot time and runtime. ++ ++ The following interfaces are available: ++ lrng_archrandom.archrandom for the CPU entropy source, ++ lrng_jent.jitterrng for the Jitter RNG entropy source, and ++ lrng_sw_noise.irq_entropy for the interrupt entropy source. ++ ++config LRNG_TESTING ++ bool ++ default y if (LRNG_RAW_HIRES_ENTROPY || LRNG_RAW_JIFFIES_ENTROPY ||LRNG_RAW_IRQ_ENTROPY || LRNG_RAW_IRQFLAGS_ENTROPY || LRNG_RAW_RETIP_ENTROPY || LRNG_RAW_REGS_ENTROPY || LRNG_RAW_ARRAY || LRNG_IRQ_PERF || LRNG_ACVT_HASH) ++ ++endif #LRNG_TESTING_MENU ++ + endif # LRNG +--- a/drivers/char/lrng/Makefile ++++ b/drivers/char/lrng/Makefile +@@ -16,3 +16,4 @@ obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o + obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o + obj-$(CONFIG_LRNG_JENT) += lrng_jent.o + obj-$(CONFIG_LRNG_HEALTH_TESTS) += lrng_health.o ++obj-$(CONFIG_LRNG_TESTING) += lrng_testing.o +--- /dev/null ++++ b/drivers/char/lrng/lrng_testing.c +@@ -0,0 +1,689 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause ++/* ++ * Linux Random Number Generator (LRNG) testing interfaces ++ * ++ * Copyright (C) 2019 - 2021, Stephan Mueller ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "lrng_internal.h" ++ ++#define LRNG_TESTING_RINGBUFFER_SIZE 1024 ++#define LRNG_TESTING_RINGBUFFER_MASK (LRNG_TESTING_RINGBUFFER_SIZE - 1) ++ ++struct lrng_testing { ++ u32 lrng_testing_rb[LRNG_TESTING_RINGBUFFER_SIZE]; ++ u32 rb_reader; ++ u32 rb_writer; ++ atomic_t lrng_testing_enabled; ++ spinlock_t lock; ++ wait_queue_head_t read_wait; ++}; ++ ++/*************************** Generic Data Handling ****************************/ ++ ++/* ++ * boot variable: ++ * 0 ==> No boot test, gathering of runtime data allowed ++ * 1 ==> Boot test enabled and ready for collecting data, gathering runtime ++ * data is disabled ++ * 2 ==> Boot test completed and disabled, gathering of runtime data is ++ * disabled ++ */ ++ ++static inline void lrng_testing_reset(struct lrng_testing *data) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&data->lock, flags); ++ data->rb_reader = 0; ++ data->rb_writer = 0; ++ spin_unlock_irqrestore(&data->lock, flags); ++} ++ ++static inline void lrng_testing_init(struct lrng_testing *data, u32 boot) ++{ ++ /* ++ * The boot time testing implies we have a running test. If the ++ * caller wants to clear it, he has to unset the boot_test flag ++ * at runtime via sysfs to enable regular runtime testing ++ */ ++ if (boot) ++ return; ++ ++ lrng_testing_reset(data); ++ atomic_set(&data->lrng_testing_enabled, 1); ++ pr_warn("Enabling data collection\n"); ++} ++ ++static inline void lrng_testing_fini(struct lrng_testing *data, u32 boot) ++{ ++ /* If we have boot data, we do not reset yet to allow data to be read */ ++ if (boot) ++ return; ++ ++ atomic_set(&data->lrng_testing_enabled, 0); ++ lrng_testing_reset(data); ++ pr_warn("Disabling data collection\n"); ++} ++ ++static inline bool lrng_testing_store(struct lrng_testing *data, u32 value, ++ u32 *boot) ++{ ++ unsigned long flags; ++ ++ if (!atomic_read(&data->lrng_testing_enabled) && (*boot != 1)) ++ return false; ++ ++ spin_lock_irqsave(&data->lock, flags); ++ ++ /* ++ * Disable entropy testing for boot time testing after ring buffer ++ * is filled. ++ */ ++ if (*boot) { ++ if (data->rb_writer > LRNG_TESTING_RINGBUFFER_SIZE) { ++ *boot = 2; ++ pr_warn_once("One time data collection test disabled\n"); ++ spin_unlock_irqrestore(&data->lock, flags); ++ return false; ++ } ++ ++ if (data->rb_writer == 1) ++ pr_warn("One time data collection test enabled\n"); ++ } ++ ++ data->lrng_testing_rb[data->rb_writer & LRNG_TESTING_RINGBUFFER_MASK] = ++ value; ++ data->rb_writer++; ++ ++ spin_unlock_irqrestore(&data->lock, flags); ++ ++ if (wq_has_sleeper(&data->read_wait)) ++ wake_up_interruptible(&data->read_wait); ++ ++ return true; ++} ++ ++static inline bool lrng_testing_have_data(struct lrng_testing *data) ++{ ++ return ((data->rb_writer & LRNG_TESTING_RINGBUFFER_MASK) != ++ (data->rb_reader & LRNG_TESTING_RINGBUFFER_MASK)); ++} ++ ++static inline int lrng_testing_reader(struct lrng_testing *data, u32 *boot, ++ u8 *outbuf, u32 outbuflen) ++{ ++ unsigned long flags; ++ int collected_data = 0; ++ ++ lrng_testing_init(data, *boot); ++ ++ while (outbuflen) { ++ spin_lock_irqsave(&data->lock, flags); ++ ++ /* We have no data or reached the writer. */ ++ if (!data->rb_writer || ++ (data->rb_writer == data->rb_reader)) { ++ ++ spin_unlock_irqrestore(&data->lock, flags); ++ ++ /* ++ * Now we gathered all boot data, enable regular data ++ * collection. ++ */ ++ if (*boot) { ++ *boot = 0; ++ goto out; ++ } ++ ++ wait_event_interruptible(data->read_wait, ++ lrng_testing_have_data(data)); ++ if (signal_pending(current)) { ++ collected_data = -ERESTARTSYS; ++ goto out; ++ } ++ ++ continue; ++ } ++ ++ /* We copy out word-wise */ ++ if (outbuflen < sizeof(u32)) { ++ spin_unlock_irqrestore(&data->lock, flags); ++ goto out; ++ } ++ ++ memcpy(outbuf, &data->lrng_testing_rb[data->rb_reader], ++ sizeof(u32)); ++ data->rb_reader++; ++ ++ spin_unlock_irqrestore(&data->lock, flags); ++ ++ outbuf += sizeof(u32); ++ outbuflen -= sizeof(u32); ++ collected_data += sizeof(u32); ++ } ++ ++out: ++ lrng_testing_fini(data, *boot); ++ return collected_data; ++} ++ ++static int lrng_testing_extract_user(struct file *file, char __user *buf, ++ size_t nbytes, loff_t *ppos, ++ int (*reader)(u8 *outbuf, u32 outbuflen)) ++{ ++ u8 *tmp, *tmp_aligned; ++ int ret = 0, large_request = (nbytes > 256); ++ ++ if (!nbytes) ++ return 0; ++ ++ /* ++ * The intention of this interface is for collecting at least ++ * 1000 samples due to the SP800-90B requirements. So, we make no ++ * effort in avoiding allocating more memory that actually needed ++ * by the user. Hence, we allocate sufficient memory to always hold ++ * that amount of data. ++ */ ++ tmp = kmalloc(LRNG_TESTING_RINGBUFFER_SIZE + sizeof(u32), GFP_KERNEL); ++ if (!tmp) ++ return -ENOMEM; ++ ++ tmp_aligned = PTR_ALIGN(tmp, sizeof(u32)); ++ ++ while (nbytes) { ++ int i; ++ ++ if (large_request && need_resched()) { ++ if (signal_pending(current)) { ++ if (ret == 0) ++ ret = -ERESTARTSYS; ++ break; ++ } ++ schedule(); ++ } ++ ++ i = min_t(int, nbytes, LRNG_TESTING_RINGBUFFER_SIZE); ++ i = reader(tmp_aligned, i); ++ if (i <= 0) { ++ if (i < 0) ++ ret = i; ++ break; ++ } ++ if (copy_to_user(buf, tmp_aligned, i)) { ++ ret = -EFAULT; ++ break; ++ } ++ ++ nbytes -= i; ++ buf += i; ++ ret += i; ++ } ++ ++ kfree_sensitive(tmp); ++ ++ if (ret > 0) ++ *ppos += ret; ++ ++ return ret; ++} ++ ++/************** Raw High-Resolution Timer Entropy Data Handling ***************/ ++ ++#ifdef CONFIG_LRNG_RAW_HIRES_ENTROPY ++ ++static u32 boot_raw_hires_test = 0; ++module_param(boot_raw_hires_test, uint, 0644); ++MODULE_PARM_DESC(boot_raw_hires_test, "Enable gathering boot time high resolution timer entropy of the first entropy events"); ++ ++static struct lrng_testing lrng_raw_hires = { ++ .rb_reader = 0, ++ .rb_writer = 0, ++ .lock = __SPIN_LOCK_UNLOCKED(lrng_raw_hires.lock), ++ .read_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lrng_raw_hires.read_wait) ++}; ++ ++bool lrng_raw_hires_entropy_store(u32 value) ++{ ++ return lrng_testing_store(&lrng_raw_hires, value, &boot_raw_hires_test); ++} ++ ++static int lrng_raw_hires_entropy_reader(u8 *outbuf, u32 outbuflen) ++{ ++ return lrng_testing_reader(&lrng_raw_hires, &boot_raw_hires_test, ++ outbuf, outbuflen); ++} ++ ++static ssize_t lrng_raw_hires_read(struct file *file, char __user *to, ++ size_t count, loff_t *ppos) ++{ ++ return lrng_testing_extract_user(file, to, count, ppos, ++ lrng_raw_hires_entropy_reader); ++} ++ ++static const struct file_operations lrng_raw_hires_fops = { ++ .owner = THIS_MODULE, ++ .read = lrng_raw_hires_read, ++}; ++ ++#endif /* CONFIG_LRNG_RAW_HIRES_ENTROPY */ ++ ++/********************* Raw Jiffies Entropy Data Handling **********************/ ++ ++#ifdef CONFIG_LRNG_RAW_JIFFIES_ENTROPY ++ ++static u32 boot_raw_jiffies_test = 0; ++module_param(boot_raw_jiffies_test, uint, 0644); ++MODULE_PARM_DESC(boot_raw_jiffies_test, "Enable gathering boot time high resolution timer entropy of the first entropy events"); ++ ++static struct lrng_testing lrng_raw_jiffies = { ++ .rb_reader = 0, ++ .rb_writer = 0, ++ .lock = __SPIN_LOCK_UNLOCKED(lrng_raw_jiffies.lock), ++ .read_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lrng_raw_jiffies.read_wait) ++}; ++ ++bool lrng_raw_jiffies_entropy_store(u32 value) ++{ ++ return lrng_testing_store(&lrng_raw_jiffies, value, ++ &boot_raw_jiffies_test); ++} ++ ++static int lrng_raw_jiffies_entropy_reader(u8 *outbuf, u32 outbuflen) ++{ ++ return lrng_testing_reader(&lrng_raw_jiffies, &boot_raw_jiffies_test, ++ outbuf, outbuflen); ++} ++ ++static ssize_t lrng_raw_jiffies_read(struct file *file, char __user *to, ++ size_t count, loff_t *ppos) ++{ ++ return lrng_testing_extract_user(file, to, count, ppos, ++ lrng_raw_jiffies_entropy_reader); ++} ++ ++static const struct file_operations lrng_raw_jiffies_fops = { ++ .owner = THIS_MODULE, ++ .read = lrng_raw_jiffies_read, ++}; ++ ++#endif /* CONFIG_LRNG_RAW_JIFFIES_ENTROPY */ ++ ++/************************** Raw IRQ Data Handling ****************************/ ++ ++#ifdef CONFIG_LRNG_RAW_IRQ_ENTROPY ++ ++static u32 boot_raw_irq_test = 0; ++module_param(boot_raw_irq_test, uint, 0644); ++MODULE_PARM_DESC(boot_raw_irq_test, "Enable gathering boot time entropy of the first IRQ entropy events"); ++ ++static struct lrng_testing lrng_raw_irq = { ++ .rb_reader = 0, ++ .rb_writer = 0, ++ .lock = __SPIN_LOCK_UNLOCKED(lrng_raw_irq.lock), ++ .read_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lrng_raw_irq.read_wait) ++}; ++ ++bool lrng_raw_irq_entropy_store(u32 value) ++{ ++ return lrng_testing_store(&lrng_raw_irq, value, &boot_raw_irq_test); ++} ++ ++static int lrng_raw_irq_entropy_reader(u8 *outbuf, u32 outbuflen) ++{ ++ return lrng_testing_reader(&lrng_raw_irq, &boot_raw_irq_test, outbuf, ++ outbuflen); ++} ++ ++static ssize_t lrng_raw_irq_read(struct file *file, char __user *to, ++ size_t count, loff_t *ppos) ++{ ++ return lrng_testing_extract_user(file, to, count, ppos, ++ lrng_raw_irq_entropy_reader); ++} ++ ++static const struct file_operations lrng_raw_irq_fops = { ++ .owner = THIS_MODULE, ++ .read = lrng_raw_irq_read, ++}; ++ ++#endif /* CONFIG_LRNG_RAW_IRQ_ENTROPY */ ++ ++/************************ Raw IRQFLAGS Data Handling **************************/ ++ ++#ifdef CONFIG_LRNG_RAW_IRQFLAGS_ENTROPY ++ ++static u32 boot_raw_irqflags_test = 0; ++module_param(boot_raw_irqflags_test, uint, 0644); ++MODULE_PARM_DESC(boot_raw_irqflags_test, "Enable gathering boot time entropy of the first IRQ flags entropy events"); ++ ++static struct lrng_testing lrng_raw_irqflags = { ++ .rb_reader = 0, ++ .rb_writer = 0, ++ .lock = __SPIN_LOCK_UNLOCKED(lrng_raw_irqflags.lock), ++ .read_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lrng_raw_irqflags.read_wait) ++}; ++ ++bool lrng_raw_irqflags_entropy_store(u32 value) ++{ ++ return lrng_testing_store(&lrng_raw_irqflags, value, ++ &boot_raw_irqflags_test); ++} ++ ++static int lrng_raw_irqflags_entropy_reader(u8 *outbuf, u32 outbuflen) ++{ ++ return lrng_testing_reader(&lrng_raw_irqflags, &boot_raw_irqflags_test, ++ outbuf, outbuflen); ++} ++ ++static ssize_t lrng_raw_irqflags_read(struct file *file, char __user *to, ++ size_t count, loff_t *ppos) ++{ ++ return lrng_testing_extract_user(file, to, count, ppos, ++ lrng_raw_irqflags_entropy_reader); ++} ++ ++static const struct file_operations lrng_raw_irqflags_fops = { ++ .owner = THIS_MODULE, ++ .read = lrng_raw_irqflags_read, ++}; ++ ++#endif /* CONFIG_LRNG_RAW_IRQFLAGS_ENTROPY */ ++ ++/************************ Raw _RET_IP_ Data Handling **************************/ ++ ++#ifdef CONFIG_LRNG_RAW_RETIP_ENTROPY ++ ++static u32 boot_raw_retip_test = 0; ++module_param(boot_raw_retip_test, uint, 0644); ++MODULE_PARM_DESC(boot_raw_retip_test, "Enable gathering boot time entropy of the first return instruction pointer entropy events"); ++ ++static struct lrng_testing lrng_raw_retip = { ++ .rb_reader = 0, ++ .rb_writer = 0, ++ .lock = __SPIN_LOCK_UNLOCKED(lrng_raw_retip.lock), ++ .read_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lrng_raw_retip.read_wait) ++}; ++ ++bool lrng_raw_retip_entropy_store(u32 value) ++{ ++ return lrng_testing_store(&lrng_raw_retip, value, &boot_raw_retip_test); ++} ++ ++static int lrng_raw_retip_entropy_reader(u8 *outbuf, u32 outbuflen) ++{ ++ return lrng_testing_reader(&lrng_raw_retip, &boot_raw_retip_test, ++ outbuf, outbuflen); ++} ++ ++static ssize_t lrng_raw_retip_read(struct file *file, char __user *to, ++ size_t count, loff_t *ppos) ++{ ++ return lrng_testing_extract_user(file, to, count, ppos, ++ lrng_raw_retip_entropy_reader); ++} ++ ++static const struct file_operations lrng_raw_retip_fops = { ++ .owner = THIS_MODULE, ++ .read = lrng_raw_retip_read, ++}; ++ ++#endif /* CONFIG_LRNG_RAW_RETIP_ENTROPY */ ++ ++/********************** Raw IRQ register Data Handling ************************/ ++ ++#ifdef CONFIG_LRNG_RAW_REGS_ENTROPY ++ ++static u32 boot_raw_regs_test = 0; ++module_param(boot_raw_regs_test, uint, 0644); ++MODULE_PARM_DESC(boot_raw_regs_test, "Enable gathering boot time entropy of the first interrupt register entropy events"); ++ ++static struct lrng_testing lrng_raw_regs = { ++ .rb_reader = 0, ++ .rb_writer = 0, ++ .lock = __SPIN_LOCK_UNLOCKED(lrng_raw_regs.lock), ++ .read_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lrng_raw_regs.read_wait) ++}; ++ ++bool lrng_raw_regs_entropy_store(u32 value) ++{ ++ return lrng_testing_store(&lrng_raw_regs, value, &boot_raw_regs_test); ++} ++ ++static int lrng_raw_regs_entropy_reader(u8 *outbuf, u32 outbuflen) ++{ ++ return lrng_testing_reader(&lrng_raw_regs, &boot_raw_regs_test, ++ outbuf, outbuflen); ++} ++ ++static ssize_t lrng_raw_regs_read(struct file *file, char __user *to, ++ size_t count, loff_t *ppos) ++{ ++ return lrng_testing_extract_user(file, to, count, ppos, ++ lrng_raw_regs_entropy_reader); ++} ++ ++static const struct file_operations lrng_raw_regs_fops = { ++ .owner = THIS_MODULE, ++ .read = lrng_raw_regs_read, ++}; ++ ++#endif /* CONFIG_LRNG_RAW_REGS_ENTROPY */ ++ ++/********************** Raw Entropy Array Data Handling ***********************/ ++ ++#ifdef CONFIG_LRNG_RAW_ARRAY ++ ++static u32 boot_raw_array = 0; ++module_param(boot_raw_array, uint, 0644); ++MODULE_PARM_DESC(boot_raw_array, "Enable gathering boot time raw noise array data of the first entropy events"); ++ ++static struct lrng_testing lrng_raw_array = { ++ .rb_reader = 0, ++ .rb_writer = 0, ++ .lock = __SPIN_LOCK_UNLOCKED(lrng_raw_array.lock), ++ .read_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lrng_raw_array.read_wait) ++}; ++ ++bool lrng_raw_array_entropy_store(u32 value) ++{ ++ return lrng_testing_store(&lrng_raw_array, value, &boot_raw_array); ++} ++ ++static int lrng_raw_array_entropy_reader(u8 *outbuf, u32 outbuflen) ++{ ++ return lrng_testing_reader(&lrng_raw_array, &boot_raw_array, outbuf, ++ outbuflen); ++} ++ ++static ssize_t lrng_raw_array_read(struct file *file, char __user *to, ++ size_t count, loff_t *ppos) ++{ ++ return lrng_testing_extract_user(file, to, count, ppos, ++ lrng_raw_array_entropy_reader); ++} ++ ++static const struct file_operations lrng_raw_array_fops = { ++ .owner = THIS_MODULE, ++ .read = lrng_raw_array_read, ++}; ++ ++#endif /* CONFIG_LRNG_RAW_ARRAY */ ++ ++/******************** Interrupt Performance Data Handling *********************/ ++ ++#ifdef CONFIG_LRNG_IRQ_PERF ++ ++static u32 boot_irq_perf = 0; ++module_param(boot_irq_perf, uint, 0644); ++MODULE_PARM_DESC(boot_irq_perf, "Enable gathering boot time interrupt performance data of the first entropy events"); ++ ++static struct lrng_testing lrng_irq_perf = { ++ .rb_reader = 0, ++ .rb_writer = 0, ++ .lock = __SPIN_LOCK_UNLOCKED(lrng_irq_perf.lock), ++ .read_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lrng_irq_perf.read_wait) ++}; ++ ++bool lrng_perf_time(u32 start) ++{ ++ return lrng_testing_store(&lrng_irq_perf, random_get_entropy() - start, ++ &boot_irq_perf); ++} ++ ++static int lrng_irq_perf_reader(u8 *outbuf, u32 outbuflen) ++{ ++ return lrng_testing_reader(&lrng_irq_perf, &boot_irq_perf, outbuf, ++ outbuflen); ++} ++ ++static ssize_t lrng_irq_perf_read(struct file *file, char __user *to, ++ size_t count, loff_t *ppos) ++{ ++ return lrng_testing_extract_user(file, to, count, ppos, ++ lrng_irq_perf_reader); ++} ++ ++static const struct file_operations lrng_irq_perf_fops = { ++ .owner = THIS_MODULE, ++ .read = lrng_irq_perf_read, ++}; ++ ++#endif /* CONFIG_LRNG_IRQ_PERF */ ++ ++/*********************************** ACVT ************************************/ ++ ++#ifdef CONFIG_LRNG_ACVT_HASH ++ ++/* maximum amount of data to be hashed as defined by ACVP */ ++#define LRNG_ACVT_MAX_SHA_MSG (65536 >> 3) ++ ++/* ++ * As we use static variables to store the data, it is clear that the ++ * test interface is only able to handle single threaded testing. This is ++ * considered to be sufficient for testing. If multi-threaded use of the ++ * ACVT test interface would be performed, the caller would get garbage ++ * but the kernel operation is unaffected by this. ++ */ ++static u8 lrng_acvt_hash_data[LRNG_ACVT_MAX_SHA_MSG] ++ __aligned(LRNG_KCAPI_ALIGN); ++static atomic_t lrng_acvt_hash_data_size = ATOMIC_INIT(0); ++static u8 lrng_acvt_hash_digest[LRNG_ATOMIC_DIGEST_SIZE]; ++ ++static ssize_t lrng_acvt_hash_write(struct file *file, const char __user *buf, ++ size_t nbytes, loff_t *ppos) ++{ ++ if (nbytes > LRNG_ACVT_MAX_SHA_MSG) ++ return -EINVAL; ++ ++ atomic_set(&lrng_acvt_hash_data_size, (int)nbytes); ++ ++ return simple_write_to_buffer(lrng_acvt_hash_data, ++ LRNG_ACVT_MAX_SHA_MSG, ppos, buf, nbytes); ++} ++ ++static ssize_t lrng_acvt_hash_read(struct file *file, char __user *to, ++ size_t count, loff_t *ppos) ++{ ++ SHASH_DESC_ON_STACK(shash, NULL); ++ const struct lrng_crypto_cb *crypto_cb = &lrng_cc20_crypto_cb; ++ ssize_t ret; ++ ++ if (count > LRNG_ATOMIC_DIGEST_SIZE) ++ return -EINVAL; ++ ++ ret = crypto_cb->lrng_hash_init(shash, NULL) ?: ++ crypto_cb->lrng_hash_update(shash, lrng_acvt_hash_data, ++ atomic_read_u32(&lrng_acvt_hash_data_size)) ?: ++ crypto_cb->lrng_hash_final(shash, lrng_acvt_hash_digest); ++ if (ret) ++ return ret; ++ ++ return simple_read_from_buffer(to, count, ppos, lrng_acvt_hash_digest, ++ sizeof(lrng_acvt_hash_digest)); ++} ++ ++static const struct file_operations lrng_acvt_hash_fops = { ++ .owner = THIS_MODULE, ++ .open = simple_open, ++ .llseek = default_llseek, ++ .read = lrng_acvt_hash_read, ++ .write = lrng_acvt_hash_write, ++}; ++ ++#endif /* CONFIG_LRNG_ACVT_DRNG */ ++ ++/************************************************************************** ++ * Debugfs interface ++ **************************************************************************/ ++ ++static int __init lrng_raw_init(void) ++{ ++ struct dentry *lrng_raw_debugfs_root; ++ ++ lrng_raw_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); ++ ++#ifdef CONFIG_LRNG_RAW_HIRES_ENTROPY ++ debugfs_create_file_unsafe("lrng_raw_hires", 0400, ++ lrng_raw_debugfs_root, NULL, ++ &lrng_raw_hires_fops); ++#endif ++#ifdef CONFIG_LRNG_RAW_JIFFIES_ENTROPY ++ debugfs_create_file_unsafe("lrng_raw_jiffies", 0400, ++ lrng_raw_debugfs_root, NULL, ++ &lrng_raw_jiffies_fops); ++#endif ++#ifdef CONFIG_LRNG_RAW_IRQ_ENTROPY ++ debugfs_create_file_unsafe("lrng_raw_irq", 0400, lrng_raw_debugfs_root, ++ NULL, &lrng_raw_irq_fops); ++#endif ++#ifdef CONFIG_LRNG_RAW_IRQFLAGS_ENTROPY ++ debugfs_create_file_unsafe("lrng_raw_irqflags", 0400, ++ lrng_raw_debugfs_root, NULL, ++ &lrng_raw_irqflags_fops); ++#endif ++#ifdef CONFIG_LRNG_RAW_RETIP_ENTROPY ++ debugfs_create_file_unsafe("lrng_raw_retip", 0400, ++ lrng_raw_debugfs_root, NULL, ++ &lrng_raw_retip_fops); ++#endif ++#ifdef CONFIG_LRNG_RAW_REGS_ENTROPY ++ debugfs_create_file_unsafe("lrng_raw_regs", 0400, ++ lrng_raw_debugfs_root, NULL, ++ &lrng_raw_regs_fops); ++#endif ++#ifdef CONFIG_LRNG_RAW_ARRAY ++ debugfs_create_file_unsafe("lrng_raw_array", 0400, ++ lrng_raw_debugfs_root, NULL, ++ &lrng_raw_array_fops); ++#endif ++#ifdef CONFIG_LRNG_IRQ_PERF ++ debugfs_create_file_unsafe("lrng_irq_perf", 0400, lrng_raw_debugfs_root, ++ NULL, &lrng_irq_perf_fops); ++#endif ++#ifdef CONFIG_LRNG_ACVT_HASH ++ debugfs_create_file_unsafe("lrng_acvt_hash", 0600, ++ lrng_raw_debugfs_root, NULL, ++ &lrng_acvt_hash_fops); ++#endif ++ ++ return 0; ++} ++ ++module_init(lrng_raw_init); diff --git a/PATCH/LRNG/696-16-v41-0013-LRNG-add-power-on-and-runtime-self-tests.patch b/PATCH/LRNG/696-16-v41-0013-LRNG-add-power-on-and-runtime-self-tests.patch new file mode 100644 index 000000000..3d37618a8 --- /dev/null +++ b/PATCH/LRNG/696-16-v41-0013-LRNG-add-power-on-and-runtime-self-tests.patch @@ -0,0 +1,494 @@ +From 142c1cde7b3e57796ff5ed0bc17e3f9d92f123d5 Mon Sep 17 00:00:00 2001 +From: Stephan Mueller +Date: Fri, 18 Jun 2021 08:26:24 +0200 +Subject: [PATCH v41 13/13] LRNG - add power-on and runtime self-tests + +Parts of the LRNG are already covered by self-tests, including: + +* Self-test of SP800-90A DRBG provided by the Linux kernel crypto API. + +* Self-test of the PRNG provided by the Linux kernel crypto API. + +* Raw noise source data testing including SP800-90B compliant + tests when enabling CONFIG_LRNG_HEALTH_TESTS + +This patch adds the self-tests for the remaining critical functions of +the LRNG that are essential to maintain entropy and provide +cryptographic strong random numbers. The following self-tests are +implemented: + +* Self-test of the time array maintenance. This test verifies whether +the time stamp array management to store multiple values in one integer +implements a concatenation of the data. + +* Self-test of the software hash implementation ensures that this +function operates compliant to the FIPS 180-4 specification. The +self-test performs a hash operation of a zeroized per-CPU data array. + +* Self-test of the ChaCha20 DRNG is based on the self-tests that are +already present and implemented with the stand-alone user space +ChaCha20 DRNG implementation available at [1]. The self-tests cover +different use cases of the DRNG seeded with known seed data. + +The status of the LRNG self-tests is provided with the selftest_status +SysFS file. If the file contains a zero, the self-tests passed. The +value 0xffffffff means that the self-tests were not executed. Any other +value indicates a self-test failure. + +The self-test may be compiled to panic the system if the self-test +fails. + +All self-tests operate on private state data structures. This implies +that none of the self-tests have any impact on the regular LRNG +operations. This allows the self-tests to be repeated at runtime by +writing anything into the selftest_status SysFS file. + +[1] https://www.chronox.de/chacha20.html + +CC: Torsten Duwe +CC: "Eric W. Biederman" +CC: "Alexander E. Patrakov" +CC: "Ahmed S. Darwish" +CC: "Theodore Y. Ts'o" +CC: Willy Tarreau +CC: Matthew Garrett +CC: Vito Caputo +CC: Andreas Dilger +CC: Jan Kara +CC: Ray Strode +CC: William Jon McCann +CC: zhangjs +CC: Andy Lutomirski +CC: Florian Weimer +CC: Lennart Poettering +CC: Nicolai Stange +CC: Marcelo Henrique Cerri +CC: Neil Horman +CC: Alexander Lobakin +Signed-off-by: Stephan Mueller +--- + drivers/char/lrng/Kconfig | 43 +++- + drivers/char/lrng/Makefile | 1 + + drivers/char/lrng/lrng_selftest.c | 351 ++++++++++++++++++++++++++++++ + 3 files changed, 387 insertions(+), 8 deletions(-) + create mode 100644 drivers/char/lrng/lrng_selftest.c + +--- a/drivers/char/lrng/Kconfig ++++ b/drivers/char/lrng/Kconfig +@@ -165,15 +165,16 @@ config LRNG_COLLECTION_SIZE + default 8192 if LRNG_COLLECTION_SIZE_8192 + + config LRNG_HEALTH_TESTS +- bool "Enable noise source online health tests" ++ bool "Enable interrupt entropy source online health tests" + help +- The online health tests validate the noise source at +- runtime for fatal errors. These tests include SP800-90B +- compliant tests which are invoked if the system is booted +- with fips=1. In case of fatal errors during active +- SP800-90B tests, the issue is logged and the noise +- data is discarded. These tests are required for full +- compliance with SP800-90B. ++ The online health tests applied to the interrupt entropy ++ source validate the noise source at runtime for fatal ++ errors. These tests include SP800-90B compliant tests ++ which are invoked if the system is booted with fips=1. ++ In case of fatal errors during active SP800-90B tests, ++ the issue is logged and the noise data is discarded. ++ These tests are required for full compliance of the ++ interrupt entropy source with SP800-90B. + + If unsure, say Y. + +@@ -485,4 +486,30 @@ config LRNG_TESTING + + endif #LRNG_TESTING_MENU + ++config LRNG_SELFTEST ++ bool "Enable power-on and on-demand self-tests" ++ help ++ The power-on self-tests are executed during boot time ++ covering the ChaCha20 DRNG, the hash operation used for ++ processing the entropy pools and the auxiliary pool, and ++ the time stamp management of the LRNG. ++ ++ The on-demand self-tests are triggered by writing any ++ value into the SysFS file selftest_status. At the same ++ time, when reading this file, the test status is ++ returned. A zero indicates that all tests were executed ++ successfully. ++ ++ If unsure, say Y. ++ ++if LRNG_SELFTEST ++ ++config LRNG_SELFTEST_PANIC ++ bool "Panic the kernel upon self-test failure" ++ help ++ If the option is enabled, the kernel is terminated if an ++ LRNG power-on self-test failure is detected. ++ ++endif # LRNG_SELFTEST ++ + endif # LRNG +--- a/drivers/char/lrng/Makefile ++++ b/drivers/char/lrng/Makefile +@@ -17,3 +17,4 @@ obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o + obj-$(CONFIG_LRNG_JENT) += lrng_jent.o + obj-$(CONFIG_LRNG_HEALTH_TESTS) += lrng_health.o + obj-$(CONFIG_LRNG_TESTING) += lrng_testing.o ++obj-$(CONFIG_LRNG_SELFTEST) += lrng_selftest.o +--- /dev/null ++++ b/drivers/char/lrng/lrng_selftest.c +@@ -0,0 +1,351 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause ++/* ++ * LRNG power-on and on-demand self-test ++ * ++ * Copyright (C) 2016 - 2021, Stephan Mueller ++ */ ++ ++/* ++ * In addition to the self-tests below, the following LRNG components ++ * are covered with self-tests during regular operation: ++ * ++ * * power-on self-test: SP800-90A DRBG provided by the Linux kernel crypto API ++ * * power-on self-test: PRNG provided by the Linux kernel crypto API ++ * * runtime test: Raw noise source data testing including SP800-90B compliant ++ * tests when enabling CONFIG_LRNG_HEALTH_TESTS ++ * ++ * Additional developer tests present with LRNG code: ++ * * SP800-90B APT and RCT test enforcement validation when enabling ++ * CONFIG_LRNG_APT_BROKEN or CONFIG_LRNG_RCT_BROKEN. ++ * * Collection of raw entropy from the interrupt noise source when enabling ++ * CONFIG_LRNG_TESTING and pulling the data from the kernel with the provided ++ * interface. ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++ ++#include "lrng_chacha20.h" ++#include "lrng_internal.h" ++#include "lrng_sw_noise.h" ++ ++#define LRNG_SELFTEST_PASSED 0 ++#define LRNG_SEFLTEST_ERROR_TIME (1 << 0) ++#define LRNG_SEFLTEST_ERROR_CHACHA20 (1 << 1) ++#define LRNG_SEFLTEST_ERROR_HASH (1 << 2) ++#define LRNG_SELFTEST_NOT_EXECUTED 0xffffffff ++ ++static u32 lrng_data_selftest_ptr = 0; ++static u32 lrng_data_selftest[LRNG_DATA_ARRAY_SIZE]; ++ ++static unsigned int lrng_selftest_status = LRNG_SELFTEST_NOT_EXECUTED; ++ ++static inline void lrng_selftest_bswap32(u32 *ptr, u32 words) ++{ ++ u32 i; ++ ++ /* Byte-swap data which is an LE representation */ ++ for (i = 0; i < words; i++) { ++ __le32 *p = (__le32 *)ptr; ++ ++ *p = cpu_to_le32(*ptr); ++ ptr++; ++ } ++} ++ ++static inline void lrng_data_process_selftest_insert(u32 time) ++{ ++ u32 ptr = lrng_data_selftest_ptr++ & LRNG_DATA_WORD_MASK; ++ unsigned int array = lrng_data_idx2array(ptr); ++ unsigned int slot = lrng_data_idx2slot(ptr); ++ ++ /* zeroization of slot to ensure the following OR adds the data */ ++ lrng_data_selftest[array] &= ++ ~(lrng_data_slot_val(0xffffffff & LRNG_DATA_SLOTSIZE_MASK, ++ slot)); ++ lrng_data_selftest[array] |= ++ lrng_data_slot_val(time & LRNG_DATA_SLOTSIZE_MASK, slot); ++} ++ ++static inline void lrng_data_process_selftest_u32(u32 data) ++{ ++ u32 pre_ptr, ptr, mask; ++ unsigned int pre_array; ++ ++ /* Increment pointer by number of slots taken for input value */ ++ lrng_data_selftest_ptr += LRNG_DATA_SLOTS_PER_UINT; ++ ++ /* ptr to current unit */ ++ ptr = lrng_data_selftest_ptr; ++ ++ lrng_pcpu_split_u32(&ptr, &pre_ptr, &mask); ++ ++ /* MSB of data go into previous unit */ ++ pre_array = lrng_data_idx2array(pre_ptr); ++ /* zeroization of slot to ensure the following OR adds the data */ ++ lrng_data_selftest[pre_array] &= ~(0xffffffff &~ mask); ++ lrng_data_selftest[pre_array] |= data & ~mask; ++ ++ /* LSB of data go into current unit */ ++ lrng_data_selftest[lrng_data_idx2array(ptr)] = data & mask; ++} ++ ++static unsigned int lrng_data_process_selftest(void) ++{ ++ u32 time; ++ u32 idx_zero_compare = (0 << 0) | (1 << 8) | (2 << 16) | (3 << 24); ++ u32 idx_one_compare = (4 << 0) | (5 << 8) | (6 << 16) | (7 << 24); ++ u32 idx_last_compare = ++ (((LRNG_DATA_NUM_VALUES - 4) & LRNG_DATA_SLOTSIZE_MASK) << 0) | ++ (((LRNG_DATA_NUM_VALUES - 3) & LRNG_DATA_SLOTSIZE_MASK) << 8) | ++ (((LRNG_DATA_NUM_VALUES - 2) & LRNG_DATA_SLOTSIZE_MASK) << 16) | ++ (((LRNG_DATA_NUM_VALUES - 1) & LRNG_DATA_SLOTSIZE_MASK) << 24); ++ ++ (void)idx_one_compare; ++ ++ /* "poison" the array to verify the operation of the zeroization */ ++ lrng_data_selftest[0] = 0xffffffff; ++ lrng_data_selftest[1] = 0xffffffff; ++ ++ lrng_data_process_selftest_insert(0); ++ /* ++ * Note, when using lrng_data_process_u32() on unaligned ptr, ++ * the first slots will go into next word, and the last slots go ++ * into the previous word. ++ */ ++ lrng_data_process_selftest_u32((4 << 0) | (1 << 8) | (2 << 16) | ++ (3 << 24)); ++ lrng_data_process_selftest_insert(5); ++ lrng_data_process_selftest_insert(6); ++ lrng_data_process_selftest_insert(7); ++ ++ if ((lrng_data_selftest[0] != idx_zero_compare) || ++ (lrng_data_selftest[1] != idx_one_compare)) ++ goto err; ++ ++ /* Reset for next test */ ++ lrng_data_selftest[0] = 0; ++ lrng_data_selftest[1] = 0; ++ lrng_data_selftest_ptr = 0; ++ ++ for (time = 0; time < LRNG_DATA_NUM_VALUES; time++) ++ lrng_data_process_selftest_insert(time); ++ ++ if ((lrng_data_selftest[0] != idx_zero_compare) || ++ (lrng_data_selftest[1] != idx_one_compare) || ++ (lrng_data_selftest[LRNG_DATA_ARRAY_SIZE - 1] != idx_last_compare)) ++ goto err; ++ ++ return LRNG_SELFTEST_PASSED; ++ ++err: ++ pr_err("LRNG data array self-test FAILED\n"); ++ return LRNG_SEFLTEST_ERROR_TIME; ++} ++ ++/* The test vectors are taken from crypto/testmgr.h */ ++static unsigned int lrng_hash_selftest(void) ++{ ++ SHASH_DESC_ON_STACK(shash, NULL); ++ const struct lrng_crypto_cb *crypto_cb = &lrng_cc20_crypto_cb; ++ static const u8 lrng_hash_selftest_result[] = ++#ifdef CONFIG_CRYPTO_LIB_SHA256 ++ { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, ++ 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, ++ 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, ++ 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }; ++#else /* CONFIG_CRYPTO_LIB_SHA256 */ ++ { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e, ++ 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c, 0x9c, 0xd0, 0xd8, 0x9d }; ++#endif /* CONFIG_CRYPTO_LIB_SHA256 */ ++ static const u8 hash_input[] = { 0x61, 0x62, 0x63 }; /* "abc" */ ++ u8 digest[sizeof(lrng_hash_selftest_result)] __aligned(sizeof(u32)); ++ ++ BUG_ON(sizeof(digest) != crypto_cb->lrng_hash_digestsize(NULL)); ++ ++ if (!crypto_cb->lrng_hash_init(shash, NULL) && ++ !crypto_cb->lrng_hash_update(shash, hash_input, ++ sizeof(hash_input)) && ++ !crypto_cb->lrng_hash_final(shash, digest) && ++ !memcmp(digest, lrng_hash_selftest_result, sizeof(digest))) ++ return 0; ++ ++ pr_err("LRNG %s Hash self-test FAILED\n", crypto_cb->lrng_hash_name()); ++ return LRNG_SEFLTEST_ERROR_HASH; ++} ++ ++/* ++ * The test vectors were generated using the ChaCha20 DRNG from ++ * https://www.chronox.de/chacha20.html ++ */ ++static unsigned int lrng_chacha20_drng_selftest(void) ++{ ++ const struct lrng_crypto_cb *crypto_cb = &lrng_cc20_crypto_cb; ++ u8 seed[CHACHA_KEY_SIZE * 2] = { ++ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, ++ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, ++ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, ++ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, ++ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, ++ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, ++ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, ++ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, ++ }; ++ struct chacha20_block chacha20; ++ int ret; ++ u8 outbuf[CHACHA_KEY_SIZE * 2] __aligned(sizeof(u32)); ++ ++ /* ++ * Expected result when ChaCha20 DRNG state is zero: ++ * * constants are set to "expand 32-byte k" ++ * * remaining state is 0 ++ * and pulling one half ChaCha20 DRNG block. ++ */ ++ static const u8 expected_halfblock[CHACHA_KEY_SIZE] = { ++ 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, ++ 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28, ++ 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, ++ 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7 }; ++ ++ /* ++ * Expected result when ChaCha20 DRNG state is zero: ++ * * constants are set to "expand 32-byte k" ++ * * remaining state is 0 ++ * followed by a reseed with two keyblocks ++ * 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, ++ * 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, ++ * 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, ++ * 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, ++ * 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, ++ * 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, ++ * 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, ++ * 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f ++ * and pulling one ChaCha20 DRNG block. ++ */ ++ static const u8 expected_oneblock[CHACHA_KEY_SIZE * 2] = { ++ 0xe3, 0xb0, 0x8a, 0xcc, 0x34, 0xc3, 0x17, 0x0e, ++ 0xc3, 0xd8, 0xc3, 0x40, 0xe7, 0x73, 0xe9, 0x0d, ++ 0xd1, 0x62, 0xa3, 0x5d, 0x7d, 0xf2, 0xf1, 0x4a, ++ 0x24, 0x42, 0xb7, 0x1e, 0xb0, 0x05, 0x17, 0x07, ++ 0xb9, 0x35, 0x10, 0x69, 0x8b, 0x46, 0xfb, 0x51, ++ 0xe9, 0x91, 0x3f, 0x46, 0xf2, 0x4d, 0xea, 0xd0, ++ 0x81, 0xc1, 0x1b, 0xa9, 0x5d, 0x52, 0x91, 0x5f, ++ 0xcd, 0xdc, 0xc6, 0xd6, 0xc3, 0x7c, 0x50, 0x23 }; ++ ++ /* ++ * Expected result when ChaCha20 DRNG state is zero: ++ * * constants are set to "expand 32-byte k" ++ * * remaining state is 0 ++ * followed by a reseed with one key block plus one byte ++ * 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, ++ * 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, ++ * 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, ++ * 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, ++ * 0x20 ++ * and pulling less than one ChaCha20 DRNG block. ++ */ ++ static const u8 expected_block_nonalinged[CHACHA_KEY_SIZE + 4] = { ++ 0x9c, 0xfc, 0x5e, 0x31, 0x21, 0x62, 0x11, 0x85, ++ 0xd3, 0x77, 0xd3, 0x69, 0x0f, 0xa8, 0x16, 0x55, ++ 0xb4, 0x4c, 0xf6, 0x52, 0xf3, 0xa8, 0x37, 0x99, ++ 0x38, 0x76, 0xa0, 0x66, 0xec, 0xbb, 0xce, 0xa9, ++ 0x9c, 0x95, 0xa1, 0xfd }; ++ ++ BUILD_BUG_ON(sizeof(seed) % sizeof(u32)); ++ ++ memset(&chacha20, 0, sizeof(chacha20)); ++ lrng_cc20_init_rfc7539(&chacha20); ++ lrng_selftest_bswap32((u32 *)seed, sizeof(seed) / sizeof(u32)); ++ ++ /* Generate with zero state */ ++ ret = crypto_cb->lrng_drng_generate_helper(&chacha20, outbuf, ++ sizeof(expected_halfblock)); ++ if (ret != sizeof(expected_halfblock)) ++ goto err; ++ if (memcmp(outbuf, expected_halfblock, sizeof(expected_halfblock))) ++ goto err; ++ ++ /* Clear state of DRNG */ ++ memset(&chacha20.key.u[0], 0, 48); ++ ++ /* Reseed with 2 key blocks */ ++ ret = crypto_cb->lrng_drng_seed_helper(&chacha20, seed, ++ sizeof(expected_oneblock)); ++ if (ret < 0) ++ goto err; ++ ret = crypto_cb->lrng_drng_generate_helper(&chacha20, outbuf, ++ sizeof(expected_oneblock)); ++ if (ret != sizeof(expected_oneblock)) ++ goto err; ++ if (memcmp(outbuf, expected_oneblock, sizeof(expected_oneblock))) ++ goto err; ++ ++ /* Clear state of DRNG */ ++ memset(&chacha20.key.u[0], 0, 48); ++ ++ /* Reseed with 1 key block and one byte */ ++ ret = crypto_cb->lrng_drng_seed_helper(&chacha20, seed, ++ sizeof(expected_block_nonalinged)); ++ if (ret < 0) ++ goto err; ++ ret = crypto_cb->lrng_drng_generate_helper(&chacha20, outbuf, ++ sizeof(expected_block_nonalinged)); ++ if (ret != sizeof(expected_block_nonalinged)) ++ goto err; ++ if (memcmp(outbuf, expected_block_nonalinged, ++ sizeof(expected_block_nonalinged))) ++ goto err; ++ ++ return LRNG_SELFTEST_PASSED; ++ ++err: ++ pr_err("LRNG ChaCha20 DRNG self-test FAILED\n"); ++ return LRNG_SEFLTEST_ERROR_CHACHA20; ++} ++ ++static int lrng_selftest(void) ++{ ++ unsigned int ret = lrng_data_process_selftest(); ++ ++ ret |= lrng_chacha20_drng_selftest(); ++ ret |= lrng_hash_selftest(); ++ ++ if (ret) { ++ if (IS_ENABLED(CONFIG_LRNG_SELFTEST_PANIC)) ++ panic("LRNG self-tests failed: %u\n", ret); ++ } else { ++ pr_info("LRNG self-tests passed\n"); ++ } ++ ++ lrng_selftest_status = ret; ++ ++ if (lrng_selftest_status) ++ return -EFAULT; ++ return 0; ++} ++ ++#ifdef CONFIG_SYSFS ++/* Re-perform self-test when any value is written to the sysfs file. */ ++static int lrng_selftest_sysfs_set(const char *val, ++ const struct kernel_param *kp) ++{ ++ return lrng_selftest(); ++} ++ ++static const struct kernel_param_ops lrng_selftest_sysfs = { ++ .set = lrng_selftest_sysfs_set, ++ .get = param_get_uint, ++}; ++module_param_cb(selftest_status, &lrng_selftest_sysfs, &lrng_selftest_status, ++ 0644); ++#endif /* CONFIG_SYSFS */ ++ ++static int __init lrng_selftest_init(void) ++{ ++ return lrng_selftest(); ++} ++ ++module_init(lrng_selftest_init); diff --git a/PATCH/LRNG/696-17-v41-01-remove_compat_ioctl.patch b/PATCH/LRNG/696-17-v41-01-remove_compat_ioctl.patch new file mode 100644 index 000000000..96949bdcb --- /dev/null +++ b/PATCH/LRNG/696-17-v41-01-remove_compat_ioctl.patch @@ -0,0 +1,18 @@ +--- a/drivers/char/lrng/lrng_interfaces.c ++++ b/drivers/char/lrng/lrng_interfaces.c +@@ -610,7 +610,6 @@ const struct file_operations random_fops + .write = lrng_drng_write, + .poll = lrng_random_poll, + .unlocked_ioctl = lrng_ioctl, +- .compat_ioctl = compat_ptr_ioctl, + .fasync = lrng_fasync, + .llseek = noop_llseek, + }; +@@ -619,7 +618,6 @@ const struct file_operations urandom_fop + .read = lrng_drng_read, + .write = lrng_drng_write, + .unlocked_ioctl = lrng_ioctl, +- .compat_ioctl = compat_ptr_ioctl, + .fasync = lrng_fasync, + .llseek = noop_llseek, + }; diff --git a/PATCH/LRNG/696-18-v41-02-jitterentropy_remove_RCT_APT.patch b/PATCH/LRNG/696-18-v41-02-jitterentropy_remove_RCT_APT.patch new file mode 100644 index 000000000..80b85e462 --- /dev/null +++ b/PATCH/LRNG/696-18-v41-02-jitterentropy_remove_RCT_APT.patch @@ -0,0 +1,15 @@ +--- a/crypto/jitterentropy.c ++++ b/crypto/jitterentropy.c +@@ -655,12 +655,6 @@ struct rand_data *jent_lrng_entropy_coll + .memblocks = JENT_MEMORY_BLOCKSIZE, + .memblocksize = JENT_MEMORY_BLOCKS, + .memaccessloops = JENT_MEMORY_ACCESSLOOPS, +- .rct_count = 0, +- .apt_observations = 0, +- .apt_count = 0, +- .apt_base = 0, +- .apt_base_set = 0, +- .health_failure = 0 + }; + + if (jent_entropy_init()) diff --git a/PATCH/LRNG/696-19-v41-03-arch_random_early.patch b/PATCH/LRNG/696-19-v41-03-arch_random_early.patch new file mode 100644 index 000000000..73fa9f53e --- /dev/null +++ b/PATCH/LRNG/696-19-v41-03-arch_random_early.patch @@ -0,0 +1,13 @@ +--- a/drivers/char/lrng/lrng_pool.c ++++ b/drivers/char/lrng/lrng_pool.c +@@ -324,8 +324,8 @@ int __init rand_initialize(void) + seed.time = ktime_get_real(); + + for (i = 0; i < ARRAY_SIZE(seed.data); i++) { +- if (!arch_get_random_seed_long_early(&(seed.data[i])) && +- !arch_get_random_long_early(&seed.data[i])) ++ if (!arch_get_random_seed_long(&(seed.data[i])) && ++ !arch_get_random_long(&seed.data[i])) + seed.data[i] = random_get_entropy(); + } + memcpy(&seed.utsname, utsname(), sizeof(*(utsname()))); diff --git a/PATCH/LRNG/696-20-v41-04-net_rand_state.patch b/PATCH/LRNG/696-20-v41-04-net_rand_state.patch new file mode 100644 index 000000000..f066f1e4e --- /dev/null +++ b/PATCH/LRNG/696-20-v41-04-net_rand_state.patch @@ -0,0 +1,10 @@ +--- a/drivers/char/lrng/lrng_sw_noise.c ++++ b/drivers/char/lrng/lrng_sw_noise.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + + #include "lrng_internal.h" + #include "lrng_sw_noise.h" diff --git a/PATCH/LRNG/696-21-v41-05-kzfree.patch b/PATCH/LRNG/696-21-v41-05-kzfree.patch new file mode 100644 index 000000000..774a6d119 --- /dev/null +++ b/PATCH/LRNG/696-21-v41-05-kzfree.patch @@ -0,0 +1,44 @@ +--- a/drivers/char/lrng/lrng_chacha20.c ++++ b/drivers/char/lrng/lrng_chacha20.c +@@ -182,7 +182,7 @@ static void lrng_cc20_drng_dealloc(void + } + + pr_debug("ChaCha20 core zeroized and freed\n"); +- kfree_sensitive(chacha20_state); ++ kzfree(chacha20_state); + } + + /******************************* Hash Operation *******************************/ +--- a/drivers/char/lrng/lrng_drbg.c ++++ b/drivers/char/lrng/lrng_drbg.c +@@ -140,7 +140,7 @@ static void lrng_drbg_drng_dealloc(void + if (drbg && drbg->d_ops) + drbg->d_ops->crypto_fini(drbg); + drbg_dealloc_state(drbg); +- kfree_sensitive(drbg); ++ kzfree(drbg); + pr_info("DRBG deallocated\n"); + } + +--- a/drivers/char/lrng/lrng_interfaces.c ++++ b/drivers/char/lrng/lrng_interfaces.c +@@ -431,7 +431,7 @@ static ssize_t lrng_read_common(char __u + + /* Wipe data just returned from memory */ + if (tmp_large) +- kfree_sensitive(tmp_large); ++ kzfree(tmp_large); + else + memzero_explicit(tmpbuf, sizeof(tmpbuf)); + +--- a/drivers/char/lrng/lrng_testing.c ++++ b/drivers/char/lrng/lrng_testing.c +@@ -236,7 +236,7 @@ static int lrng_testing_extract_user(str + ret += i; + } + +- kfree_sensitive(tmp); ++ kzfree(tmp); + + if (ret > 0) + *ppos += ret; diff --git a/PATCH/LRNG/696-22-v41-06-sha-includes.patch b/PATCH/LRNG/696-22-v41-06-sha-includes.patch new file mode 100644 index 000000000..41852b792 --- /dev/null +++ b/PATCH/LRNG/696-22-v41-06-sha-includes.patch @@ -0,0 +1,32 @@ +--- a/drivers/char/lrng/lrng_internal.h ++++ b/drivers/char/lrng/lrng_internal.h +@@ -6,8 +6,7 @@ + #ifndef _LRNG_INTERNAL_H + #define _LRNG_INTERNAL_H + +-#include +-#include ++#include + #include + #include + #include +--- a/drivers/char/lrng/lrng_chacha20.c ++++ b/drivers/char/lrng/lrng_chacha20.c +@@ -189,7 +189,7 @@ static void lrng_cc20_drng_dealloc(void + + #ifdef CONFIG_CRYPTO_LIB_SHA256 + +-#include ++#include + + static u32 lrng_cc20_hash_digestsize(void *hash) + { +@@ -231,7 +231,7 @@ static void lrng_cc20_hash_desc_zero(str + + #else /* CONFIG_CRYPTO_LIB_SHA256 */ + +-#include ++#include + #include + + /* diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 95250684d..221dad843 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -41,6 +41,12 @@ wget https://github.com/hamadmarri/cacule-cpu-scheduler/raw/master/patches/CacUL #wget https://github.com/hamadmarri/cacule-cpu-scheduler/raw/vR2.1/patches/CacULE/v5.4/cacule-5.4.patch -O ./target/linux/generic/hack-5.4/694-cacule-5.4.patch # UKSM cp -f ../PATCH/UKSM/695-uksm-5.4.patch ./target/linux/generic/hack-5.4/695-uksm-5.4.patch +# LRNG +cp -rf ../PATCH/LRNG/* ./target/linux/generic/hack-5.4/ +echo ' +CONFIG_LRNG=y +CONFIG_LRNG_JENT=y +' >> ./target/linux/generic/config-5.4 # Grub 2 wget -qO - https://github.com/QiuSimons/openwrt-NoTengoBattery/commit/afed16a.patch | patch -p1 # Haproxy From 74d6d58719ff56844afcf2e5a82af88059ff55f1 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 26 Aug 2021 11:50:57 +0800 Subject: [PATCH 182/244] Update ChinaDNS-NG --- SCRIPTS/02_prepare_package.sh | 4 ++-- SEED/R2C/config.seed | 1 + SEED/R2S/config.seed | 1 + SEED/R4S/config.seed | 1 + SEED/X86/config.seed | 1 + 5 files changed, 6 insertions(+), 2 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 221dad843..9bd5da898 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -158,7 +158,7 @@ svn co https://github.com/QiuSimons/slim-wrt/branches/main/slimapps/application/ rm -rf ./feeds/packages/net/miniupnpd svn co https://github.com/openwrt/packages/trunk/net/miniupnpd feeds/packages/net/miniupnpd # ChinaDNS -git clone -b luci --depth 1 https://github.com/pexcn/openwrt-chinadns-ng.git package/new/luci-app-chinadns-ng +git clone -b luci --depth 1 https://github.com/QiuSimons/openwrt-chinadns-ng.git package/new/luci-app-chinadns-ng svn co https://github.com/xiaorouji/openwrt-passwall/trunk/chinadns-ng package/new/chinadns-ng # 内存压缩 #wget -O- https://patch-diff.githubusercontent.com/raw/openwrt/openwrt/pull/2840.patch | patch -p1 @@ -389,7 +389,7 @@ svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/addition-trans-zh package/ # Lets Fuck mkdir package/base-files/files/usr/bin wget -P package/base-files/files/usr/bin/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/fuck -wget -P package/base-files/files/usr/bin/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/chinadnslist +#wget -P package/base-files/files/usr/bin/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/chinadnslist #wget -P package/base-files/files/usr/bin/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/setdns # 最大连接数 sed -i 's/16384/65535/g' package/kernel/linux/files/sysctl-nf-conntrack.conf diff --git a/SEED/R2C/config.seed b/SEED/R2C/config.seed index 67d17824a..8caf4bdb1 100644 --- a/SEED/R2C/config.seed +++ b/SEED/R2C/config.seed @@ -91,6 +91,7 @@ CONFIG_PACKAGE_luci-app-argon-config=y CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y CONFIG_PACKAGE_luci-app-boostupnp=y +CONFIG_PACKAGE_luci-app-chinadns-ng=y CONFIG_PACKAGE_luci-app-control-weburl=y CONFIG_PACKAGE_luci-app-cpufreq=y CONFIG_PACKAGE_luci-app-cpulimit=y diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 8768f8415..a326dc954 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -91,6 +91,7 @@ CONFIG_PACKAGE_luci-app-argon-config=y CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y CONFIG_PACKAGE_luci-app-boostupnp=y +CONFIG_PACKAGE_luci-app-chinadns-ng=y CONFIG_PACKAGE_luci-app-control-weburl=y CONFIG_PACKAGE_luci-app-cpufreq=y CONFIG_PACKAGE_luci-app-cpulimit=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index e38091c00..bc9c6e683 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -92,6 +92,7 @@ CONFIG_PACKAGE_luci-app-argon-config=y CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y CONFIG_PACKAGE_luci-app-boostupnp=y +CONFIG_PACKAGE_luci-app-chinadns-ng=y CONFIG_PACKAGE_luci-app-control-weburl=y CONFIG_PACKAGE_luci-app-cpufreq=y CONFIG_PACKAGE_luci-app-cpulimit=y diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index ec530887a..86371953e 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -92,6 +92,7 @@ CONFIG_PACKAGE_luci-app-argon-config=y CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y CONFIG_PACKAGE_luci-app-boostupnp=y +CONFIG_PACKAGE_luci-app-chinadns-ng=y CONFIG_PACKAGE_luci-app-control-weburl=y CONFIG_PACKAGE_luci-app-cpufreq=y CONFIG_PACKAGE_luci-app-cpulimit=y From 61202ce808daea727c64cd65c9aff00f585d41aa Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 26 Aug 2021 17:30:36 +0800 Subject: [PATCH 183/244] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 539b8e3d1..702f047b6 100644 --- a/README.md +++ b/README.md @@ -25,13 +25,13 @@ - 基于原生 OpenWrt 21.02 编译,默认管理地址192.168.1.1 - 默认开启了 Software Offload - 内置升级功能可用,物理 Reset 按键可用 -- 预配置了部分插件(包括但不限于 DNS 套娃,(注意,6月29日开始取消了dns套娃,使用dnsfilter作为广告过滤手段,使用dnsproxy作为dns分流措施,海外端口5335,国内端口6050。) +- 预配置了部分插件(包括但不限于 DNS 套娃,(注意,使用dnsfilter作为广告过滤手段,使用dnsproxy作为dns分流措施,海外端口6051,国内端口6050,chinadns-ng监听端口5335。) - 可无脑 opkg kmod - R2C/R2S核心频率1.6(交换了LAN WAN),R4S核心频率2.2/1.8(建议使用5v4a电源,死机大多数情况下,都是因为你用的电源过于垃圾,另外,你也可以选择使用自带的app限制最大频率,茄子🍆) - O3 编译,CFLAG优化 - 插件包含:SSRP,PassWall,OpenClash,AdguardHome,微信推送,网易云解锁,SQM,DNSProxy,网络唤醒,DDNS,迅雷快鸟,UPNP,FullCone(防火墙中开启,默认开启),流量分载,irq优化,京东签到,Zerotier,FRPC,FRPS,无线打印,流量监控,过滤军刀,R2S-OLED - ss协议在armv8上实现了aes硬件加速(请仅使用aead加密的连接方式) -- 集成并默认启用了UKSM,BBRv2,以及CacULE Scheduler +- 集成并默认启用了UKSM,BBRv2,LRNG,以及CacULE Scheduler - 如有任何问题,请先尝试ssh进入后台,输入fuck后回车,等待机器重启后确认问题是否已经解决 ### 下载 From 1ed082ac84f4ec7b6a4f77b9c3f1447cec8371cf Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 1 Sep 2021 23:27:18 +0800 Subject: [PATCH 184/244] 21.02.0 --- .github/workflows/R2C-OpenWrt.yml | 4 ++-- .github/workflows/R2S-OpenWrt.yml | 4 ++-- .github/workflows/R4S-OpenWrt.yml | 4 ++-- .github/workflows/X86-OpenWrt.yml | 4 ++-- SCRIPTS/02_prepare_package.sh | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/R2C-OpenWrt.yml b/.github/workflows/R2C-OpenWrt.yml index 2aefd5a03..4fda15d5b 100644 --- a/.github/workflows/R2C-OpenWrt.yml +++ b/.github/workflows/R2C-OpenWrt.yml @@ -138,9 +138,9 @@ jobs: id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-21.02.0-RC4 + name: OpenWRT-21.02.0 allowUpdates: true - tag: 21.02.0-rc4 + tag: 21.02.0 commit: master replacesArtifacts: true token: ${{ secrets.workflow_token }} diff --git a/.github/workflows/R2S-OpenWrt.yml b/.github/workflows/R2S-OpenWrt.yml index 98db410fc..65171ccdb 100644 --- a/.github/workflows/R2S-OpenWrt.yml +++ b/.github/workflows/R2S-OpenWrt.yml @@ -136,9 +136,9 @@ jobs: id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-21.02.0-RC4 + name: OpenWRT-21.02.0 allowUpdates: true - tag: 21.02.0-rc4 + tag: 21.02.0 commit: master replacesArtifacts: true token: ${{ secrets.workflow_token }} diff --git a/.github/workflows/R4S-OpenWrt.yml b/.github/workflows/R4S-OpenWrt.yml index 1973c97cf..3ba326c88 100644 --- a/.github/workflows/R4S-OpenWrt.yml +++ b/.github/workflows/R4S-OpenWrt.yml @@ -136,9 +136,9 @@ jobs: id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-21.02.0-RC4 + name: OpenWRT-21.02.0 allowUpdates: true - tag: 21.02.0-rc4 + tag: 21.02.0 commit: master replacesArtifacts: true token: ${{ secrets.workflow_token }} diff --git a/.github/workflows/X86-OpenWrt.yml b/.github/workflows/X86-OpenWrt.yml index 650a14652..5c6ef6c3d 100644 --- a/.github/workflows/X86-OpenWrt.yml +++ b/.github/workflows/X86-OpenWrt.yml @@ -136,9 +136,9 @@ jobs: id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-21.02.0-RC4 + name: OpenWRT-21.02.0 allowUpdates: true - tag: 21.02.0-rc4 + tag: 21.02.0 commit: master replacesArtifacts: true token: ${{ secrets.workflow_token }} diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 9bd5da898..324b87961 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -271,9 +271,6 @@ svn co https://github.com/xiaorouji/openwrt-passwall/trunk/trojan-go package/new svn co https://github.com/xiaorouji/openwrt-passwall/trunk/brook package/new/brook svn co https://github.com/xiaorouji/openwrt-passwall/trunk/trojan-plus package/new/trojan-plus svn co https://github.com/xiaorouji/openwrt-passwall/trunk/ssocks package/new/ssocks -svn co https://github.com/xiaorouji/openwrt-passwall/trunk/xray-core package/new/xray-core -svn co https://github.com/xiaorouji/openwrt-passwall/trunk/v2ray-plugin package/new/v2ray-plugin -svn co https://github.com/xiaorouji/openwrt-passwall/trunk/xray-plugin package/new/xray-plugin svn co https://github.com/xiaorouji/openwrt-passwall/trunk/hysteria package/new/hysteria # qBittorrent 下载 svn co https://github.com/garypang13/openwrt-static-qb/trunk/qBittorrent-Enhanced-Edition package/lean/qBittorrent-Enhanced-Edition @@ -307,6 +304,9 @@ svn co https://github.com/coolsnowwolf/packages/trunk/net/shadowsocks-libev pack svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/trojan package/lean/trojan svn co https://github.com/fw876/helloworld/trunk/naiveproxy package/lean/naiveproxy svn co https://github.com/fw876/helloworld/trunk/v2ray-core package/lean/v2ray-core +svn co https://github.com/fw876/helloworld/trunk/xray-core package/new/xray-core +svn co https://github.com/fw876/helloworld/trunk/v2ray-plugin package/new/v2ray-plugin +svn co https://github.com/fw876/helloworld/trunk/xray-plugin package/new/xray-plugin svn co https://github.com/immortalwrt/packages/trunk/net/shadowsocks-rust feeds/packages/net/shadowsocks-rust ln -sf ../../../feeds/packages/net/shadowsocks-rust ./package/feeds/packages/shadowsocks-rust svn co https://github.com/immortalwrt/packages/trunk/net/kcptun feeds/packages/net/kcptun From 27c25566f77f7a364e0a1a58d7f8efe9a21d8f9c Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 8 Sep 2021 19:52:13 +0800 Subject: [PATCH 185/244] Fix --- SCRIPTS/01_get_ready.sh | 10 +--- SCRIPTS/02_prepare_package.sh | 101 +++++++++++----------------------- SCRIPTS/R2S/02_target_only.sh | 4 -- SCRIPTS/R4S/02_target_only.sh | 4 -- 4 files changed, 34 insertions(+), 85 deletions(-) diff --git a/SCRIPTS/01_get_ready.sh b/SCRIPTS/01_get_ready.sh index c4ee97996..89a283398 100644 --- a/SCRIPTS/01_get_ready.sh +++ b/SCRIPTS/01_get_ready.sh @@ -1,11 +1,7 @@ #!/bin/bash -latest_release="$(curl -s https://github.com/openwrt/openwrt/releases |grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" |sed -n '/21/p' |sed -n 1p)" -curl -LO "https://github.com/openwrt/openwrt/archive/${latest_release}" -mkdir openwrt_back -shopt -s extglob -tar zxvf ${latest_release} --strip-components 1 -C ./openwrt_back -rm -f ${latest_release} +latest_release="$(curl -s https://github.com/openwrt/openwrt/releases |grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" |sed -n '/21/p' |sed -n 1p |sed 's/.tar.gz//g')" +git clone --single-branch -b ${latest_release} https://github.com/openwrt/openwrt openwrt_back git clone --single-branch -b openwrt-21.02 https://github.com/openwrt/openwrt openwrt_new rm -f ./openwrt_new/include/version.mk rm -f ./openwrt_new/include/kernel-version.mk @@ -20,7 +16,7 @@ cp -rf ./openwrt_new/* ./openwrt/ # 获取源代码 #git clone --single-branch -b openwrt-21.02 https://github.com/openwrt/openwrt openwrt -git clone -b main --depth 1 https://github.com/Lienol/openwrt.git openwrt-lienol +#git clone -b main --depth 1 https://github.com/Lienol/openwrt.git openwrt-lienol #git clone -b main --depth 1 https://github.com/Lienol/openwrt-packages packages-lienol #git clone -b main --depth 1 https://github.com/Lienol/openwrt-luci luci-lienol #git clone -b linksys-ea6350v3-mastertrack --depth 1 https://github.com/NoTengoBattery/openwrt NoTengoBattery diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 324b87961..8d845ce81 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -17,7 +17,6 @@ rm -rf ./scripts/download.pl rm -rf ./include/download.mk wget -P scripts/ https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/scripts/download.pl wget -P include/ https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/include/download.mk -#wget -P include/ https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/include/package-immortalwrt.mk sed -i '/unshift/d' scripts/download.pl sed -i '/mirror02/d' scripts/download.pl echo "net.netfilter.nf_conntrack_helper = 1" >> ./package/kernel/linux/files/sysctl-nf-conntrack.conf @@ -38,7 +37,6 @@ wget -qO - https://github.com/openwrt/openwrt/commit/cfaf039.patch | patch -p1 # CacULE wget -qO - https://github.com/QiuSimons/openwrt-NoTengoBattery/commit/7d44cab.patch | patch -p1 wget https://github.com/hamadmarri/cacule-cpu-scheduler/raw/master/patches/CacULE/v5.4/cacule-5.4.patch -O ./target/linux/generic/hack-5.4/694-cacule-5.4.patch -#wget https://github.com/hamadmarri/cacule-cpu-scheduler/raw/vR2.1/patches/CacULE/v5.4/cacule-5.4.patch -O ./target/linux/generic/hack-5.4/694-cacule-5.4.patch # UKSM cp -f ../PATCH/UKSM/695-uksm-5.4.patch ./target/linux/generic/hack-5.4/695-uksm-5.4.patch # LRNG @@ -66,23 +64,11 @@ popd # Patch FireWall 以增添 FullCone 功能 mkdir package/network/config/firewall/patches wget -P package/network/config/firewall/patches/ https://github.com/immortalwrt/immortalwrt/raw/master/package/network/config/firewall/patches/fullconenat.patch -wget -qO- https://github.com/msylgj/R2S-R4S-OpenWrt/raw/21.02/SCRIPTS/fix_firewall_flock.patch | patch -p1 +wget -qO- https://github.com/msylgj/R2S-R4S-OpenWrt/raw/21.02/PATCHES/001-fix-firewall-flock.patch | patch -p1 # Patch LuCI 以增添 FullCone 开关 patch -p1 < ../PATCH/firewall/luci-app-firewall_add_fullcone.patch # FullCone 相关组件 -cp -rf ../openwrt-lienol/package/network/fullconenat ./package/network/fullconenat - -### Shortcut-FE 部分 ### -# Patch Kernel 以支持 Shortcut-FE -#pushd target/linux/generic/hack-5.4 -#wget https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/generic/hack-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch -#popd -# Patch LuCI 以增添 Shortcut-FE 开关 -#patch -p1 < ../PATCH/firewall/luci-app-firewall_add_sfe_switch.patch -# Shortcut-FE 相关组件 -#svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/shortcut-fe package/lean/shortcut-fe -#svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/fast-classifier package/lean/fast-classifier -#wget -P package/base-files/files/etc/init.d/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/shortcut-fe +svn co https://github.com/Lienol/openwrt/trunk/package/network/fullconenat package/network/fullconenat ### 获取额外的基础软件包 ### # 更换为 ImmortalWrt Uboot 以及 Target @@ -91,6 +77,8 @@ svn co https://github.com/immortalwrt/immortalwrt/branches/master/target/linux/r rm -rf ./package/boot/uboot-rockchip svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/boot/uboot-rockchip package/boot/uboot-rockchip svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/boot/arm-trusted-firmware-rockchip-vendor package/boot/arm-trusted-firmware-rockchip-vendor +rm -rf ./package/kernel/linux/modules/video.mk +wget -P package/kernel/linux/modules/ https://github.com/immortalwrt/immortalwrt/raw/master/package/kernel/linux/modules/video.mk # R4S超频到 2.2/1.8 GHz rm -rf ./target/linux/rockchip/patches-5.4/992-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch cp -f ../PATCH/target_r4s/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch ./target/linux/rockchip/patches-5.4/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch @@ -118,7 +106,6 @@ rm -rf ./feeds/packages/lang/node-yarn svn co https://github.com/nxhack/openwrt-node-packages/trunk/node-yarn feeds/packages/lang/node-yarn ln -sf ../../../feeds/packages/lang/node-yarn ./package/feeds/packages/node-yarn # R8168驱动 -#svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/kernel/r8168 package/new/r8168 git clone -b master --depth 1 https://github.com/BROBIRD/openwrt-r8168.git package/new/r8168 patch -p1 < ../PATCH/r8168/r8168-fix_LAN_led-for_r4s-from_TL.patch # R8152驱动 @@ -137,16 +124,13 @@ svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/luci-app-control-weburl pa svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-adbyby-plus package/lean/luci-app-adbyby-plus svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/adbyby package/lean/adbyby # 广告过滤 AdGuard -cp -rf ../openwrt-lienol/package/diy/luci-app-adguardhome ./package/new/luci-app-adguardhome +svn co https://github.com/Lienol/openwrt/trunk/package/diy/luci-app-adguardhome package/new/luci-app-adguardhome rm -rf ./feeds/packages/net/adguardhome svn co https://github.com/openwrt/packages/trunk/net/adguardhome feeds/packages/net/adguardhome sed -i '/\t)/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/AdGuardHome' ./feeds/packages/net/adguardhome/Makefile sed -i '/init/d' feeds/packages/net/adguardhome/Makefile # Argon 主题 git clone -b master --depth 1 https://github.com/jerrykuku/luci-theme-argon.git package/new/luci-theme-argon -#wget -P ./package/new/luci-theme-argon/htdocs/luci-static/argon/css/ -N https://github.com/msylgj/luci-theme-argon/raw/patch-1/htdocs/luci-static/argon/css/dark.css -#wget -P ./package/new/luci-theme-argon/luasrc/view/themes/argon -N https://github.com/jerrykuku/luci-theme-argon/raw/9fdcfc866ca80d8d094d554c6aedc18682661973/luasrc/view/themes/argon/footer.htm -#wget -P ./package/new/luci-theme-argon/luasrc/view/themes/argon -N https://github.com/jerrykuku/luci-theme-argon/raw/9fdcfc866ca80d8d094d554c6aedc18682661973/luasrc/view/themes/argon/header.htm git clone -b master --depth 1 https://github.com/jerrykuku/luci-app-argon-config.git package/new/luci-app-argon-config # MAC 地址与 IP 绑定 svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-arpbind feeds/luci/applications/luci-app-arpbind @@ -160,15 +144,6 @@ svn co https://github.com/openwrt/packages/trunk/net/miniupnpd feeds/packages/ne # ChinaDNS git clone -b luci --depth 1 https://github.com/QiuSimons/openwrt-chinadns-ng.git package/new/luci-app-chinadns-ng svn co https://github.com/xiaorouji/openwrt-passwall/trunk/chinadns-ng package/new/chinadns-ng -# 内存压缩 -#wget -O- https://patch-diff.githubusercontent.com/raw/openwrt/openwrt/pull/2840.patch | patch -p1 -#wget -O- https://github.com/NoTengoBattery/openwrt/commit/40f1d5.patch | patch -p1 -#wget -O- https://github.com/NoTengoBattery/openwrt/commit/a83a0b.patch | patch -p1 -#wget -O- https://github.com/NoTengoBattery/openwrt/commit/6d5fb4.patch | patch -p1 -#mkdir ./package/new -#cp -rf ../NoTengoBattery/feeds/luci/applications/luci-app-compressed-memory ./package/new/luci-app-compressed-memory -#sed -i 's,include ../..,include $(TOPDIR)/feeds/luci,g' ./package/new/luci-app-compressed-memory/Makefile -#cp -rf ../NoTengoBattery/package/system/compressed-memory ./package/system/compressed-memory # CPU 控制相关 svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-cpufreq feeds/luci/applications/luci-app-cpufreq ln -sf ../../../feeds/luci/applications/luci-app-cpufreq ./package/feeds/luci/luci-app-cpufreq @@ -179,12 +154,6 @@ svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/luci-app-cpulimit package/ svn co https://github.com/immortalwrt/packages/trunk/utils/cpulimit feeds/packages/utils/cpulimit ln -sf ../../../feeds/packages/utils/cpulimit ./package/feeds/packages/cpulimit # 动态DNS -#rm -rf ./feeds/packages/net/ddns-scripts -#rm -rf ./feeds/luci/applications/luci-app-ddns -#svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/ddns-scripts_aliyun package/lean/ddns-scripts_aliyun -#svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/ddns-scripts_dnspod package/lean/ddns-scripts_dnspod -#svn co https://github.com/openwrt/packages/branches/openwrt-18.06/net/ddns-scripts feeds/packages/net/ddns-scripts -#svn co https://github.com/openwrt/luci/branches/openwrt-18.06/applications/luci-app-ddns feeds/luci/applications/luci-app-ddns git clone --depth 1 https://github.com/small-5/ddns-scripts-dnspod package/lean/ddns-scripts_dnspod git clone --depth 1 https://github.com/small-5/ddns-scripts-aliyun package/lean/ddns-scripts_aliyun svn co https://github.com/QiuSimons/OpenWrt_luci-app/trunk/luci-app-tencentddns package/lean/luci-app-tencentddns @@ -216,15 +185,6 @@ svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/ipv6-helper packa # 京东签到 By Jerrykuku git clone --depth 1 https://github.com/jerrykuku/node-request.git package/new/node-request git clone --depth 1 https://github.com/jerrykuku/luci-app-jd-dailybonus.git package/new/luci-app-jd-dailybonus -#pushd package/new/luci-app-jd-dailybonus -#sed -i 's,wget-ssl,wget,g' root/usr/share/jd-dailybonus/newapp.sh luasrc/controller/jd-dailybonus.lua -#sed -i 's,* sh,*,g' root/usr/share/jd-dailybonus/newapp.sh -#popd -#rm -rf ./package/new/luci-app-jd-dailybonus/root/usr/share/jd-dailybonus/JD_DailyBonus.js -#wget -P package/new/luci-app-jd-dailybonus/root/usr/share/jd-dailybonus/ https://github.com/NobyDa/Script/raw/master/JD-DailyBonus/JD_DailyBonus.js -# 回滚通用即插即用 -#rm -rf ./feeds/packages/net/miniupnpd -#svn co https://github.com/coolsnowwolf/packages/trunk/net/miniupnpd feeds/packages/net/miniupnpd # MentoHUST git clone --depth 1 https://github.com/BoringCat/luci-app-mentohust package/new/luci-app-mentohust git clone --depth 1 https://github.com/KyleRicardo/MentoHUST-OpenWrt-ipk package/new/MentoHUST @@ -242,23 +202,15 @@ git clone -b master --depth 1 https://github.com/destan19/OpenAppFilter.git pack git clone -b master --depth 1 https://github.com/NateLol/luci-app-oled.git package/new/luci-app-oled # OpenClash git clone --single-branch --depth 1 -b dev https://github.com/vernesong/OpenClash.git package/new/luci-app-openclash -pushd package/new/luci-app-openclash -#wget -qO - https://github.com/vernesong/OpenClash/pull/1499.patch | patch -p1 -popd # 花生壳内网穿透 -#svn co https://github.com/QiuSimons/dragino2-teasiu/trunk/package/teasiu/luci-app-phtunnel package/new/luci-app-phtunnel -#svn co https://github.com/QiuSimons/dragino2-teasiu/trunk/package/teasiu/phtunnel package/new/phtunnel svn co https://github.com/teasiu/dragino2/trunk/devices/common/diy/package/teasiu/luci-app-phtunnel package/new/luci-app-phtunnel svn co https://github.com/teasiu/dragino2/trunk/devices/common/diy/package/teasiu/phtunnel package/new/phtunnel svn co https://github.com/QiuSimons/dragino2-teasiu/trunk/package/teasiu/luci-app-oray package/new/luci-app-oray -# Pandownload -#svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/lean/pandownload-fake-server package/lean/pandownload-fake-server # Passwall svn co https://github.com/xiaorouji/openwrt-passwall/trunk/luci-app-passwall package/new/luci-app-passwall sed -i 's,default n,default y,g' package/new/luci-app-passwall/Makefile sed -i '/V2ray:v2ray/d' package/new/luci-app-passwall/Makefile sed -i '/plugin:v2ray/d' package/new/luci-app-passwall/Makefile -#sed -i '/Proxy:naive/d' package/new/luci-app-passwall/Makefile wget -P package/new/luci-app-passwall/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/move_2_services.sh chmod -R 755 ./package/new/luci-app-passwall/move_2_services.sh pushd package/new/luci-app-passwall @@ -273,10 +225,12 @@ svn co https://github.com/xiaorouji/openwrt-passwall/trunk/trojan-plus package/n svn co https://github.com/xiaorouji/openwrt-passwall/trunk/ssocks package/new/ssocks svn co https://github.com/xiaorouji/openwrt-passwall/trunk/hysteria package/new/hysteria # qBittorrent 下载 -svn co https://github.com/garypang13/openwrt-static-qb/trunk/qBittorrent-Enhanced-Edition package/lean/qBittorrent-Enhanced-Edition -sed -i 's/4.3.3.10/4.3.4.10/g' package/lean/qBittorrent-Enhanced-Edition/Makefile -svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-qbittorrent feeds/luci/applications/luci-app-qbittorrent -ln -sf ../../../feeds/luci/applications/luci-app-qbittorrent ./package/feeds/luci/luci-app-qbittorrent +svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-qbittorrent package/lean/luci-app-qbittorrent +svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/qBittorrent-static package/lean/qBittorrent-static +svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/qBittorrent package/lean/qBittorrent +svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/rblibtorrent package/lean/rblibtorrent +svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/qtbase package/lean/qtbase +svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/qttools package/lean/qttools # 清理内存 svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-ramfree package/lean/luci-app-ramfree # ServerChan 微信推送 @@ -290,10 +244,8 @@ svn co https://github.com/immortalwrt/luci/branches/openwrt-18.06/applications/l rm -rf ./feeds/packages/net/kcptun rm -rf ./feeds/packages/net/shadowsocks-libev rm -rf ./feeds/packages/net/xray-core -#svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/shadowsocksr-libev package/lean/shadowsocksr-libev svn co https://github.com/fw876/helloworld/trunk/shadowsocksr-libev package/lean/shadowsocksr-libev svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/pdnsd-alt package/lean/pdnsd -#svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/kcptun package/lean/kcptun svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/srelay package/lean/srelay svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/microsocks package/lean/microsocks svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/dns2socks package/lean/dns2socks @@ -304,9 +256,9 @@ svn co https://github.com/coolsnowwolf/packages/trunk/net/shadowsocks-libev pack svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/trojan package/lean/trojan svn co https://github.com/fw876/helloworld/trunk/naiveproxy package/lean/naiveproxy svn co https://github.com/fw876/helloworld/trunk/v2ray-core package/lean/v2ray-core -svn co https://github.com/fw876/helloworld/trunk/xray-core package/new/xray-core -svn co https://github.com/fw876/helloworld/trunk/v2ray-plugin package/new/v2ray-plugin -svn co https://github.com/fw876/helloworld/trunk/xray-plugin package/new/xray-plugin +svn co https://github.com/fw876/helloworld/trunk/xray-core package/lean/xray-core +svn co https://github.com/fw876/helloworld/trunk/v2ray-plugin package/lean/v2ray-plugin +svn co https://github.com/fw876/helloworld/trunk/xray-plugin package/lean/xray-plugin svn co https://github.com/immortalwrt/packages/trunk/net/shadowsocks-rust feeds/packages/net/shadowsocks-rust ln -sf ../../../feeds/packages/net/shadowsocks-rust ./package/feeds/packages/shadowsocks-rust svn co https://github.com/immortalwrt/packages/trunk/net/kcptun feeds/packages/net/kcptun @@ -315,8 +267,7 @@ ln -sf ../../../feeds/packages/net/kcptun ./package/feeds/packages/kcptun svn co https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/lean/luci-app-ssr-plus rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans pushd package/lean -#wget -qO - https://github.com/fw876/helloworld/pull/513.patch | patch -p1 -#wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/c1674ad.patch | patch -p1 +wget -qO - https://github.com/fw876/helloworld/pull/645.patch | patch -p1 wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/5bbf6e7.patch | patch -p1 wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/323fbf0.patch | patch -p1 popd @@ -325,7 +276,6 @@ sed -i 's,default n,default y,g' Makefile sed -i 's,Xray:xray ,Xray:xray-core ,g' Makefile sed -i '/V2ray:v2ray/d' Makefile sed -i '/plugin:v2ray/d' Makefile -#sed -i '/Proxy:naive/d' Makefile sed -i '/result.encrypt_method/a\result.fast_open = "1"' root/usr/share/shadowsocksr/subscribe.lua sed -i 's,ispip.clang.cn/all_cn,cdn.jsdelivr.net/gh/QiuSimons/Chnroute@master/dist/chnroute/chnroute,' root/etc/init.d/shadowsocksr sed -i 's,YW5vbnltb3Vz/domain-list-community/release/gfwlist.txt,Loyalsoldier/v2ray-rules-dat/release/gfw.txt,' root/etc/init.d/shadowsocksr @@ -346,9 +296,6 @@ svn co https://github.com/immortalwrt/packages/trunk/libs/quickjspp feeds/packag ln -sf ../../../feeds/packages/libs/quickjspp ./package/feeds/packages/quickjspp # 网易云音乐解锁 git clone --depth 1 https://github.com/immortalwrt/luci-app-unblockneteasemusic.git package/new/UnblockNeteaseMusic -#pushd package/new/UnblockNeteaseMusic -#wget -qO - https://github.com/immortalwrt/luci-app-unblockneteasemusic/pull/78.patch | patch -p1 -#popd # USB 打印机 svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-usb-printer package/lean/luci-app-usb-printer # UU加速器 @@ -389,11 +336,25 @@ svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/addition-trans-zh package/ # Lets Fuck mkdir package/base-files/files/usr/bin wget -P package/base-files/files/usr/bin/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/fuck -#wget -P package/base-files/files/usr/bin/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/chinadnslist -#wget -P package/base-files/files/usr/bin/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/setdns # 最大连接数 sed -i 's/16384/65535/g' package/kernel/linux/files/sysctl-nf-conntrack.conf # 生成默认配置及缓存 rm -rf .config +### Shortcut-FE 部分 ### +# Patch Kernel 以支持 Shortcut-FE +#pushd target/linux/generic/hack-5.4 +#wget https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/generic/hack-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch +#popd +# Patch LuCI 以增添 Shortcut-FE 开关 +#patch -p1 < ../PATCH/firewall/luci-app-firewall_add_sfe_switch.patch +# Shortcut-FE 相关组件 +#svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/shortcut-fe package/lean/shortcut-fe +#svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/fast-classifier package/lean/fast-classifier +#wget -P package/base-files/files/etc/init.d/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/shortcut-fe + +# 回滚通用即插即用 +#rm -rf ./feeds/packages/net/miniupnpd +#svn co https://github.com/coolsnowwolf/packages/trunk/net/miniupnpd feeds/packages/net/miniupnpd + #exit 0 diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index 20896c3bc..8962db65f 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -30,10 +30,6 @@ sed -i '/;;/i\ethtool -K eth0 rx off tx off && logger -t disable-offloading "dis sed -i 's,"eth1" "eth0","eth0" "eth1",g' target/linux/rockchip/armv8/base-files/etc/board.d/02_network sed -i "s,'eth1' 'eth0','eth0' 'eth1',g" target/linux/rockchip/armv8/base-files/etc/board.d/02_network -# 添加 R2S GPU 驱动 -rm -rf ./package/kernel/linux/modules/video.mk -wget -P package/kernel/linux/modules/ https://github.com/immortalwrt/immortalwrt/raw/master/package/kernel/linux/modules/video.mk - #Vermagic latest_version="$(curl -s https://github.com/openwrt/openwrt/releases |grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" |sed -n '/21/p' |sed -n 1p |sed 's/v//g' |sed 's/.tar.gz//g')" wget https://downloads.openwrt.org/releases/${latest_version}/targets/rockchip/armv8/packages/Packages.gz diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index 01e686e04..6ff03f3e2 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -26,10 +26,6 @@ CONFIG_UKSM=y sed -i '/set_interface_core 20 "eth1"/a\set_interface_core 8 "ff3c0000" "ff3c0000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity sed -i '/set_interface_core 20 "eth1"/a\ethtool -C eth0 rx-usecs 1000 rx-frames 25 tx-usecs 100 tx-frames 25' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity -# 添加 R4S GPU 驱动 -rm -rf ./package/kernel/linux/modules/video.mk -wget -P package/kernel/linux/modules/ https://github.com/immortalwrt/immortalwrt/raw/master/package/kernel/linux/modules/video.mk - #Vermagic latest_version="$(curl -s https://github.com/openwrt/openwrt/releases |grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" |sed -n '/21/p' |sed -n 1p |sed 's/v//g' |sed 's/.tar.gz//g')" wget https://downloads.openwrt.org/releases/${latest_version}/targets/rockchip/armv8/packages/Packages.gz From 903649daaf59c1ee976b83c0eabe8a43781af4b5 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 9 Sep 2021 16:18:15 +0800 Subject: [PATCH 186/244] Disable Mitigations --- SCRIPTS/02_prepare_package.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 8d845ce81..2dc5ec043 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -83,6 +83,14 @@ wget -P package/kernel/linux/modules/ https://github.com/immortalwrt/immortalwrt rm -rf ./target/linux/rockchip/patches-5.4/992-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch cp -f ../PATCH/target_r4s/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch ./target/linux/rockchip/patches-5.4/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch cp -f ../PATCH/target_r4s/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch ./target/linux/rockchip/patches-5.4/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch +# Disable Mitigations +https://github.com/immortalwrt/immortalwrt/tree/master/target/linux/rockchip/image +sed -i 's,rootwait,rootwait mitigations=off,g' target/linux/rockchip/image/mmc.bootscript +sed -i 's,rootwait,rootwait mitigations=off,g' target/linux/rockchip/image/nanopi-r2s.bootscript +sed -i 's,rootwait,rootwait mitigations=off,g' target/linux/rockchip/image/nanopi-r4s.bootscript +sed -i 's,noinitrd,noinitrd mitigations=off,g' target/linux/x86/image/grub-efi.cfg +sed -i 's,noinitrd,noinitrd mitigations=off,g' target/linux/x86/image/grub-iso.cfg +sed -i 's,noinitrd,noinitrd mitigations=off,g' target/linux/x86/image/grub-pc.cfg # AutoCore svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/emortal/autocore package/lean/autocore rm -rf ./feeds/packages/utils/coremark From 7c499a1ed8fbd66c197177dcbd22cfb1e28c8565 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sun, 12 Sep 2021 16:43:32 +0800 Subject: [PATCH 187/244] Add: klever1988/cachewrtbuild --- .github/workflows/R2C-OpenWrt.yml | 15 +++++++-------- .github/workflows/R2S-OpenWrt.yml | 17 +++++++---------- .github/workflows/R4S-OpenWrt.yml | 17 +++++++---------- .github/workflows/X86-OpenWrt.yml | 17 +++++++---------- 4 files changed, 28 insertions(+), 38 deletions(-) diff --git a/.github/workflows/R2C-OpenWrt.yml b/.github/workflows/R2C-OpenWrt.yml index 4fda15d5b..d9d848f2c 100644 --- a/.github/workflows/R2C-OpenWrt.yml +++ b/.github/workflows/R2C-OpenWrt.yml @@ -75,6 +75,7 @@ jobs: run: | cd openwrt mv ../SEED/R2C/config.seed .config + #echo -e 'CONFIG_DEVEL=y\nCONFIG_CCACHE=y' >> .config make defconfig - name: Smart chmod run: | @@ -85,25 +86,23 @@ jobs: find ./ -type f | grep -v -f ${MY_Filter} | xargs -s1024 file | grep 'executable\|ELF' | cut -d ':' -f1 | xargs -s1024 chmod 755 rm -f ${MY_Filter} unset MY_Filter + - name: Cache + uses: klever1988/cachewrtbuild@main + with: + ccache: 'true' + prefix: ${{ github.workspace }}/openwrt - name: Make Download run: | df -h cd openwrt make download -j50 - - name: Make Toolchain - run: | - df -h - cd openwrt - let make_process=$(nproc)+2 - make toolchain/install -j${make_process} || make toolchain/install -j${make_process} V=s - name: Compile Openwrt id: compileopenwrt continue-on-error: true run: | df -h cd openwrt - let Make_Process=$(nproc)+2 - make -j${Make_Process} || make -j${Make_Process} V=s + make -j$(($(nproc) + 1)) || make -j$(($(nproc) + 1)) V=s echo $? - name: If Error if: steps.compileopenwrt.outcome == 'failure' diff --git a/.github/workflows/R2S-OpenWrt.yml b/.github/workflows/R2S-OpenWrt.yml index 65171ccdb..a4e704ae9 100644 --- a/.github/workflows/R2S-OpenWrt.yml +++ b/.github/workflows/R2S-OpenWrt.yml @@ -71,8 +71,8 @@ jobs: run: | cd openwrt mv ../SEED/R2S/config.seed .config + #echo -e 'CONFIG_DEVEL=y\nCONFIG_CCACHE=y' >> .config make defconfig - - name: Smart chmod run: | MY_Filter=$(mktemp) @@ -82,26 +82,23 @@ jobs: find ./ -type f | grep -v -f ${MY_Filter} | xargs -s1024 file | grep 'executable\|ELF' | cut -d ':' -f1 | xargs -s1024 chmod 755 rm -f ${MY_Filter} unset MY_Filter - + - name: Cache + uses: klever1988/cachewrtbuild@main + with: + ccache: 'true' + prefix: ${{ github.workspace }}/openwrt - name: Make Download run: | df -h cd openwrt make download -j50 - - name: Make Toolchain - run: | - df -h - cd openwrt - let make_process=$(nproc)+2 - make toolchain/install -j${make_process} || make toolchain/install -j${make_process} V=s - name: Compile Openwrt id: compileopenwrt continue-on-error: true run: | df -h cd openwrt - let Make_Process=$(nproc)+2 - make -j${Make_Process} || make -j${Make_Process} V=s + make -j$(($(nproc) + 1)) || make -j$(($(nproc) + 1)) V=s echo $? - name: If Error if: steps.compileopenwrt.outcome == 'failure' diff --git a/.github/workflows/R4S-OpenWrt.yml b/.github/workflows/R4S-OpenWrt.yml index 3ba326c88..5b11a9e5c 100644 --- a/.github/workflows/R4S-OpenWrt.yml +++ b/.github/workflows/R4S-OpenWrt.yml @@ -71,8 +71,8 @@ jobs: run: | cd openwrt mv ../SEED/R4S/config.seed .config + #echo -e 'CONFIG_DEVEL=y\nCONFIG_CCACHE=y' >> .config make defconfig - - name: Smart chmod run: | MY_Filter=$(mktemp) @@ -82,26 +82,23 @@ jobs: find ./ -type f | grep -v -f ${MY_Filter} | xargs -s1024 file | grep 'executable\|ELF' | cut -d ':' -f1 | xargs -s1024 chmod 755 rm -f ${MY_Filter} unset MY_Filter - + - name: Cache + uses: klever1988/cachewrtbuild@main + with: + ccache: 'true' + prefix: ${{ github.workspace }}/openwrt - name: Make Download run: | df -h cd openwrt make download -j50 - - name: Make Toolchain - run: | - df -h - cd openwrt - let make_process=$(nproc)+2 - make toolchain/install -j${make_process} || make toolchain/install -j${make_process} V=s - name: Compile Openwrt id: compileopenwrt continue-on-error: true run: | df -h cd openwrt - let Make_Process=$(nproc)+2 - make -j${Make_Process} || make -j${Make_Process} V=s + make -j$(($(nproc) + 1)) || make -j$(($(nproc) + 1)) V=s echo $? - name: If Error if: steps.compileopenwrt.outcome == 'failure' diff --git a/.github/workflows/X86-OpenWrt.yml b/.github/workflows/X86-OpenWrt.yml index 5c6ef6c3d..02b01d220 100644 --- a/.github/workflows/X86-OpenWrt.yml +++ b/.github/workflows/X86-OpenWrt.yml @@ -71,8 +71,8 @@ jobs: run: | cd openwrt mv ../SEED/X86/config.seed .config + #echo -e 'CONFIG_DEVEL=y\nCONFIG_CCACHE=y' >> .config make defconfig - - name: Smart chmod run: | MY_Filter=$(mktemp) @@ -82,26 +82,23 @@ jobs: find ./ -type f | grep -v -f ${MY_Filter} | xargs -s1024 file | grep 'executable\|ELF' | cut -d ':' -f1 | xargs -s1024 chmod 755 rm -f ${MY_Filter} unset MY_Filter - + - name: Cache + uses: klever1988/cachewrtbuild@main + with: + ccache: 'true' + prefix: ${{ github.workspace }}/openwrt - name: Make Download run: | df -h cd openwrt make download -j50 - - name: Make Toolchain - run: | - df -h - cd openwrt - let make_process=$(nproc)+2 - make toolchain/install -j${make_process} || make toolchain/install -j${make_process} V=s - name: Compile Openwrt id: compileopenwrt continue-on-error: true run: | df -h cd openwrt - let Make_Process=$(nproc)+2 - make -j${Make_Process} || make -j${Make_Process} V=s + make -j$(($(nproc) + 1)) || make -j$(($(nproc) + 1)) V=s echo $? - name: If Error if: steps.compileopenwrt.outcome == 'failure' From e25445826cf7e1ec2503accd30ffe5f470c7ec19 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 16 Sep 2021 12:20:42 +0800 Subject: [PATCH 188/244] #253 --- SEED/R2C/config.seed | 2 +- SEED/R2S/config.seed | 2 +- SEED/R4S/config.seed | 2 +- SEED/X86/config.seed | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/SEED/R2C/config.seed b/SEED/R2C/config.seed index 8caf4bdb1..04d77b30d 100644 --- a/SEED/R2C/config.seed +++ b/SEED/R2C/config.seed @@ -92,7 +92,7 @@ CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y CONFIG_PACKAGE_luci-app-boostupnp=y CONFIG_PACKAGE_luci-app-chinadns-ng=y -CONFIG_PACKAGE_luci-app-control-weburl=y +CONFIG_PACKAGE_luci-app-oaf=y CONFIG_PACKAGE_luci-app-cpufreq=y CONFIG_PACKAGE_luci-app-cpulimit=y CONFIG_PACKAGE_luci-app-ddns=y diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index a326dc954..0f51d1dc0 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -92,7 +92,7 @@ CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y CONFIG_PACKAGE_luci-app-boostupnp=y CONFIG_PACKAGE_luci-app-chinadns-ng=y -CONFIG_PACKAGE_luci-app-control-weburl=y +CONFIG_PACKAGE_luci-app-oaf=y CONFIG_PACKAGE_luci-app-cpufreq=y CONFIG_PACKAGE_luci-app-cpulimit=y CONFIG_PACKAGE_luci-app-ddns=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index bc9c6e683..a5bf18872 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -93,7 +93,7 @@ CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y CONFIG_PACKAGE_luci-app-boostupnp=y CONFIG_PACKAGE_luci-app-chinadns-ng=y -CONFIG_PACKAGE_luci-app-control-weburl=y +CONFIG_PACKAGE_luci-app-oaf=y CONFIG_PACKAGE_luci-app-cpufreq=y CONFIG_PACKAGE_luci-app-cpulimit=y CONFIG_PACKAGE_luci-app-ddns=y diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index 86371953e..6986d1d8d 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -93,7 +93,7 @@ CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y CONFIG_PACKAGE_luci-app-boostupnp=y CONFIG_PACKAGE_luci-app-chinadns-ng=y -CONFIG_PACKAGE_luci-app-control-weburl=y +CONFIG_PACKAGE_luci-app-oaf=y CONFIG_PACKAGE_luci-app-cpufreq=y CONFIG_PACKAGE_luci-app-cpulimit=y CONFIG_PACKAGE_luci-app-ddns=y From 54c476a356e08093ea5477373014915a725691f3 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 16 Sep 2021 18:03:07 +0800 Subject: [PATCH 189/244] MosDNS --- SCRIPTS/02_prepare_package.sh | 2 ++ SEED/R2C/config.seed | 7 ++++--- SEED/R2S/config.seed | 7 ++++--- SEED/R4S/config.seed | 7 ++++--- SEED/X86/config.seed | 7 ++++--- 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 2dc5ec043..f28885b94 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -206,6 +206,8 @@ svn co https://github.com/QiuSimons/openwrt-mos/trunk/luci-app-mosdns package/ne svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-netdata package/lean/luci-app-netdata # 上网 APP 过滤 git clone -b master --depth 1 https://github.com/destan19/OpenAppFilter.git package/new/OpenAppFilter +sed -i 's,先关闭ACC加速,在防火墙中关闭 FullCone 及 流量分载 ,g' package/new/OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/appfilter.lua +sed -i 's,flowoffload.@flow[0],firewall.@defaults[0],g' package/new/OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/appfilter.lua # OLED 驱动程序 git clone -b master --depth 1 https://github.com/NateLol/luci-app-oled.git package/new/luci-app-oled # OpenClash diff --git a/SEED/R2C/config.seed b/SEED/R2C/config.seed index 04d77b30d..734f43897 100644 --- a/SEED/R2C/config.seed +++ b/SEED/R2C/config.seed @@ -85,13 +85,16 @@ CONFIG_PACKAGE_luci-proto-ppp=y ### APPLICATION ### #CONFIG_PACKAGE_luci-app-adguardhome=y #CONFIG_PACKAGE_adguardhome=y +#CONFIG_PACKAGE_luci-app-chinadns-ng=y +#CONFIG_PACKAGE_luci-app-dnsproxy=y +#CONFIG_PACKAGE_luci-app-smartdns=y CONFIG_PACKAGE_luci-app-wireguard=y CONFIG_PACKAGE_luci-app-socat=y CONFIG_PACKAGE_luci-app-argon-config=y CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y CONFIG_PACKAGE_luci-app-boostupnp=y -CONFIG_PACKAGE_luci-app-chinadns-ng=y +CONFIG_PACKAGE_luci-app-mosdns=y CONFIG_PACKAGE_luci-app-oaf=y CONFIG_PACKAGE_luci-app-cpufreq=y CONFIG_PACKAGE_luci-app-cpulimit=y @@ -104,14 +107,12 @@ CONFIG_PACKAGE_frpc=y CONFIG_PACKAGE_luci-app-frps=y CONFIG_PACKAGE_frps=y CONFIG_PACKAGE_luci-app-jd-dailybonus=y -CONFIG_PACKAGE_luci-app-dnsproxy=y #CONFIG_PACKAGE_luci-app-oled=y CONFIG_PACKAGE_luci-app-openclash=y CONFIG_PACKAGE_luci-app-opkg=y #CONFIG_PACKAGE_luci-app-qbittorrent=y CONFIG_PACKAGE_luci-app-ramfree=y CONFIG_PACKAGE_luci-app-serverchan=y -#CONFIG_PACKAGE_luci-app-smartdns=y CONFIG_PACKAGE_luci-app-sqm=y CONFIG_PACKAGE_luci-app-vlmcsd=y CONFIG_PACKAGE_luci-app-vssr=y diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 0f51d1dc0..eff342d5d 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -85,13 +85,16 @@ CONFIG_PACKAGE_luci-proto-ppp=y ### APPLICATION ### #CONFIG_PACKAGE_luci-app-adguardhome=y #CONFIG_PACKAGE_adguardhome=y +#CONFIG_PACKAGE_luci-app-chinadns-ng=y +#CONFIG_PACKAGE_luci-app-dnsproxy=y +#CONFIG_PACKAGE_luci-app-smartdns=y CONFIG_PACKAGE_luci-app-wireguard=y CONFIG_PACKAGE_luci-app-socat=y CONFIG_PACKAGE_luci-app-argon-config=y CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y CONFIG_PACKAGE_luci-app-boostupnp=y -CONFIG_PACKAGE_luci-app-chinadns-ng=y +CONFIG_PACKAGE_luci-app-mosdns=y CONFIG_PACKAGE_luci-app-oaf=y CONFIG_PACKAGE_luci-app-cpufreq=y CONFIG_PACKAGE_luci-app-cpulimit=y @@ -104,14 +107,12 @@ CONFIG_PACKAGE_frpc=y CONFIG_PACKAGE_luci-app-frps=y CONFIG_PACKAGE_frps=y CONFIG_PACKAGE_luci-app-jd-dailybonus=y -CONFIG_PACKAGE_luci-app-dnsproxy=y CONFIG_PACKAGE_luci-app-oled=y CONFIG_PACKAGE_luci-app-openclash=y CONFIG_PACKAGE_luci-app-opkg=y #CONFIG_PACKAGE_luci-app-qbittorrent=y CONFIG_PACKAGE_luci-app-ramfree=y CONFIG_PACKAGE_luci-app-serverchan=y -#CONFIG_PACKAGE_luci-app-smartdns=y CONFIG_PACKAGE_luci-app-sqm=y CONFIG_PACKAGE_luci-app-vlmcsd=y CONFIG_PACKAGE_luci-app-vssr=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index a5bf18872..e005f4d7c 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -86,13 +86,16 @@ CONFIG_PACKAGE_luci-proto-ppp=y ### APPLICATION ### #CONFIG_PACKAGE_luci-app-adguardhome=y #CONFIG_PACKAGE_adguardhome=y +#CONFIG_PACKAGE_luci-app-chinadns-ng=y +#CONFIG_PACKAGE_luci-app-dnsproxy=y +#CONFIG_PACKAGE_luci-app-smartdns=y CONFIG_PACKAGE_luci-app-wireguard=y CONFIG_PACKAGE_luci-app-socat=y CONFIG_PACKAGE_luci-app-argon-config=y CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y CONFIG_PACKAGE_luci-app-boostupnp=y -CONFIG_PACKAGE_luci-app-chinadns-ng=y +CONFIG_PACKAGE_luci-app-mosdns=y CONFIG_PACKAGE_luci-app-oaf=y CONFIG_PACKAGE_luci-app-cpufreq=y CONFIG_PACKAGE_luci-app-cpulimit=y @@ -105,13 +108,11 @@ CONFIG_PACKAGE_frpc=y CONFIG_PACKAGE_luci-app-frps=y CONFIG_PACKAGE_frps=y CONFIG_PACKAGE_luci-app-jd-dailybonus=y -CONFIG_PACKAGE_luci-app-dnsproxy=y CONFIG_PACKAGE_luci-app-openclash=y CONFIG_PACKAGE_luci-app-opkg=y #CONFIG_PACKAGE_luci-app-qbittorrent=y CONFIG_PACKAGE_luci-app-ramfree=y CONFIG_PACKAGE_luci-app-serverchan=y -#CONFIG_PACKAGE_luci-app-smartdns=y CONFIG_PACKAGE_luci-app-sqm=y CONFIG_PACKAGE_luci-app-vlmcsd=y CONFIG_PACKAGE_luci-app-vssr=y diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index 6986d1d8d..1207f058b 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -86,13 +86,16 @@ CONFIG_PACKAGE_luci-proto-ppp=y ### APPLICATION ### #CONFIG_PACKAGE_luci-app-adguardhome=y #CONFIG_PACKAGE_adguardhome=y +#CONFIG_PACKAGE_luci-app-chinadns-ng=y +#CONFIG_PACKAGE_luci-app-dnsproxy=y +#CONFIG_PACKAGE_luci-app-smartdns=y CONFIG_PACKAGE_luci-app-wireguard=y CONFIG_PACKAGE_luci-app-socat=y CONFIG_PACKAGE_luci-app-argon-config=y CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y CONFIG_PACKAGE_luci-app-boostupnp=y -CONFIG_PACKAGE_luci-app-chinadns-ng=y +CONFIG_PACKAGE_luci-app-mosdns=y CONFIG_PACKAGE_luci-app-oaf=y CONFIG_PACKAGE_luci-app-cpufreq=y CONFIG_PACKAGE_luci-app-cpulimit=y @@ -105,13 +108,11 @@ CONFIG_PACKAGE_frpc=y CONFIG_PACKAGE_luci-app-frps=y CONFIG_PACKAGE_frps=y CONFIG_PACKAGE_luci-app-jd-dailybonus=y -CONFIG_PACKAGE_luci-app-dnsproxy=y CONFIG_PACKAGE_luci-app-openclash=y CONFIG_PACKAGE_luci-app-opkg=y #CONFIG_PACKAGE_luci-app-qbittorrent=y CONFIG_PACKAGE_luci-app-ramfree=y CONFIG_PACKAGE_luci-app-serverchan=y -#CONFIG_PACKAGE_luci-app-smartdns=y CONFIG_PACKAGE_luci-app-sqm=y CONFIG_PACKAGE_luci-app-vlmcsd=y CONFIG_PACKAGE_luci-app-vssr=y From 15e738fd8fac13e8dc8b57a95091893076c2d6c0 Mon Sep 17 00:00:00 2001 From: JSZMonkey <22406031+JSZMonkey@users.noreply.github.com> Date: Fri, 17 Sep 2021 13:12:58 +0800 Subject: [PATCH 190/244] Patch 1 (#260) --- SEED/R2C/config.seed | 2 +- SEED/R2S/config.seed | 2 +- SEED/R4S/config.seed | 2 +- SEED/X86/config.seed | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/SEED/R2C/config.seed b/SEED/R2C/config.seed index 734f43897..16701302a 100644 --- a/SEED/R2C/config.seed +++ b/SEED/R2C/config.seed @@ -129,7 +129,7 @@ CONFIG_PACKAGE_zerotier=y CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y -CONFIG_PACKAGE_dnsproxy=y +#CONFIG_PACKAGE_dnsproxy=y CONFIG_PACKAGE_luci-app-dnsfilter=y ### THEME ### diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index eff342d5d..9bfe4979e 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -129,7 +129,7 @@ CONFIG_PACKAGE_zerotier=y CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y -CONFIG_PACKAGE_dnsproxy=y +#CONFIG_PACKAGE_dnsproxy=y CONFIG_PACKAGE_luci-app-dnsfilter=y ### THEME ### diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index e005f4d7c..187adf15f 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -129,7 +129,7 @@ CONFIG_PACKAGE_zerotier=y CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y -CONFIG_PACKAGE_dnsproxy=y +#CONFIG_PACKAGE_dnsproxy=y CONFIG_PACKAGE_luci-app-dnsfilter=y ### THEME ### diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index 1207f058b..647643706 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -129,7 +129,7 @@ CONFIG_PACKAGE_zerotier=y CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y -CONFIG_PACKAGE_dnsproxy=y +#CONFIG_PACKAGE_dnsproxy=y CONFIG_PACKAGE_luci-app-dnsfilter=y ### THEME ### From 62169a8fbeae448d7681a58a8bbf6b99e8aa431f Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 17 Sep 2021 17:20:06 +0800 Subject: [PATCH 191/244] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 702f047b6..dc568ad32 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ - 基于原生 OpenWrt 21.02 编译,默认管理地址192.168.1.1 - 默认开启了 Software Offload - 内置升级功能可用,物理 Reset 按键可用 -- 预配置了部分插件(包括但不限于 DNS 套娃,(注意,使用dnsfilter作为广告过滤手段,使用dnsproxy作为dns分流措施,海外端口6051,国内端口6050,chinadns-ng监听端口5335。) +- 预配置了部分插件(包括但不限于 DNS 套娃,(注意,使用dnsfilter作为广告过滤手段,使用MosDNS作为dns分流措施。) - 可无脑 opkg kmod - R2C/R2S核心频率1.6(交换了LAN WAN),R4S核心频率2.2/1.8(建议使用5v4a电源,死机大多数情况下,都是因为你用的电源过于垃圾,另外,你也可以选择使用自带的app限制最大频率,茄子🍆) - O3 编译,CFLAG优化 From c0f456d2da83d07d5b78d29734c3555794b460f5 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 17 Sep 2021 17:24:11 +0800 Subject: [PATCH 192/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index f28885b94..342c0b04a 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -170,14 +170,14 @@ ln -sf ../../../feeds/luci/applications/luci-app-aliddns ./package/feeds/luci/lu # Docker 容器(会导致 OpenWrt 出现 UDP 转发问题,慎用) sed -i 's/+docker/+docker \\\n\t+dockerd/g' ./feeds/luci/applications/luci-app-dockerman/Makefile # Dnsfilter -git clone --depth 1 https://github.com/garypang13/luci-app-dnsfilter.git package/new/luci-app-dnsfilter +git clone --depth 1 https://github.com/kiddin9/luci-app-dnsfilter.git package/new/luci-app-dnsfilter # Dnsproxy svn co https://github.com/immortalwrt/packages/trunk/net/dnsproxy feeds/packages/net/dnsproxy ln -sf ../../../feeds/packages/net/dnsproxy ./package/feeds/packages/dnsproxy sed -i '/CURDIR/d' feeds/packages/net/dnsproxy/Makefile svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/luci-app-dnsproxy package/new/luci-app-dnsproxy # Edge 主题 -git clone -b master --depth 1 https://github.com/garypang13/luci-theme-edge.git package/new/luci-theme-edge +git clone -b master --depth 1 https://github.com/kiddin9/luci-theme-edge.git package/new/luci-theme-edge # FRP 内网穿透 rm -rf ./feeds/luci/applications/luci-app-frps rm -rf ./feeds/luci/applications/luci-app-frpc @@ -329,7 +329,7 @@ svn co https://github.com/sundaqiang/openwrt-packages/trunk/luci-app-services-wo git clone -b master --depth 1 https://github.com/brvphoenix/wrtbwmon.git package/new/wrtbwmon git clone -b master --depth 1 https://github.com/brvphoenix/luci-app-wrtbwmon.git package/new/luci-app-wrtbwmon # 迅雷快鸟宽带加速 -git clone --depth 1 https://github.com/garypang13/luci-app-xlnetacc.git package/lean/luci-app-xlnetacc +git clone --depth 1 https://github.com/kiddin9/luci-app-xlnetacc.git package/lean/luci-app-xlnetacc # Zerotier svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-zerotier feeds/luci/applications/luci-app-zerotier wget -P feeds/luci/applications/luci-app-zerotier/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/move_2_services.sh From ddc0f58c515fd2ba49864aa80568ba8943a75f1d Mon Sep 17 00:00:00 2001 From: Topsy Chen <62056970+thomaswcy@users.noreply.github.com> Date: Fri, 17 Sep 2021 17:24:40 +0800 Subject: [PATCH 193/244] #261 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dc568ad32..f5952cd49 100644 --- a/README.md +++ b/README.md @@ -40,14 +40,14 @@ ### 鸣谢 -| [CTCGFW](https://github.com/immortalwrt) | [coolsnowwolf](https://github.com/coolsnowwolf) | [Lienol](https://github.com/Lienol) | +| [ImmortalWrt](https://github.com/immortalwrt) | [coolsnowwolf](https://github.com/coolsnowwolf) | [Lienol](https://github.com/Lienol) | | :----------------------------------------------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: | | | | | | [NoTengoBattery](https://github.com/NoTengoBattery) | [tty228](https://github.com/tty228) | [destan19](https://github.com/destan19) | | | | | | [jerrykuku](https://github.com/jerrykuku) | [lisaac](https://github.com/lisaac) | [rufengsuixing](https://github.com/rufengsuixing) | | | | | -| [ElonH](https://github.com/ElonH) | [NateLol](https://github.com/NateLol) | [garypang13](https://github.com/garypang13) | +| [ElonH](https://github.com/ElonH) | [NateLol](https://github.com/NateLol) | [kiddin9](https://github.com/garypang13) | | | | | | [AmadeusGhost](https://github.com/AmadeusGhost) | [1715173329](https://github.com/1715173329) | [vernesong](https://github.com/vernesong) | | | | | From 18210c4dcd0f05a0bf46917fb56322632de4e9c8 Mon Sep 17 00:00:00 2001 From: Topsy Chen <62056970+thomaswcy@users.noreply.github.com> Date: Fri, 17 Sep 2021 17:30:51 +0800 Subject: [PATCH 194/244] #262 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f5952cd49..51d2fb1ea 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ | | | | | [jerrykuku](https://github.com/jerrykuku) | [lisaac](https://github.com/lisaac) | [rufengsuixing](https://github.com/rufengsuixing) | | | | | -| [ElonH](https://github.com/ElonH) | [NateLol](https://github.com/NateLol) | [kiddin9](https://github.com/garypang13) | +| [ElonH](https://github.com/ElonH) | [NateLol](https://github.com/NateLol) | [kiddin9](https://github.com/kiddin9) | | | | | | [AmadeusGhost](https://github.com/AmadeusGhost) | [1715173329](https://github.com/1715173329) | [vernesong](https://github.com/vernesong) | | | | | From bfea2f09c863b9b86bbeccc7bb26e6160d65fb32 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sun, 19 Sep 2021 22:07:21 +0800 Subject: [PATCH 195/244] #0919 --- README.md | 2 +- SEED/R2C/config.seed | 2 +- SEED/R2S/config.seed | 2 +- SEED/R4S/config.seed | 2 +- SEED/X86/config.seed | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 51d2fb1ea..8dfacf798 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ - 基于原生 OpenWrt 21.02 编译,默认管理地址192.168.1.1 - 默认开启了 Software Offload - 内置升级功能可用,物理 Reset 按键可用 -- 预配置了部分插件(包括但不限于 DNS 套娃,(注意,使用dnsfilter作为广告过滤手段,使用MosDNS作为dns分流措施。) +- 预配置了部分插件(注意,使用MosDNS同时作为广告过滤手段及dns分流措施。) - 可无脑 opkg kmod - R2C/R2S核心频率1.6(交换了LAN WAN),R4S核心频率2.2/1.8(建议使用5v4a电源,死机大多数情况下,都是因为你用的电源过于垃圾,另外,你也可以选择使用自带的app限制最大频率,茄子🍆) - O3 编译,CFLAG优化 diff --git a/SEED/R2C/config.seed b/SEED/R2C/config.seed index 16701302a..d691b5cdc 100644 --- a/SEED/R2C/config.seed +++ b/SEED/R2C/config.seed @@ -130,7 +130,7 @@ CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y #CONFIG_PACKAGE_dnsproxy=y -CONFIG_PACKAGE_luci-app-dnsfilter=y +#CONFIG_PACKAGE_luci-app-dnsfilter=y ### THEME ### CONFIG_PACKAGE_luci-theme-argon=y diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 9bfe4979e..ba87c0067 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -130,7 +130,7 @@ CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y #CONFIG_PACKAGE_dnsproxy=y -CONFIG_PACKAGE_luci-app-dnsfilter=y +#CONFIG_PACKAGE_luci-app-dnsfilter=y ### THEME ### CONFIG_PACKAGE_luci-theme-argon=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index 187adf15f..c1133c676 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -130,7 +130,7 @@ CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y #CONFIG_PACKAGE_dnsproxy=y -CONFIG_PACKAGE_luci-app-dnsfilter=y +#CONFIG_PACKAGE_luci-app-dnsfilter=y ### THEME ### CONFIG_PACKAGE_luci-theme-argon=y diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index 647643706..093345927 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -130,7 +130,7 @@ CONFIG_PACKAGE_coremark=y CONFIG_PACKAGE_htop=y CONFIG_PACKAGE_subconverter=y #CONFIG_PACKAGE_dnsproxy=y -CONFIG_PACKAGE_luci-app-dnsfilter=y +#CONFIG_PACKAGE_luci-app-dnsfilter=y ### THEME ### CONFIG_PACKAGE_luci-theme-argon=y From e2a024ebaeb2b20cb31a5afc441352fe919aa189 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 28 Sep 2021 10:35:01 +0800 Subject: [PATCH 196/244] LRNG: update to v42 --- ...ha1.patch => 696-01-v42-000001-sha1.patch} | 0 ... => 696-02-v42-000002-GRND_INSECURE.patch} | 0 ... => 696-03-v42-000003-jent-backport.patch} | 0 ...-0001-Linux-Random-Number-Generator.patch} | 4078 +++++++++-------- ...ate-one-DRNG-instance-per-NUMA-node.patch} | 46 +- ...003-LRNG-sysctls-and-proc-interface.patch} | 44 +- ...04-LRNG-add-switchable-DRNG-support.patch} | 42 +- ...RNG-add-common-generic-hash-support.patch} | 22 +- ...externalize-DRBG-functions-for-LRNG.patch} | 34 +- ...7-LRNG-add-SP800-90A-DRBG-extension.patch} | 17 +- ...dd-kernel-crypto-API-PRNG-extension.patch} | 17 +- ...de-access-to-a-static-Jitter-RNG-sta.patch | 148 - ...o-move-Jitter-RNG-header-include-dir.patch | 77 + ...NG-add-Jitter-RNG-fast-noise-source.patch} | 37 +- ...dd-SP800-90B-compliant-health-tests.patch} | 23 +- ...erface-for-gathering-of-raw-entropy.patch} | 35 +- ...add-power-on-and-runtime-self-tests.patch} | 49 +- ...> 696-17-v42-01-remove_compat_ioctl.patch} | 0 ...-v41-02-jitterentropy_remove_RCT_APT.patch | 15 - ... => 696-18-v42-03-arch_random_early.patch} | 4 +- ...tch => 696-19-v42-04-net_rand_state.patch} | 6 +- ...zfree.patch => 696-20-v42-05-kzfree.patch} | 0 ...patch => 696-21-v42-06-sha-includes.patch} | 0 .../LRNG/696-22-v42-07-chacha_constants.patch | 13 + 24 files changed, 2484 insertions(+), 2223 deletions(-) rename PATCH/LRNG/{696-01-v41-000001-sha1.patch => 696-01-v42-000001-sha1.patch} (100%) rename PATCH/LRNG/{696-02-v41-000002-GRND_INSECURE.patch => 696-02-v42-000002-GRND_INSECURE.patch} (100%) rename PATCH/LRNG/{696-03-v41-000003-jent-backport.patch => 696-03-v42-000003-jent-backport.patch} (100%) rename PATCH/LRNG/{696-04-v41-0001-Linux-Random-Number-Generator.patch => 696-04-v42-0001-Linux-Random-Number-Generator.patch} (91%) rename PATCH/LRNG/{696-05-v41-0002-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch => 696-05-v42-0002-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch} (81%) rename PATCH/LRNG/{696-06-v41-0003-LRNG-sysctls-and-proc-interface.patch => 696-06-v42-0003-LRNG-sysctls-and-proc-interface.patch} (89%) rename PATCH/LRNG/{696-07-v41-0004-LRNG-add-switchable-DRNG-support.patch => 696-07-v42-0004-LRNG-add-switchable-DRNG-support.patch} (91%) rename PATCH/LRNG/{696-08-v41-0005-LRNG-add-common-generic-hash-support.patch => 696-08-v42-0005-LRNG-add-common-generic-hash-support.patch} (87%) rename PATCH/LRNG/{696-09-v41-0006-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch => 696-09-v42-0006-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch} (76%) rename PATCH/LRNG/{696-10-v41-0007-LRNG-add-SP800-90A-DRBG-extension.patch => 696-10-v42-0007-LRNG-add-SP800-90A-DRBG-extension.patch} (93%) rename PATCH/LRNG/{696-11-v41-0008-LRNG-add-kernel-crypto-API-PRNG-extension.patch => 696-11-v42-0008-LRNG-add-kernel-crypto-API-PRNG-extension.patch} (94%) delete mode 100644 PATCH/LRNG/696-12-v41-0009-crypto-provide-access-to-a-static-Jitter-RNG-sta.patch create mode 100644 PATCH/LRNG/696-12-v42-0009-crypto-move-Jitter-RNG-header-include-dir.patch rename PATCH/LRNG/{696-13-v41-0010-LRNG-add-Jitter-RNG-fast-noise-source.patch => 696-13-v42-0010-LRNG-add-Jitter-RNG-fast-noise-source.patch} (82%) rename PATCH/LRNG/{696-14-v41-0011-LRNG-add-SP800-90B-compliant-health-tests.patch => 696-14-v42-0011-LRNG-add-SP800-90B-compliant-health-tests.patch} (96%) rename PATCH/LRNG/{696-15-v41-0012-LRNG-add-interface-for-gathering-of-raw-entropy.patch => 696-15-v42-0012-LRNG-add-interface-for-gathering-of-raw-entropy.patch} (96%) rename PATCH/LRNG/{696-16-v41-0013-LRNG-add-power-on-and-runtime-self-tests.patch => 696-16-v42-0013-LRNG-add-power-on-and-runtime-self-tests.patch} (92%) rename PATCH/LRNG/{696-17-v41-01-remove_compat_ioctl.patch => 696-17-v42-01-remove_compat_ioctl.patch} (100%) delete mode 100644 PATCH/LRNG/696-18-v41-02-jitterentropy_remove_RCT_APT.patch rename PATCH/LRNG/{696-19-v41-03-arch_random_early.patch => 696-18-v42-03-arch_random_early.patch} (85%) rename PATCH/LRNG/{696-20-v41-04-net_rand_state.patch => 696-19-v42-04-net_rand_state.patch} (59%) rename PATCH/LRNG/{696-21-v41-05-kzfree.patch => 696-20-v42-05-kzfree.patch} (100%) rename PATCH/LRNG/{696-22-v41-06-sha-includes.patch => 696-21-v42-06-sha-includes.patch} (100%) create mode 100644 PATCH/LRNG/696-22-v42-07-chacha_constants.patch diff --git a/PATCH/LRNG/696-01-v41-000001-sha1.patch b/PATCH/LRNG/696-01-v42-000001-sha1.patch similarity index 100% rename from PATCH/LRNG/696-01-v41-000001-sha1.patch rename to PATCH/LRNG/696-01-v42-000001-sha1.patch diff --git a/PATCH/LRNG/696-02-v41-000002-GRND_INSECURE.patch b/PATCH/LRNG/696-02-v42-000002-GRND_INSECURE.patch similarity index 100% rename from PATCH/LRNG/696-02-v41-000002-GRND_INSECURE.patch rename to PATCH/LRNG/696-02-v42-000002-GRND_INSECURE.patch diff --git a/PATCH/LRNG/696-03-v41-000003-jent-backport.patch b/PATCH/LRNG/696-03-v42-000003-jent-backport.patch similarity index 100% rename from PATCH/LRNG/696-03-v41-000003-jent-backport.patch rename to PATCH/LRNG/696-03-v42-000003-jent-backport.patch diff --git a/PATCH/LRNG/696-04-v41-0001-Linux-Random-Number-Generator.patch b/PATCH/LRNG/696-04-v42-0001-Linux-Random-Number-Generator.patch similarity index 91% rename from PATCH/LRNG/696-04-v41-0001-Linux-Random-Number-Generator.patch rename to PATCH/LRNG/696-04-v42-0001-Linux-Random-Number-Generator.patch index 3fa0088a8..36f1bc80d 100644 --- a/PATCH/LRNG/696-04-v41-0001-Linux-Random-Number-Generator.patch +++ b/PATCH/LRNG/696-04-v42-0001-Linux-Random-Number-Generator.patch @@ -1,7 +1,7 @@ -From 13918cf8b7d4f1383ff2a61687d45441b03b3b74 Mon Sep 17 00:00:00 2001 +From 4c05d448e19e351788d6baaaf5356f4905e11486 Mon Sep 17 00:00:00 2001 From: Stephan Mueller -Date: Wed, 23 Jun 2021 18:42:39 +0200 -Subject: [PATCH v41 01/13] Linux Random Number Generator +Date: Wed, 4 Aug 2021 21:27:54 +0200 +Subject: [PATCH v42 01/13] Linux Random Number Generator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -282,7 +282,8 @@ CC: Andy Lutomirski CC: Florian Weimer CC: Lennart Poettering CC: Nicolai Stange -CC: Alexander Lobakin +Reviewed-by: Alexander Lobakin +Tested-by: Alexander Lobakin Mathematical aspects Reviewed-by: "Peter, Matthias" Reviewed-by: Marcelo Henrique Cerri Reviewed-by: Roman Drahtmueller @@ -290,42 +291,46 @@ Tested-by: Marcelo Henrique Cerri Tested-by: Neil Horman Signed-off-by: Stephan Mueller --- - MAINTAINERS | 7 + - drivers/char/Kconfig | 2 + - drivers/char/Makefile | 9 +- - drivers/char/lrng/Kconfig | 205 ++++++++ - drivers/char/lrng/Makefile | 9 + - drivers/char/lrng/lrng_archrandom.c | 91 ++++ - drivers/char/lrng/lrng_aux.c | 136 ++++++ - drivers/char/lrng/lrng_chacha20.c | 321 +++++++++++++ - drivers/char/lrng/lrng_chacha20.h | 29 ++ - drivers/char/lrng/lrng_drng.c | 422 +++++++++++++++++ - drivers/char/lrng/lrng_interfaces.c | 650 ++++++++++++++++++++++++++ - drivers/char/lrng/lrng_internal.h | 416 +++++++++++++++++ - drivers/char/lrng/lrng_pool.c | 622 ++++++++++++++++++++++++ - drivers/char/lrng/lrng_sw_noise.c | 702 ++++++++++++++++++++++++++++ - drivers/char/lrng/lrng_sw_noise.h | 71 +++ - include/linux/lrng.h | 81 ++++ - 16 files changed, 3772 insertions(+), 1 deletion(-) + MAINTAINERS | 7 + + drivers/char/Kconfig | 2 + + drivers/char/Makefile | 9 +- + drivers/char/lrng/Kconfig | 205 +++++++ + drivers/char/lrng/Makefile | 9 + + drivers/char/lrng/lrng_aux.c | 136 +++++ + drivers/char/lrng/lrng_chacha20.c | 321 ++++++++++ + drivers/char/lrng/lrng_chacha20.h | 25 + + drivers/char/lrng/lrng_drng.c | 444 ++++++++++++++ + drivers/char/lrng/lrng_es_archrandom.c | 91 +++ + drivers/char/lrng/lrng_es_aux.c | 274 +++++++++ + drivers/char/lrng/lrng_es_irq.c | 796 +++++++++++++++++++++++++ + drivers/char/lrng/lrng_es_irq.h | 71 +++ + drivers/char/lrng/lrng_es_mgr.c | 375 ++++++++++++ + drivers/char/lrng/lrng_interfaces.c | 650 ++++++++++++++++++++ + drivers/char/lrng/lrng_internal.h | 446 ++++++++++++++ + include/linux/lrng.h | 81 +++ + 17 files changed, 3941 insertions(+), 1 deletion(-) create mode 100644 drivers/char/lrng/Kconfig create mode 100644 drivers/char/lrng/Makefile - create mode 100644 drivers/char/lrng/lrng_archrandom.c create mode 100644 drivers/char/lrng/lrng_aux.c create mode 100644 drivers/char/lrng/lrng_chacha20.c create mode 100644 drivers/char/lrng/lrng_chacha20.h create mode 100644 drivers/char/lrng/lrng_drng.c + create mode 100644 drivers/char/lrng/lrng_es_archrandom.c + create mode 100644 drivers/char/lrng/lrng_es_aux.c + create mode 100644 drivers/char/lrng/lrng_es_irq.c + create mode 100644 drivers/char/lrng/lrng_es_irq.h + create mode 100644 drivers/char/lrng/lrng_es_mgr.c create mode 100644 drivers/char/lrng/lrng_interfaces.c create mode 100644 drivers/char/lrng/lrng_internal.h - create mode 100644 drivers/char/lrng/lrng_pool.c - create mode 100644 drivers/char/lrng/lrng_sw_noise.c - create mode 100644 drivers/char/lrng/lrng_sw_noise.h create mode 100644 include/linux/lrng.h +diff --git a/MAINTAINERS b/MAINTAINERS +index d7b4f32875a9..f609786d1d1d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -9494,6 +9494,13 @@ F: Documentation/core-api/atomic_ops.rst - F: Documentation/core-api/refcount-vs-atomic.rst +@@ -10737,6 +10737,13 @@ F: Documentation/litmus-tests/ F: Documentation/memory-barriers.txt + F: tools/memory-model/ +LINUX RANDOM NUMBER GENERATOR (LRNG) DRIVER +M: Stephan Mueller @@ -337,9 +342,11 @@ Signed-off-by: Stephan Mueller LIS3LV02D ACCELEROMETER DRIVER M: Eric Piel S: Maintained +diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig +index ea3ead00f30f..10d1a41a01d2 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig -@@ -535,6 +535,8 @@ config ADI +@@ -427,6 +427,8 @@ config ADI and SSM (Silicon Secured Memory). Intended consumers of this driver include crash and makedumpfile. @@ -348,6 +355,8 @@ Signed-off-by: Stephan Mueller endmenu config RANDOM_TRUST_CPU +diff --git a/drivers/char/Makefile b/drivers/char/Makefile +index 264eb398fdd4..7371f7464a49 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -3,7 +3,14 @@ @@ -366,6 +375,9 @@ Signed-off-by: Stephan Mueller obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o obj-y += misc.o obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o +diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig +new file mode 100644 +index 000000000000..1cb2f55666ac --- /dev/null +++ b/drivers/char/lrng/Kconfig @@ -0,0 +1,205 @@ @@ -574,6 +586,9 @@ Signed-off-by: Stephan Mueller +endmenu # "Entropy Source Configuration" + +endif # LRNG +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +new file mode 100644 +index 000000000000..c26f932628d7 --- /dev/null +++ b/drivers/char/lrng/Makefile @@ -0,0 +1,9 @@ @@ -582,104 +597,13 @@ Signed-off-by: Stephan Mueller +# Makefile for the Linux Random Number Generator. +# + -+obj-y += lrng_pool.o lrng_aux.o \ -+ lrng_sw_noise.o lrng_archrandom.o \ ++obj-y += lrng_es_mgr.o lrng_aux.o \ ++ lrng_es_irq.o lrng_es_archrandom.o \ + lrng_drng.o lrng_chacha20.o \ -+ lrng_interfaces.o ---- /dev/null -+++ b/drivers/char/lrng/lrng_archrandom.c -@@ -0,0 +1,91 @@ -+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause -+/* -+ * LRNG Fast Entropy Source: CPU-based entropy source -+ * -+ * Copyright (C) 2016 - 2021, Stephan Mueller -+ */ -+ -+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+#include -+ -+#include "lrng_internal.h" -+ -+/* -+ * Estimated entropy of data is a 32th of LRNG_DRNG_SECURITY_STRENGTH_BITS. -+ * As we have no ability to review the implementation of those noise sources, -+ * it is prudent to have a conservative estimate here. -+ */ -+#define LRNG_ARCHRANDOM_DEFAULT_STRENGTH CONFIG_LRNG_CPU_ENTROPY_RATE -+#define LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH LRNG_DRNG_SECURITY_STRENGTH_BITS -+#ifdef CONFIG_RANDOM_TRUST_CPU -+static u32 archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH; -+#else -+static u32 archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH; -+#endif -+#ifdef CONFIG_LRNG_RUNTIME_ES_CONFIG -+module_param(archrandom, uint, 0644); -+MODULE_PARM_DESC(archrandom, "Entropy in bits of 256 data bits from CPU noise source (e.g. RDRAND)"); -+#endif -+ -+static int __init lrng_parse_trust_cpu(char *arg) -+{ -+ int ret; -+ bool trust_cpu = false; -+ -+ ret = kstrtobool(arg, &trust_cpu); -+ if (ret) -+ return ret; -+ -+ if (trust_cpu) { -+ archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH; -+ lrng_pool_add_entropy(); -+ } else { -+ archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH; -+ } -+ -+ return 0; -+} -+early_param("random.trust_cpu", lrng_parse_trust_cpu); -+ -+u32 lrng_archrandom_entropylevel(u32 requested_bits) -+{ -+ return lrng_fast_noise_entropylevel(archrandom, requested_bits); -+} -+ -+/** -+ * lrng_get_arch() - Get CPU noise source entropy -+ * -+ * @outbuf: buffer to store entropy of size LRNG_DRNG_SECURITY_STRENGTH_BYTES -+ * -+ * Return: -+ * * > 0 on success where value provides the added entropy in bits -+ * * 0 if no fast source was available -+ */ -+u32 lrng_get_arch(u8 *outbuf, u32 requested_bits) -+{ -+ u32 i, ent_bits = lrng_archrandom_entropylevel(requested_bits); -+ -+ /* operate on full blocks */ -+ BUILD_BUG_ON(LRNG_DRNG_SECURITY_STRENGTH_BYTES % sizeof(unsigned long)); -+ BUILD_BUG_ON(CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS % -+ sizeof(unsigned long)); -+ /* ensure we have aligned buffers */ -+ BUILD_BUG_ON(LRNG_KCAPI_ALIGN % sizeof(unsigned long)); -+ -+ if (!ent_bits) -+ return 0; -+ -+ for (i = 0; i < (requested_bits >> 3); -+ i += sizeof(unsigned long)) { -+ if (!arch_get_random_seed_long((unsigned long *)(outbuf + i)) && -+ !arch_get_random_long((unsigned long *)(outbuf + i))) { -+ archrandom = 0; -+ return 0; -+ } -+ } -+ -+ pr_debug("obtained %u bits of entropy from CPU RNG noise source\n", -+ ent_bits); -+ return ent_bits; -+} ++ lrng_interfaces.o lrng_es_aux.o +diff --git a/drivers/char/lrng/lrng_aux.c b/drivers/char/lrng/lrng_aux.c +new file mode 100644 +index 000000000000..a970bbc879ed --- /dev/null +++ b/drivers/char/lrng/lrng_aux.c @@ -0,0 +1,136 @@ @@ -819,6 +743,9 @@ Signed-off-by: Stephan Mueller + + return start + (get_random_long() % range << PAGE_SHIFT); +} +diff --git a/drivers/char/lrng/lrng_chacha20.c b/drivers/char/lrng/lrng_chacha20.c +new file mode 100644 +index 000000000000..ebbd67b600e0 --- /dev/null +++ b/drivers/char/lrng/lrng_chacha20.c @@ -0,0 +1,321 @@ @@ -1143,9 +1070,12 @@ Signed-off-by: Stephan Mueller + .lrng_hash_final = lrng_cc20_hash_final, + .lrng_hash_desc_zero = lrng_cc20_hash_desc_zero, +}; +diff --git a/drivers/char/lrng/lrng_chacha20.h b/drivers/char/lrng/lrng_chacha20.h +new file mode 100644 +index 000000000000..bd0c0bee38f3 --- /dev/null +++ b/drivers/char/lrng/lrng_chacha20.h -@@ -0,0 +1,29 @@ +@@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ +/* + * LRNG ChaCha20 definitions @@ -1169,15 +1099,14 @@ Signed-off-by: Stephan Mueller + +static inline void lrng_cc20_init_rfc7539(struct chacha20_block *chacha20) +{ -+ /* String "expand 32-byte k" */ -+ chacha20->constants[0] = 0x61707865; -+ chacha20->constants[1] = 0x3320646e; -+ chacha20->constants[2] = 0x79622d32; -+ chacha20->constants[3] = 0x6b206574; ++ chacha_init_consts(chacha20->constants); +} +diff --git a/drivers/char/lrng/lrng_drng.c b/drivers/char/lrng/lrng_drng.c +new file mode 100644 +index 000000000000..701fb26c699a --- /dev/null +++ b/drivers/char/lrng/lrng_drng.c -@@ -0,0 +1,422 @@ +@@ -0,0 +1,444 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* + * LRNG DRNG processing @@ -1229,6 +1158,13 @@ Signed-off-by: Stephan Mueller + .hash_lock = __RW_LOCK_UNLOCKED(lrng_drng_atomic.hash_lock) +}; + ++static u32 max_wo_reseed = LRNG_DRNG_MAX_WITHOUT_RESEED; ++#ifdef CONFIG_LRNG_RUNTIME_MAX_WO_RESEED_CONFIG ++module_param(max_wo_reseed, uint, 0444); ++MODULE_PARM_DESC(max_wo_reseed, ++ "Maximum number of DRNG generate operation without full reseed\n"); ++#endif ++ +/********************************** Helper ************************************/ + +bool lrng_get_available(void) @@ -1254,6 +1190,7 @@ Signed-off-by: Stephan Mueller +void lrng_drng_reset(struct lrng_drng *drng) +{ + atomic_set(&drng->requests, LRNG_DRNG_RESEED_THRESH); ++ atomic_set(&drng->requests_since_fully_seeded, 0); + drng->last_seeded = jiffies; + drng->fully_seeded = false; + drng->force_reseed = true; @@ -1320,7 +1257,7 @@ Signed-off-by: Stephan Mueller + +/* Inject a data buffer into the DRNG */ +static void lrng_drng_inject(struct lrng_drng *drng, -+ const u8 *inbuf, u32 inbuflen) ++ const u8 *inbuf, u32 inbuflen, bool fully_seeded) +{ + const char *drng_type = unlikely(drng == &lrng_drng_atomic) ? + "atomic" : "regular"; @@ -1332,18 +1269,31 @@ Signed-off-by: Stephan Mueller + if (drng->crypto_cb->lrng_drng_seed_helper(drng->drng, + inbuf, inbuflen) < 0) { + pr_warn("seeding of %s DRNG failed\n", drng_type); -+ atomic_set(&drng->requests, 1); ++ drng->force_reseed = true; + } else { ++ int gc = LRNG_DRNG_RESEED_THRESH - atomic_read(&drng->requests); ++ + pr_debug("%s DRNG stats since last seeding: %lu secs; generate calls: %d\n", + drng_type, + (time_after(jiffies, drng->last_seeded) ? -+ (jiffies - drng->last_seeded) : 0) / HZ, -+ (LRNG_DRNG_RESEED_THRESH - -+ atomic_read(&drng->requests))); ++ (jiffies - drng->last_seeded) : 0) / HZ, gc); ++ ++ /* Count the numbers of generate ops since last fully seeded */ ++ if (fully_seeded) ++ atomic_set(&drng->requests_since_fully_seeded, 0); ++ else ++ atomic_add(gc, &drng->requests_since_fully_seeded); ++ + drng->last_seeded = jiffies; + atomic_set(&drng->requests, LRNG_DRNG_RESEED_THRESH); + drng->force_reseed = false; + ++ if (!drng->fully_seeded) { ++ drng->fully_seeded = fully_seeded; ++ if (drng->fully_seeded) ++ pr_debug("DRNG fully seeded\n"); ++ } ++ + if (drng->drng == lrng_drng_atomic.drng) { + lrng_drng_atomic.last_seeded = jiffies; + atomic_set(&lrng_drng_atomic.requests, @@ -1361,15 +1311,11 @@ Signed-off-by: Stephan Mueller +{ + struct entropy_buf seedbuf __aligned(LRNG_KCAPI_ALIGN); + -+ lrng_fill_seed_buffer(&seedbuf, lrng_get_seed_entropy_osr()); ++ lrng_fill_seed_buffer(&seedbuf, ++ lrng_get_seed_entropy_osr(drng->fully_seeded)); + lrng_init_ops(&seedbuf); -+ lrng_drng_inject(drng, (u8 *)&seedbuf, sizeof(seedbuf)); -+ -+ if (!drng->fully_seeded) { -+ drng->fully_seeded = lrng_fully_seeded(&seedbuf); -+ if (drng->fully_seeded) -+ pr_debug("DRNG fully seeded\n"); -+ } ++ lrng_drng_inject(drng, (u8 *)&seedbuf, sizeof(seedbuf), ++ lrng_fully_seeded(drng->fully_seeded, &seedbuf)); + memzero_explicit(&seedbuf, sizeof(seedbuf)); +} + @@ -1400,7 +1346,7 @@ Signed-off-by: Stephan Mueller + pr_warn("Error generating random numbers for atomic DRNG: %d\n", + ret); + } else { -+ lrng_drng_inject(&lrng_drng_atomic, seedbuf, ret); ++ lrng_drng_inject(&lrng_drng_atomic, seedbuf, ret, true); + } + memzero_explicit(&seedbuf, sizeof(seedbuf)); + } @@ -1496,6 +1442,11 @@ Signed-off-by: Stephan Mueller + + lrng_drngs_init_cc20(false); + ++ /* If DRNG operated without proper reseed for too long, block LRNG */ ++ BUILD_BUG_ON(LRNG_DRNG_MAX_WITHOUT_RESEED < LRNG_DRNG_RESEED_THRESH); ++ if (atomic_read_u32(&drng->requests_since_fully_seeded) > max_wo_reseed) ++ lrng_unset_fully_seeded(drng); ++ + while (outbuflen) { + u32 todo = min_t(u32, outbuflen, LRNG_DRNG_MAX_REQSIZE); + int ret; @@ -1507,7 +1458,7 @@ Signed-off-by: Stephan Mueller + lrng_drng_reseed_max_time * HZ)) { + if (likely(drng != &lrng_drng_atomic)) { + if (lrng_pool_trylock()) { -+ atomic_set(&drng->requests, 1); ++ drng->force_reseed = true; + } else { + lrng_drng_seed(drng); + lrng_pool_unlock(); @@ -1600,1085 +1551,1271 @@ Signed-off-by: Stephan Mueller +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Stephan Mueller "); +MODULE_DESCRIPTION("Linux Random Number Generator"); +diff --git a/drivers/char/lrng/lrng_es_archrandom.c b/drivers/char/lrng/lrng_es_archrandom.c +new file mode 100644 +index 000000000000..ae87fa9bae58 --- /dev/null -+++ b/drivers/char/lrng/lrng_interfaces.c -@@ -0,0 +1,650 @@ ++++ b/drivers/char/lrng/lrng_es_archrandom.c +@@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* -+ * LRNG User and kernel space interfaces ++ * LRNG Fast Entropy Source: CPU-based entropy source + * + * Copyright (C) 2016 - 2021, Stephan Mueller + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + -+#include -+#include -+#include -+#include -+#include -+#include -+#include +#include -+#include -+#include -+#include -+ -+#define CREATE_TRACE_POINTS -+#include + +#include "lrng_internal.h" + +/* -+ * If the entropy count falls under this number of bits, then we -+ * should wake up processes which are selecting or polling on write -+ * access to /dev/random. ++ * Estimated entropy of data is a 32th of LRNG_DRNG_SECURITY_STRENGTH_BITS. ++ * As we have no ability to review the implementation of those noise sources, ++ * it is prudent to have a conservative estimate here. + */ -+u32 lrng_write_wakeup_bits = LRNG_WRITE_WAKEUP_ENTROPY; -+ -+static LIST_HEAD(lrng_ready_list); -+static DEFINE_SPINLOCK(lrng_ready_list_lock); -+ -+static DECLARE_WAIT_QUEUE_HEAD(lrng_write_wait); -+static DECLARE_WAIT_QUEUE_HEAD(lrng_init_wait); -+static struct fasync_struct *fasync; -+ -+struct ctl_table random_table[]; -+ -+/********************************** Helper ***********************************/ ++#define LRNG_ARCHRANDOM_DEFAULT_STRENGTH CONFIG_LRNG_CPU_ENTROPY_RATE ++#define LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH LRNG_DRNG_SECURITY_STRENGTH_BITS ++#ifdef CONFIG_RANDOM_TRUST_CPU ++static u32 archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH; ++#else ++static u32 archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH; ++#endif ++#ifdef CONFIG_LRNG_RUNTIME_ES_CONFIG ++module_param(archrandom, uint, 0644); ++MODULE_PARM_DESC(archrandom, "Entropy in bits of 256 data bits from CPU noise source (e.g. RDRAND)"); ++#endif + -+/* Is the DRNG seed level too low? */ -+static inline bool lrng_need_entropy(void) ++static int __init lrng_parse_trust_cpu(char *arg) +{ -+ return (lrng_avail_aux_entropy() < lrng_write_wakeup_bits); -+} ++ int ret; ++ bool trust_cpu = false; + -+void lrng_writer_wakeup(void) -+{ -+ if (lrng_need_entropy() && wq_has_sleeper(&lrng_write_wait)) { -+ wake_up_interruptible(&lrng_write_wait); -+ kill_fasync(&fasync, SIGIO, POLL_OUT); ++ ret = kstrtobool(arg, &trust_cpu); ++ if (ret) ++ return ret; ++ ++ if (trust_cpu) { ++ archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH; ++ lrng_pool_add_entropy(); ++ } else { ++ archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH; + } ++ ++ return 0; +} ++early_param("random.trust_cpu", lrng_parse_trust_cpu); + -+void lrng_init_wakeup(void) ++u32 lrng_archrandom_entropylevel(u32 requested_bits) +{ -+ wake_up_all(&lrng_init_wait); -+ kill_fasync(&fasync, SIGIO, POLL_IN); ++ return lrng_fast_noise_entropylevel(archrandom, requested_bits); +} + +/** -+ * lrng_process_ready_list() - Ping all kernel internal callers waiting until -+ * the DRNG is completely initialized to inform that the DRNG reached that -+ * seed level. ++ * lrng_get_arch() - Get CPU noise source entropy + * -+ * When the SP800-90B testing is enabled, the ping only happens if the SP800-90B -+ * startup health tests are completed. This implies that kernel internal -+ * callers always have an SP800-90B compliant noise source when being -+ * pinged. ++ * @outbuf: buffer to store entropy of size LRNG_DRNG_SECURITY_STRENGTH_BYTES ++ * ++ * Return: ++ * * > 0 on success where value provides the added entropy in bits ++ * * 0 if no fast source was available + */ -+void lrng_process_ready_list(void) ++u32 lrng_get_arch(u8 *outbuf, u32 requested_bits) +{ -+ unsigned long flags; -+ struct random_ready_callback *rdy, *tmp; ++ u32 i, ent_bits = lrng_archrandom_entropylevel(requested_bits); + -+ if (!lrng_state_operational()) -+ return; ++ /* operate on full blocks */ ++ BUILD_BUG_ON(LRNG_DRNG_SECURITY_STRENGTH_BYTES % sizeof(unsigned long)); ++ BUILD_BUG_ON(CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS % ++ sizeof(unsigned long)); ++ /* ensure we have aligned buffers */ ++ BUILD_BUG_ON(LRNG_KCAPI_ALIGN % sizeof(unsigned long)); + -+ spin_lock_irqsave(&lrng_ready_list_lock, flags); -+ list_for_each_entry_safe(rdy, tmp, &lrng_ready_list, list) { -+ struct module *owner = rdy->owner; ++ if (!ent_bits) ++ return 0; + -+ list_del_init(&rdy->list); -+ rdy->func(rdy); -+ module_put(owner); ++ for (i = 0; i < (requested_bits >> 3); ++ i += sizeof(unsigned long)) { ++ if (!arch_get_random_seed_long((unsigned long *)(outbuf + i)) && ++ !arch_get_random_long((unsigned long *)(outbuf + i))) { ++ archrandom = 0; ++ return 0; ++ } + } -+ spin_unlock_irqrestore(&lrng_ready_list_lock, flags); -+} -+ -+void lrng_debug_report_seedlevel(const char *name) -+{ -+#ifdef CONFIG_WARN_ALL_UNSEEDED_RANDOM -+ static void *previous = NULL; -+ void *caller = (void *) _RET_IP_; + -+ if (READ_ONCE(previous) == caller) -+ return; ++ pr_debug("obtained %u bits of entropy from CPU RNG noise source\n", ++ ent_bits); ++ return ent_bits; ++} +diff --git a/drivers/char/lrng/lrng_es_aux.c b/drivers/char/lrng/lrng_es_aux.c +new file mode 100644 +index 000000000000..9a12f7f79866 +--- /dev/null ++++ b/drivers/char/lrng/lrng_es_aux.c +@@ -0,0 +1,274 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause ++/* ++ * LRNG Slow Entropy Source: Auxiliary entropy pool ++ * ++ * Copyright (C) 2016 - 2021, Stephan Mueller ++ */ + -+ if (!lrng_state_min_seeded()) -+ pr_notice("%pS %s called without reaching minimally seeded level (available entropy %u)\n", -+ caller, name, lrng_avail_entropy()); ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + -+ WRITE_ONCE(previous, caller); -+#endif -+} ++#include + -+/************************ LRNG kernel input interfaces ************************/ ++#include "lrng_internal.h" + -+/** -+ * add_hwgenerator_randomness() - Interface for in-kernel drivers of true -+ * hardware RNGs. -+ * -+ * Those devices may produce endless random bits and will be throttled -+ * when our pool is full. ++/* ++ * This is the auxiliary pool + * -+ * @buffer: buffer holding the entropic data from HW noise sources to be used to -+ * insert into entropy pool. -+ * @count: length of buffer -+ * @entropy_bits: amount of entropy in buffer (value is in bits) ++ * The aux pool array is aligned to 8 bytes to comfort the kernel crypto API ++ * cipher implementations of the hash functions used to read the pool: for some ++ * accelerated implementations, we need an alignment to avoid a realignment ++ * which involves memcpy(). The alignment to 8 bytes should satisfy all crypto ++ * implementations. + */ -+void add_hwgenerator_randomness(const char *buffer, size_t count, -+ size_t entropy_bits) -+{ -+ /* -+ * Suspend writing if we are fully loaded with entropy. -+ * We'll be woken up again once below lrng_write_wakeup_thresh, -+ * or when the calling thread is about to terminate. -+ */ -+ wait_event_interruptible(lrng_write_wait, -+ lrng_need_entropy() || -+ lrng_state_exseed_allow(lrng_noise_source_hw) || -+ kthread_should_stop()); -+ lrng_state_exseed_set(lrng_noise_source_hw, false); -+ lrng_pool_insert_aux(buffer, count, entropy_bits); -+} -+EXPORT_SYMBOL_GPL(add_hwgenerator_randomness); ++struct lrng_pool { ++ u8 aux_pool[LRNG_POOL_SIZE]; /* Aux pool: digest state */ ++ atomic_t aux_entropy_bits; ++ atomic_t digestsize; /* Digest size of used hash */ ++ bool initialized; /* Aux pool initialized? */ + -+/** -+ * add_bootloader_randomness() - Handle random seed passed by bootloader. -+ * -+ * If the seed is trustworthy, it would be regarded as hardware RNGs. Otherwise -+ * it would be regarded as device data. -+ * The decision is controlled by CONFIG_RANDOM_TRUST_BOOTLOADER. -+ * -+ * @buf: buffer holding the entropic data from HW noise sources to be used to -+ * insert into entropy pool. -+ * @size: length of buffer -+ */ -+void add_bootloader_randomness(const void *buf, unsigned int size) ++ /* Serialize read of entropy pool and update of aux pool */ ++ spinlock_t lock; ++}; ++ ++static struct lrng_pool lrng_pool __aligned(LRNG_KCAPI_ALIGN) = { ++ .aux_entropy_bits = ATOMIC_INIT(0), ++ .digestsize = ATOMIC_INIT(LRNG_ATOMIC_DIGEST_SIZE), ++ .initialized = false, ++ .lock = __SPIN_LOCK_UNLOCKED(lrng_pool.lock) ++}; ++ ++/********************************** Helper ***********************************/ ++ ++/* Entropy in bits present in aux pool */ ++u32 lrng_avail_aux_entropy(void) +{ -+ lrng_pool_insert_aux(buf, size, -+ IS_ENABLED(CONFIG_RANDOM_TRUST_BOOTLOADER) ? -+ size * 8 : 0); ++ /* Cap available entropy with max entropy */ ++ u32 avail_bits = min_t(u32, lrng_get_digestsize(), ++ atomic_read_u32(&lrng_pool.aux_entropy_bits)); ++ ++ /* Consider oversampling rate due to aux pool conditioning */ ++ return lrng_reduce_by_osr(avail_bits); +} -+EXPORT_SYMBOL_GPL(add_bootloader_randomness); + -+/* -+ * Callback for HID layer -- use the HID event values to stir the entropy pool -+ */ -+void add_input_randomness(unsigned int type, unsigned int code, -+ unsigned int value) ++/* Set the digest size of the used hash in bytes */ ++static inline void lrng_set_digestsize(u32 digestsize) +{ -+ static unsigned char last_value; -+ -+ /* ignore autorepeat and the like */ -+ if (value == last_value) -+ return; ++ struct lrng_pool *pool = &lrng_pool; ++ u32 ent_bits = atomic_xchg_relaxed(&pool->aux_entropy_bits, 0), ++ old_digestsize = lrng_get_digestsize(); + -+ last_value = value; ++ atomic_set(&lrng_pool.digestsize, digestsize); + -+ lrng_pcpu_array_add_u32((type << 4) ^ code ^ (code >> 4) ^ value); ++ /* ++ * In case the new digest is larger than the old one, cap the available ++ * entropy to the old message digest used to process the existing data. ++ */ ++ ent_bits = min_t(u32, ent_bits, old_digestsize); ++ atomic_add(ent_bits, &pool->aux_entropy_bits); +} -+EXPORT_SYMBOL_GPL(add_input_randomness); + -+/** -+ * add_device_randomness() - Add device- or boot-specific data to the entropy -+ * pool to help initialize it. -+ * -+ * None of this adds any entropy; it is meant to avoid the problem of -+ * the entropy pool having similar initial state across largely -+ * identical devices. -+ * -+ * @buf: buffer holding the entropic data from HW noise sources to be used to -+ * insert into entropy pool. -+ * @size: length of buffer -+ */ -+void add_device_randomness(const void *buf, unsigned int size) ++/* Obtain the digest size provided by the used hash in bits */ ++u32 lrng_get_digestsize(void) +{ -+ lrng_pool_insert_aux((u8 *)buf, size, 0); ++ return atomic_read_u32(&lrng_pool.digestsize) << 3; +} -+EXPORT_SYMBOL(add_device_randomness); + -+#ifdef CONFIG_BLOCK -+void rand_initialize_disk(struct gendisk *disk) { } -+void add_disk_randomness(struct gendisk *disk) { } -+EXPORT_SYMBOL(add_disk_randomness); -+#endif ++/* Set entropy content in user-space controllable aux pool */ ++void lrng_pool_set_entropy(u32 entropy_bits) ++{ ++ atomic_set(&lrng_pool.aux_entropy_bits, entropy_bits); ++} + -+/** -+ * del_random_ready_callback() - Delete a previously registered readiness -+ * callback function. ++/* ++ * Replace old with new hash for auxiliary pool handling + * -+ * @rdy: callback definition that was registered initially ++ * Assumption: the caller must guarantee that the new_cb is available during the ++ * entire operation (e.g. it must hold the write lock against pointer updating). + */ -+void del_random_ready_callback(struct random_ready_callback *rdy) ++int lrng_aux_switch_hash(const struct lrng_crypto_cb *new_cb, void *new_hash, ++ const struct lrng_crypto_cb *old_cb) +{ -+ unsigned long flags; -+ struct module *owner = NULL; ++ struct lrng_pool *pool = &lrng_pool; ++ struct shash_desc *shash = (struct shash_desc *)pool->aux_pool; ++ u8 digest[LRNG_MAX_DIGESTSIZE]; ++ int ret; + -+ spin_lock_irqsave(&lrng_ready_list_lock, flags); -+ if (!list_empty(&rdy->list)) { -+ list_del_init(&rdy->list); -+ owner = rdy->owner; ++ if (!IS_ENABLED(CONFIG_LRNG_DRNG_SWITCH)) ++ return -EOPNOTSUPP; ++ ++ if (unlikely(!pool->initialized)) ++ return 0; ++ ++ /* Get the aux pool hash with old digest ... */ ++ ret = old_cb->lrng_hash_final(shash, digest) ?: ++ /* ... re-initialize the hash with the new digest ... */ ++ new_cb->lrng_hash_init(shash, new_hash) ?: ++ /* ++ * ... feed the old hash into the new state. We may feed ++ * uninitialized memory into the new state, but this is ++ * considered no issue and even good as we have some more ++ * uncertainty here. ++ */ ++ new_cb->lrng_hash_update(shash, digest, sizeof(digest)); ++ if (!ret) { ++ lrng_set_digestsize(new_cb->lrng_hash_digestsize(new_hash)); ++ pr_debug("Re-initialize aux entropy pool with hash %s\n", ++ new_cb->lrng_hash_name()); + } -+ spin_unlock_irqrestore(&lrng_ready_list_lock, flags); + -+ module_put(owner); ++ memzero_explicit(digest, sizeof(digest)); ++ return ret; +} -+EXPORT_SYMBOL(del_random_ready_callback); + -+/** -+ * add_random_ready_callback() - Add a callback function that will be invoked -+ * when the DRNG is fully initialized and seeded. -+ * -+ * @rdy: callback definition to be invoked when the LRNG is seeded -+ * -+ * Return: -+ * * 0 if callback is successfully added -+ * * -EALREADY if pool is already initialised (callback not called) -+ * * -ENOENT if module for callback is not alive -+ */ -+int add_random_ready_callback(struct random_ready_callback *rdy) ++/* Insert data into auxiliary pool by using the hash update function. */ ++static int ++lrng_pool_insert_aux_locked(const u8 *inbuf, u32 inbuflen, u32 entropy_bits) +{ -+ struct module *owner; ++ struct lrng_pool *pool = &lrng_pool; ++ struct shash_desc *shash = (struct shash_desc *)pool->aux_pool; ++ struct lrng_drng *drng = lrng_drng_init_instance(); ++ const struct lrng_crypto_cb *crypto_cb; + unsigned long flags; -+ int err = -EALREADY; ++ void *hash; ++ int ret; + -+ if (likely(lrng_state_operational())) -+ return err; ++ entropy_bits = min_t(u32, entropy_bits, inbuflen << 3); + -+ owner = rdy->owner; -+ if (!try_module_get(owner)) -+ return -ENOENT; ++ read_lock_irqsave(&drng->hash_lock, flags); + -+ spin_lock_irqsave(&lrng_ready_list_lock, flags); -+ if (lrng_state_operational()) -+ goto out; ++ crypto_cb = drng->crypto_cb; ++ hash = drng->hash; + -+ owner = NULL; ++ if (unlikely(!pool->initialized)) { ++ ret = crypto_cb->lrng_hash_init(shash, hash); ++ if (ret) ++ goto out; ++ pool->initialized = true; ++ } + -+ list_add(&rdy->list, &lrng_ready_list); -+ err = 0; ++ ret = crypto_cb->lrng_hash_update(shash, inbuf, inbuflen); ++ if (ret) ++ goto out; ++ ++ /* ++ * Cap the available entropy to the hash output size compliant to ++ * SP800-90B section 3.1.5.1 table 1. ++ */ ++ entropy_bits += atomic_read_u32(&pool->aux_entropy_bits); ++ atomic_set(&pool->aux_entropy_bits, ++ min_t(u32, entropy_bits, ++ crypto_cb->lrng_hash_digestsize(hash) << 3)); + +out: -+ spin_unlock_irqrestore(&lrng_ready_list_lock, flags); ++ read_unlock_irqrestore(&drng->hash_lock, flags); ++ return ret; ++} + -+ module_put(owner); ++int lrng_pool_insert_aux(const u8 *inbuf, u32 inbuflen, u32 entropy_bits) ++{ ++ struct lrng_pool *pool = &lrng_pool; ++ unsigned long flags; ++ int ret; + -+ return err; ++ spin_lock_irqsave(&pool->lock, flags); ++ ret = lrng_pool_insert_aux_locked(inbuf, inbuflen, entropy_bits); ++ spin_unlock_irqrestore(&pool->lock, flags); ++ ++ lrng_pool_add_entropy(); ++ ++ return ret; +} -+EXPORT_SYMBOL(add_random_ready_callback); + -+/*********************** LRNG kernel output interfaces ************************/ ++/************************* Get data from entropy pool *************************/ + +/** -+ * get_random_bytes() - Provider of cryptographic strong random numbers for -+ * kernel-internal usage. -+ * -+ * This function is appropriate for all in-kernel use cases. However, -+ * it will always use the ChaCha20 DRNG. -+ * -+ * @buf: buffer to store the random bytes -+ * @nbytes: size of the buffer -+ */ -+void get_random_bytes(void *buf, int nbytes) ++ * Get auxiliary entropy pool and its entropy content for seed buffer. ++ * Caller must hold lrng_pool.pool->lock. ++ * @outbuf: buffer to store data in with size requested_bits ++ * @requested_bits: Requested amount of entropy ++ * @return: amount of entropy in outbuf in bits. ++ */ ++static inline u32 lrng_get_aux_pool(u8 *outbuf, u32 requested_bits) +{ -+ lrng_drng_get_atomic((u8 *)buf, (u32)nbytes); -+ lrng_debug_report_seedlevel("get_random_bytes"); ++ struct lrng_pool *pool = &lrng_pool; ++ struct shash_desc *shash = (struct shash_desc *)pool->aux_pool; ++ struct lrng_drng *drng = lrng_drng_init_instance(); ++ const struct lrng_crypto_cb *crypto_cb; ++ unsigned long flags; ++ void *hash; ++ u32 collected_ent_bits, returned_ent_bits, unused_bits = 0, ++ digestsize; ++ u8 aux_output[LRNG_MAX_DIGESTSIZE]; ++ ++ if (unlikely(!pool->initialized)) ++ return 0; ++ ++ read_lock_irqsave(&drng->hash_lock, flags); ++ ++ crypto_cb = drng->crypto_cb; ++ hash = drng->hash; ++ digestsize = crypto_cb->lrng_hash_digestsize(hash); ++ ++ /* Ensure that no more than the size of aux_pool can be requested */ ++ requested_bits = min_t(u32, requested_bits, (LRNG_MAX_DIGESTSIZE << 3)); ++ ++ /* Cap entropy with entropy counter from aux pool and the used digest */ ++ collected_ent_bits = min_t(u32, digestsize << 3, ++ atomic_xchg_relaxed(&pool->aux_entropy_bits, 0)); ++ ++ /* We collected too much entropy and put the overflow back */ ++ if (collected_ent_bits > (requested_bits + lrng_compress_osr())) { ++ /* Amount of bits we collected too much */ ++ unused_bits = collected_ent_bits - requested_bits; ++ /* Put entropy back */ ++ atomic_add(unused_bits, &pool->aux_entropy_bits); ++ /* Fix collected entropy */ ++ collected_ent_bits = requested_bits; ++ } ++ ++ /* Apply oversampling: discount requested oversampling rate */ ++ returned_ent_bits = lrng_reduce_by_osr(collected_ent_bits); ++ ++ pr_debug("obtained %u bits by collecting %u bits of entropy from aux pool, %u bits of entropy remaining\n", ++ returned_ent_bits, collected_ent_bits, unused_bits); ++ ++ /* Get the digest for the aux pool to be returned to the caller ... */ ++ if (crypto_cb->lrng_hash_final(shash, aux_output) || ++ /* ++ * ... and re-initialize the aux state. Do not add the aux pool ++ * digest for backward secrecy as it will be added with the ++ * insertion of the complete seed buffer after it has been filled. ++ */ ++ crypto_cb->lrng_hash_init(shash, hash)) { ++ returned_ent_bits = 0; ++ } else { ++ /* ++ * Do not truncate the output size exactly to collected_ent_bits ++ * as the aux pool may contain data that is not credited with ++ * entropy, but we want to use them to stir the DRNG state. ++ */ ++ memcpy(outbuf, aux_output, requested_bits >> 3); ++ } ++ ++ read_unlock_irqrestore(&drng->hash_lock, flags); ++ memzero_explicit(aux_output, digestsize); ++ return returned_ent_bits; +} -+EXPORT_SYMBOL(get_random_bytes); + -+/** -+ * get_random_bytes_full() - Provider of cryptographic strong random numbers -+ * for kernel-internal usage. -+ * -+ * This function is appropriate only for non-atomic use cases as this -+ * function may sleep. Though, it provides access to the full functionality -+ * of LRNG including the switchable DRNG support, that may support other -+ * DRNGs such as the SP800-90A DRBG. -+ * -+ * @buf: buffer to store the random bytes -+ * @nbytes: size of the buffer -+ */ -+void get_random_bytes_full(void *buf, int nbytes) ++void lrng_get_backtrack_aux(struct entropy_buf *entropy_buf, u32 requested_bits) +{ -+ lrng_drng_get_sleep((u8 *)buf, (u32)nbytes); -+ lrng_debug_report_seedlevel("get_random_bytes_full"); -+} -+EXPORT_SYMBOL(get_random_bytes_full); ++ struct lrng_pool *pool = &lrng_pool; ++ unsigned long flags; + -+/** -+ * wait_for_random_bytes() - Wait for the LRNG to be seeded and thus -+ * guaranteed to supply cryptographically secure random numbers. -+ * -+ * This applies to: the /dev/urandom device, the get_random_bytes function, -+ * and the get_random_{u32,u64,int,long} family of functions. Using any of -+ * these functions without first calling this function forfeits the guarantee -+ * of security. ++ /* Ensure aux pool extraction and backtracking op are atomic */ ++ spin_lock_irqsave(&pool->lock, flags); ++ ++ entropy_buf->a_bits = lrng_get_aux_pool(entropy_buf->a, requested_bits); ++ ++ /* Mix the extracted data back into pool for backtracking resistance */ ++ if (lrng_pool_insert_aux_locked((u8 *)entropy_buf, ++ sizeof(struct entropy_buf), 0)) ++ pr_warn("Backtracking resistance operation failed\n"); ++ ++ spin_unlock_irqrestore(&pool->lock, flags); ++} +diff --git a/drivers/char/lrng/lrng_es_irq.c b/drivers/char/lrng/lrng_es_irq.c +new file mode 100644 +index 000000000000..675425d87481 +--- /dev/null ++++ b/drivers/char/lrng/lrng_es_irq.c +@@ -0,0 +1,796 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause ++/* ++ * LRNG Slow Entropy Source: Interrupt data collection + * -+ * Return: -+ * * 0 if the LRNG has been seeded. -+ * * -ERESTARTSYS if the function was interrupted by a signal. ++ * Copyright (C) 2016 - 2021, Stephan Mueller + */ -+int wait_for_random_bytes(void) -+{ -+ if (likely(lrng_state_min_seeded())) -+ return 0; -+ return wait_event_interruptible(lrng_init_wait, -+ lrng_state_min_seeded()); -+} -+EXPORT_SYMBOL(wait_for_random_bytes); + -+/** -+ * get_random_bytes_arch() - This function will use the architecture-specific -+ * hardware random number generator if it is available. ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "lrng_internal.h" ++#include "lrng_es_irq.h" ++ ++/* Number of interrupts required for LRNG_DRNG_SECURITY_STRENGTH_BITS entropy */ ++static u32 lrng_irq_entropy_bits = LRNG_IRQ_ENTROPY_BITS; ++/* Is high-resolution timer present? */ ++static bool lrng_irq_highres_timer = false; ++ ++static u32 irq_entropy __read_mostly = LRNG_IRQ_ENTROPY_BITS; ++#ifdef CONFIG_LRNG_RUNTIME_ES_CONFIG ++module_param(irq_entropy, uint, 0444); ++MODULE_PARM_DESC(irq_entropy, ++ "How many interrupts must be collected for obtaining 256 bits of entropy\n"); ++#endif ++ ++/* Per-CPU array holding concatenated entropy events */ ++static DEFINE_PER_CPU(u32 [LRNG_DATA_ARRAY_SIZE], lrng_pcpu_array) ++ __aligned(LRNG_KCAPI_ALIGN); ++static DEFINE_PER_CPU(u32, lrng_pcpu_array_ptr) = 0; ++static DEFINE_PER_CPU(atomic_t, lrng_pcpu_array_irqs) = ATOMIC_INIT(0); ++ ++/* ++ * The entropy collection is performed by executing the following steps: ++ * 1. fill up the per-CPU array holding the time stamps ++ * 2. once the per-CPU array is full, a compression of the data into ++ * the entropy pool is performed - this happens in interrupt context + * -+ * The arch-specific hw RNG will almost certainly be faster than what we can -+ * do in software, but it is impossible to verify that it is implemented -+ * securely (as opposed, to, say, the AES encryption of a sequence number using -+ * a key known by the NSA). So it's useful if we need the speed, but only if -+ * we're willing to trust the hardware manufacturer not to have put in a back -+ * door. ++ * If step 2 is not desired in interrupt context, the following boolean ++ * needs to be set to false. This implies that old entropy data in the ++ * per-CPU array collected since the last DRNG reseed is overwritten with ++ * new entropy data instead of retaining the entropy with the compression ++ * operation. + * -+ * @buf: buffer allocated by caller to store the random data in -+ * @nbytes: length of outbuf ++ * Impact on entropy: + * -+ * Return: number of bytes filled in. ++ * If continuous compression is enabled, the maximum entropy that is collected ++ * per CPU between DRNG reseeds is equal to the digest size of the used hash. ++ * ++ * If continuous compression is disabled, the maximum number of entropy events ++ * that can be collected per CPU is equal to LRNG_DATA_ARRAY_SIZE. This amount ++ * of events is converted into an entropy statement which then represents the ++ * maximum amount of entropy collectible per CPU between DRNG reseeds. + */ -+int __must_check get_random_bytes_arch(void *buf, int nbytes) -+{ -+ u8 *p = buf; ++static bool lrng_pcpu_continuous_compression __read_mostly = ++ IS_ENABLED(CONFIG_LRNG_ENABLE_CONTINUOUS_COMPRESSION); + -+ while (nbytes) { -+ unsigned long v; -+ int chunk = min_t(int, nbytes, sizeof(unsigned long)); ++#ifdef CONFIG_LRNG_SWITCHABLE_CONTINUOUS_COMPRESSION ++module_param(lrng_pcpu_continuous_compression, bool, 0444); ++MODULE_PARM_DESC(lrng_pcpu_continuous_compression, ++ "Perform entropy compression if per-CPU entropy data array is full\n"); ++#endif + -+ if (!arch_get_random_long(&v)) -+ break; ++/* ++ * Per-CPU entropy pool with compressed entropy event ++ * ++ * The per-CPU entropy pool is defined as the hash state. New data is simply ++ * inserted into the entropy pool by performing a hash update operation. ++ * To read the entropy pool, a hash final must be invoked. However, before ++ * the entropy pool is released again after a hash final, the hash init must ++ * be performed. ++ */ ++static DEFINE_PER_CPU(u8 [LRNG_POOL_SIZE], lrng_pcpu_pool) ++ __aligned(LRNG_KCAPI_ALIGN); ++/* ++ * Lock to allow other CPUs to read the pool - as this is only done during ++ * reseed which is infrequent, this lock is hardly contended. ++ */ ++static DEFINE_PER_CPU(spinlock_t, lrng_pcpu_lock); ++static DEFINE_PER_CPU(bool, lrng_pcpu_lock_init) = false; + -+ memcpy(p, &v, chunk); -+ p += chunk; -+ nbytes -= chunk; -+ } ++/* Number of time stamps analyzed to calculate a GCD */ ++#define LRNG_GCD_WINDOW_SIZE 100 ++static u32 lrng_gcd_history[LRNG_GCD_WINDOW_SIZE]; ++static atomic_t lrng_gcd_history_ptr = ATOMIC_INIT(-1); + -+ if (nbytes) -+ lrng_drng_get_atomic((u8 *)p, (u32)nbytes); ++/* The common divisor for all timestamps */ ++static u32 lrng_gcd_timer = 0; + -+ return nbytes; ++static inline bool lrng_gcd_tested(void) ++{ ++ return (lrng_gcd_timer != 0); +} -+EXPORT_SYMBOL(get_random_bytes_arch); + -+/* -+ * Returns whether or not the LRNG has been seeded. -+ * -+ * Returns: true if the urandom pool has been seeded. -+ * false if the urandom pool has not been seeded. -+ */ -+bool rng_is_initialized(void) ++/* Set the GCD for use in IRQ ES - if 0, the GCD calculation is restarted. */ ++static inline void _lrng_gcd_set(u32 running_gcd) +{ -+ return lrng_state_operational(); ++ lrng_gcd_timer = running_gcd; ++ mb(); +} -+EXPORT_SYMBOL(rng_is_initialized); + -+/************************ LRNG user output interfaces *************************/ -+ -+static ssize_t lrng_read_common(char __user *buf, size_t nbytes) ++static void lrng_gcd_set(u32 running_gcd) +{ -+ ssize_t ret = 0; -+ u8 tmpbuf[LRNG_DRNG_BLOCKSIZE] __aligned(LRNG_KCAPI_ALIGN); -+ u8 *tmp_large = NULL, *tmp = tmpbuf; -+ u32 tmplen = sizeof(tmpbuf); -+ -+ if (nbytes == 0) -+ return 0; -+ -+ /* -+ * Satisfy large read requests -- as the common case are smaller -+ * request sizes, such as 16 or 32 bytes, avoid a kmalloc overhead for -+ * those by using the stack variable of tmpbuf. -+ */ -+ if (!CONFIG_BASE_SMALL && (nbytes > sizeof(tmpbuf))) { -+ tmplen = min_t(u32, nbytes, LRNG_DRNG_MAX_REQSIZE); -+ tmp_large = kmalloc(tmplen + LRNG_KCAPI_ALIGN, GFP_KERNEL); -+ if (!tmp_large) -+ tmplen = sizeof(tmpbuf); -+ else -+ tmp = PTR_ALIGN(tmp_large, LRNG_KCAPI_ALIGN); ++ if (!lrng_gcd_tested()) { ++ _lrng_gcd_set(running_gcd); ++ pr_debug("Setting GCD to %u\n", running_gcd); + } ++} + -+ while (nbytes) { -+ u32 todo = min_t(u32, nbytes, tmplen); -+ int rc = 0; ++u32 lrng_gcd_analyze(u32 *history, size_t nelem) ++{ ++ u32 running_gcd = 0; ++ size_t i; + -+ /* Reschedule if we received a large request. */ -+ if ((tmp_large) && need_resched()) { -+ if (signal_pending(current)) { -+ if (ret == 0) -+ ret = -ERESTARTSYS; -+ break; -+ } -+ schedule(); -+ } ++ /* Now perform the analysis on the accumulated time data. */ ++ for (i = 0; i < nelem; i++) { ++ /* ++ * NOTE: this would be the place to add more analysis on the ++ * appropriateness of the timer like checking the presence ++ * of sufficient variations in the timer. ++ */ + -+ rc = lrng_drng_get_sleep(tmp, todo); -+ if (rc <= 0) { -+ if (rc < 0) -+ ret = rc; -+ break; -+ } -+ if (copy_to_user(buf, tmp, rc)) { -+ ret = -EFAULT; -+ break; -+ } ++ /* ++ * This calculates the gcd of all the time values. that is ++ * gcd(time_1, time_2, ..., time_nelem) ++ * ++ * Some timers increment by a fixed (non-1) amount each step. ++ * This code checks for such increments, and allows the library ++ * to output the number of such changes have occurred. ++ */ ++ running_gcd = (u32)gcd(history[i], running_gcd); + -+ nbytes -= rc; -+ buf += rc; -+ ret += rc; ++ /* Zeroize data */ ++ history[i] = 0; + } + -+ /* Wipe data just returned from memory */ -+ if (tmp_large) -+ kfree_sensitive(tmp_large); -+ else -+ memzero_explicit(tmpbuf, sizeof(tmpbuf)); -+ -+ return ret; ++ return running_gcd; +} + -+static ssize_t -+lrng_read_common_block(int nonblock, char __user *buf, size_t nbytes) ++static void jent_gcd_add_value(u32 time) +{ -+ if (nbytes == 0) -+ return 0; ++ u32 ptr = (u32)atomic_inc_return_relaxed(&lrng_gcd_history_ptr); + -+ if (unlikely(!lrng_state_operational())) { -+ int ret; ++ if (ptr < LRNG_GCD_WINDOW_SIZE) { ++ lrng_gcd_history[ptr] = time; ++ } else if (ptr == LRNG_GCD_WINDOW_SIZE) { ++ u32 gcd = lrng_gcd_analyze(lrng_gcd_history, ++ LRNG_GCD_WINDOW_SIZE); + -+ if (nonblock) -+ return -EAGAIN; ++ if (!gcd) ++ gcd = 1; + -+ ret = wait_event_interruptible(lrng_init_wait, -+ lrng_state_operational()); -+ if (unlikely(ret)) -+ return ret; -+ } ++ /* ++ * Ensure that we have variations in the time stamp below the ++ * given value. This is just a safety measure to prevent the GCD ++ * becoming too large. ++ */ ++ if (gcd >= 1000) { ++ pr_warn("calculated GCD is larger than expected: %u\n", ++ gcd); ++ gcd = 1000; ++ } + -+ return lrng_read_common(buf, nbytes); ++ /* Adjust all deltas by the observed (small) common factor. */ ++ lrng_gcd_set(gcd); ++ atomic_set(&lrng_gcd_history_ptr, 0); ++ } +} + -+static ssize_t lrng_drng_read_block(struct file *file, char __user *buf, -+ size_t nbytes, loff_t *ppos) ++/* Return boolean whether LRNG identified presence of high-resolution timer */ ++bool lrng_pool_highres_timer(void) +{ -+ return lrng_read_common_block(file->f_flags & O_NONBLOCK, buf, nbytes); ++ return lrng_irq_highres_timer; +} + -+static __poll_t lrng_random_poll(struct file *file, poll_table *wait) ++/* Convert entropy in bits into number of IRQs with the same entropy content. */ ++static inline u32 lrng_entropy_to_data(u32 entropy_bits) +{ -+ __poll_t mask; -+ -+ poll_wait(file, &lrng_init_wait, wait); -+ poll_wait(file, &lrng_write_wait, wait); -+ mask = 0; -+ if (lrng_state_operational()) -+ mask |= EPOLLIN | EPOLLRDNORM; -+ if (lrng_need_entropy() || -+ lrng_state_exseed_allow(lrng_noise_source_user)) -+ mask |= EPOLLOUT | EPOLLWRNORM; -+ return mask; ++ return ((entropy_bits * lrng_irq_entropy_bits) / ++ LRNG_DRNG_SECURITY_STRENGTH_BITS); +} + -+static ssize_t lrng_drng_write_common(const char __user *buffer, size_t count, -+ u32 entropy_bits) ++/* Convert number of IRQs into entropy value. */ ++static inline u32 lrng_data_to_entropy(u32 irqnum) +{ -+ ssize_t ret = 0; -+ u8 buf[64] __aligned(LRNG_KCAPI_ALIGN); -+ const char __user *p = buffer; -+ u32 orig_entropy_bits = entropy_bits; -+ -+ if (!lrng_get_available()) -+ return -EAGAIN; -+ -+ count = min_t(size_t, count, INT_MAX); -+ while (count > 0) { -+ size_t bytes = min_t(size_t, count, sizeof(buf)); -+ u32 ent = min_t(u32, bytes<<3, entropy_bits); ++ return ((irqnum * LRNG_DRNG_SECURITY_STRENGTH_BITS) / ++ lrng_irq_entropy_bits); ++} + -+ if (copy_from_user(&buf, p, bytes)) -+ return -EFAULT; -+ /* Inject data into entropy pool */ -+ lrng_pool_insert_aux(buf, bytes, ent); ++static inline bool lrng_pcpu_pool_online(int cpu) ++{ ++ return per_cpu(lrng_pcpu_lock_init, cpu); ++} + -+ count -= bytes; -+ p += bytes; -+ ret += bytes; -+ entropy_bits -= ent; ++bool lrng_pcpu_continuous_compression_state(void) ++{ ++ return lrng_pcpu_continuous_compression; ++} + -+ cond_resched(); ++static void lrng_pcpu_check_compression_state(void) ++{ ++ /* One pool must hold sufficient entropy for disabled compression */ ++ if (!lrng_pcpu_continuous_compression) { ++ u32 max_ent = min_t(u32, lrng_get_digestsize(), ++ lrng_data_to_entropy(LRNG_DATA_NUM_VALUES)); ++ if (max_ent < lrng_security_strength()) { ++ pr_warn("Force continuous compression operation to ensure LRNG can hold enough entropy\n"); ++ lrng_pcpu_continuous_compression = true; ++ } + } -+ -+ /* Force reseed of DRNG during next data request. */ -+ if (!orig_entropy_bits) -+ lrng_drng_force_reseed(); -+ -+ return ret; +} + -+static ssize_t lrng_drng_read(struct file *file, char __user *buf, -+ size_t nbytes, loff_t *ppos) ++static int __init lrng_init_time_source(void) +{ -+ if (!lrng_state_min_seeded()) -+ pr_notice_ratelimited("%s - use of insufficiently seeded DRNG (%zu bytes read)\n", -+ current->comm, nbytes); -+ else if (!lrng_state_operational()) -+ pr_debug_ratelimited("%s - use of not fully seeded DRNG (%zu bytes read)\n", -+ current->comm, nbytes); ++ /* Set a minimum number of interrupts that must be collected */ ++ irq_entropy = max_t(u32, LRNG_IRQ_ENTROPY_BITS, irq_entropy); ++ ++ if ((random_get_entropy() & LRNG_DATA_SLOTSIZE_MASK) || ++ (random_get_entropy() & LRNG_DATA_SLOTSIZE_MASK)) { ++ /* ++ * As the highres timer is identified here, previous interrupts ++ * obtained during boot time are treated like a lowres-timer ++ * would have been present. ++ */ ++ lrng_irq_highres_timer = true; ++ lrng_irq_entropy_bits = irq_entropy; ++ } else { ++ lrng_health_disable(); ++ lrng_irq_highres_timer = false; ++ lrng_irq_entropy_bits = irq_entropy * ++ LRNG_IRQ_OVERSAMPLING_FACTOR; ++ pr_warn("operating without high-resolution timer and applying IRQ oversampling factor %u\n", ++ LRNG_IRQ_OVERSAMPLING_FACTOR); ++ lrng_pcpu_check_compression_state(); ++ } + -+ return lrng_read_common(buf, nbytes); ++ return 0; +} ++core_initcall(lrng_init_time_source); + -+static ssize_t lrng_drng_write(struct file *file, const char __user *buffer, -+ size_t count, loff_t *ppos) ++/* ++ * Reset all per-CPU pools - reset entropy estimator but leave the pool data ++ * that may or may not have entropy unchanged. ++ */ ++void lrng_pcpu_reset(void) +{ -+ return lrng_drng_write_common(buffer, count, 0); ++ int cpu; ++ ++ /* Trigger GCD calculation anew. */ ++ _lrng_gcd_set(0); ++ ++ for_each_online_cpu(cpu) ++ atomic_set(per_cpu_ptr(&lrng_pcpu_array_irqs, cpu), 0); +} + -+static long lrng_ioctl(struct file *f, unsigned int cmd, unsigned long arg) ++u32 lrng_pcpu_avail_pool_size(void) +{ -+ u32 digestsize_bits; -+ int size, ent_count_bits; -+ int __user *p = (int __user *)arg; ++ u32 max_size = 0, max_pool = lrng_get_digestsize(); ++ int cpu; + -+ switch (cmd) { -+ case RNDGETENTCNT: -+ ent_count_bits = lrng_avail_entropy(); -+ if (put_user(ent_count_bits, p)) -+ return -EFAULT; -+ return 0; -+ case RNDADDTOENTCNT: -+ if (!capable(CAP_SYS_ADMIN)) -+ return -EPERM; -+ if (get_user(ent_count_bits, p)) -+ return -EFAULT; -+ ent_count_bits = (int)lrng_avail_aux_entropy() + ent_count_bits; -+ if (ent_count_bits < 0) -+ ent_count_bits = 0; -+ digestsize_bits = lrng_get_digestsize(); -+ if (ent_count_bits > digestsize_bits) -+ ent_count_bits = digestsize_bits; -+ lrng_pool_set_entropy(ent_count_bits); -+ return 0; -+ case RNDADDENTROPY: -+ if (!capable(CAP_SYS_ADMIN)) -+ return -EPERM; -+ if (get_user(ent_count_bits, p++)) -+ return -EFAULT; -+ if (ent_count_bits < 0) -+ return -EINVAL; -+ if (get_user(size, p++)) -+ return -EFAULT; -+ if (size < 0) -+ return -EINVAL; -+ lrng_state_exseed_set(lrng_noise_source_user, false); -+ /* there cannot be more entropy than data */ -+ ent_count_bits = min(ent_count_bits, size<<3); -+ return lrng_drng_write_common((const char __user *)p, size, -+ ent_count_bits); -+ case RNDZAPENTCNT: -+ case RNDCLEARPOOL: -+ /* Clear the entropy pool counter. */ -+ if (!capable(CAP_SYS_ADMIN)) -+ return -EPERM; -+ lrng_pool_set_entropy(0); -+ return 0; -+ case RNDRESEEDCRNG: -+ /* -+ * We leave the capability check here since it is present -+ * in the upstream's RNG implementation. Yet, user space -+ * can trigger a reseed as easy as writing into /dev/random -+ * or /dev/urandom where no privilege is needed. -+ */ -+ if (!capable(CAP_SYS_ADMIN)) -+ return -EPERM; -+ /* Force a reseed of all DRNGs */ -+ lrng_drng_force_reseed(); -+ return 0; -+ default: -+ return -EINVAL; ++ if (!lrng_pcpu_continuous_compression) ++ max_pool = min_t(u32, max_pool, LRNG_DATA_NUM_VALUES); ++ ++ for_each_online_cpu(cpu) { ++ if (lrng_pcpu_pool_online(cpu)) ++ max_size += max_pool; + } ++ ++ return max_size; +} + -+static int lrng_fasync(int fd, struct file *filp, int on) ++/* Return entropy of unused IRQs present in all per-CPU pools. */ ++u32 lrng_pcpu_avail_entropy(void) +{ -+ return fasync_helper(fd, filp, on, &fasync); -+} ++ u32 digestsize_irqs, irq = 0; ++ int cpu; + -+const struct file_operations random_fops = { -+ .read = lrng_drng_read_block, -+ .write = lrng_drng_write, -+ .poll = lrng_random_poll, -+ .unlocked_ioctl = lrng_ioctl, -+ .compat_ioctl = compat_ptr_ioctl, -+ .fasync = lrng_fasync, -+ .llseek = noop_llseek, -+}; ++ /* Obtain the cap of maximum numbers of IRQs we count */ ++ digestsize_irqs = lrng_entropy_to_data(lrng_get_digestsize()); ++ if (!lrng_pcpu_continuous_compression) { ++ /* Cap to max. number of IRQs the array can hold */ ++ digestsize_irqs = min_t(u32, digestsize_irqs, ++ LRNG_DATA_NUM_VALUES); ++ } + -+const struct file_operations urandom_fops = { -+ .read = lrng_drng_read, -+ .write = lrng_drng_write, -+ .unlocked_ioctl = lrng_ioctl, -+ .compat_ioctl = compat_ptr_ioctl, -+ .fasync = lrng_fasync, -+ .llseek = noop_llseek, -+}; ++ for_each_online_cpu(cpu) { ++ if (!lrng_pcpu_pool_online(cpu)) ++ continue; ++ irq += min_t(u32, digestsize_irqs, ++ atomic_read_u32(per_cpu_ptr(&lrng_pcpu_array_irqs, ++ cpu))); ++ } + -+SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count, -+ unsigned int, flags) -+{ -+ if (flags & ~(GRND_NONBLOCK|GRND_RANDOM|GRND_INSECURE)) -+ return -EINVAL; ++ /* Consider oversampling rate */ ++ return lrng_reduce_by_osr(lrng_data_to_entropy(irq)); ++} + -+ /* -+ * Requesting insecure and blocking randomness at the same time makes -+ * no sense. -+ */ -+ if ((flags & -+ (GRND_INSECURE|GRND_RANDOM)) == (GRND_INSECURE|GRND_RANDOM)) -+ return -EINVAL; ++/** ++ * Trigger a switch of the hash implementation for the per-CPU pool. ++ * ++ * For each per-CPU pool, obtain the message digest with the old hash ++ * implementation, initialize the per-CPU pool again with the new hash ++ * implementation and inject the message digest into the new state. ++ * ++ * Assumption: the caller must guarantee that the new_cb is available during the ++ * entire operation (e.g. it must hold the lock against pointer updating). ++ */ ++int lrng_pcpu_switch_hash(int node, ++ const struct lrng_crypto_cb *new_cb, void *new_hash, ++ const struct lrng_crypto_cb *old_cb) ++{ ++ u8 digest[LRNG_MAX_DIGESTSIZE]; ++ u32 digestsize_irqs, found_irqs; ++ int ret = 0, cpu; + -+ if (count > INT_MAX) -+ count = INT_MAX; ++ if (!IS_ENABLED(CONFIG_LRNG_DRNG_SWITCH)) ++ return -EOPNOTSUPP; + -+ if (flags & GRND_INSECURE) -+ return lrng_drng_read(NULL, buf, count, NULL); ++ for_each_online_cpu(cpu) { ++ struct shash_desc *pcpu_shash; + -+ return lrng_read_common_block(flags & GRND_NONBLOCK, buf, count); -+} ---- /dev/null -+++ b/drivers/char/lrng/lrng_internal.h -@@ -0,0 +1,416 @@ -+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ -+/* -+ * Copyright (C) 2018 - 2021, Stephan Mueller -+ */ ++ /* ++ * Only switch the per-CPU pools for the current node because ++ * the crypto_cb only applies NUMA-node-wide. ++ */ ++ if (cpu_to_node(cpu) != node || !lrng_pcpu_pool_online(cpu)) ++ continue; + -+#ifndef _LRNG_INTERNAL_H -+#define _LRNG_INTERNAL_H ++ pcpu_shash = (struct shash_desc *)per_cpu_ptr(lrng_pcpu_pool, ++ cpu); + -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++ digestsize_irqs = old_cb->lrng_hash_digestsize(pcpu_shash); ++ digestsize_irqs = lrng_entropy_to_data(digestsize_irqs << 3); + -+/*************************** General LRNG parameter ***************************/ ++ if (pcpu_shash->tfm == new_hash) ++ continue; + -+/* Security strength of LRNG -- this must match DRNG security strength */ -+#define LRNG_DRNG_SECURITY_STRENGTH_BYTES 32 -+#define LRNG_DRNG_SECURITY_STRENGTH_BITS (LRNG_DRNG_SECURITY_STRENGTH_BYTES * 8) -+#define LRNG_DRNG_BLOCKSIZE 64 /* Maximum of DRNG block sizes */ ++ /* Get the per-CPU pool hash with old digest ... */ ++ ret = old_cb->lrng_hash_final(pcpu_shash, digest) ?: ++ /* ... re-initialize the hash with the new digest ... */ ++ new_cb->lrng_hash_init(pcpu_shash, new_hash) ?: ++ /* ++ * ... feed the old hash into the new state. We may feed ++ * uninitialized memory into the new state, but this is ++ * considered no issue and even good as we have some more ++ * uncertainty here. ++ */ ++ new_cb->lrng_hash_update(pcpu_shash, digest, ++ sizeof(digest)); ++ if (ret) ++ goto out; + -+/* -+ * SP800-90A defines a maximum request size of 1<<16 bytes. The given value is -+ * considered a safer margin. -+ * -+ * This value is allowed to be changed. -+ */ -+#define LRNG_DRNG_MAX_REQSIZE (1<<12) ++ /* ++ * In case the new digest is larger than the old one, cap ++ * the available entropy to the old message digest used to ++ * process the existing data. ++ */ ++ found_irqs = atomic_xchg_relaxed( ++ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu), 0); ++ found_irqs = min_t(u32, found_irqs, digestsize_irqs); ++ atomic_add_return_relaxed(found_irqs, ++ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu)); + -+/* -+ * SP800-90A defines a maximum number of requests between reseeds of 2^48. -+ * The given value is considered a much safer margin, balancing requests for -+ * frequent reseeds with the need to conserve entropy. This value MUST NOT be -+ * larger than INT_MAX because it is used in an atomic_t. -+ * -+ * This value is allowed to be changed. -+ */ -+#define LRNG_DRNG_RESEED_THRESH (1<<20) ++ pr_debug("Re-initialize per-CPU entropy pool for CPU %d on NUMA node %d with hash %s\n", ++ cpu, node, new_cb->lrng_hash_name()); ++ } + -+/* -+ * Number of interrupts to be recorded to assume that DRNG security strength -+ * bits of entropy are received. -+ * Note: a value below the DRNG security strength should not be defined as this -+ * may imply the DRNG can never be fully seeded in case other noise -+ * sources are unavailable. -+ * -+ * This value is allowed to be changed. -+ */ -+#define LRNG_IRQ_ENTROPY_BITS CONFIG_LRNG_IRQ_ENTROPY_RATE ++out: ++ memzero_explicit(digest, sizeof(digest)); ++ return ret; ++} + +/* -+ * Min required seed entropy is 128 bits covering the minimum entropy -+ * requirement of SP800-131A and the German BSI's TR02102. -+ * -+ * This value is allowed to be changed. ++ * When reading the per-CPU message digest, make sure we use the crypto ++ * callbacks defined for the NUMA node the per-CPU pool is defined for because ++ * the LRNG crypto switch support is only atomic per NUMA node. + */ -+#define LRNG_FULL_SEED_ENTROPY_BITS LRNG_DRNG_SECURITY_STRENGTH_BITS -+#define LRNG_MIN_SEED_ENTROPY_BITS 128 -+#define LRNG_INIT_ENTROPY_BITS 32 ++static inline u32 ++lrng_pcpu_pool_hash_one(const struct lrng_crypto_cb *pcpu_crypto_cb, ++ void *pcpu_hash, int cpu, u8 *digest, u32 *digestsize) ++{ ++ struct shash_desc *pcpu_shash = ++ (struct shash_desc *)per_cpu_ptr(lrng_pcpu_pool, cpu); ++ spinlock_t *lock = per_cpu_ptr(&lrng_pcpu_lock, cpu); ++ unsigned long flags; ++ u32 digestsize_irqs, found_irqs; + -+/* -+ * Wakeup value -+ * -+ * This value is allowed to be changed but must not be larger than the -+ * digest size of the hash operation used update the aux_pool. -+ */ -+#ifdef CONFIG_CRYPTO_LIB_SHA256 -+# define LRNG_ATOMIC_DIGEST_SIZE SHA256_DIGEST_SIZE -+#else -+# define LRNG_ATOMIC_DIGEST_SIZE SHA1_DIGEST_SIZE -+#endif -+#define LRNG_WRITE_WAKEUP_ENTROPY LRNG_ATOMIC_DIGEST_SIZE ++ /* Lock guarding against reading / writing to per-CPU pool */ ++ spin_lock_irqsave(lock, flags); + -+/* -+ * If the switching support is configured, we must provide support up to -+ * the largest digest size. Without switching support, we know it is only -+ * the built-in digest size. -+ */ -+#ifdef CONFIG_LRNG_DRNG_SWITCH -+# define LRNG_MAX_DIGESTSIZE 64 -+#else -+# define LRNG_MAX_DIGESTSIZE LRNG_ATOMIC_DIGEST_SIZE -+#endif ++ *digestsize = pcpu_crypto_cb->lrng_hash_digestsize(pcpu_hash); ++ digestsize_irqs = lrng_entropy_to_data(*digestsize << 3); + -+/* -+ * Oversampling factor of IRQ events to obtain -+ * LRNG_DRNG_SECURITY_STRENGTH_BYTES. This factor is used when a -+ * high-resolution time stamp is not available. In this case, jiffies and -+ * register contents are used to fill the entropy pool. These noise sources -+ * are much less entropic than the high-resolution timer. The entropy content -+ * is the entropy content assumed with LRNG_IRQ_ENTROPY_BITS divided by -+ * LRNG_IRQ_OVERSAMPLING_FACTOR. ++ /* Obtain entropy statement like for the entropy pool */ ++ found_irqs = atomic_xchg_relaxed( ++ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu), 0); ++ /* Cap to maximum amount of data we can hold in hash */ ++ found_irqs = min_t(u32, found_irqs, digestsize_irqs); ++ ++ /* Cap to maximum amount of data we can hold in array */ ++ if (!lrng_pcpu_continuous_compression) ++ found_irqs = min_t(u32, found_irqs, LRNG_DATA_NUM_VALUES); ++ ++ /* Store all not-yet compressed data in data array into hash, ... */ ++ if (pcpu_crypto_cb->lrng_hash_update(pcpu_shash, ++ (u8 *)per_cpu_ptr(lrng_pcpu_array, cpu), ++ LRNG_DATA_ARRAY_SIZE * sizeof(u32)) ?: ++ /* ... get the per-CPU pool digest, ... */ ++ pcpu_crypto_cb->lrng_hash_final(pcpu_shash, digest) ?: ++ /* ... re-initialize the hash, ... */ ++ pcpu_crypto_cb->lrng_hash_init(pcpu_shash, pcpu_hash) ?: ++ /* ... feed the old hash into the new state. */ ++ pcpu_crypto_cb->lrng_hash_update(pcpu_shash, digest, *digestsize)) ++ found_irqs = 0; ++ ++ spin_unlock_irqrestore(lock, flags); ++ return found_irqs; ++} ++ ++/** ++ * Hash all per-CPU pools and return the digest to be used as seed data for ++ * seeding a DRNG. The caller must guarantee backtracking resistance. ++ * The function will only copy as much data as entropy is available into the ++ * caller-provided output buffer. + * -+ * This value is allowed to be changed. ++ * This function handles the translation from the number of received interrupts ++ * into an entropy statement. The conversion depends on LRNG_IRQ_ENTROPY_BITS ++ * which defines how many interrupts must be received to obtain 256 bits of ++ * entropy. With this value, the function lrng_data_to_entropy converts a given ++ * data size (received interrupts, requested amount of data, etc.) into an ++ * entropy statement. lrng_entropy_to_data does the reverse. ++ * ++ * @outbuf: buffer to store data in with size requested_bits ++ * @requested_bits: Requested amount of entropy ++ * @fully_seeded: indicator whether LRNG is fully seeded ++ * @return: amount of entropy in outbuf in bits. + */ -+#define LRNG_IRQ_OVERSAMPLING_FACTOR 10 ++u32 lrng_pcpu_pool_hash(u8 *outbuf, u32 requested_bits, bool fully_seeded) ++{ ++ SHASH_DESC_ON_STACK(shash, NULL); ++ const struct lrng_crypto_cb *crypto_cb; ++ struct lrng_drng **lrng_drng = lrng_drng_instances(); ++ struct lrng_drng *drng = lrng_drng_init_instance(); ++ u8 digest[LRNG_MAX_DIGESTSIZE]; ++ unsigned long flags, flags2; ++ u32 found_irqs, collected_irqs = 0, collected_ent_bits, requested_irqs, ++ returned_ent_bits; ++ int ret, cpu; ++ void *hash; + -+/* Alignmask that is intended to be identical to CRYPTO_MINALIGN */ -+#define LRNG_KCAPI_ALIGN ARCH_KMALLOC_MINALIGN ++ /* Lock guarding replacement of per-NUMA hash */ ++ read_lock_irqsave(&drng->hash_lock, flags); + -+/* -+ * This definition must provide a buffer that is equal to SHASH_DESC_ON_STACK -+ * as it will be casted into a struct shash_desc. -+ */ -+#define LRNG_POOL_SIZE (sizeof(struct shash_desc) + HASH_MAX_DESCSIZE) ++ crypto_cb = drng->crypto_cb; ++ hash = drng->hash; + -+/************************ Default DRNG implementation *************************/ ++ /* The hash state of filled with all per-CPU pool hashes. */ ++ ret = crypto_cb->lrng_hash_init(shash, hash); ++ if (ret) ++ goto err; + -+extern struct chacha20_state chacha20; -+extern const struct lrng_crypto_cb lrng_cc20_crypto_cb; -+void lrng_cc20_init_state(struct chacha20_state *state); ++ requested_irqs = lrng_entropy_to_data(requested_bits + ++ lrng_compress_osr()); + -+/********************************** /proc *************************************/ ++ /* ++ * Harvest entropy from each per-CPU hash state - even though we may ++ * have collected sufficient entropy, we will hash all per-CPU pools. ++ */ ++ for_each_online_cpu(cpu) { ++ struct lrng_drng *pcpu_drng = drng; ++ u32 digestsize, pcpu_unused_irqs = 0; ++ int node = cpu_to_node(cpu); + -+static inline void lrng_pool_inc_numa_node(void) { } ++ /* If pool is not online, then no entropy is present. */ ++ if (!lrng_pcpu_pool_online(cpu)) ++ continue; + -+/****************************** LRNG interfaces *******************************/ ++ if (lrng_drng && lrng_drng[node]) ++ pcpu_drng = lrng_drng[node]; + -+extern u32 lrng_write_wakeup_bits; -+extern int lrng_drng_reseed_max_time; ++ if (pcpu_drng == drng) { ++ found_irqs = lrng_pcpu_pool_hash_one(crypto_cb, hash, ++ cpu, digest, ++ &digestsize); ++ } else { ++ read_lock_irqsave(&pcpu_drng->hash_lock, flags2); ++ found_irqs = ++ lrng_pcpu_pool_hash_one(pcpu_drng->crypto_cb, ++ pcpu_drng->hash, cpu, ++ digest, &digestsize); ++ read_unlock_irqrestore(&pcpu_drng->hash_lock, flags2); ++ } + -+void lrng_writer_wakeup(void); -+void lrng_init_wakeup(void); -+void lrng_debug_report_seedlevel(const char *name); -+void lrng_process_ready_list(void); ++ /* Inject the digest into the state of all per-CPU pools */ ++ ret = crypto_cb->lrng_hash_update(shash, digest, digestsize); ++ if (ret) ++ goto err; + -+/* External interface to use of the switchable DRBG inside the kernel */ -+void get_random_bytes_full(void *buf, int nbytes); ++ collected_irqs += found_irqs; ++ if (collected_irqs > requested_irqs) { ++ pcpu_unused_irqs = collected_irqs - requested_irqs; ++ atomic_add_return_relaxed(pcpu_unused_irqs, ++ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu)); ++ collected_irqs = requested_irqs; ++ } ++ pr_debug("%u interrupts used from entropy pool of CPU %d, %u interrupts remain unused\n", ++ found_irqs - pcpu_unused_irqs, cpu, pcpu_unused_irqs); ++ } + -+/************************* Jitter RNG Entropy Source **************************/ ++ ret = crypto_cb->lrng_hash_final(shash, digest); ++ if (ret) ++ goto err; + -+#ifdef CONFIG_LRNG_JENT -+u32 lrng_get_jent(u8 *outbuf, u32 requested_bits); -+u32 lrng_jent_entropylevel(u32 requested_bits); -+#else /* CONFIG_CRYPTO_JITTERENTROPY */ -+static inline u32 lrng_get_jent(u8 *outbuf, u32 requested_bits) { return 0; } -+static inline u32 lrng_jent_entropylevel(u32 requested_bits) { return 0; } -+#endif /* CONFIG_CRYPTO_JITTERENTROPY */ ++ collected_ent_bits = lrng_data_to_entropy(collected_irqs); ++ /* Cap to maximum entropy that can ever be generated with given hash */ ++ collected_ent_bits = min_t(u32, collected_ent_bits, ++ crypto_cb->lrng_hash_digestsize(hash) << 3); ++ /* Apply oversampling: discount requested oversampling rate */ ++ returned_ent_bits = lrng_reduce_by_osr(collected_ent_bits); + -+/************************** CPU-based Entropy Source **************************/ ++ pr_debug("obtained %u bits by collecting %u bits of entropy from entropy pool noise source\n", ++ returned_ent_bits, collected_ent_bits); + -+static inline u32 lrng_fast_noise_entropylevel(u32 ent_bits, u32 requested_bits) -+{ -+ /* Obtain entropy statement */ -+ ent_bits = ent_bits * requested_bits / LRNG_DRNG_SECURITY_STRENGTH_BITS; -+ /* Cap entropy to buffer size in bits */ -+ ent_bits = min_t(u32, ent_bits, requested_bits); -+ return ent_bits; -+} ++ /* ++ * Truncate to available entropy as implicitly allowed by SP800-90B ++ * section 3.1.5.1.1 table 1 which awards truncated hashes full ++ * entropy. ++ * ++ * During boot time, we read requested_bits data with ++ * returned_ent_bits entropy. In case our conservative entropy ++ * estimate underestimates the available entropy we can transport as ++ * much available entropy as possible. ++ */ ++ memcpy(outbuf, digest, fully_seeded ? returned_ent_bits >> 3 : ++ requested_bits >> 3); + -+u32 lrng_get_arch(u8 *outbuf, u32 requested_bits); -+u32 lrng_archrandom_entropylevel(u32 requested_bits); ++out: ++ crypto_cb->lrng_hash_desc_zero(shash); ++ read_unlock_irqrestore(&drng->hash_lock, flags); ++ memzero_explicit(digest, sizeof(digest)); ++ return returned_ent_bits; + -+/************************** Interrupt Entropy Source **************************/ ++err: ++ returned_ent_bits = 0; ++ goto out; ++} + -+bool lrng_pcpu_continuous_compression_state(void); -+void lrng_pcpu_reset(void); -+u32 lrng_pcpu_avail_pool_size(void); -+u32 lrng_pcpu_avail_entropy(void); -+int lrng_pcpu_switch_hash(int node, -+ const struct lrng_crypto_cb *new_cb, void *new_hash, -+ const struct lrng_crypto_cb *old_cb); -+u32 lrng_pcpu_pool_hash(u8 *outbuf, u32 requested_bits, bool fully_seeded); -+void lrng_pcpu_array_add_u32(u32 data); ++/* Compress the lrng_pcpu_array array into lrng_pcpu_pool */ ++static inline void lrng_pcpu_array_compress(void) ++{ ++ struct shash_desc *shash = ++ (struct shash_desc *)this_cpu_ptr(lrng_pcpu_pool); ++ struct lrng_drng **lrng_drng = lrng_drng_instances(); ++ struct lrng_drng *drng = lrng_drng_init_instance(); ++ const struct lrng_crypto_cb *crypto_cb; ++ spinlock_t *lock = this_cpu_ptr(&lrng_pcpu_lock); ++ unsigned long flags, flags2; ++ int node = numa_node_id(); ++ void *hash; ++ bool init = false; + -+/****************************** DRNG processing *******************************/ ++ /* Get NUMA-node local hash instance */ ++ if (lrng_drng && lrng_drng[node]) ++ drng = lrng_drng[node]; + -+/* DRNG state handle */ -+struct lrng_drng { -+ void *drng; /* DRNG handle */ -+ void *hash; /* Hash handle */ -+ const struct lrng_crypto_cb *crypto_cb; /* Crypto callbacks */ -+ atomic_t requests; /* Number of DRNG requests */ -+ unsigned long last_seeded; /* Last time it was seeded */ -+ bool fully_seeded; /* Is DRNG fully seeded? */ -+ bool force_reseed; /* Force a reseed */ ++ read_lock_irqsave(&drng->hash_lock, flags); ++ crypto_cb = drng->crypto_cb; ++ hash = drng->hash; + -+ /* Lock write operations on DRNG state, DRNG replacement of crypto_cb */ -+ struct mutex lock; -+ spinlock_t spin_lock; -+ /* Lock *hash replacement - always take before DRNG lock */ -+ rwlock_t hash_lock; -+}; ++ if (unlikely(!this_cpu_read(lrng_pcpu_lock_init))) { ++ init = true; ++ spin_lock_init(lock); ++ this_cpu_write(lrng_pcpu_lock_init, true); ++ pr_debug("Initializing per-CPU entropy pool for CPU %d on NUMA node %d with hash %s\n", ++ raw_smp_processor_id(), node, ++ crypto_cb->lrng_hash_name()); ++ } + -+extern struct mutex lrng_crypto_cb_update; ++ spin_lock_irqsave(lock, flags2); + -+struct lrng_drng *lrng_drng_init_instance(void); -+struct lrng_drng *lrng_drng_atomic_instance(void); ++ if (unlikely(init) && crypto_cb->lrng_hash_init(shash, hash)) { ++ this_cpu_write(lrng_pcpu_lock_init, false); ++ pr_warn("Initialization of hash failed\n"); ++ } else if (lrng_pcpu_continuous_compression) { ++ /* Add entire per-CPU data array content into entropy pool. */ ++ if (crypto_cb->lrng_hash_update(shash, ++ (u8 *)this_cpu_ptr(lrng_pcpu_array), ++ LRNG_DATA_ARRAY_SIZE * sizeof(u32))) ++ pr_warn_ratelimited("Hashing of entropy data failed\n"); ++ } + -+static __always_inline bool lrng_drng_is_atomic(struct lrng_drng *drng) -+{ -+ return (drng->drng == lrng_drng_atomic_instance()->drng); ++ spin_unlock_irqrestore(lock, flags2); ++ read_unlock_irqrestore(&drng->hash_lock, flags); +} + -+/* Lock the DRNG */ -+static __always_inline void lrng_drng_lock(struct lrng_drng *drng, -+ unsigned long *flags) -+ __acquires(&drng->spin_lock) ++/* Compress data array into hash */ ++static inline void lrng_pcpu_array_to_hash(u32 ptr) +{ -+ /* Use spin lock in case the atomic DRNG context is used */ -+ if (lrng_drng_is_atomic(drng)) { -+ spin_lock_irqsave(&drng->spin_lock, *flags); ++ u32 *array = this_cpu_ptr(lrng_pcpu_array); ++ ++ /* ++ * During boot time the hash operation is triggered more often than ++ * during regular operation. ++ */ ++ if (unlikely(!lrng_state_fully_seeded())) { ++ if ((ptr & 31) && (ptr < LRNG_DATA_WORD_MASK)) ++ return; ++ } else if (ptr < LRNG_DATA_WORD_MASK) { ++ return; ++ } ++ ++ if (lrng_raw_array_entropy_store(*array)) { ++ u32 i; + + /* -+ * In case a lock transition happened while we were spinning, -+ * catch this case and use the new lock type. ++ * If we fed even a part of the array to external analysis, we ++ * mark that the entire array and the per-CPU pool to have no ++ * entropy. This is due to the non-IID property of the data as ++ * we do not fully know whether the existing dependencies ++ * diminish the entropy beyond to what we expect it has. + */ -+ if (!lrng_drng_is_atomic(drng)) { -+ spin_unlock_irqrestore(&drng->spin_lock, *flags); -+ __acquire(&drng->spin_lock); -+ mutex_lock(&drng->lock); -+ } -+ } else { -+ __acquire(&drng->spin_lock); -+ mutex_lock(&drng->lock); -+ } -+} ++ atomic_set(this_cpu_ptr(&lrng_pcpu_array_irqs), 0); + -+/* Unlock the DRNG */ -+static __always_inline void lrng_drng_unlock(struct lrng_drng *drng, -+ unsigned long *flags) -+ __releases(&drng->spin_lock) -+{ -+ if (lrng_drng_is_atomic(drng)) { -+ spin_unlock_irqrestore(&drng->spin_lock, *flags); ++ for (i = 1; i < LRNG_DATA_ARRAY_SIZE; i++) ++ lrng_raw_array_entropy_store(*(array + i)); + } else { -+ mutex_unlock(&drng->lock); -+ __release(&drng->spin_lock); ++ lrng_pcpu_array_compress(); ++ /* Ping pool handler about received entropy */ ++ lrng_pool_add_entropy(); + } +} + -+void lrng_reset(void); -+void lrng_drngs_init_cc20(bool force_seed); -+bool lrng_sp80090c_compliant(void); -+ -+static inline u32 lrng_compress_osr(void) ++/* ++ * Concatenate full 32 bit word at the end of time array even when current ++ * ptr is not aligned to sizeof(data). ++ */ ++static inline void _lrng_pcpu_array_add_u32(u32 data) +{ -+ return lrng_sp80090c_compliant() ? CONFIG_LRNG_OVERSAMPLE_ES_BITS : 0; -+} ++ /* Increment pointer by number of slots taken for input value */ ++ u32 pre_ptr, mask, ptr = this_cpu_add_return(lrng_pcpu_array_ptr, ++ LRNG_DATA_SLOTS_PER_UINT); ++ unsigned int pre_array; + -+static inline u32 lrng_reduce_by_osr(u32 entropy_bits) -+{ -+ u32 osr_bits = lrng_compress_osr(); -+ return (entropy_bits >= osr_bits) ? (entropy_bits - osr_bits) : 0; -+} ++ /* ++ * This function injects a unit into the array - guarantee that ++ * array unit size is equal to data type of input data. ++ */ ++ BUILD_BUG_ON(LRNG_DATA_ARRAY_MEMBER_BITS != (sizeof(data) << 3)); + -+bool lrng_get_available(void); -+void lrng_set_available(void); -+void lrng_drng_reset(struct lrng_drng *drng); -+int lrng_drng_get_atomic(u8 *outbuf, u32 outbuflen); -+int lrng_drng_get_sleep(u8 *outbuf, u32 outbuflen); -+void lrng_drng_force_reseed(void); -+void lrng_drng_seed_work(struct work_struct *dummy); ++ /* ++ * The following logic requires at least two units holding ++ * the data as otherwise the pointer would immediately wrap when ++ * injection an u32 word. ++ */ ++ BUILD_BUG_ON(LRNG_DATA_NUM_VALUES <= LRNG_DATA_SLOTS_PER_UINT); + -+static inline struct lrng_drng **lrng_drng_instances(void) { return NULL; } -+static inline void lrng_drngs_numa_alloc(void) { return; } ++ lrng_pcpu_split_u32(&ptr, &pre_ptr, &mask); + -+/************************* Entropy sources management *************************/ ++ /* MSB of data go into previous unit */ ++ pre_array = lrng_data_idx2array(pre_ptr); ++ /* zeroization of slot to ensure the following OR adds the data */ ++ this_cpu_and(lrng_pcpu_array[pre_array], ~(0xffffffff &~ mask)); ++ this_cpu_or(lrng_pcpu_array[pre_array], data & ~mask); + -+enum lrng_external_noise_source { -+ lrng_noise_source_hw, -+ lrng_noise_source_user -+}; ++ /* Invoke compression as we just filled data array completely */ ++ if (unlikely(pre_ptr > ptr)) ++ lrng_pcpu_array_to_hash(LRNG_DATA_WORD_MASK); + -+u32 lrng_avail_aux_entropy(void); -+u32 lrng_get_digestsize(void); ++ /* LSB of data go into current unit */ ++ this_cpu_write(lrng_pcpu_array[lrng_data_idx2array(ptr)], ++ data & mask); + -+/* Obtain the security strength of the LRNG in bits */ -+static inline u32 lrng_security_strength(void) ++ if (likely(pre_ptr <= ptr)) ++ lrng_pcpu_array_to_hash(ptr); ++} ++ ++/* Concatenate a 32-bit word at the end of the per-CPU array */ ++void lrng_pcpu_array_add_u32(u32 data) +{ + /* -+ * We use a hash to read the entropy in the entropy pool. According to -+ * SP800-90B table 1, the entropy can be at most the digest size. -+ * Considering this together with the last sentence in section 3.1.5.1.2 -+ * the security strength of a (approved) hash is equal to its output -+ * size. On the other hand the entropy cannot be larger than the -+ * security strength of the used DRBG. ++ * Disregard entropy-less data without continuous compression to ++ * avoid it overwriting data with entropy when array ptr wraps. + */ -+ return min_t(u32, LRNG_FULL_SEED_ENTROPY_BITS, lrng_get_digestsize()); ++ if (lrng_pcpu_continuous_compression) ++ _lrng_pcpu_array_add_u32(data); +} + -+static inline u32 lrng_get_seed_entropy_osr(void) ++/* Concatenate data of max LRNG_DATA_SLOTSIZE_MASK at the end of time array */ ++static inline void lrng_pcpu_array_add_slot(u32 data) +{ -+ u32 requested_bits = lrng_security_strength(); -+ -+ /* Apply oversampling during initialization according to SP800-90C */ -+ if (lrng_sp80090c_compliant()) -+ requested_bits += CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS; -+ return requested_bits; -+} -+ -+void lrng_set_entropy_thresh(u32 new); -+u32 lrng_avail_entropy(void); -+void lrng_reset_state(void); -+ -+bool lrng_state_exseed_allow(enum lrng_external_noise_source source); -+void lrng_state_exseed_set(enum lrng_external_noise_source source, bool type); -+bool lrng_state_min_seeded(void); -+bool lrng_state_fully_seeded(void); -+bool lrng_state_operational(void); -+ -+int lrng_pool_trylock(void); -+void lrng_pool_unlock(void); -+void lrng_pool_all_numa_nodes_seeded(bool set); -+bool lrng_pool_highres_timer(void); -+void lrng_pool_set_entropy(u32 entropy_bits); -+int lrng_aux_switch_hash(const struct lrng_crypto_cb *new_cb, void *new_hash, -+ const struct lrng_crypto_cb *old_cb); -+int lrng_pool_insert_aux(const u8 *inbuf, u32 inbuflen, u32 entropy_bits); -+void lrng_pool_add_entropy(void); -+ -+struct entropy_buf { -+ u8 a[LRNG_DRNG_SECURITY_STRENGTH_BYTES + -+ (CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS >> 3)]; -+ u8 b[LRNG_DRNG_SECURITY_STRENGTH_BYTES + -+ (CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS >> 3)]; -+ u8 c[LRNG_DRNG_SECURITY_STRENGTH_BYTES + -+ (CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS >> 3)]; -+ u8 d[LRNG_DRNG_SECURITY_STRENGTH_BYTES + -+ (CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS >> 3)]; -+ u32 now, a_bits, b_bits, c_bits, d_bits; -+}; ++ /* Get slot */ ++ u32 ptr = this_cpu_inc_return(lrng_pcpu_array_ptr) & ++ LRNG_DATA_WORD_MASK; ++ unsigned int array = lrng_data_idx2array(ptr); ++ unsigned int slot = lrng_data_idx2slot(ptr); + -+bool lrng_fully_seeded(struct entropy_buf *eb); -+void lrng_unset_operational(void); -+void lrng_fill_seed_buffer(struct entropy_buf *entropy_buf, u32 requested_bits); -+void lrng_init_ops(struct entropy_buf *eb); ++ BUILD_BUG_ON(LRNG_DATA_ARRAY_MEMBER_BITS % LRNG_DATA_SLOTSIZE_BITS); ++ /* Ensure consistency of values */ ++ BUILD_BUG_ON(LRNG_DATA_ARRAY_MEMBER_BITS != ++ sizeof(lrng_pcpu_array[0]) << 3); + -+/************************** Health Test linking code **************************/ ++ /* zeroization of slot to ensure the following OR adds the data */ ++ this_cpu_and(lrng_pcpu_array[array], ++ ~(lrng_data_slot_val(0xffffffff & LRNG_DATA_SLOTSIZE_MASK, ++ slot))); ++ /* Store data into slot */ ++ this_cpu_or(lrng_pcpu_array[array], lrng_data_slot_val(data, slot)); + -+enum lrng_health_res { -+ lrng_health_pass, /* Health test passes on time stamp */ -+ lrng_health_fail_use, /* Time stamp unhealthy, but mix in */ -+ lrng_health_fail_drop /* Time stamp unhealthy, drop it */ -+}; ++ lrng_pcpu_array_to_hash(ptr); ++} + -+#ifdef CONFIG_LRNG_HEALTH_TESTS -+bool lrng_sp80090b_startup_complete(void); -+bool lrng_sp80090b_compliant(void); ++static inline void ++lrng_time_process_common(u32 time, void(*add_time)(u32 data)) ++{ ++ enum lrng_health_res health_test; + -+enum lrng_health_res lrng_health_test(u32 now_time); -+void lrng_health_disable(void); ++ if (lrng_raw_hires_entropy_store(time)) ++ return; + -+#else /* CONFIG_LRNG_HEALTH_TESTS */ -+static inline bool lrng_sp80090b_startup_complete(void) { return true; } -+static inline bool lrng_sp80090b_compliant(void) { return false; } ++ health_test = lrng_health_test(time); ++ if (health_test > lrng_health_fail_use) ++ return; + -+static inline enum lrng_health_res -+lrng_health_test(u32 now_time) { return lrng_health_pass; } -+static inline void lrng_health_disable(void) { } -+#endif /* CONFIG_LRNG_HEALTH_TESTS */ ++ if (health_test == lrng_health_pass) ++ atomic_inc_return(this_cpu_ptr(&lrng_pcpu_array_irqs)); + -+/****************************** Helper code ***********************************/ ++ add_time(time); ++} + -+static inline u32 atomic_read_u32(atomic_t *v) ++/* ++ * Batching up of entropy in per-CPU array before injecting into entropy pool. ++ */ ++static inline void lrng_time_process(void) +{ -+ return (u32)atomic_read(v); ++ u32 now_time = random_get_entropy(); ++ ++ if (unlikely(!lrng_gcd_tested())) { ++ /* When GCD is unknown, we process the full time stamp */ ++ lrng_time_process_common(now_time, _lrng_pcpu_array_add_u32); ++ jent_gcd_add_value(now_time); ++ } else { ++ /* GCD is known and applied */ ++ lrng_time_process_common((now_time / lrng_gcd_timer) & ++ LRNG_DATA_SLOTSIZE_MASK, ++ lrng_pcpu_array_add_slot); ++ } ++ ++ lrng_perf_time(now_time); +} + -+/*************************** Auxiliary functions ******************************/ ++/* Hot code path - Callback for interrupt handler */ ++void add_interrupt_randomness(int irq, int irq_flg) ++{ ++ if (lrng_pool_highres_timer()) { ++ lrng_time_process(); ++ } else { ++ struct pt_regs *regs = get_irq_regs(); ++ static atomic_t reg_idx = ATOMIC_INIT(0); ++ u64 ip; ++ u32 tmp; + -+void invalidate_batched_entropy(void); ++ if (regs) { ++ u32 *ptr = (u32 *)regs; ++ int reg_ptr = atomic_add_return_relaxed(1, ®_idx); ++ size_t n = (sizeof(struct pt_regs) / sizeof(u32)); + -+/***************************** Testing code ***********************************/ ++ ip = instruction_pointer(regs); ++ tmp = *(ptr + (reg_ptr % n)); ++ tmp = lrng_raw_regs_entropy_store(tmp) ? 0 : tmp; ++ _lrng_pcpu_array_add_u32(tmp); ++ } else { ++ ip = _RET_IP_; ++ } + -+#ifdef CONFIG_LRNG_RAW_HIRES_ENTROPY -+bool lrng_raw_hires_entropy_store(u32 value); -+#else /* CONFIG_LRNG_RAW_HIRES_ENTROPY */ -+static inline bool lrng_raw_hires_entropy_store(u32 value) { return false; } -+#endif /* CONFIG_LRNG_RAW_HIRES_ENTROPY */ ++ lrng_time_process(); + -+#ifdef CONFIG_LRNG_RAW_JIFFIES_ENTROPY -+bool lrng_raw_jiffies_entropy_store(u32 value); -+#else /* CONFIG_LRNG_RAW_JIFFIES_ENTROPY */ -+static inline bool lrng_raw_jiffies_entropy_store(u32 value) { return false; } -+#endif /* CONFIG_LRNG_RAW_JIFFIES_ENTROPY */ ++ /* ++ * The XOR operation combining the different values is not ++ * considered to destroy entropy since the entirety of all ++ * processed values delivers the entropy (and not each ++ * value separately of the other values). ++ */ ++ tmp = lrng_raw_jiffies_entropy_store(jiffies) ? 0 : jiffies; ++ tmp ^= lrng_raw_irq_entropy_store(irq) ? 0 : irq; ++ tmp ^= lrng_raw_irqflags_entropy_store(irq_flg) ? 0 : irq_flg; ++ tmp ^= lrng_raw_retip_entropy_store(ip) ? 0 : ip; ++ tmp ^= ip >> 32; ++ _lrng_pcpu_array_add_u32(tmp); ++ } ++} ++EXPORT_SYMBOL(add_interrupt_randomness); +diff --git a/drivers/char/lrng/lrng_es_irq.h b/drivers/char/lrng/lrng_es_irq.h +new file mode 100644 +index 000000000000..00b16b1aa45f +--- /dev/null ++++ b/drivers/char/lrng/lrng_es_irq.h +@@ -0,0 +1,71 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ ++/* ++ * LRNG Slow Noise Source: Time stamp array handling ++ * ++ * Copyright (C) 2016 - 2021, Stephan Mueller ++ */ + -+#ifdef CONFIG_LRNG_RAW_IRQ_ENTROPY -+bool lrng_raw_irq_entropy_store(u32 value); -+#else /* CONFIG_LRNG_RAW_IRQ_ENTROPY */ -+static inline bool lrng_raw_irq_entropy_store(u32 value) { return false; } -+#endif /* CONFIG_LRNG_RAW_IRQ_ENTROPY */ ++/* ++ * To limit the impact on the interrupt handling, the LRNG concatenates ++ * entropic LSB parts of the time stamps in a per-CPU array and only ++ * injects them into the entropy pool when the array is full. ++ */ + -+#ifdef CONFIG_LRNG_RAW_IRQFLAGS_ENTROPY -+bool lrng_raw_irqflags_entropy_store(u32 value); -+#else /* CONFIG_LRNG_RAW_IRQFLAGS_ENTROPY */ -+static inline bool lrng_raw_irqflags_entropy_store(u32 value) { return false; } -+#endif /* CONFIG_LRNG_RAW_IRQFLAGS_ENTROPY */ ++/* Store multiple integers in one u32 */ ++#define LRNG_DATA_SLOTSIZE_BITS (8) ++#define LRNG_DATA_SLOTSIZE_MASK ((1 << LRNG_DATA_SLOTSIZE_BITS) - 1) ++#define LRNG_DATA_ARRAY_MEMBER_BITS (4 << 3) /* ((sizeof(u32)) << 3) */ ++#define LRNG_DATA_SLOTS_PER_UINT (LRNG_DATA_ARRAY_MEMBER_BITS / \ ++ LRNG_DATA_SLOTSIZE_BITS) + -+#ifdef CONFIG_LRNG_RAW_RETIP_ENTROPY -+bool lrng_raw_retip_entropy_store(u32 value); -+#else /* CONFIG_LRNG_RAW_RETIP_ENTROPY */ -+static inline bool lrng_raw_retip_entropy_store(u32 value) { return false; } -+#endif /* CONFIG_LRNG_RAW_RETIP_ENTROPY */ ++/* ++ * Number of time values to store in the array - in small environments ++ * only one atomic_t variable per CPU is used. ++ */ ++#define LRNG_DATA_NUM_VALUES (CONFIG_LRNG_COLLECTION_SIZE) ++/* Mask of LSB of time stamp to store */ ++#define LRNG_DATA_WORD_MASK (LRNG_DATA_NUM_VALUES - 1) + -+#ifdef CONFIG_LRNG_RAW_REGS_ENTROPY -+bool lrng_raw_regs_entropy_store(u32 value); -+#else /* CONFIG_LRNG_RAW_REGS_ENTROPY */ -+static inline bool lrng_raw_regs_entropy_store(u32 value) { return false; } -+#endif /* CONFIG_LRNG_RAW_REGS_ENTROPY */ ++#define LRNG_DATA_SLOTS_MASK (LRNG_DATA_SLOTS_PER_UINT - 1) ++#define LRNG_DATA_ARRAY_SIZE (LRNG_DATA_NUM_VALUES / \ ++ LRNG_DATA_SLOTS_PER_UINT) + -+#ifdef CONFIG_LRNG_RAW_ARRAY -+bool lrng_raw_array_entropy_store(u32 value); -+#else /* CONFIG_LRNG_RAW_ARRAY */ -+static inline bool lrng_raw_array_entropy_store(u32 value) { return false; } -+#endif /* CONFIG_LRNG_RAW_ARRAY */ ++/* Starting bit index of slot */ ++static inline unsigned int lrng_data_slot2bitindex(unsigned int slot) ++{ ++ return (LRNG_DATA_SLOTSIZE_BITS * slot); ++} + -+#ifdef CONFIG_LRNG_IRQ_PERF -+bool lrng_perf_time(u32 start); -+#else /* CONFIG_LRNG_IRQ_PERF */ -+static inline bool lrng_perf_time(u32 start) { return false; } -+#endif /*CONFIG_LRNG_IRQ_PERF */ ++/* Convert index into the array index */ ++static inline unsigned int lrng_data_idx2array(unsigned int idx) ++{ ++ return idx / LRNG_DATA_SLOTS_PER_UINT; ++} + -+#endif /* _LRNG_INTERNAL_H */ ++/* Convert index into the slot of a given array index */ ++static inline unsigned int lrng_data_idx2slot(unsigned int idx) ++{ ++ return idx & LRNG_DATA_SLOTS_MASK; ++} ++ ++/* Convert value into slot value */ ++static inline unsigned int lrng_data_slot_val(unsigned int val, ++ unsigned int slot) ++{ ++ return val << lrng_data_slot2bitindex(slot); ++} ++ ++/* ++ * Return the pointers for the previous and current units to inject a u32 into. ++ * Also return the mask which the u32 word is to be processed. ++ */ ++static inline void lrng_pcpu_split_u32(u32 *ptr, u32 *pre_ptr, u32 *mask) ++{ ++ /* ptr to previous unit */ ++ *pre_ptr = (*ptr - LRNG_DATA_SLOTS_PER_UINT) & LRNG_DATA_WORD_MASK; ++ *ptr &= LRNG_DATA_WORD_MASK; ++ ++ /* mask to split data into the two parts for the two units */ ++ *mask = ((1 << (*pre_ptr & (LRNG_DATA_SLOTS_PER_UINT - 1)) * ++ LRNG_DATA_SLOTSIZE_BITS)) - 1; ++} +diff --git a/drivers/char/lrng/lrng_es_mgr.c b/drivers/char/lrng/lrng_es_mgr.c +new file mode 100644 +index 000000000000..d0d66ff36de2 --- /dev/null -+++ b/drivers/char/lrng/lrng_pool.c -@@ -0,0 +1,622 @@ ++++ b/drivers/char/lrng/lrng_es_mgr.c +@@ -0,0 +1,375 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* + * LRNG Entropy sources management -+ * LRNG Slow Entropy Source: Auxiliary entropy pool + * + * Copyright (C) 2016 - 2021, Stephan Mueller + */ @@ -2693,7 +2830,7 @@ Signed-off-by: Stephan Mueller +#include + +#include "lrng_internal.h" -+#include "lrng_sw_noise.h" ++#include "lrng_es_irq.h" + +struct lrng_state { + bool can_invalidate; /* Can invalidate batched entropy? */ @@ -2719,32 +2856,6 @@ Signed-off-by: Stephan Mueller + struct work_struct lrng_seed_work; /* (re)seed work queue */ +}; + -+/* -+ * This is the auxiliary pool -+ * -+ * The aux pool array is aligned to 8 bytes to comfort the kernel crypto API -+ * cipher implementations of the hash functions used to read the pool: for some -+ * accelerated implementations, we need an alignment to avoid a realignment -+ * which involves memcpy(). The alignment to 8 bytes should satisfy all crypto -+ * implementations. -+ */ -+struct lrng_pool { -+ u8 aux_pool[LRNG_POOL_SIZE]; /* Aux pool: digest state */ -+ atomic_t aux_entropy_bits; -+ atomic_t digestsize; /* Digest size of used hash */ -+ bool initialized; /* Aux pool initialized? */ -+ -+ /* Serialize read of entropy pool and update of aux pool */ -+ spinlock_t lock; -+}; -+ -+static struct lrng_pool lrng_pool __aligned(LRNG_KCAPI_ALIGN) = { -+ .aux_entropy_bits = ATOMIC_INIT(0), -+ .digestsize = ATOMIC_INIT(LRNG_ATOMIC_DIGEST_SIZE), -+ .initialized = false, -+ .lock = __SPIN_LOCK_UNLOCKED(lrng_pool.lock) -+}; -+ +static struct lrng_state lrng_state = { + false, false, false, false, false, false, true, true, + .boot_entropy_thresh = ATOMIC_INIT(LRNG_INIT_ENTROPY_BITS), @@ -2776,40 +2887,6 @@ Signed-off-by: Stephan Mueller + lrng_state_exseed_set(lrng_noise_source_user, true); +} + -+/* Entropy in bits present in aux pool */ -+u32 lrng_avail_aux_entropy(void) -+{ -+ /* Cap available entropy with max entropy */ -+ u32 avail_bits = min_t(u32, lrng_get_digestsize(), -+ atomic_read_u32(&lrng_pool.aux_entropy_bits)); -+ -+ /* Consider oversampling rate due to aux pool conditioning */ -+ return lrng_reduce_by_osr(avail_bits); -+} -+ -+/* Set the digest size of the used hash in bytes */ -+static inline void lrng_set_digestsize(u32 digestsize) -+{ -+ struct lrng_pool *pool = &lrng_pool; -+ u32 ent_bits = atomic_xchg_relaxed(&pool->aux_entropy_bits, 0), -+ old_digestsize = lrng_get_digestsize(); -+ -+ atomic_set(&lrng_pool.digestsize, digestsize); -+ -+ /* -+ * In case the new digest is larger than the old one, cap the available -+ * entropy to the old message digest used to process the existing data. -+ */ -+ ent_bits = min_t(u32, ent_bits, old_digestsize); -+ atomic_add(ent_bits, &pool->aux_entropy_bits); -+} -+ -+/* Obtain the digest size provided by the used hash in bits */ -+u32 lrng_get_digestsize(void) -+{ -+ return atomic_read_u32(&lrng_pool.digestsize) << 3; -+} -+ +/* + * Reading of the LRNG pool is only allowed by one caller. The reading is + * only performed to (re)seed DRNGs. Thus, if this "lock" is already taken, @@ -2838,7 +2915,7 @@ Signed-off-by: Stephan Mueller + */ +void lrng_reset_state(void) +{ -+ atomic_set(&lrng_pool.aux_entropy_bits, 0); ++ lrng_pool_set_entropy(0); + lrng_pcpu_reset(); + lrng_state.lrng_operational = false; + lrng_state.lrng_fully_seeded = false; @@ -2872,37 +2949,49 @@ Signed-off-by: Stephan Mueller +} + +/* Policy to check whether entropy buffer contains full seeded entropy */ -+bool lrng_fully_seeded(struct entropy_buf *eb) ++bool lrng_fully_seeded(bool fully_seeded, struct entropy_buf *eb) +{ + return ((eb->a_bits + eb->b_bits + eb->c_bits + eb->d_bits) >= -+ lrng_get_seed_entropy_osr()); ++ lrng_get_seed_entropy_osr(fully_seeded)); +} + -+/* Disable the fully seeded and operational mode */ -+void lrng_unset_operational(void) ++/* Mark one DRNG as not fully seeded */ ++void lrng_unset_fully_seeded(struct lrng_drng *drng) +{ ++ drng->fully_seeded = false; + lrng_pool_all_numa_nodes_seeded(false); -+ lrng_state.lrng_operational = false; -+ lrng_state.lrng_fully_seeded = false; ++ ++ /* ++ * The init DRNG instance must always be fully seeded as this instance ++ * is the fall-back if any of the per-NUMA node DRNG instances is ++ * insufficiently seeded. Thus, we mark the entire LRNG as ++ * non-operational if the initial DRNG becomes not fully seeded. ++ */ ++ if (drng == lrng_drng_init_instance() && lrng_state_operational()) { ++ pr_debug("LRNG set to non-operational\n"); ++ lrng_state.lrng_operational = false; ++ lrng_state.lrng_fully_seeded = false; ++ ++ /* If sufficient entropy is available, reseed now. */ ++ lrng_pool_add_entropy(); ++ } +} + +/* Policy to enable LRNG operational mode */ +static inline void lrng_set_operational(u32 external_es) +{ ++ /* LRNG is operational if the initial DRNG is fully seeded ... */ + if (lrng_state.lrng_fully_seeded && ++ /* ... and either internal ES SP800-90B startup is complete ... */ + (lrng_sp80090b_startup_complete() || -+ (lrng_get_seed_entropy_osr() <= external_es))) { ++ /* ... or the external ES provided sufficient entropy. */ ++ (lrng_get_seed_entropy_osr(lrng_state_fully_seeded()) <= ++ external_es))) { + lrng_state.lrng_operational = true; -+ lrng_process_ready_list(); -+ lrng_init_wakeup(); -+ pr_info("LRNG fully operational\n"); -+ } -+} -+ -+/* Set entropy content in user-space controllable aux pool */ -+void lrng_pool_set_entropy(u32 entropy_bits) -+{ -+ atomic_set(&lrng_pool.aux_entropy_bits, entropy_bits); ++ lrng_process_ready_list(); ++ lrng_init_wakeup(); ++ pr_info("LRNG fully operational\n"); ++ } +} + +/* Available entropy in the entire LRNG considering all entropy sources */ @@ -2941,7 +3030,8 @@ Signed-off-by: Stephan Mueller + if (state->lrng_operational) + return; + -+ requested_bits = lrng_get_seed_entropy_osr(); ++ requested_bits = lrng_get_seed_entropy_osr( ++ state->all_online_numa_node_seeded); + + /* + * Entropy provided by external entropy sources - if they provide @@ -2954,7 +3044,7 @@ Signed-off-by: Stephan Mueller + if (state->lrng_fully_seeded) { + lrng_set_operational(external_es); + lrng_set_entropy_thresh(requested_bits); -+ } else if (lrng_fully_seeded(eb)) { ++ } else if (lrng_fully_seeded(state->all_online_numa_node_seeded, eb)) { + if (state->can_invalidate) + invalidate_batched_entropy(); + @@ -3022,1060 +3112,1193 @@ Signed-off-by: Stephan Mueller + return 0; +} + ++/* Hot code path during boot - mix data into entropy pool during boot */ ++void lrng_pool_add_entropy(void) ++{ ++ /* ++ * Once all DRNGs are fully seeded, the interrupt noise ++ * sources will not trigger any reseeding any more. ++ */ ++ if (likely(lrng_state.all_online_numa_node_seeded)) ++ return; ++ ++ /* Only try to reseed if the DRNG is alive. */ ++ if (!lrng_get_available()) ++ return; ++ ++ /* Only trigger the DRNG reseed if we have collected entropy. */ ++ if (lrng_avail_entropy() < ++ atomic_read_u32(&lrng_state.boot_entropy_thresh)) ++ return; ++ ++ /* Ensure that the seeding only occurs once at any given time. */ ++ if (lrng_pool_trylock()) ++ return; ++ ++ /* Seed the DRNG with IRQ noise. */ ++ if (lrng_state.perform_seedwork) ++ schedule_work(&lrng_state.lrng_seed_work); ++ else ++ lrng_drng_seed_work(NULL); ++} ++ ++/* Fill the seed buffer with data from the noise sources */ ++void lrng_fill_seed_buffer(struct entropy_buf *entropy_buf, u32 requested_bits) ++{ ++ struct lrng_state *state = &lrng_state; ++ u32 req_ent = lrng_sp80090c_compliant() ? ++ lrng_security_strength() : LRNG_MIN_SEED_ENTROPY_BITS; ++ ++ /* Guarantee that requested bits is a multiple of bytes */ ++ BUILD_BUG_ON(LRNG_DRNG_SECURITY_STRENGTH_BITS % 8); ++ ++ /* always reseed the DRNG with the current time stamp */ ++ entropy_buf->now = random_get_entropy(); ++ ++ /* ++ * Require at least 128 bits of entropy for any reseed. If the LRNG is ++ * operated SP800-90C compliant we want to comply with SP800-90A section ++ * 9.2 mandating that DRNG is reseeded with the security strength. ++ */ ++ if (state->lrng_fully_seeded && (lrng_avail_entropy() < req_ent)) { ++ entropy_buf->a_bits = entropy_buf->b_bits = 0; ++ entropy_buf->c_bits = entropy_buf->d_bits = 0; ++ goto wakeup; ++ } ++ ++ /* Concatenate the output of the entropy sources. */ ++ entropy_buf->b_bits = lrng_pcpu_pool_hash(entropy_buf->b, ++ requested_bits, ++ state->lrng_fully_seeded); ++ entropy_buf->c_bits = lrng_get_arch(entropy_buf->c, requested_bits); ++ entropy_buf->d_bits = lrng_get_jent(entropy_buf->d, requested_bits); ++ lrng_get_backtrack_aux(entropy_buf, requested_bits); ++ ++ /* allow external entropy provider to provide seed */ ++ lrng_state_exseed_allow_all(); ++ ++wakeup: ++ /* ++ * Shall we wake up user space writers? This location covers ++ * ensures that the user space provider does not dominate the internal ++ * noise sources since in case the first call of this function finds ++ * sufficient entropy in the entropy pool, it will not trigger the ++ * wakeup. This implies that when the next /dev/urandom read happens, ++ * the entropy pool is drained. ++ */ ++ lrng_writer_wakeup(); ++} +diff --git a/drivers/char/lrng/lrng_interfaces.c b/drivers/char/lrng/lrng_interfaces.c +new file mode 100644 +index 000000000000..3a56bfdca01e +--- /dev/null ++++ b/drivers/char/lrng/lrng_interfaces.c +@@ -0,0 +1,650 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* -+ * Replace old with new hash for auxiliary pool handling ++ * LRNG User and kernel space interfaces + * -+ * Assumption: the caller must guarantee that the new_cb is available during the -+ * entire operation (e.g. it must hold the write lock against pointer updating). ++ * Copyright (C) 2016 - 2021, Stephan Mueller + */ -+int lrng_aux_switch_hash(const struct lrng_crypto_cb *new_cb, void *new_hash, -+ const struct lrng_crypto_cb *old_cb) -+{ -+ struct lrng_pool *pool = &lrng_pool; -+ struct shash_desc *shash = (struct shash_desc *)pool->aux_pool; -+ u8 digest[LRNG_MAX_DIGESTSIZE]; -+ int ret; + -+ if (!IS_ENABLED(CONFIG_LRNG_DRNG_SWITCH)) -+ return -EOPNOTSUPP; ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + -+ if (unlikely(!pool->initialized)) -+ return 0; ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+ /* Get the aux pool hash with old digest ... */ -+ ret = old_cb->lrng_hash_final(shash, digest) ?: -+ /* ... re-initialize the hash with the new digest ... */ -+ new_cb->lrng_hash_init(shash, new_hash) ?: -+ /* -+ * ... feed the old hash into the new state. We may feed -+ * uninitialized memory into the new state, but this is -+ * considered no issue and even good as we have some more -+ * uncertainty here. -+ */ -+ new_cb->lrng_hash_update(shash, digest, sizeof(digest)); -+ if (!ret) { -+ lrng_set_digestsize(new_cb->lrng_hash_digestsize(new_hash)); -+ pr_debug("Re-initialize aux entropy pool with hash %s\n", -+ new_cb->lrng_hash_name()); ++#define CREATE_TRACE_POINTS ++#include ++ ++#include "lrng_internal.h" ++ ++/* ++ * If the entropy count falls under this number of bits, then we ++ * should wake up processes which are selecting or polling on write ++ * access to /dev/random. ++ */ ++u32 lrng_write_wakeup_bits = LRNG_WRITE_WAKEUP_ENTROPY; ++ ++static LIST_HEAD(lrng_ready_list); ++static DEFINE_SPINLOCK(lrng_ready_list_lock); ++ ++static DECLARE_WAIT_QUEUE_HEAD(lrng_write_wait); ++static DECLARE_WAIT_QUEUE_HEAD(lrng_init_wait); ++static struct fasync_struct *fasync; ++ ++struct ctl_table random_table[]; ++ ++/********************************** Helper ***********************************/ ++ ++/* Is the DRNG seed level too low? */ ++static inline bool lrng_need_entropy(void) ++{ ++ return (lrng_avail_aux_entropy() < lrng_write_wakeup_bits); ++} ++ ++void lrng_writer_wakeup(void) ++{ ++ if (lrng_need_entropy() && wq_has_sleeper(&lrng_write_wait)) { ++ wake_up_interruptible(&lrng_write_wait); ++ kill_fasync(&fasync, SIGIO, POLL_OUT); + } ++} + -+ memzero_explicit(digest, sizeof(digest)); -+ return ret; ++void lrng_init_wakeup(void) ++{ ++ wake_up_all(&lrng_init_wait); ++ kill_fasync(&fasync, SIGIO, POLL_IN); +} + -+/* -+ * Insert data into auxiliary pool by hashing the input data together with -+ * the auxiliary pool. The message digest is the new state of the auxiliary -+ * pool. ++/** ++ * lrng_process_ready_list() - Ping all kernel internal callers waiting until ++ * the DRNG is completely initialized to inform that the DRNG reached that ++ * seed level. ++ * ++ * When the SP800-90B testing is enabled, the ping only happens if the SP800-90B ++ * startup health tests are completed. This implies that kernel internal ++ * callers always have an SP800-90B compliant noise source when being ++ * pinged. + */ -+static int -+lrng_pool_insert_aux_locked(const u8 *inbuf, u32 inbuflen, u32 entropy_bits) ++void lrng_process_ready_list(void) +{ -+ struct lrng_pool *pool = &lrng_pool; -+ struct shash_desc *shash = (struct shash_desc *)pool->aux_pool; -+ struct lrng_drng *drng = lrng_drng_init_instance(); -+ const struct lrng_crypto_cb *crypto_cb; + unsigned long flags; -+ void *hash; -+ int ret; -+ -+ entropy_bits = min_t(u32, entropy_bits, inbuflen << 3); ++ struct random_ready_callback *rdy, *tmp; + -+ read_lock_irqsave(&drng->hash_lock, flags); ++ if (!lrng_state_operational()) ++ return; + -+ crypto_cb = drng->crypto_cb; -+ hash = drng->hash; ++ spin_lock_irqsave(&lrng_ready_list_lock, flags); ++ list_for_each_entry_safe(rdy, tmp, &lrng_ready_list, list) { ++ struct module *owner = rdy->owner; + -+ if (unlikely(!pool->initialized)) { -+ ret = crypto_cb->lrng_hash_init(shash, hash); -+ if (ret) -+ goto out; -+ pool->initialized = true; ++ list_del_init(&rdy->list); ++ rdy->func(rdy); ++ module_put(owner); + } ++ spin_unlock_irqrestore(&lrng_ready_list_lock, flags); ++} + -+ ret = crypto_cb->lrng_hash_update(shash, inbuf, inbuflen); -+ if (ret) -+ goto out; ++void lrng_debug_report_seedlevel(const char *name) ++{ ++#ifdef CONFIG_WARN_ALL_UNSEEDED_RANDOM ++ static void *previous = NULL; ++ void *caller = (void *) _RET_IP_; ++ ++ if (READ_ONCE(previous) == caller) ++ return; ++ ++ if (!lrng_state_min_seeded()) ++ pr_notice("%pS %s called without reaching minimally seeded level (available entropy %u)\n", ++ caller, name, lrng_avail_entropy()); ++ ++ WRITE_ONCE(previous, caller); ++#endif ++} ++ ++/************************ LRNG kernel input interfaces ************************/ + ++/** ++ * add_hwgenerator_randomness() - Interface for in-kernel drivers of true ++ * hardware RNGs. ++ * ++ * Those devices may produce endless random bits and will be throttled ++ * when our pool is full. ++ * ++ * @buffer: buffer holding the entropic data from HW noise sources to be used to ++ * insert into entropy pool. ++ * @count: length of buffer ++ * @entropy_bits: amount of entropy in buffer (value is in bits) ++ */ ++void add_hwgenerator_randomness(const char *buffer, size_t count, ++ size_t entropy_bits) ++{ + /* -+ * Cap the available entropy to the hash output size compliant to -+ * SP800-90B section 3.1.5.1 table 1. ++ * Suspend writing if we are fully loaded with entropy. ++ * We'll be woken up again once below lrng_write_wakeup_thresh, ++ * or when the calling thread is about to terminate. + */ -+ entropy_bits += atomic_read_u32(&pool->aux_entropy_bits); -+ atomic_set(&pool->aux_entropy_bits, -+ min_t(u32, entropy_bits, -+ crypto_cb->lrng_hash_digestsize(hash) << 3)); -+ -+out: -+ read_unlock_irqrestore(&drng->hash_lock, flags); -+ return ret; ++ wait_event_interruptible(lrng_write_wait, ++ lrng_need_entropy() || ++ lrng_state_exseed_allow(lrng_noise_source_hw) || ++ kthread_should_stop()); ++ lrng_state_exseed_set(lrng_noise_source_hw, false); ++ lrng_pool_insert_aux(buffer, count, entropy_bits); +} ++EXPORT_SYMBOL_GPL(add_hwgenerator_randomness); + -+int lrng_pool_insert_aux(const u8 *inbuf, u32 inbuflen, u32 entropy_bits) ++/** ++ * add_bootloader_randomness() - Handle random seed passed by bootloader. ++ * ++ * If the seed is trustworthy, it would be regarded as hardware RNGs. Otherwise ++ * it would be regarded as device data. ++ * The decision is controlled by CONFIG_RANDOM_TRUST_BOOTLOADER. ++ * ++ * @buf: buffer holding the entropic data from HW noise sources to be used to ++ * insert into entropy pool. ++ * @size: length of buffer ++ */ ++void add_bootloader_randomness(const void *buf, unsigned int size) +{ -+ struct lrng_pool *pool = &lrng_pool; -+ unsigned long flags; -+ int ret; -+ -+ spin_lock_irqsave(&pool->lock, flags); -+ ret = lrng_pool_insert_aux_locked(inbuf, inbuflen, entropy_bits); -+ spin_unlock_irqrestore(&pool->lock, flags); -+ -+ lrng_pool_add_entropy(); -+ -+ return ret; ++ lrng_pool_insert_aux(buf, size, ++ IS_ENABLED(CONFIG_RANDOM_TRUST_BOOTLOADER) ? ++ size * 8 : 0); +} ++EXPORT_SYMBOL_GPL(add_bootloader_randomness); + -+/* Hot code path during boot - mix data into entropy pool during boot */ -+void lrng_pool_add_entropy(void) ++/* ++ * Callback for HID layer -- use the HID event values to stir the entropy pool ++ */ ++void add_input_randomness(unsigned int type, unsigned int code, ++ unsigned int value) +{ -+ /* -+ * Once all DRNGs are fully seeded, the interrupt noise -+ * sources will not trigger any reseeding any more. -+ */ -+ if (likely(lrng_state.all_online_numa_node_seeded)) -+ return; ++ static unsigned char last_value; + -+ /* Only try to reseed if the DRNG is alive. */ -+ if (!lrng_get_available()) ++ /* ignore autorepeat and the like */ ++ if (value == last_value) + return; + -+ /* Only trigger the DRNG reseed if we have collected entropy. */ -+ if (lrng_avail_entropy() < -+ atomic_read_u32(&lrng_state.boot_entropy_thresh)) -+ return; ++ last_value = value; + -+ /* Ensure that the seeding only occurs once at any given time. */ -+ if (lrng_pool_trylock()) -+ return; ++ lrng_pcpu_array_add_u32((type << 4) ^ code ^ (code >> 4) ^ value); ++} ++EXPORT_SYMBOL_GPL(add_input_randomness); + -+ /* Seed the DRNG with IRQ noise. */ -+ if (lrng_state.perform_seedwork) -+ schedule_work(&lrng_state.lrng_seed_work); -+ else -+ lrng_drng_seed_work(NULL); ++/** ++ * add_device_randomness() - Add device- or boot-specific data to the entropy ++ * pool to help initialize it. ++ * ++ * None of this adds any entropy; it is meant to avoid the problem of ++ * the entropy pool having similar initial state across largely ++ * identical devices. ++ * ++ * @buf: buffer holding the entropic data from HW noise sources to be used to ++ * insert into entropy pool. ++ * @size: length of buffer ++ */ ++void add_device_randomness(const void *buf, unsigned int size) ++{ ++ lrng_pool_insert_aux((u8 *)buf, size, 0); +} ++EXPORT_SYMBOL(add_device_randomness); + -+/************************* Get data from entropy pool *************************/ ++#ifdef CONFIG_BLOCK ++void rand_initialize_disk(struct gendisk *disk) { } ++void add_disk_randomness(struct gendisk *disk) { } ++EXPORT_SYMBOL(add_disk_randomness); ++#endif + +/** -+ * Get auxiliary entropy pool and its entropy content for seed buffer. -+ * Caller must hold lrng_pool.pool->lock. -+ * @outbuf: buffer to store data in with size requested_bits -+ * @requested_bits: Requested amount of entropy -+ * @return: amount of entropy in outbuf in bits. ++ * del_random_ready_callback() - Delete a previously registered readiness ++ * callback function. ++ * ++ * @rdy: callback definition that was registered initially + */ -+static inline u32 lrng_get_aux_pool(u8 *outbuf, u32 requested_bits) ++void del_random_ready_callback(struct random_ready_callback *rdy) +{ -+ struct lrng_pool *pool = &lrng_pool; -+ struct shash_desc *shash = (struct shash_desc *)pool->aux_pool; -+ struct lrng_drng *drng = lrng_drng_init_instance(); -+ const struct lrng_crypto_cb *crypto_cb; + unsigned long flags; -+ void *hash; -+ u32 collected_ent_bits, returned_ent_bits, unused_bits = 0, -+ digestsize; -+ u8 aux_output[LRNG_MAX_DIGESTSIZE]; -+ -+ if (unlikely(!pool->initialized)) -+ return 0; -+ -+ read_lock_irqsave(&drng->hash_lock, flags); -+ -+ crypto_cb = drng->crypto_cb; -+ hash = drng->hash; -+ digestsize = crypto_cb->lrng_hash_digestsize(hash); -+ -+ /* Ensure that no more than the size of aux_pool can be requested */ -+ requested_bits = min_t(u32, requested_bits, (LRNG_MAX_DIGESTSIZE << 3)); -+ -+ /* Cap entropy with entropy counter from aux pool and the used digest */ -+ collected_ent_bits = min_t(u32, digestsize << 3, -+ atomic_xchg_relaxed(&pool->aux_entropy_bits, 0)); -+ -+ /* We collected too much entropy and put the overflow back */ -+ if (collected_ent_bits > (requested_bits + lrng_compress_osr())) { -+ /* Amount of bits we collected too much */ -+ unused_bits = collected_ent_bits - requested_bits; -+ /* Put entropy back */ -+ atomic_add(unused_bits, &pool->aux_entropy_bits); -+ /* Fix collected entropy */ -+ collected_ent_bits = requested_bits; -+ } -+ -+ /* Apply oversampling: discount requested oversampling rate */ -+ returned_ent_bits = lrng_reduce_by_osr(collected_ent_bits); -+ -+ pr_debug("obtained %u bits by collecting %u bits of entropy from aux pool, %u bits of entropy remaining\n", -+ returned_ent_bits, collected_ent_bits, unused_bits); ++ struct module *owner = NULL; + -+ /* Get the digest for the aux pool to be returned to the caller ... */ -+ if (crypto_cb->lrng_hash_final(shash, aux_output) || -+ /* -+ * ... and re-initialize the aux state. Do not add the aux pool -+ * digest for backward secrecy as it will be added with the -+ * insertion of the complete seed buffer after it has been filled. -+ */ -+ crypto_cb->lrng_hash_init(shash, hash)) { -+ returned_ent_bits = 0; -+ } else { -+ /* -+ * Do not truncate the output size exactly to collected_ent_bits -+ * as the aux pool may contain data that is not credited with -+ * entropy, but we want to use them to stir the DRNG state. -+ */ -+ memcpy(outbuf, aux_output, requested_bits >> 3); ++ spin_lock_irqsave(&lrng_ready_list_lock, flags); ++ if (!list_empty(&rdy->list)) { ++ list_del_init(&rdy->list); ++ owner = rdy->owner; + } ++ spin_unlock_irqrestore(&lrng_ready_list_lock, flags); + -+ read_unlock_irqrestore(&drng->hash_lock, flags); -+ memzero_explicit(aux_output, digestsize); -+ return returned_ent_bits; ++ module_put(owner); +} ++EXPORT_SYMBOL(del_random_ready_callback); + -+/* Fill the seed buffer with data from the noise sources */ -+void lrng_fill_seed_buffer(struct entropy_buf *entropy_buf, u32 requested_bits) ++/** ++ * add_random_ready_callback() - Add a callback function that will be invoked ++ * when the DRNG is fully initialized and seeded. ++ * ++ * @rdy: callback definition to be invoked when the LRNG is seeded ++ * ++ * Return: ++ * * 0 if callback is successfully added ++ * * -EALREADY if pool is already initialised (callback not called) ++ * * -ENOENT if module for callback is not alive ++ */ ++int add_random_ready_callback(struct random_ready_callback *rdy) +{ -+ struct lrng_pool *pool = &lrng_pool; -+ struct lrng_state *state = &lrng_state; ++ struct module *owner; + unsigned long flags; -+ u32 pcpu_request, req_ent = lrng_sp80090c_compliant() ? -+ lrng_security_strength() : LRNG_MIN_SEED_ENTROPY_BITS; -+ -+ /* Guarantee that requested bits is a multiple of bytes */ -+ BUILD_BUG_ON(LRNG_DRNG_SECURITY_STRENGTH_BITS % 8); -+ -+ /* always reseed the DRNG with the current time stamp */ -+ entropy_buf->now = random_get_entropy(); -+ -+ /* -+ * Require at least 128 bits of entropy for any reseed. If the LRNG is -+ * operated SP800-90C compliant we want to comply with SP800-90A section -+ * 9.2 mandating that DRNG is reseeded with the security strength. -+ */ -+ if (state->lrng_fully_seeded && (lrng_avail_entropy() < req_ent)) { -+ entropy_buf->a_bits = entropy_buf->b_bits = 0; -+ entropy_buf->c_bits = entropy_buf->d_bits = 0; -+ goto wakeup; -+ } -+ -+ /* Ensure aux pool extraction and backtracking op are atomic */ -+ spin_lock_irqsave(&pool->lock, flags); -+ -+ /* Concatenate the output of the entropy sources. */ -+ entropy_buf->a_bits = lrng_get_aux_pool(entropy_buf->a, requested_bits); -+ -+ /* -+ * If the aux pool returned entropy, pull respective less from per-CPU -+ * pool, but attempt to at least get LRNG_MIN_SEED_ENTROPY_BITS entropy. -+ */ -+ pcpu_request = max_t(u32, requested_bits - entropy_buf->a_bits, -+ LRNG_MIN_SEED_ENTROPY_BITS); -+ entropy_buf->b_bits = lrng_pcpu_pool_hash(entropy_buf->b, pcpu_request, -+ state->lrng_fully_seeded); -+ -+ entropy_buf->c_bits = lrng_get_arch(entropy_buf->c, requested_bits); -+ entropy_buf->d_bits = lrng_get_jent(entropy_buf->d, requested_bits); -+ -+ /* Mix the extracted data back into pool for backtracking resistance */ -+ if (lrng_pool_insert_aux_locked((u8 *)entropy_buf, -+ sizeof(struct entropy_buf), 0)) -+ pr_warn("Backtracking resistance operation failed\n"); ++ int err = -EALREADY; + -+ spin_unlock_irqrestore(&pool->lock, flags); ++ if (likely(lrng_state_operational())) ++ return err; + -+ /* allow external entropy provider to provide seed */ -+ lrng_state_exseed_allow_all(); ++ owner = rdy->owner; ++ if (!try_module_get(owner)) ++ return -ENOENT; + -+wakeup: -+ /* -+ * Shall we wake up user space writers? This location covers -+ * ensures that the user space provider does not dominate the internal -+ * noise sources since in case the first call of this function finds -+ * sufficient entropy in the entropy pool, it will not trigger the -+ * wakeup. This implies that when the next /dev/urandom read happens, -+ * the entropy pool is drained. -+ */ -+ lrng_writer_wakeup(); -+} ---- /dev/null -+++ b/drivers/char/lrng/lrng_sw_noise.c -@@ -0,0 +1,702 @@ -+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause -+/* -+ * LRNG Slow Entropy Source: Interrupt data collection -+ * -+ * Copyright (C) 2016 - 2021, Stephan Mueller -+ */ ++ spin_lock_irqsave(&lrng_ready_list_lock, flags); ++ if (lrng_state_operational()) ++ goto out; + -+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ owner = NULL; + -+#include -+#include -+#include -+#include -+#include ++ list_add(&rdy->list, &lrng_ready_list); ++ err = 0; + -+#include "lrng_internal.h" -+#include "lrng_sw_noise.h" ++out: ++ spin_unlock_irqrestore(&lrng_ready_list_lock, flags); + -+/* Number of interrupts required for LRNG_DRNG_SECURITY_STRENGTH_BITS entropy */ -+static u32 lrng_irq_entropy_bits = LRNG_IRQ_ENTROPY_BITS; -+/* Is high-resolution timer present? */ -+static bool lrng_irq_highres_timer = false; ++ module_put(owner); + -+static u32 irq_entropy __read_mostly = LRNG_IRQ_ENTROPY_BITS; -+#ifdef CONFIG_LRNG_RUNTIME_ES_CONFIG -+module_param(irq_entropy, uint, 0444); -+MODULE_PARM_DESC(irq_entropy, -+ "How many interrupts must be collected for obtaining 256 bits of entropy\n"); -+#endif ++ return err; ++} ++EXPORT_SYMBOL(add_random_ready_callback); + -+/* Per-CPU array holding concatenated entropy events */ -+static DEFINE_PER_CPU(u32 [LRNG_DATA_ARRAY_SIZE], lrng_pcpu_array) -+ __aligned(LRNG_KCAPI_ALIGN); -+static DEFINE_PER_CPU(u32, lrng_pcpu_array_ptr) = 0; -+static DEFINE_PER_CPU(atomic_t, lrng_pcpu_array_irqs) = ATOMIC_INIT(0); ++/*********************** LRNG kernel output interfaces ************************/ + -+/* -+ * The entropy collection is performed by executing the following steps: -+ * 1. fill up the per-CPU array holding the time stamps -+ * 2. once the per-CPU array is full, a compression of the data into -+ * the entropy pool is performed - this happens in interrupt context -+ * -+ * If step 2 is not desired in interrupt context, the following boolean -+ * needs to be set to false. This implies that old entropy data in the -+ * per-CPU array collected since the last DRNG reseed is overwritten with -+ * new entropy data instead of retaining the entropy with the compression -+ * operation. -+ * -+ * Impact on entropy: ++/** ++ * get_random_bytes() - Provider of cryptographic strong random numbers for ++ * kernel-internal usage. + * -+ * If continuous compression is enabled, the maximum entropy that is collected -+ * per CPU between DRNG reseeds is equal to the digest size of the used hash. ++ * This function is appropriate for all in-kernel use cases. However, ++ * it will always use the ChaCha20 DRNG. + * -+ * If continuous compression is disabled, the maximum number of entropy events -+ * that can be collected per CPU is equal to LRNG_DATA_ARRAY_SIZE. This amount -+ * of events is converted into an entropy statement which then represents the -+ * maximum amount of entropy collectible per CPU between DRNG reseeds. ++ * @buf: buffer to store the random bytes ++ * @nbytes: size of the buffer + */ -+static bool lrng_pcpu_continuous_compression __read_mostly = -+ IS_ENABLED(CONFIG_LRNG_ENABLE_CONTINUOUS_COMPRESSION); -+ -+#ifdef CONFIG_LRNG_SWITCHABLE_CONTINUOUS_COMPRESSION -+module_param(lrng_pcpu_continuous_compression, bool, 0444); -+MODULE_PARM_DESC(lrng_pcpu_continuous_compression, -+ "Perform entropy compression if per-CPU entropy data array is full\n"); -+#endif ++void get_random_bytes(void *buf, int nbytes) ++{ ++ lrng_drng_get_atomic((u8 *)buf, (u32)nbytes); ++ lrng_debug_report_seedlevel("get_random_bytes"); ++} ++EXPORT_SYMBOL(get_random_bytes); + -+/* -+ * Per-CPU entropy pool with compressed entropy event ++/** ++ * get_random_bytes_full() - Provider of cryptographic strong random numbers ++ * for kernel-internal usage. + * -+ * The per-CPU entropy pool is defined as the hash state. New data is simply -+ * inserted into the entropy pool by performing a hash update operation. -+ * To read the entropy pool, a hash final must be invoked. However, before -+ * the entropy pool is released again after a hash final, the hash init must -+ * be performed. -+ */ -+static DEFINE_PER_CPU(u8 [LRNG_POOL_SIZE], lrng_pcpu_pool) -+ __aligned(LRNG_KCAPI_ALIGN); -+/* -+ * Lock to allow other CPUs to read the pool - as this is only done during -+ * reseed which is infrequent, this lock is hardly contended. ++ * This function is appropriate only for non-atomic use cases as this ++ * function may sleep. Though, it provides access to the full functionality ++ * of LRNG including the switchable DRNG support, that may support other ++ * DRNGs such as the SP800-90A DRBG. ++ * ++ * @buf: buffer to store the random bytes ++ * @nbytes: size of the buffer + */ -+static DEFINE_PER_CPU(spinlock_t, lrng_pcpu_lock); -+static DEFINE_PER_CPU(bool, lrng_pcpu_lock_init) = false; -+ -+/* Return boolean whether LRNG identified presence of high-resolution timer */ -+bool lrng_pool_highres_timer(void) ++void get_random_bytes_full(void *buf, int nbytes) +{ -+ return lrng_irq_highres_timer; ++ lrng_drng_get_sleep((u8 *)buf, (u32)nbytes); ++ lrng_debug_report_seedlevel("get_random_bytes_full"); +} ++EXPORT_SYMBOL(get_random_bytes_full); + -+/* Convert entropy in bits into number of IRQs with the same entropy content. */ -+static inline u32 lrng_entropy_to_data(u32 entropy_bits) ++/** ++ * wait_for_random_bytes() - Wait for the LRNG to be seeded and thus ++ * guaranteed to supply cryptographically secure random numbers. ++ * ++ * This applies to: the /dev/urandom device, the get_random_bytes function, ++ * and the get_random_{u32,u64,int,long} family of functions. Using any of ++ * these functions without first calling this function forfeits the guarantee ++ * of security. ++ * ++ * Return: ++ * * 0 if the LRNG has been seeded. ++ * * -ERESTARTSYS if the function was interrupted by a signal. ++ */ ++int wait_for_random_bytes(void) +{ -+ return ((entropy_bits * lrng_irq_entropy_bits) / -+ LRNG_DRNG_SECURITY_STRENGTH_BITS); ++ if (likely(lrng_state_min_seeded())) ++ return 0; ++ return wait_event_interruptible(lrng_init_wait, ++ lrng_state_min_seeded()); +} ++EXPORT_SYMBOL(wait_for_random_bytes); + -+/* Convert number of IRQs into entropy value. */ -+static inline u32 lrng_data_to_entropy(u32 irqnum) ++/** ++ * get_random_bytes_arch() - This function will use the architecture-specific ++ * hardware random number generator if it is available. ++ * ++ * The arch-specific hw RNG will almost certainly be faster than what we can ++ * do in software, but it is impossible to verify that it is implemented ++ * securely (as opposed, to, say, the AES encryption of a sequence number using ++ * a key known by the NSA). So it's useful if we need the speed, but only if ++ * we're willing to trust the hardware manufacturer not to have put in a back ++ * door. ++ * ++ * @buf: buffer allocated by caller to store the random data in ++ * @nbytes: length of outbuf ++ * ++ * Return: number of bytes filled in. ++ */ ++int __must_check get_random_bytes_arch(void *buf, int nbytes) +{ -+ return ((irqnum * LRNG_DRNG_SECURITY_STRENGTH_BITS) / -+ lrng_irq_entropy_bits); ++ u8 *p = buf; ++ ++ while (nbytes) { ++ unsigned long v; ++ int chunk = min_t(int, nbytes, sizeof(unsigned long)); ++ ++ if (!arch_get_random_long(&v)) ++ break; ++ ++ memcpy(p, &v, chunk); ++ p += chunk; ++ nbytes -= chunk; ++ } ++ ++ if (nbytes) ++ lrng_drng_get_atomic((u8 *)p, (u32)nbytes); ++ ++ return nbytes; +} ++EXPORT_SYMBOL(get_random_bytes_arch); + -+static inline bool lrng_pcpu_pool_online(int cpu) ++/* ++ * Returns whether or not the LRNG has been seeded. ++ * ++ * Returns: true if the urandom pool has been seeded. ++ * false if the urandom pool has not been seeded. ++ */ ++bool rng_is_initialized(void) +{ -+ return per_cpu(lrng_pcpu_lock_init, cpu); ++ return lrng_state_operational(); +} ++EXPORT_SYMBOL(rng_is_initialized); + -+bool lrng_pcpu_continuous_compression_state(void) ++/************************ LRNG user output interfaces *************************/ ++ ++static ssize_t lrng_read_common(char __user *buf, size_t nbytes) +{ -+ return lrng_pcpu_continuous_compression; ++ ssize_t ret = 0; ++ u8 tmpbuf[LRNG_DRNG_BLOCKSIZE] __aligned(LRNG_KCAPI_ALIGN); ++ u8 *tmp_large = NULL, *tmp = tmpbuf; ++ u32 tmplen = sizeof(tmpbuf); ++ ++ if (nbytes == 0) ++ return 0; ++ ++ /* ++ * Satisfy large read requests -- as the common case are smaller ++ * request sizes, such as 16 or 32 bytes, avoid a kmalloc overhead for ++ * those by using the stack variable of tmpbuf. ++ */ ++ if (!CONFIG_BASE_SMALL && (nbytes > sizeof(tmpbuf))) { ++ tmplen = min_t(u32, nbytes, LRNG_DRNG_MAX_REQSIZE); ++ tmp_large = kmalloc(tmplen + LRNG_KCAPI_ALIGN, GFP_KERNEL); ++ if (!tmp_large) ++ tmplen = sizeof(tmpbuf); ++ else ++ tmp = PTR_ALIGN(tmp_large, LRNG_KCAPI_ALIGN); ++ } ++ ++ while (nbytes) { ++ u32 todo = min_t(u32, nbytes, tmplen); ++ int rc = 0; ++ ++ /* Reschedule if we received a large request. */ ++ if ((tmp_large) && need_resched()) { ++ if (signal_pending(current)) { ++ if (ret == 0) ++ ret = -ERESTARTSYS; ++ break; ++ } ++ schedule(); ++ } ++ ++ rc = lrng_drng_get_sleep(tmp, todo); ++ if (rc <= 0) { ++ if (rc < 0) ++ ret = rc; ++ break; ++ } ++ if (copy_to_user(buf, tmp, rc)) { ++ ret = -EFAULT; ++ break; ++ } ++ ++ nbytes -= rc; ++ buf += rc; ++ ret += rc; ++ } ++ ++ /* Wipe data just returned from memory */ ++ if (tmp_large) ++ kfree_sensitive(tmp_large); ++ else ++ memzero_explicit(tmpbuf, sizeof(tmpbuf)); ++ ++ return ret; +} + -+static void lrng_pcpu_check_compression_state(void) ++static ssize_t ++lrng_read_common_block(int nonblock, char __user *buf, size_t nbytes) +{ -+ /* One pool must hold sufficient entropy for disabled compression */ -+ if (!lrng_pcpu_continuous_compression) { -+ u32 max_ent = min_t(u32, lrng_get_digestsize(), -+ lrng_data_to_entropy(LRNG_DATA_NUM_VALUES)); -+ if (max_ent < lrng_security_strength()) { -+ pr_warn("Force continuous compression operation to ensure LRNG can hold enough entropy\n"); -+ lrng_pcpu_continuous_compression = true; -+ } ++ if (nbytes == 0) ++ return 0; ++ ++ if (unlikely(!lrng_state_operational())) { ++ int ret; ++ ++ if (nonblock) ++ return -EAGAIN; ++ ++ ret = wait_event_interruptible(lrng_init_wait, ++ lrng_state_operational()); ++ if (unlikely(ret)) ++ return ret; + } ++ ++ return lrng_read_common(buf, nbytes); +} + -+static int __init lrng_init_time_source(void) ++static ssize_t lrng_drng_read_block(struct file *file, char __user *buf, ++ size_t nbytes, loff_t *ppos) +{ -+ /* Set a minimum number of interrupts that must be collected */ -+ irq_entropy = max_t(u32, LRNG_IRQ_ENTROPY_BITS, irq_entropy); -+ -+ if ((random_get_entropy() & LRNG_DATA_SLOTSIZE_MASK) || -+ (random_get_entropy() & LRNG_DATA_SLOTSIZE_MASK)) { -+ /* -+ * As the highres timer is identified here, previous interrupts -+ * obtained during boot time are treated like a lowres-timer -+ * would have been present. -+ */ -+ lrng_irq_highres_timer = true; -+ lrng_irq_entropy_bits = irq_entropy; -+ } else { -+ lrng_health_disable(); -+ lrng_irq_highres_timer = false; -+ lrng_irq_entropy_bits = irq_entropy * -+ LRNG_IRQ_OVERSAMPLING_FACTOR; -+ pr_warn("operating without high-resolution timer and applying IRQ oversampling factor %u\n", -+ LRNG_IRQ_OVERSAMPLING_FACTOR); -+ lrng_pcpu_check_compression_state(); -+ } -+ -+ return 0; ++ return lrng_read_common_block(file->f_flags & O_NONBLOCK, buf, nbytes); +} -+core_initcall(lrng_init_time_source); + -+/* -+ * Reset all per-CPU pools - reset entropy estimator but leave the pool data -+ * that may or may not have entropy unchanged. -+ */ -+void lrng_pcpu_reset(void) ++static __poll_t lrng_random_poll(struct file *file, poll_table *wait) +{ -+ int cpu; ++ __poll_t mask; + -+ for_each_online_cpu(cpu) -+ atomic_set(per_cpu_ptr(&lrng_pcpu_array_irqs, cpu), 0); ++ poll_wait(file, &lrng_init_wait, wait); ++ poll_wait(file, &lrng_write_wait, wait); ++ mask = 0; ++ if (lrng_state_operational()) ++ mask |= EPOLLIN | EPOLLRDNORM; ++ if (lrng_need_entropy() || ++ lrng_state_exseed_allow(lrng_noise_source_user)) ++ mask |= EPOLLOUT | EPOLLWRNORM; ++ return mask; +} + -+u32 lrng_pcpu_avail_pool_size(void) ++static ssize_t lrng_drng_write_common(const char __user *buffer, size_t count, ++ u32 entropy_bits) +{ -+ u32 max_size = 0, max_pool = lrng_get_digestsize(); -+ int cpu; ++ ssize_t ret = 0; ++ u8 buf[64] __aligned(LRNG_KCAPI_ALIGN); ++ const char __user *p = buffer; ++ u32 orig_entropy_bits = entropy_bits; + -+ if (!lrng_pcpu_continuous_compression) -+ max_pool = min_t(u32, max_pool, LRNG_DATA_NUM_VALUES); ++ if (!lrng_get_available()) ++ return -EAGAIN; + -+ for_each_online_cpu(cpu) { -+ if (lrng_pcpu_pool_online(cpu)) -+ max_size += max_pool; -+ } ++ count = min_t(size_t, count, INT_MAX); ++ while (count > 0) { ++ size_t bytes = min_t(size_t, count, sizeof(buf)); ++ u32 ent = min_t(u32, bytes<<3, entropy_bits); + -+ return max_size; -+} ++ if (copy_from_user(&buf, p, bytes)) ++ return -EFAULT; ++ /* Inject data into entropy pool */ ++ lrng_pool_insert_aux(buf, bytes, ent); + -+/* Return entropy of unused IRQs present in all per-CPU pools. */ -+u32 lrng_pcpu_avail_entropy(void) -+{ -+ u32 digestsize_irqs, irq = 0; -+ int cpu; ++ count -= bytes; ++ p += bytes; ++ ret += bytes; ++ entropy_bits -= ent; + -+ /* Obtain the cap of maximum numbers of IRQs we count */ -+ digestsize_irqs = lrng_entropy_to_data(lrng_get_digestsize()); -+ if (!lrng_pcpu_continuous_compression) { -+ /* Cap to max. number of IRQs the array can hold */ -+ digestsize_irqs = min_t(u32, digestsize_irqs, -+ LRNG_DATA_NUM_VALUES); ++ cond_resched(); + } + -+ for_each_online_cpu(cpu) { -+ if (!lrng_pcpu_pool_online(cpu)) -+ continue; -+ irq += min_t(u32, digestsize_irqs, -+ atomic_read_u32(per_cpu_ptr(&lrng_pcpu_array_irqs, -+ cpu))); -+ } ++ /* Force reseed of DRNG during next data request. */ ++ if (!orig_entropy_bits) ++ lrng_drng_force_reseed(); + -+ /* Consider oversampling rate */ -+ return lrng_reduce_by_osr(lrng_data_to_entropy(irq)); ++ return ret; +} + -+/** -+ * Trigger a switch of the hash implementation for the per-CPU pool. -+ * -+ * For each per-CPU pool, obtain the message digest with the old hash -+ * implementation, initialize the per-CPU pool again with the new hash -+ * implementation and inject the message digest into the new state. -+ * -+ * Assumption: the caller must guarantee that the new_cb is available during the -+ * entire operation (e.g. it must hold the lock against pointer updating). -+ */ -+int lrng_pcpu_switch_hash(int node, -+ const struct lrng_crypto_cb *new_cb, void *new_hash, -+ const struct lrng_crypto_cb *old_cb) ++static ssize_t lrng_drng_read(struct file *file, char __user *buf, ++ size_t nbytes, loff_t *ppos) +{ -+ u8 digest[LRNG_MAX_DIGESTSIZE]; -+ u32 digestsize_irqs, found_irqs; -+ int ret = 0, cpu; ++ if (!lrng_state_min_seeded()) ++ pr_notice_ratelimited("%s - use of insufficiently seeded DRNG (%zu bytes read)\n", ++ current->comm, nbytes); ++ else if (!lrng_state_operational()) ++ pr_debug_ratelimited("%s - use of not fully seeded DRNG (%zu bytes read)\n", ++ current->comm, nbytes); + -+ if (!IS_ENABLED(CONFIG_LRNG_DRNG_SWITCH)) -+ return -EOPNOTSUPP; ++ return lrng_read_common(buf, nbytes); ++} + -+ for_each_online_cpu(cpu) { -+ struct shash_desc *pcpu_shash; ++static ssize_t lrng_drng_write(struct file *file, const char __user *buffer, ++ size_t count, loff_t *ppos) ++{ ++ return lrng_drng_write_common(buffer, count, 0); ++} + ++static long lrng_ioctl(struct file *f, unsigned int cmd, unsigned long arg) ++{ ++ u32 digestsize_bits; ++ int size, ent_count_bits; ++ int __user *p = (int __user *)arg; ++ ++ switch (cmd) { ++ case RNDGETENTCNT: ++ ent_count_bits = lrng_avail_entropy(); ++ if (put_user(ent_count_bits, p)) ++ return -EFAULT; ++ return 0; ++ case RNDADDTOENTCNT: ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ if (get_user(ent_count_bits, p)) ++ return -EFAULT; ++ ent_count_bits = (int)lrng_avail_aux_entropy() + ent_count_bits; ++ if (ent_count_bits < 0) ++ ent_count_bits = 0; ++ digestsize_bits = lrng_get_digestsize(); ++ if (ent_count_bits > digestsize_bits) ++ ent_count_bits = digestsize_bits; ++ lrng_pool_set_entropy(ent_count_bits); ++ return 0; ++ case RNDADDENTROPY: ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ if (get_user(ent_count_bits, p++)) ++ return -EFAULT; ++ if (ent_count_bits < 0) ++ return -EINVAL; ++ if (get_user(size, p++)) ++ return -EFAULT; ++ if (size < 0) ++ return -EINVAL; ++ lrng_state_exseed_set(lrng_noise_source_user, false); ++ /* there cannot be more entropy than data */ ++ ent_count_bits = min(ent_count_bits, size<<3); ++ return lrng_drng_write_common((const char __user *)p, size, ++ ent_count_bits); ++ case RNDZAPENTCNT: ++ case RNDCLEARPOOL: ++ /* Clear the entropy pool counter. */ ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ lrng_pool_set_entropy(0); ++ return 0; ++ case RNDRESEEDCRNG: + /* -+ * Only switch the per-CPU pools for the current node because -+ * the crypto_cb only applies NUMA-node-wide. ++ * We leave the capability check here since it is present ++ * in the upstream's RNG implementation. Yet, user space ++ * can trigger a reseed as easy as writing into /dev/random ++ * or /dev/urandom where no privilege is needed. + */ -+ if (cpu_to_node(cpu) != node || !lrng_pcpu_pool_online(cpu)) -+ continue; ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ /* Force a reseed of all DRNGs */ ++ lrng_drng_force_reseed(); ++ return 0; ++ default: ++ return -EINVAL; ++ } ++} + -+ pcpu_shash = (struct shash_desc *)per_cpu_ptr(lrng_pcpu_pool, -+ cpu); ++static int lrng_fasync(int fd, struct file *filp, int on) ++{ ++ return fasync_helper(fd, filp, on, &fasync); ++} + -+ digestsize_irqs = old_cb->lrng_hash_digestsize(pcpu_shash); -+ digestsize_irqs = lrng_entropy_to_data(digestsize_irqs << 3); ++const struct file_operations random_fops = { ++ .read = lrng_drng_read_block, ++ .write = lrng_drng_write, ++ .poll = lrng_random_poll, ++ .unlocked_ioctl = lrng_ioctl, ++ .compat_ioctl = compat_ptr_ioctl, ++ .fasync = lrng_fasync, ++ .llseek = noop_llseek, ++}; + -+ if (pcpu_shash->tfm == new_hash) -+ continue; ++const struct file_operations urandom_fops = { ++ .read = lrng_drng_read, ++ .write = lrng_drng_write, ++ .unlocked_ioctl = lrng_ioctl, ++ .compat_ioctl = compat_ptr_ioctl, ++ .fasync = lrng_fasync, ++ .llseek = noop_llseek, ++}; + -+ /* Get the per-CPU pool hash with old digest ... */ -+ ret = old_cb->lrng_hash_final(pcpu_shash, digest) ?: -+ /* ... re-initialize the hash with the new digest ... */ -+ new_cb->lrng_hash_init(pcpu_shash, new_hash) ?: -+ /* -+ * ... feed the old hash into the new state. We may feed -+ * uninitialized memory into the new state, but this is -+ * considered no issue and even good as we have some more -+ * uncertainty here. -+ */ -+ new_cb->lrng_hash_update(pcpu_shash, digest, -+ sizeof(digest)); -+ if (ret) -+ goto out; ++SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count, ++ unsigned int, flags) ++{ ++ if (flags & ~(GRND_NONBLOCK|GRND_RANDOM|GRND_INSECURE)) ++ return -EINVAL; + -+ /* -+ * In case the new digest is larger than the old one, cap -+ * the available entropy to the old message digest used to -+ * process the existing data. -+ */ -+ found_irqs = atomic_xchg_relaxed( -+ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu), 0); -+ found_irqs = min_t(u32, found_irqs, digestsize_irqs); -+ atomic_add_return_relaxed(found_irqs, -+ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu)); ++ /* ++ * Requesting insecure and blocking randomness at the same time makes ++ * no sense. ++ */ ++ if ((flags & ++ (GRND_INSECURE|GRND_RANDOM)) == (GRND_INSECURE|GRND_RANDOM)) ++ return -EINVAL; + -+ pr_debug("Re-initialize per-CPU entropy pool for CPU %d on NUMA node %d with hash %s\n", -+ cpu, node, new_cb->lrng_hash_name()); -+ } ++ if (count > INT_MAX) ++ count = INT_MAX; + -+out: -+ memzero_explicit(digest, sizeof(digest)); -+ return ret; -+} ++ if (flags & GRND_INSECURE) ++ return lrng_drng_read(NULL, buf, count, NULL); + ++ return lrng_read_common_block(flags & GRND_NONBLOCK, buf, count); ++} +diff --git a/drivers/char/lrng/lrng_internal.h b/drivers/char/lrng/lrng_internal.h +new file mode 100644 +index 000000000000..a21e5be716b0 +--- /dev/null ++++ b/drivers/char/lrng/lrng_internal.h +@@ -0,0 +1,446 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ +/* -+ * When reading the per-CPU message digest, make sure we use the crypto -+ * callbacks defined for the NUMA node the per-CPU pool is defined for because -+ * the LRNG crypto switch support is only atomic per NUMA node. ++ * Copyright (C) 2018 - 2021, Stephan Mueller + */ -+static inline u32 -+lrng_pcpu_pool_hash_one(const struct lrng_crypto_cb *pcpu_crypto_cb, -+ void *pcpu_hash, int cpu, u8 *digest, u32 *digestsize) -+{ -+ struct shash_desc *pcpu_shash = -+ (struct shash_desc *)per_cpu_ptr(lrng_pcpu_pool, cpu); -+ spinlock_t *lock = per_cpu_ptr(&lrng_pcpu_lock, cpu); -+ unsigned long flags; -+ u32 digestsize_irqs, found_irqs; + -+ /* Lock guarding against reading / writing to per-CPU pool */ -+ spin_lock_irqsave(lock, flags); ++#ifndef _LRNG_INTERNAL_H ++#define _LRNG_INTERNAL_H + -+ *digestsize = pcpu_crypto_cb->lrng_hash_digestsize(pcpu_hash); -+ digestsize_irqs = lrng_entropy_to_data(*digestsize << 3); ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+ /* Obtain entropy statement like for the entropy pool */ -+ found_irqs = atomic_xchg_relaxed( -+ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu), 0); -+ /* Cap to maximum amount of data we can hold in hash */ -+ found_irqs = min_t(u32, found_irqs, digestsize_irqs); ++/*************************** General LRNG parameter ***************************/ + -+ /* Cap to maximum amount of data we can hold in array */ -+ if (!lrng_pcpu_continuous_compression) -+ found_irqs = min_t(u32, found_irqs, LRNG_DATA_NUM_VALUES); ++/* Security strength of LRNG -- this must match DRNG security strength */ ++#define LRNG_DRNG_SECURITY_STRENGTH_BYTES 32 ++#define LRNG_DRNG_SECURITY_STRENGTH_BITS (LRNG_DRNG_SECURITY_STRENGTH_BYTES * 8) ++#define LRNG_DRNG_BLOCKSIZE 64 /* Maximum of DRNG block sizes */ + -+ /* Store all not-yet compressed data in data array into hash, ... */ -+ if (pcpu_crypto_cb->lrng_hash_update(pcpu_shash, -+ (u8 *)per_cpu_ptr(lrng_pcpu_array, cpu), -+ LRNG_DATA_ARRAY_SIZE * sizeof(u32)) ?: -+ /* ... get the per-CPU pool digest, ... */ -+ pcpu_crypto_cb->lrng_hash_final(pcpu_shash, digest) ?: -+ /* ... re-initialize the hash, ... */ -+ pcpu_crypto_cb->lrng_hash_init(pcpu_shash, pcpu_hash) ?: -+ /* ... feed the old hash into the new state. */ -+ pcpu_crypto_cb->lrng_hash_update(pcpu_shash, digest, *digestsize)) -+ found_irqs = 0; ++/* ++ * SP800-90A defines a maximum request size of 1<<16 bytes. The given value is ++ * considered a safer margin. ++ * ++ * This value is allowed to be changed. ++ */ ++#define LRNG_DRNG_MAX_REQSIZE (1<<12) + -+ spin_unlock_irqrestore(lock, flags); -+ return found_irqs; -+} ++/* ++ * SP800-90A defines a maximum number of requests between reseeds of 2^48. ++ * The given value is considered a much safer margin, balancing requests for ++ * frequent reseeds with the need to conserve entropy. This value MUST NOT be ++ * larger than INT_MAX because it is used in an atomic_t. ++ * ++ * This value is allowed to be changed. ++ */ ++#define LRNG_DRNG_RESEED_THRESH (1<<20) + -+/** -+ * Hash all per-CPU pools and return the digest to be used as seed data for -+ * seeding a DRNG. The caller must guarantee backtracking resistance. -+ * The function will only copy as much data as entropy is available into the -+ * caller-provided output buffer. ++/* ++ * Maximum DRNG generation operations without reseed having full entropy ++ * This value defines the absolute maximum value of DRNG generation operations ++ * without a reseed holding full entropy. LRNG_DRNG_RESEED_THRESH is the ++ * threshold when a new reseed is attempted. But it is possible that this fails ++ * to deliver full entropy. In this case the DRNG will continue to provide data ++ * even though it was not reseeded with full entropy. To avoid in the extreme ++ * case that no reseed is performed for too long, this threshold is enforced. ++ * If that absolute low value is reached, the LRNG is marked as not operational. + * -+ * This function handles the translation from the number of received interrupts -+ * into an entropy statement. The conversion depends on LRNG_IRQ_ENTROPY_BITS -+ * which defines how many interrupts must be received to obtain 256 bits of -+ * entropy. With this value, the function lrng_data_to_entropy converts a given -+ * data size (received interrupts, requested amount of data, etc.) into an -+ * entropy statement. lrng_entropy_to_data does the reverse. ++ * This value is allowed to be changed. ++ */ ++#define LRNG_DRNG_MAX_WITHOUT_RESEED (1<<30) ++ ++/* ++ * Number of interrupts to be recorded to assume that DRNG security strength ++ * bits of entropy are received. ++ * Note: a value below the DRNG security strength should not be defined as this ++ * may imply the DRNG can never be fully seeded in case other noise ++ * sources are unavailable. + * -+ * @outbuf: buffer to store data in with size requested_bits -+ * @requested_bits: Requested amount of entropy -+ * @fully_seeded: indicator whether LRNG is fully seeded -+ * @return: amount of entropy in outbuf in bits. ++ * This value is allowed to be changed. + */ -+u32 lrng_pcpu_pool_hash(u8 *outbuf, u32 requested_bits, bool fully_seeded) -+{ -+ SHASH_DESC_ON_STACK(shash, NULL); -+ const struct lrng_crypto_cb *crypto_cb; -+ struct lrng_drng **lrng_drng = lrng_drng_instances(); -+ struct lrng_drng *drng = lrng_drng_init_instance(); -+ u8 digest[LRNG_MAX_DIGESTSIZE]; -+ unsigned long flags, flags2; -+ u32 found_irqs, collected_irqs = 0, collected_ent_bits, requested_irqs, -+ returned_ent_bits; -+ int ret, cpu; -+ void *hash; ++#define LRNG_IRQ_ENTROPY_BITS CONFIG_LRNG_IRQ_ENTROPY_RATE + -+ /* Lock guarding replacement of per-NUMA hash */ -+ read_lock_irqsave(&drng->hash_lock, flags); ++/* ++ * Min required seed entropy is 128 bits covering the minimum entropy ++ * requirement of SP800-131A and the German BSI's TR02102. ++ * ++ * This value is allowed to be changed. ++ */ ++#define LRNG_FULL_SEED_ENTROPY_BITS LRNG_DRNG_SECURITY_STRENGTH_BITS ++#define LRNG_MIN_SEED_ENTROPY_BITS 128 ++#define LRNG_INIT_ENTROPY_BITS 32 + -+ crypto_cb = drng->crypto_cb; -+ hash = drng->hash; ++/* ++ * Wakeup value ++ * ++ * This value is allowed to be changed but must not be larger than the ++ * digest size of the hash operation used update the aux_pool. ++ */ ++#ifdef CONFIG_CRYPTO_LIB_SHA256 ++# define LRNG_ATOMIC_DIGEST_SIZE SHA256_DIGEST_SIZE ++#else ++# define LRNG_ATOMIC_DIGEST_SIZE SHA1_DIGEST_SIZE ++#endif ++#define LRNG_WRITE_WAKEUP_ENTROPY LRNG_ATOMIC_DIGEST_SIZE + -+ /* The hash state of filled with all per-CPU pool hashes. */ -+ ret = crypto_cb->lrng_hash_init(shash, hash); -+ if (ret) -+ goto err; ++/* ++ * If the switching support is configured, we must provide support up to ++ * the largest digest size. Without switching support, we know it is only ++ * the built-in digest size. ++ */ ++#ifdef CONFIG_LRNG_DRNG_SWITCH ++# define LRNG_MAX_DIGESTSIZE 64 ++#else ++# define LRNG_MAX_DIGESTSIZE LRNG_ATOMIC_DIGEST_SIZE ++#endif ++ ++/* ++ * Oversampling factor of IRQ events to obtain ++ * LRNG_DRNG_SECURITY_STRENGTH_BYTES. This factor is used when a ++ * high-resolution time stamp is not available. In this case, jiffies and ++ * register contents are used to fill the entropy pool. These noise sources ++ * are much less entropic than the high-resolution timer. The entropy content ++ * is the entropy content assumed with LRNG_IRQ_ENTROPY_BITS divided by ++ * LRNG_IRQ_OVERSAMPLING_FACTOR. ++ * ++ * This value is allowed to be changed. ++ */ ++#define LRNG_IRQ_OVERSAMPLING_FACTOR 10 + -+ requested_irqs = lrng_entropy_to_data(requested_bits) + -+ lrng_compress_osr(); ++/* Alignmask that is intended to be identical to CRYPTO_MINALIGN */ ++#define LRNG_KCAPI_ALIGN ARCH_KMALLOC_MINALIGN + -+ /* -+ * Harvest entropy from each per-CPU hash state - even though we may -+ * have collected sufficient entropy, we will hash all per-CPU pools. -+ */ -+ for_each_online_cpu(cpu) { -+ struct lrng_drng *pcpu_drng = drng; -+ u32 digestsize, pcpu_unused_irqs = 0; -+ int node = cpu_to_node(cpu); ++/* ++ * This definition must provide a buffer that is equal to SHASH_DESC_ON_STACK ++ * as it will be casted into a struct shash_desc. ++ */ ++#define LRNG_POOL_SIZE (sizeof(struct shash_desc) + HASH_MAX_DESCSIZE) + -+ /* If pool is not online, then no entropy is present. */ -+ if (!lrng_pcpu_pool_online(cpu)) -+ continue; ++/************************ Default DRNG implementation *************************/ + -+ if (lrng_drng && lrng_drng[node]) -+ pcpu_drng = lrng_drng[node]; ++extern struct chacha20_state chacha20; ++extern const struct lrng_crypto_cb lrng_cc20_crypto_cb; ++void lrng_cc20_init_state(struct chacha20_state *state); + -+ if (pcpu_drng == drng) { -+ found_irqs = lrng_pcpu_pool_hash_one(crypto_cb, hash, -+ cpu, digest, -+ &digestsize); -+ } else { -+ read_lock_irqsave(&pcpu_drng->hash_lock, flags2); -+ found_irqs = -+ lrng_pcpu_pool_hash_one(pcpu_drng->crypto_cb, -+ pcpu_drng->hash, cpu, -+ digest, &digestsize); -+ read_unlock_irqrestore(&pcpu_drng->hash_lock, flags2); -+ } ++/********************************** /proc *************************************/ + -+ /* Inject the digest into the state of all per-CPU pools */ -+ ret = crypto_cb->lrng_hash_update(shash, digest, digestsize); -+ if (ret) -+ goto err; ++#ifdef CONFIG_SYSCTL ++void lrng_pool_inc_numa_node(void); ++#else ++static inline void lrng_pool_inc_numa_node(void) { } ++#endif + -+ collected_irqs += found_irqs; -+ if (collected_irqs > requested_irqs) { -+ pcpu_unused_irqs = collected_irqs - requested_irqs; -+ atomic_add_return_relaxed(pcpu_unused_irqs, -+ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu)); -+ collected_irqs = requested_irqs; -+ } -+ pr_debug("%u interrupts used from entropy pool of CPU %d, %u interrupts remain unused\n", -+ found_irqs - pcpu_unused_irqs, cpu, pcpu_unused_irqs); -+ } ++/****************************** LRNG interfaces *******************************/ + -+ ret = crypto_cb->lrng_hash_final(shash, digest); -+ if (ret) -+ goto err; ++extern u32 lrng_write_wakeup_bits; ++extern int lrng_drng_reseed_max_time; ++ ++void lrng_writer_wakeup(void); ++void lrng_init_wakeup(void); ++void lrng_debug_report_seedlevel(const char *name); ++void lrng_process_ready_list(void); + -+ collected_ent_bits = lrng_data_to_entropy(collected_irqs); -+ /* Cap to maximum entropy that can ever be generated with given hash */ -+ collected_ent_bits = min_t(u32, collected_ent_bits, -+ crypto_cb->lrng_hash_digestsize(hash) << 3); -+ /* Apply oversampling: discount requested oversampling rate */ -+ returned_ent_bits = lrng_reduce_by_osr(collected_ent_bits); ++/* External interface to use of the switchable DRBG inside the kernel */ ++void get_random_bytes_full(void *buf, int nbytes); + -+ pr_debug("obtained %u bits by collecting %u bits of entropy from entropy pool noise source\n", -+ returned_ent_bits, collected_ent_bits); ++/************************* Jitter RNG Entropy Source **************************/ + -+ /* -+ * Truncate to available entropy as implicitly allowed by SP800-90B -+ * section 3.1.5.1.1 table 1 which awards truncated hashes full -+ * entropy. -+ * -+ * During boot time, we read requested_bits data with -+ * returned_ent_bits entropy. In case our conservative entropy -+ * estimate underestimates the available entropy we can transport as -+ * much available entropy as possible. -+ */ -+ memcpy(outbuf, digest, fully_seeded ? returned_ent_bits >> 3 : -+ requested_bits >> 3); ++#ifdef CONFIG_LRNG_JENT ++u32 lrng_get_jent(u8 *outbuf, u32 requested_bits); ++u32 lrng_jent_entropylevel(u32 requested_bits); ++#else /* CONFIG_CRYPTO_JITTERENTROPY */ ++static inline u32 lrng_get_jent(u8 *outbuf, u32 requested_bits) { return 0; } ++static inline u32 lrng_jent_entropylevel(u32 requested_bits) { return 0; } ++#endif /* CONFIG_CRYPTO_JITTERENTROPY */ + -+out: -+ crypto_cb->lrng_hash_desc_zero(shash); -+ read_unlock_irqrestore(&drng->hash_lock, flags); -+ memzero_explicit(digest, sizeof(digest)); -+ return returned_ent_bits; ++/************************** CPU-based Entropy Source **************************/ + -+err: -+ returned_ent_bits = 0; -+ goto out; ++static inline u32 lrng_fast_noise_entropylevel(u32 ent_bits, u32 requested_bits) ++{ ++ /* Obtain entropy statement */ ++ ent_bits = ent_bits * requested_bits / LRNG_DRNG_SECURITY_STRENGTH_BITS; ++ /* Cap entropy to buffer size in bits */ ++ ent_bits = min_t(u32, ent_bits, requested_bits); ++ return ent_bits; +} + -+/* Compress the lrng_pcpu_array array into lrng_pcpu_pool */ -+static inline void lrng_pcpu_array_compress(void) -+{ -+ struct shash_desc *shash = -+ (struct shash_desc *)this_cpu_ptr(lrng_pcpu_pool); -+ struct lrng_drng **lrng_drng = lrng_drng_instances(); -+ struct lrng_drng *drng = lrng_drng_init_instance(); -+ const struct lrng_crypto_cb *crypto_cb; -+ spinlock_t *lock = this_cpu_ptr(&lrng_pcpu_lock); -+ unsigned long flags, flags2; -+ int node = numa_node_id(); -+ void *hash; -+ bool init = false; ++u32 lrng_get_arch(u8 *outbuf, u32 requested_bits); ++u32 lrng_archrandom_entropylevel(u32 requested_bits); + -+ /* Get NUMA-node local hash instance */ -+ if (lrng_drng && lrng_drng[node]) -+ drng = lrng_drng[node]; ++/************************** Interrupt Entropy Source **************************/ + -+ read_lock_irqsave(&drng->hash_lock, flags); -+ crypto_cb = drng->crypto_cb; -+ hash = drng->hash; ++bool lrng_pcpu_continuous_compression_state(void); ++void lrng_pcpu_reset(void); ++u32 lrng_pcpu_avail_pool_size(void); ++u32 lrng_pcpu_avail_entropy(void); ++int lrng_pcpu_switch_hash(int node, ++ const struct lrng_crypto_cb *new_cb, void *new_hash, ++ const struct lrng_crypto_cb *old_cb); ++u32 lrng_pcpu_pool_hash(u8 *outbuf, u32 requested_bits, bool fully_seeded); ++void lrng_pcpu_array_add_u32(u32 data); ++u32 lrng_gcd_analyze(u32 *history, size_t nelem); + -+ if (unlikely(!this_cpu_read(lrng_pcpu_lock_init))) { -+ init = true; -+ spin_lock_init(lock); -+ this_cpu_write(lrng_pcpu_lock_init, true); -+ pr_debug("Initializing per-CPU entropy pool for CPU %d on NUMA node %d with hash %s\n", -+ raw_smp_processor_id(), node, -+ crypto_cb->lrng_hash_name()); -+ } ++/****************************** DRNG processing *******************************/ + -+ spin_lock_irqsave(lock, flags2); ++/* DRNG state handle */ ++struct lrng_drng { ++ void *drng; /* DRNG handle */ ++ void *hash; /* Hash handle */ ++ const struct lrng_crypto_cb *crypto_cb; /* Crypto callbacks */ ++ atomic_t requests; /* Number of DRNG requests */ ++ atomic_t requests_since_fully_seeded; /* Number DRNG requests since ++ last fully seeded */ ++ unsigned long last_seeded; /* Last time it was seeded */ ++ bool fully_seeded; /* Is DRNG fully seeded? */ ++ bool force_reseed; /* Force a reseed */ + -+ if (unlikely(init) && crypto_cb->lrng_hash_init(shash, hash)) { -+ this_cpu_write(lrng_pcpu_lock_init, false); -+ pr_warn("Initialization of hash failed\n"); -+ } else if (lrng_pcpu_continuous_compression) { -+ /* Add entire per-CPU data array content into entropy pool. */ -+ if (crypto_cb->lrng_hash_update(shash, -+ (u8 *)this_cpu_ptr(lrng_pcpu_array), -+ LRNG_DATA_ARRAY_SIZE * sizeof(u32))) -+ pr_warn_ratelimited("Hashing of entropy data failed\n"); -+ } ++ /* Lock write operations on DRNG state, DRNG replacement of crypto_cb */ ++ struct mutex lock; ++ spinlock_t spin_lock; ++ /* Lock *hash replacement - always take before DRNG lock */ ++ rwlock_t hash_lock; ++}; + -+ spin_unlock_irqrestore(lock, flags2); -+ read_unlock_irqrestore(&drng->hash_lock, flags); -+} ++extern struct mutex lrng_crypto_cb_update; + -+/* Compress data array into hash */ -+static inline void lrng_pcpu_array_to_hash(u32 ptr) -+{ -+ u32 *array = this_cpu_ptr(lrng_pcpu_array); ++struct lrng_drng *lrng_drng_init_instance(void); ++struct lrng_drng *lrng_drng_atomic_instance(void); + -+ /* -+ * During boot time the hash operation is triggered more often than -+ * during regular operation. -+ */ -+ if (unlikely(!lrng_state_fully_seeded())) { -+ if ((ptr & 31) && (ptr < LRNG_DATA_WORD_MASK)) -+ return; -+ } else if (ptr < LRNG_DATA_WORD_MASK) { -+ return; -+ } ++static __always_inline bool lrng_drng_is_atomic(struct lrng_drng *drng) ++{ ++ return (drng->drng == lrng_drng_atomic_instance()->drng); ++} + -+ if (lrng_raw_array_entropy_store(*array)) { -+ u32 i; ++/* Lock the DRNG */ ++static __always_inline void lrng_drng_lock(struct lrng_drng *drng, ++ unsigned long *flags) ++ __acquires(&drng->spin_lock) ++{ ++ /* Use spin lock in case the atomic DRNG context is used */ ++ if (lrng_drng_is_atomic(drng)) { ++ spin_lock_irqsave(&drng->spin_lock, *flags); + + /* -+ * If we fed even a part of the array to external analysis, we -+ * mark that the entire array and the per-CPU pool to have no -+ * entropy. This is due to the non-IID property of the data as -+ * we do not fully know whether the existing dependencies -+ * diminish the entropy beyond to what we expect it has. ++ * In case a lock transition happened while we were spinning, ++ * catch this case and use the new lock type. + */ -+ atomic_set(this_cpu_ptr(&lrng_pcpu_array_irqs), 0); ++ if (!lrng_drng_is_atomic(drng)) { ++ spin_unlock_irqrestore(&drng->spin_lock, *flags); ++ __acquire(&drng->spin_lock); ++ mutex_lock(&drng->lock); ++ } ++ } else { ++ __acquire(&drng->spin_lock); ++ mutex_lock(&drng->lock); ++ } ++} + -+ for (i = 1; i < LRNG_DATA_ARRAY_SIZE; i++) -+ lrng_raw_array_entropy_store(*(array + i)); ++/* Unlock the DRNG */ ++static __always_inline void lrng_drng_unlock(struct lrng_drng *drng, ++ unsigned long *flags) ++ __releases(&drng->spin_lock) ++{ ++ if (lrng_drng_is_atomic(drng)) { ++ spin_unlock_irqrestore(&drng->spin_lock, *flags); + } else { -+ lrng_pcpu_array_compress(); -+ /* Ping pool handler about received entropy */ -+ lrng_pool_add_entropy(); ++ mutex_unlock(&drng->lock); ++ __release(&drng->spin_lock); + } +} + -+/* -+ * Concatenate full 32 bit word at the end of time array even when current -+ * ptr is not aligned to sizeof(data). -+ */ -+static inline void _lrng_pcpu_array_add_u32(u32 data) ++void lrng_reset(void); ++void lrng_drngs_init_cc20(bool force_seed); ++bool lrng_sp80090c_compliant(void); ++ ++static inline u32 lrng_compress_osr(void) +{ -+ /* Increment pointer by number of slots taken for input value */ -+ u32 pre_ptr, mask, ptr = this_cpu_add_return(lrng_pcpu_array_ptr, -+ LRNG_DATA_SLOTS_PER_UINT); -+ unsigned int pre_array; ++ return lrng_sp80090c_compliant() ? CONFIG_LRNG_OVERSAMPLE_ES_BITS : 0; ++} + -+ /* -+ * This function injects a unit into the array - guarantee that -+ * array unit size is equal to data type of input data. -+ */ -+ BUILD_BUG_ON(LRNG_DATA_ARRAY_MEMBER_BITS != (sizeof(data) << 3)); ++static inline u32 lrng_reduce_by_osr(u32 entropy_bits) ++{ ++ u32 osr_bits = lrng_compress_osr(); ++ return (entropy_bits >= osr_bits) ? (entropy_bits - osr_bits) : 0; ++} + -+ /* -+ * The following logic requires at least two units holding -+ * the data as otherwise the pointer would immediately wrap when -+ * injection an u32 word. -+ */ -+ BUILD_BUG_ON(LRNG_DATA_NUM_VALUES <= LRNG_DATA_SLOTS_PER_UINT); ++bool lrng_get_available(void); ++void lrng_set_available(void); ++void lrng_drng_reset(struct lrng_drng *drng); ++int lrng_drng_get_atomic(u8 *outbuf, u32 outbuflen); ++int lrng_drng_get_sleep(u8 *outbuf, u32 outbuflen); ++void lrng_drng_force_reseed(void); ++void lrng_drng_seed_work(struct work_struct *dummy); + -+ lrng_pcpu_split_u32(&ptr, &pre_ptr, &mask); ++#ifdef CONFIG_NUMA ++struct lrng_drng **lrng_drng_instances(void); ++void lrng_drngs_numa_alloc(void); ++#else /* CONFIG_NUMA */ ++static inline struct lrng_drng **lrng_drng_instances(void) { return NULL; } ++static inline void lrng_drngs_numa_alloc(void) { return; } ++#endif /* CONFIG_NUMA */ + -+ /* MSB of data go into previous unit */ -+ pre_array = lrng_data_idx2array(pre_ptr); -+ /* zeroization of slot to ensure the following OR adds the data */ -+ this_cpu_and(lrng_pcpu_array[pre_array], ~(0xffffffff &~ mask)); -+ this_cpu_or(lrng_pcpu_array[pre_array], data & ~mask); ++/************************* Entropy sources management *************************/ ++ ++enum lrng_external_noise_source { ++ lrng_noise_source_hw, ++ lrng_noise_source_user ++}; ++ ++void lrng_set_entropy_thresh(u32 new); ++u32 lrng_avail_entropy(void); ++void lrng_reset_state(void); ++ ++bool lrng_state_exseed_allow(enum lrng_external_noise_source source); ++void lrng_state_exseed_set(enum lrng_external_noise_source source, bool type); ++bool lrng_state_min_seeded(void); ++bool lrng_state_fully_seeded(void); ++bool lrng_state_operational(void); ++ ++int lrng_pool_trylock(void); ++void lrng_pool_unlock(void); ++void lrng_pool_all_numa_nodes_seeded(bool set); ++bool lrng_pool_highres_timer(void); ++void lrng_pool_add_entropy(void); ++ ++struct entropy_buf { ++ u8 a[LRNG_DRNG_SECURITY_STRENGTH_BYTES + ++ (CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS >> 3)]; ++ u8 b[LRNG_DRNG_SECURITY_STRENGTH_BYTES + ++ (CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS >> 3)]; ++ u8 c[LRNG_DRNG_SECURITY_STRENGTH_BYTES + ++ (CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS >> 3)]; ++ u8 d[LRNG_DRNG_SECURITY_STRENGTH_BYTES + ++ (CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS >> 3)]; ++ u32 now, a_bits, b_bits, c_bits, d_bits; ++}; + -+ /* Invoke compression as we just filled data array completely */ -+ if (unlikely(pre_ptr > ptr)) -+ lrng_pcpu_array_to_hash(LRNG_DATA_WORD_MASK); ++bool lrng_fully_seeded(bool fully_seeded, struct entropy_buf *eb); ++void lrng_unset_fully_seeded(struct lrng_drng *drng); ++void lrng_fill_seed_buffer(struct entropy_buf *entropy_buf, u32 requested_bits); ++void lrng_init_ops(struct entropy_buf *eb); + -+ /* LSB of data go into current unit */ -+ this_cpu_write(lrng_pcpu_array[lrng_data_idx2array(ptr)], -+ data & mask); ++/*********************** Auxiliary Pool Entropy Source ************************/ + -+ if (likely(pre_ptr <= ptr)) -+ lrng_pcpu_array_to_hash(ptr); -+} ++u32 lrng_avail_aux_entropy(void); ++u32 lrng_get_digestsize(void); ++void lrng_pool_set_entropy(u32 entropy_bits); ++int lrng_aux_switch_hash(const struct lrng_crypto_cb *new_cb, void *new_hash, ++ const struct lrng_crypto_cb *old_cb); ++int lrng_pool_insert_aux(const u8 *inbuf, u32 inbuflen, u32 entropy_bits); ++void lrng_get_backtrack_aux(struct entropy_buf *entropy_buf, ++ u32 requested_bits); + -+/* Concatenate a 32-bit word at the end of the per-CPU array */ -+void lrng_pcpu_array_add_u32(u32 data) ++/* Obtain the security strength of the LRNG in bits */ ++static inline u32 lrng_security_strength(void) +{ + /* -+ * Disregard entropy-less data without continuous compression to -+ * avoid it overwriting data with entropy when array ptr wraps. ++ * We use a hash to read the entropy in the entropy pool. According to ++ * SP800-90B table 1, the entropy can be at most the digest size. ++ * Considering this together with the last sentence in section 3.1.5.1.2 ++ * the security strength of a (approved) hash is equal to its output ++ * size. On the other hand the entropy cannot be larger than the ++ * security strength of the used DRBG. + */ -+ if (lrng_pcpu_continuous_compression) -+ _lrng_pcpu_array_add_u32(data); ++ return min_t(u32, LRNG_FULL_SEED_ENTROPY_BITS, lrng_get_digestsize()); +} + -+/* Concatenate data of max LRNG_DATA_SLOTSIZE_MASK at the end of time array */ -+static inline void lrng_pcpu_array_add_slot(u32 data) ++static inline u32 lrng_get_seed_entropy_osr(bool fully_seeded) +{ -+ /* Get slot */ -+ u32 ptr = this_cpu_inc_return(lrng_pcpu_array_ptr) & -+ LRNG_DATA_WORD_MASK; -+ unsigned int array = lrng_data_idx2array(ptr); -+ unsigned int slot = lrng_data_idx2slot(ptr); -+ -+ BUILD_BUG_ON(LRNG_DATA_ARRAY_MEMBER_BITS % LRNG_DATA_SLOTSIZE_BITS); -+ /* Ensure consistency of values */ -+ BUILD_BUG_ON(LRNG_DATA_ARRAY_MEMBER_BITS != -+ sizeof(lrng_pcpu_array[0]) << 3); -+ -+ /* zeroization of slot to ensure the following OR adds the data */ -+ this_cpu_and(lrng_pcpu_array[array], -+ ~(lrng_data_slot_val(0xffffffff & LRNG_DATA_SLOTSIZE_MASK, -+ slot))); -+ /* Store data into slot */ -+ this_cpu_or(lrng_pcpu_array[array], lrng_data_slot_val(data, slot)); ++ u32 requested_bits = lrng_security_strength(); + -+ lrng_pcpu_array_to_hash(ptr); ++ /* Apply oversampling during initialization according to SP800-90C */ ++ if (lrng_sp80090c_compliant() && !fully_seeded) ++ requested_bits += CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS; ++ return requested_bits; +} + -+static inline void -+lrng_time_process_common(u32 time, void(*add_time)(u32 data)) -+{ -+ enum lrng_health_res health_test; -+ -+ if (lrng_raw_hires_entropy_store(time)) -+ return; ++/************************** Health Test linking code **************************/ + -+ health_test = lrng_health_test(time); -+ if (health_test > lrng_health_fail_use) -+ return; ++enum lrng_health_res { ++ lrng_health_pass, /* Health test passes on time stamp */ ++ lrng_health_fail_use, /* Time stamp unhealthy, but mix in */ ++ lrng_health_fail_drop /* Time stamp unhealthy, drop it */ ++}; + -+ if (health_test == lrng_health_pass) -+ atomic_inc_return(this_cpu_ptr(&lrng_pcpu_array_irqs)); ++#ifdef CONFIG_LRNG_HEALTH_TESTS ++bool lrng_sp80090b_startup_complete(void); ++bool lrng_sp80090b_compliant(void); + -+ add_time(time); -+} ++enum lrng_health_res lrng_health_test(u32 now_time); ++void lrng_health_disable(void); + -+/* -+ * Batching up of entropy in per-CPU array before injecting into entropy pool. -+ */ -+static inline void lrng_time_process(void) -+{ -+ u32 now_time = random_get_entropy(); ++#else /* CONFIG_LRNG_HEALTH_TESTS */ ++static inline bool lrng_sp80090b_startup_complete(void) { return true; } ++static inline bool lrng_sp80090b_compliant(void) { return false; } + -+ if (unlikely(!lrng_state_fully_seeded())) { -+ /* During boot time, we process the full time stamp */ -+ lrng_time_process_common(now_time, _lrng_pcpu_array_add_u32); -+ } else { -+ /* Runtime operation */ -+ lrng_time_process_common(now_time & LRNG_DATA_SLOTSIZE_MASK, -+ lrng_pcpu_array_add_slot); -+ } ++static inline enum lrng_health_res ++lrng_health_test(u32 now_time) { return lrng_health_pass; } ++static inline void lrng_health_disable(void) { } ++#endif /* CONFIG_LRNG_HEALTH_TESTS */ + -+ lrng_perf_time(now_time); -+} ++/****************************** Helper code ***********************************/ + -+/* Hot code path - Callback for interrupt handler */ -+void add_interrupt_randomness(int irq, int irq_flg) ++static inline u32 atomic_read_u32(atomic_t *v) +{ -+ if (lrng_pool_highres_timer()) { -+ lrng_time_process(); -+ } else { -+ struct pt_regs *regs = get_irq_regs(); -+ static atomic_t reg_idx = ATOMIC_INIT(0); -+ u64 ip; -+ u32 tmp; -+ -+ if (regs) { -+ u32 *ptr = (u32 *)regs; -+ int reg_ptr = atomic_add_return_relaxed(1, ®_idx); -+ size_t n = (sizeof(struct pt_regs) / sizeof(u32)); -+ -+ ip = instruction_pointer(regs); -+ tmp = *(ptr + (reg_ptr % n)); -+ tmp = lrng_raw_regs_entropy_store(tmp) ? 0 : tmp; -+ _lrng_pcpu_array_add_u32(tmp); -+ } else { -+ ip = _RET_IP_; -+ } ++ return (u32)atomic_read(v); ++} + -+ lrng_time_process(); ++/*************************** Auxiliary functions ******************************/ + -+ /* -+ * The XOR operation combining the different values is not -+ * considered to destroy entropy since the entirety of all -+ * processed values delivers the entropy (and not each -+ * value separately of the other values). -+ */ -+ tmp = lrng_raw_jiffies_entropy_store(jiffies) ? 0 : jiffies; -+ tmp ^= lrng_raw_irq_entropy_store(irq) ? 0 : irq; -+ tmp ^= lrng_raw_irqflags_entropy_store(irq_flg) ? 0 : irq_flg; -+ tmp ^= lrng_raw_retip_entropy_store(ip) ? 0 : ip; -+ tmp ^= ip >> 32; -+ _lrng_pcpu_array_add_u32(tmp); -+ } -+} -+EXPORT_SYMBOL(add_interrupt_randomness); ---- /dev/null -+++ b/drivers/char/lrng/lrng_sw_noise.h -@@ -0,0 +1,71 @@ -+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ -+/* -+ * LRNG Slow Noise Source: Time stamp array handling -+ * -+ * Copyright (C) 2016 - 2021, Stephan Mueller -+ */ ++void invalidate_batched_entropy(void); + -+/* -+ * To limit the impact on the interrupt handling, the LRNG concatenates -+ * entropic LSB parts of the time stamps in a per-CPU array and only -+ * injects them into the entropy pool when the array is full. -+ */ ++/***************************** Testing code ***********************************/ + -+/* Store multiple integers in one u32 */ -+#define LRNG_DATA_SLOTSIZE_BITS (8) -+#define LRNG_DATA_SLOTSIZE_MASK ((1 << LRNG_DATA_SLOTSIZE_BITS) - 1) -+#define LRNG_DATA_ARRAY_MEMBER_BITS (4 << 3) /* ((sizeof(u32)) << 3) */ -+#define LRNG_DATA_SLOTS_PER_UINT (LRNG_DATA_ARRAY_MEMBER_BITS / \ -+ LRNG_DATA_SLOTSIZE_BITS) ++#ifdef CONFIG_LRNG_RAW_HIRES_ENTROPY ++bool lrng_raw_hires_entropy_store(u32 value); ++#else /* CONFIG_LRNG_RAW_HIRES_ENTROPY */ ++static inline bool lrng_raw_hires_entropy_store(u32 value) { return false; } ++#endif /* CONFIG_LRNG_RAW_HIRES_ENTROPY */ + -+/* -+ * Number of time values to store in the array - in small environments -+ * only one atomic_t variable per CPU is used. -+ */ -+#define LRNG_DATA_NUM_VALUES (CONFIG_LRNG_COLLECTION_SIZE) -+/* Mask of LSB of time stamp to store */ -+#define LRNG_DATA_WORD_MASK (LRNG_DATA_NUM_VALUES - 1) ++#ifdef CONFIG_LRNG_RAW_JIFFIES_ENTROPY ++bool lrng_raw_jiffies_entropy_store(u32 value); ++#else /* CONFIG_LRNG_RAW_JIFFIES_ENTROPY */ ++static inline bool lrng_raw_jiffies_entropy_store(u32 value) { return false; } ++#endif /* CONFIG_LRNG_RAW_JIFFIES_ENTROPY */ + -+#define LRNG_DATA_SLOTS_MASK (LRNG_DATA_SLOTS_PER_UINT - 1) -+#define LRNG_DATA_ARRAY_SIZE (LRNG_DATA_NUM_VALUES / \ -+ LRNG_DATA_SLOTS_PER_UINT) ++#ifdef CONFIG_LRNG_RAW_IRQ_ENTROPY ++bool lrng_raw_irq_entropy_store(u32 value); ++#else /* CONFIG_LRNG_RAW_IRQ_ENTROPY */ ++static inline bool lrng_raw_irq_entropy_store(u32 value) { return false; } ++#endif /* CONFIG_LRNG_RAW_IRQ_ENTROPY */ + -+/* Starting bit index of slot */ -+static inline unsigned int lrng_data_slot2bitindex(unsigned int slot) -+{ -+ return (LRNG_DATA_SLOTSIZE_BITS * slot); -+} ++#ifdef CONFIG_LRNG_RAW_IRQFLAGS_ENTROPY ++bool lrng_raw_irqflags_entropy_store(u32 value); ++#else /* CONFIG_LRNG_RAW_IRQFLAGS_ENTROPY */ ++static inline bool lrng_raw_irqflags_entropy_store(u32 value) { return false; } ++#endif /* CONFIG_LRNG_RAW_IRQFLAGS_ENTROPY */ + -+/* Convert index into the array index */ -+static inline unsigned int lrng_data_idx2array(unsigned int idx) -+{ -+ return idx / LRNG_DATA_SLOTS_PER_UINT; -+} ++#ifdef CONFIG_LRNG_RAW_RETIP_ENTROPY ++bool lrng_raw_retip_entropy_store(u32 value); ++#else /* CONFIG_LRNG_RAW_RETIP_ENTROPY */ ++static inline bool lrng_raw_retip_entropy_store(u32 value) { return false; } ++#endif /* CONFIG_LRNG_RAW_RETIP_ENTROPY */ + -+/* Convert index into the slot of a given array index */ -+static inline unsigned int lrng_data_idx2slot(unsigned int idx) -+{ -+ return idx & LRNG_DATA_SLOTS_MASK; -+} ++#ifdef CONFIG_LRNG_RAW_REGS_ENTROPY ++bool lrng_raw_regs_entropy_store(u32 value); ++#else /* CONFIG_LRNG_RAW_REGS_ENTROPY */ ++static inline bool lrng_raw_regs_entropy_store(u32 value) { return false; } ++#endif /* CONFIG_LRNG_RAW_REGS_ENTROPY */ + -+/* Convert value into slot value */ -+static inline unsigned int lrng_data_slot_val(unsigned int val, -+ unsigned int slot) -+{ -+ return val << lrng_data_slot2bitindex(slot); -+} ++#ifdef CONFIG_LRNG_RAW_ARRAY ++bool lrng_raw_array_entropy_store(u32 value); ++#else /* CONFIG_LRNG_RAW_ARRAY */ ++static inline bool lrng_raw_array_entropy_store(u32 value) { return false; } ++#endif /* CONFIG_LRNG_RAW_ARRAY */ + -+/* -+ * Return the pointers for the previous and current units to inject a u32 into. -+ * Also return the mask which the u32 word is to be processed. -+ */ -+static inline void lrng_pcpu_split_u32(u32 *ptr, u32 *pre_ptr, u32 *mask) -+{ -+ /* ptr to previous unit */ -+ *pre_ptr = (*ptr - LRNG_DATA_SLOTS_PER_UINT) & LRNG_DATA_WORD_MASK; -+ *ptr &= LRNG_DATA_WORD_MASK; ++#ifdef CONFIG_LRNG_IRQ_PERF ++bool lrng_perf_time(u32 start); ++#else /* CONFIG_LRNG_IRQ_PERF */ ++static inline bool lrng_perf_time(u32 start) { return false; } ++#endif /*CONFIG_LRNG_IRQ_PERF */ + -+ /* mask to split data into the two parts for the two units */ -+ *mask = ((1 << (*pre_ptr & (LRNG_DATA_SLOTS_PER_UINT - 1)) * -+ LRNG_DATA_SLOTSIZE_BITS)) - 1; -+} ++#endif /* _LRNG_INTERNAL_H */ +diff --git a/include/linux/lrng.h b/include/linux/lrng.h +new file mode 100644 +index 000000000000..e9dc860a1ebb --- /dev/null +++ b/include/linux/lrng.h @@ -0,0 +1,81 @@ @@ -4160,3 +4383,6 @@ Signed-off-by: Stephan Mueller +#endif /* CONFIG_LRNG_DRNG_SWITCH */ + +#endif /* _LRNG_H */ +-- +2.31.1 + diff --git a/PATCH/LRNG/696-05-v41-0002-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch b/PATCH/LRNG/696-05-v42-0002-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch similarity index 81% rename from PATCH/LRNG/696-05-v41-0002-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch rename to PATCH/LRNG/696-05-v42-0002-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch index 9cf20b6b5..926dea3ca 100644 --- a/PATCH/LRNG/696-05-v41-0002-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch +++ b/PATCH/LRNG/696-05-v42-0002-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch @@ -1,7 +1,7 @@ -From 0a73760d76194fd8fa2aa039d121b28c9d9e200a Mon Sep 17 00:00:00 2001 +From 4cb1d63f92167475f34f710802c007ed2b5c7ff2 Mon Sep 17 00:00:00 2001 From: Stephan Mueller -Date: Fri, 18 Jun 2021 08:03:15 +0200 -Subject: [PATCH v41 02/13] LRNG - allocate one DRNG instance per NUMA node +Date: Mon, 2 Aug 2021 21:49:21 +0200 +Subject: [PATCH v42 02/13] LRNG - allocate one DRNG instance per NUMA node In order to improve NUMA-locality when serving getrandom(2) requests, allocate one DRNG instance per node. @@ -37,43 +37,32 @@ CC: Florian Weimer CC: Lennart Poettering CC: Nicolai Stange CC: Eric Biggers -CC: Alexander Lobakin +Reviewed-by: Alexander Lobakin +Tested-by: Alexander Lobakin Reviewed-by: Marcelo Henrique Cerri Reviewed-by: Roman Drahtmueller Tested-by: Marcelo Henrique Cerri Tested-by: Neil Horman Signed-off-by: Stephan Mueller --- - drivers/char/lrng/Makefile | 2 + - drivers/char/lrng/lrng_internal.h | 5 ++ - drivers/char/lrng/lrng_numa.c | 122 ++++++++++++++++++++++++++++++ - 3 files changed, 129 insertions(+) + drivers/char/lrng/Makefile | 2 + + drivers/char/lrng/lrng_numa.c | 122 ++++++++++++++++++++++++++++++++++ + 2 files changed, 124 insertions(+) create mode 100644 drivers/char/lrng/lrng_numa.c +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +index c26f932628d7..80b152059598 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile -@@ -7,3 +7,5 @@ obj-y += lrng_pool.o lrng_aux.o \ - lrng_sw_noise.o lrng_archrandom.o \ +@@ -7,3 +7,5 @@ obj-y += lrng_es_mgr.o lrng_aux.o \ + lrng_es_irq.o lrng_es_archrandom.o \ lrng_drng.o lrng_chacha20.o \ - lrng_interfaces.o + lrng_interfaces.o lrng_es_aux.o + +obj-$(CONFIG_NUMA) += lrng_numa.o ---- a/drivers/char/lrng/lrng_internal.h -+++ b/drivers/char/lrng/lrng_internal.h -@@ -254,8 +254,13 @@ int lrng_drng_get_sleep(u8 *outbuf, u32 - void lrng_drng_force_reseed(void); - void lrng_drng_seed_work(struct work_struct *dummy); - -+#ifdef CONFIG_NUMA -+struct lrng_drng **lrng_drng_instances(void); -+void lrng_drngs_numa_alloc(void); -+#else /* CONFIG_NUMA */ - static inline struct lrng_drng **lrng_drng_instances(void) { return NULL; } - static inline void lrng_drngs_numa_alloc(void) { return; } -+#endif /* CONFIG_NUMA */ - - /************************* Entropy sources management *************************/ - +diff --git a/drivers/char/lrng/lrng_numa.c b/drivers/char/lrng/lrng_numa.c +new file mode 100644 +index 000000000000..fbfb40a5fb8d --- /dev/null +++ b/drivers/char/lrng/lrng_numa.c @@ -0,0 +1,122 @@ @@ -199,3 +188,6 @@ Signed-off-by: Stephan Mueller +{ + schedule_work(&lrng_drngs_numa_alloc_work); +} +-- +2.31.1 + diff --git a/PATCH/LRNG/696-06-v41-0003-LRNG-sysctls-and-proc-interface.patch b/PATCH/LRNG/696-06-v42-0003-LRNG-sysctls-and-proc-interface.patch similarity index 89% rename from PATCH/LRNG/696-06-v41-0003-LRNG-sysctls-and-proc-interface.patch rename to PATCH/LRNG/696-06-v42-0003-LRNG-sysctls-and-proc-interface.patch index f517737f6..5ec5f3c54 100644 --- a/PATCH/LRNG/696-06-v41-0003-LRNG-sysctls-and-proc-interface.patch +++ b/PATCH/LRNG/696-06-v42-0003-LRNG-sysctls-and-proc-interface.patch @@ -1,7 +1,7 @@ -From 28ba413daaf3dc24f8efb15335a8da82201e42d7 Mon Sep 17 00:00:00 2001 +From 4e3f238b369d19b1b3e9be3b43765ce563626347 Mon Sep 17 00:00:00 2001 From: Stephan Mueller -Date: Wed, 23 Jun 2021 18:44:26 +0200 -Subject: [PATCH v41 03/13] LRNG - sysctls and /proc interface +Date: Mon, 2 Aug 2021 21:52:37 +0200 +Subject: [PATCH v42 03/13] LRNG - sysctls and /proc interface The LRNG sysctl interface provides the same controls as the existing /dev/random implementation. These sysctls behave identically and are @@ -51,7 +51,8 @@ CC: Andy Lutomirski CC: Florian Weimer CC: Lennart Poettering CC: Nicolai Stange -CC: Alexander Lobakin +Reviewed-by: Alexander Lobakin +Tested-by: Alexander Lobakin Reviewed-by: Marcelo Henrique Cerri Reviewed-by: Roman Drahtmueller Tested-by: Marcelo Henrique Cerri @@ -60,21 +61,24 @@ Signed-off-by: Stephan Mueller --- drivers/char/lrng/Makefile | 1 + drivers/char/lrng/lrng_interfaces.c | 2 - - drivers/char/lrng/lrng_internal.h | 4 + drivers/char/lrng/lrng_proc.c | 185 ++++++++++++++++++++++++++++ - 4 files changed, 190 insertions(+), 2 deletions(-) + 3 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 drivers/char/lrng/lrng_proc.c +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +index 80b152059598..3144e87c2166 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile -@@ -9,3 +9,4 @@ obj-y += lrng_pool.o lrng_aux.o \ - lrng_interfaces.o +@@ -9,3 +9,4 @@ obj-y += lrng_es_mgr.o lrng_aux.o \ + lrng_interfaces.o lrng_es_aux.o obj-$(CONFIG_NUMA) += lrng_numa.o +obj-$(CONFIG_SYSCTL) += lrng_proc.o +diff --git a/drivers/char/lrng/lrng_interfaces.c b/drivers/char/lrng/lrng_interfaces.c +index 3a56bfdca01e..4b8c56849112 100644 --- a/drivers/char/lrng/lrng_interfaces.c +++ b/drivers/char/lrng/lrng_interfaces.c -@@ -38,8 +38,6 @@ static DECLARE_WAIT_QUEUE_HEAD(lrng_writ +@@ -38,8 +38,6 @@ static DECLARE_WAIT_QUEUE_HEAD(lrng_write_wait); static DECLARE_WAIT_QUEUE_HEAD(lrng_init_wait); static struct fasync_struct *fasync; @@ -83,20 +87,9 @@ Signed-off-by: Stephan Mueller /********************************** Helper ***********************************/ /* Is the DRNG seed level too low? */ ---- a/drivers/char/lrng/lrng_internal.h -+++ b/drivers/char/lrng/lrng_internal.h -@@ -114,7 +114,11 @@ void lrng_cc20_init_state(struct chacha2 - - /********************************** /proc *************************************/ - -+#ifdef CONFIG_SYSCTL -+void lrng_pool_inc_numa_node(void); -+#else - static inline void lrng_pool_inc_numa_node(void) { } -+#endif - - /****************************** LRNG interfaces *******************************/ - +diff --git a/drivers/char/lrng/lrng_proc.c b/drivers/char/lrng/lrng_proc.c +new file mode 100644 +index 000000000000..a842c6c897f2 --- /dev/null +++ b/drivers/char/lrng/lrng_proc.c @@ -0,0 +1,185 @@ @@ -114,7 +107,7 @@ Signed-off-by: Stephan Mueller +#include + +#include "lrng_internal.h" -+#include "lrng_sw_noise.h" ++#include "lrng_es_irq.h" + +/* + * This function is used to return both the bootid UUID, and random @@ -285,3 +278,6 @@ Signed-off-by: Stephan Mueller +} + +module_init(lrng_proc_type_init); +-- +2.31.1 + diff --git a/PATCH/LRNG/696-07-v41-0004-LRNG-add-switchable-DRNG-support.patch b/PATCH/LRNG/696-07-v42-0004-LRNG-add-switchable-DRNG-support.patch similarity index 91% rename from PATCH/LRNG/696-07-v41-0004-LRNG-add-switchable-DRNG-support.patch rename to PATCH/LRNG/696-07-v42-0004-LRNG-add-switchable-DRNG-support.patch index 975c74cf0..9a88d1d4f 100644 --- a/PATCH/LRNG/696-07-v41-0004-LRNG-add-switchable-DRNG-support.patch +++ b/PATCH/LRNG/696-07-v42-0004-LRNG-add-switchable-DRNG-support.patch @@ -1,7 +1,7 @@ -From 2ea9e51004f8a85964977ec7cd26f9f5a294295a Mon Sep 17 00:00:00 2001 +From e26ee3e543f80be93cca6155ea9f861603652f59 Mon Sep 17 00:00:00 2001 From: Stephan Mueller -Date: Fri, 18 Jun 2021 08:06:39 +0200 -Subject: [PATCH v41 04/13] LRNG - add switchable DRNG support +Date: Mon, 2 Aug 2021 21:54:12 +0200 +Subject: [PATCH v42 04/13] LRNG - add switchable DRNG support The DRNG switch support allows replacing the DRNG mechanism of the LRNG. The switching support rests on the interface definition of @@ -56,7 +56,8 @@ CC: Andy Lutomirski CC: Florian Weimer CC: Lennart Poettering CC: Nicolai Stange -CC: Alexander Lobakin +Reviewed-by: Alexander Lobakin +Tested-by: Alexander Lobakin Reviewed-by: Marcelo Henrique Cerri Reviewed-by: Roman Drahtmueller Tested-by: Marcelo Henrique Cerri @@ -65,10 +66,12 @@ Signed-off-by: Stephan Mueller --- drivers/char/lrng/Kconfig | 7 + drivers/char/lrng/Makefile | 1 + - drivers/char/lrng/lrng_switch.c | 231 ++++++++++++++++++++++++++++++++ - 3 files changed, 239 insertions(+) + drivers/char/lrng/lrng_switch.c | 226 ++++++++++++++++++++++++++++++++ + 3 files changed, 234 insertions(+) create mode 100644 drivers/char/lrng/lrng_switch.c +diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig +index 1cb2f55666ac..c10a0c3f2015 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig @@ -202,4 +202,11 @@ config LRNG_CPU_ENTROPY_RATE @@ -83,16 +86,21 @@ Signed-off-by: Stephan Mueller + option other DRNGs can be selected and loaded at runtime. + endif # LRNG +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +index 3144e87c2166..dc3ef329b2c4 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile -@@ -10,3 +10,4 @@ obj-y += lrng_pool.o lrng_aux.o \ +@@ -10,3 +10,4 @@ obj-y += lrng_es_mgr.o lrng_aux.o \ obj-$(CONFIG_NUMA) += lrng_numa.o obj-$(CONFIG_SYSCTL) += lrng_proc.o +obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_switch.o +diff --git a/drivers/char/lrng/lrng_switch.c b/drivers/char/lrng/lrng_switch.c +new file mode 100644 +index 000000000000..f3b2f30d1c21 --- /dev/null +++ b/drivers/char/lrng/lrng_switch.c -@@ -0,0 +1,231 @@ +@@ -0,0 +1,226 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* + * LRNG DRNG switching support @@ -213,22 +221,17 @@ Signed-off-by: Stephan Mueller + pr_info("Entropy pool read-hash allocated for DRNG for NUMA node %d\n", + node); + -+ if (lrng_state_min_seeded()) -+ lrng_set_entropy_thresh(lrng_get_seed_entropy_osr()); -+ + /* Reseed if previous LRNG security strength was insufficient */ + if (current_security_strength < lrng_security_strength()) + drng_store->force_reseed = true; + + /* Force oversampling seeding as we initialize DRNG */ -+ if (IS_ENABLED(CONFIG_LRNG_OVERSAMPLE_ENTROPY_SOURCES)) { -+ drng_store->force_reseed = true; -+ drng_store->fully_seeded = false; ++ if (IS_ENABLED(CONFIG_LRNG_OVERSAMPLE_ENTROPY_SOURCES)) ++ lrng_unset_fully_seeded(drng_store); + -+ /* Block output interfaces until again fully seeded */ -+ if (drng_store == lrng_drng_init_instance()) -+ lrng_unset_operational(); -+ } ++ if (lrng_state_min_seeded()) ++ lrng_set_entropy_thresh(lrng_get_seed_entropy_osr( ++ drng_store->fully_seeded)); + + /* ChaCha20 serves as atomic instance left untouched. */ + if (old_drng != &chacha20) { @@ -324,3 +327,6 @@ Signed-off-by: Stephan Mueller + return ret; +} +EXPORT_SYMBOL(lrng_set_drng_cb); +-- +2.31.1 + diff --git a/PATCH/LRNG/696-08-v41-0005-LRNG-add-common-generic-hash-support.patch b/PATCH/LRNG/696-08-v42-0005-LRNG-add-common-generic-hash-support.patch similarity index 87% rename from PATCH/LRNG/696-08-v41-0005-LRNG-add-common-generic-hash-support.patch rename to PATCH/LRNG/696-08-v42-0005-LRNG-add-common-generic-hash-support.patch index ea5685b89..f61ba6959 100644 --- a/PATCH/LRNG/696-08-v41-0005-LRNG-add-common-generic-hash-support.patch +++ b/PATCH/LRNG/696-08-v42-0005-LRNG-add-common-generic-hash-support.patch @@ -1,7 +1,7 @@ -From 2ca28b8684c0673b2e0363cc109479ecf1cae641 Mon Sep 17 00:00:00 2001 +From 844dc223fc4da1867daf13d7c8ae432fdc6de890 Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Fri, 18 Jun 2021 08:08:20 +0200 -Subject: [PATCH v41 05/13] LRNG - add common generic hash support +Subject: [PATCH v42 05/13] LRNG - add common generic hash support The LRNG switchable DRNG support also allows the replacement of the hash implementation used as conditioning component. The common generic hash @@ -31,10 +31,11 @@ CC: Andy Lutomirski CC: Florian Weimer CC: Lennart Poettering CC: Nicolai Stange -CC: Alexander Lobakin CC: "Peter, Matthias" CC: Marcelo Henrique Cerri CC: Neil Horman +Reviewed-by: Alexander Lobakin +Tested-by: Alexander Lobakin Signed-off-by: Stephan Mueller --- drivers/char/lrng/Kconfig | 8 +++ @@ -45,6 +46,8 @@ Signed-off-by: Stephan Mueller create mode 100644 drivers/char/lrng/lrng_kcapi_hash.c create mode 100644 drivers/char/lrng/lrng_kcapi_hash.h +diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig +index c10a0c3f2015..ab17c45a356b 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig @@ -209,4 +209,12 @@ menuconfig LRNG_DRNG_SWITCH @@ -60,13 +63,18 @@ Signed-off-by: Stephan Mueller +endif # LRNG_DRNG_SWITCH + endif # LRNG +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +index dc3ef329b2c4..299715bb0ec2 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile -@@ -11,3 +11,4 @@ obj-y += lrng_pool.o lrng_aux.o \ +@@ -11,3 +11,4 @@ obj-y += lrng_es_mgr.o lrng_aux.o \ obj-$(CONFIG_NUMA) += lrng_numa.o obj-$(CONFIG_SYSCTL) += lrng_proc.o obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_switch.o +obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.o +diff --git a/drivers/char/lrng/lrng_kcapi_hash.c b/drivers/char/lrng/lrng_kcapi_hash.c +new file mode 100644 +index 000000000000..9647d980e468 --- /dev/null +++ b/drivers/char/lrng/lrng_kcapi_hash.c @@ -0,0 +1,103 @@ @@ -173,6 +181,9 @@ Signed-off-by: Stephan Mueller + shash_desc_zero(shash); +} +EXPORT_SYMBOL(lrng_kcapi_hash_zero); +diff --git a/drivers/char/lrng/lrng_kcapi_hash.h b/drivers/char/lrng/lrng_kcapi_hash.h +new file mode 100644 +index 000000000000..2f94558d2dd6 --- /dev/null +++ b/drivers/char/lrng/lrng_kcapi_hash.h @@ -0,0 +1,20 @@ @@ -196,3 +207,6 @@ Signed-off-by: Stephan Mueller +void lrng_kcapi_hash_zero(struct shash_desc *shash); + +#endif /* _LRNG_KCAPI_HASH_H */ +-- +2.31.1 + diff --git a/PATCH/LRNG/696-09-v41-0006-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch b/PATCH/LRNG/696-09-v42-0006-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch similarity index 76% rename from PATCH/LRNG/696-09-v41-0006-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch rename to PATCH/LRNG/696-09-v42-0006-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch index 30f827960..e63392caf 100644 --- a/PATCH/LRNG/696-09-v41-0006-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch +++ b/PATCH/LRNG/696-09-v42-0006-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch @@ -1,7 +1,7 @@ -From f83f3fc4de379c8be7b382277c4ac3d2b491d3c1 Mon Sep 17 00:00:00 2001 +From 3b4bc70c349cde883e2b2545d65dc37a3ef89050 Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Tue, 15 Sep 2020 22:17:43 +0200 -Subject: [PATCH v41 06/13] crypto: DRBG - externalize DRBG functions for LRNG +Subject: [PATCH v42 06/13] crypto: DRBG - externalize DRBG functions for LRNG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -26,7 +26,8 @@ CC: Andy Lutomirski CC: Florian Weimer CC: Lennart Poettering CC: Nicolai Stange -CC: Alexander Lobakin +Reviewed-by: Alexander Lobakin +Tested-by: Alexander Lobakin Reviewed-by: Roman Drahtmueller Tested-by: Roman Drahtmüller Tested-by: Marcelo Henrique Cerri @@ -37,9 +38,11 @@ Signed-off-by: Stephan Mueller include/crypto/drbg.h | 7 +++++++ 2 files changed, 17 insertions(+), 6 deletions(-) +diff --git a/crypto/drbg.c b/crypto/drbg.c +index ea85d4a0fe9e..74a9dca67698 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c -@@ -113,7 +113,7 @@ +@@ -114,7 +114,7 @@ * the SHA256 / AES 256 over other ciphers. Thus, the favored * DRBGs are the latest entries in this array. */ @@ -48,7 +51,7 @@ Signed-off-by: Stephan Mueller #ifdef CONFIG_CRYPTO_DRBG_CTR { .flags = DRBG_CTR | DRBG_STRENGTH128, -@@ -190,6 +190,7 @@ static const struct drbg_core drbg_cores +@@ -191,6 +191,7 @@ static const struct drbg_core drbg_cores[] = { }, #endif /* CONFIG_CRYPTO_DRBG_HMAC */ }; @@ -56,7 +59,7 @@ Signed-off-by: Stephan Mueller static int drbg_uninstantiate(struct drbg_state *drbg); -@@ -205,7 +206,7 @@ static int drbg_uninstantiate(struct drb +@@ -206,7 +207,7 @@ static int drbg_uninstantiate(struct drbg_state *drbg); * Return: normalized strength in *bytes* value or 32 as default * to counter programming errors */ @@ -65,7 +68,7 @@ Signed-off-by: Stephan Mueller { switch (flags & DRBG_STRENGTH_MASK) { case DRBG_STRENGTH128: -@@ -218,6 +219,7 @@ static inline unsigned short drbg_sec_st +@@ -219,6 +220,7 @@ static inline unsigned short drbg_sec_strength(drbg_flag_t flags) return 32; } } @@ -73,7 +76,7 @@ Signed-off-by: Stephan Mueller /* * FIPS 140-2 continuous self test for the noise source -@@ -1202,7 +1204,7 @@ out: +@@ -1215,7 +1217,7 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers, } /* Free all substructures in a DRBG state without the DRBG state structure */ @@ -82,7 +85,7 @@ Signed-off-by: Stephan Mueller { if (!drbg) return; -@@ -1223,12 +1225,13 @@ static inline void drbg_dealloc_state(st +@@ -1236,12 +1238,13 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg) drbg->fips_primed = false; } } @@ -97,7 +100,7 @@ Signed-off-by: Stephan Mueller { int ret = -ENOMEM; unsigned int sb_size = 0; -@@ -1309,6 +1312,7 @@ err: +@@ -1322,6 +1325,7 @@ static inline int drbg_alloc_state(struct drbg_state *drbg) drbg_dealloc_state(drbg); return ret; } @@ -105,7 +108,7 @@ Signed-off-by: Stephan Mueller /************************************************************************* * DRBG interface functions -@@ -1876,8 +1880,7 @@ out: +@@ -1891,8 +1895,7 @@ static int drbg_kcapi_sym_ctr(struct drbg_state *drbg, * * return: flags */ @@ -115,7 +118,7 @@ Signed-off-by: Stephan Mueller { int i = 0; size_t start = 0; -@@ -1904,6 +1907,7 @@ static inline void drbg_convert_tfm_core +@@ -1919,6 +1922,7 @@ static inline void drbg_convert_tfm_core(const char *cra_driver_name, } } } @@ -123,9 +126,11 @@ Signed-off-by: Stephan Mueller static int drbg_kcapi_init(struct crypto_tfm *tfm) { +diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h +index c4165126937e..71d53e028e6d 100644 --- a/include/crypto/drbg.h +++ b/include/crypto/drbg.h -@@ -282,4 +282,11 @@ enum drbg_prefixes { +@@ -278,4 +278,11 @@ enum drbg_prefixes { DRBG_PREFIX3 }; @@ -137,3 +142,6 @@ Signed-off-by: Stephan Mueller +extern unsigned short drbg_sec_strength(drbg_flag_t flags); + #endif /* _DRBG_H */ +-- +2.31.1 + diff --git a/PATCH/LRNG/696-10-v41-0007-LRNG-add-SP800-90A-DRBG-extension.patch b/PATCH/LRNG/696-10-v42-0007-LRNG-add-SP800-90A-DRBG-extension.patch similarity index 93% rename from PATCH/LRNG/696-10-v41-0007-LRNG-add-SP800-90A-DRBG-extension.patch rename to PATCH/LRNG/696-10-v42-0007-LRNG-add-SP800-90A-DRBG-extension.patch index 235965811..96d12d6c2 100644 --- a/PATCH/LRNG/696-10-v41-0007-LRNG-add-SP800-90A-DRBG-extension.patch +++ b/PATCH/LRNG/696-10-v42-0007-LRNG-add-SP800-90A-DRBG-extension.patch @@ -1,7 +1,7 @@ -From 288d9cf9f2e949fb6c7dc3cf623186d07d4173fd Mon Sep 17 00:00:00 2001 +From 553e810748bf00be31f1dc6232290cdd70d00e26 Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Fri, 18 Jun 2021 08:09:59 +0200 -Subject: [PATCH v41 07/13] LRNG - add SP800-90A DRBG extension +Subject: [PATCH v42 07/13] LRNG - add SP800-90A DRBG extension Using the LRNG switchable DRNG support, the SP800-90A DRBG extension is implemented. @@ -37,7 +37,8 @@ CC: Andy Lutomirski CC: Florian Weimer CC: Lennart Poettering CC: Nicolai Stange -CC: Alexander Lobakin +Reviewed-by: Alexander Lobakin +Tested-by: Alexander Lobakin Reviewed-by: Roman Drahtmueller Tested-by: Marcelo Henrique Cerri Tested-by: Neil Horman @@ -49,6 +50,8 @@ Signed-off-by: Stephan Mueller 3 files changed, 209 insertions(+) create mode 100644 drivers/char/lrng/lrng_drbg.c +diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig +index ab17c45a356b..aa611363b97e 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig @@ -215,6 +215,16 @@ config LRNG_KCAPI_HASH @@ -68,6 +71,8 @@ Signed-off-by: Stephan Mueller endif # LRNG_DRNG_SWITCH endif # LRNG +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +index 299715bb0ec2..7e5acb8cac3d 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_NUMA) += lrng_numa.o @@ -75,6 +80,9 @@ Signed-off-by: Stephan Mueller obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_switch.o obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.o +obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o +diff --git a/drivers/char/lrng/lrng_drbg.c b/drivers/char/lrng/lrng_drbg.c +new file mode 100644 +index 000000000000..6ca6b05eccf4 --- /dev/null +++ b/drivers/char/lrng/lrng_drbg.c @@ -0,0 +1,198 @@ @@ -276,3 +284,6 @@ Signed-off-by: Stephan Mueller +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Stephan Mueller "); +MODULE_DESCRIPTION("Linux Random Number Generator - SP800-90A DRBG backend"); +-- +2.31.1 + diff --git a/PATCH/LRNG/696-11-v41-0008-LRNG-add-kernel-crypto-API-PRNG-extension.patch b/PATCH/LRNG/696-11-v42-0008-LRNG-add-kernel-crypto-API-PRNG-extension.patch similarity index 94% rename from PATCH/LRNG/696-11-v41-0008-LRNG-add-kernel-crypto-API-PRNG-extension.patch rename to PATCH/LRNG/696-11-v42-0008-LRNG-add-kernel-crypto-API-PRNG-extension.patch index 59f2a0349..98e72a232 100644 --- a/PATCH/LRNG/696-11-v41-0008-LRNG-add-kernel-crypto-API-PRNG-extension.patch +++ b/PATCH/LRNG/696-11-v42-0008-LRNG-add-kernel-crypto-API-PRNG-extension.patch @@ -1,7 +1,7 @@ -From 570409d073bb1d6645214532a431d5bc45454c0f Mon Sep 17 00:00:00 2001 +From cfc5387cf2f3226f4543318ec09957571d8ec63e Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Fri, 18 Jun 2021 08:10:53 +0200 -Subject: [PATCH v41 08/13] LRNG - add kernel crypto API PRNG extension +Subject: [PATCH v42 08/13] LRNG - add kernel crypto API PRNG extension Add runtime-pluggable support for all PRNGs that are accessible via the kernel crypto API, including hardware PRNGs. The PRNG is selected @@ -33,7 +33,8 @@ CC: Andy Lutomirski CC: Florian Weimer CC: Lennart Poettering CC: Nicolai Stange -CC: Alexander Lobakin +Reviewed-by: Alexander Lobakin +Tested-by: Alexander Lobakin Reviewed-by: Marcelo Henrique Cerri Reviewed-by: Roman Drahtmueller Tested-by: Marcelo Henrique Cerri @@ -46,6 +47,8 @@ Signed-off-by: Stephan Mueller 3 files changed, 241 insertions(+) create mode 100644 drivers/char/lrng/lrng_kcapi.c +diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig +index aa611363b97e..ffd2df43f2d4 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig @@ -225,6 +225,19 @@ config LRNG_DRBG @@ -68,6 +71,8 @@ Signed-off-by: Stephan Mueller endif # LRNG_DRNG_SWITCH endif # LRNG +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +index 7e5acb8cac3d..ad7c413cc0d9 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_SYSCTL) += lrng_proc.o @@ -75,6 +80,9 @@ Signed-off-by: Stephan Mueller obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.o obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o +obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o +diff --git a/drivers/char/lrng/lrng_kcapi.c b/drivers/char/lrng/lrng_kcapi.c +new file mode 100644 +index 000000000000..b06449cb2365 --- /dev/null +++ b/drivers/char/lrng/lrng_kcapi.c @@ -0,0 +1,227 @@ @@ -305,3 +313,6 @@ Signed-off-by: Stephan Mueller +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Stephan Mueller "); +MODULE_DESCRIPTION("Linux Random Number Generator - kernel crypto API DRNG backend"); +-- +2.31.1 + diff --git a/PATCH/LRNG/696-12-v41-0009-crypto-provide-access-to-a-static-Jitter-RNG-sta.patch b/PATCH/LRNG/696-12-v41-0009-crypto-provide-access-to-a-static-Jitter-RNG-sta.patch deleted file mode 100644 index 6d98d1c94..000000000 --- a/PATCH/LRNG/696-12-v41-0009-crypto-provide-access-to-a-static-Jitter-RNG-sta.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 927d21648cb471466dc4ee32e1de9964b74d8b95 Mon Sep 17 00:00:00 2001 -From: Stephan Mueller -Date: Wed, 16 Sep 2020 09:50:27 +0200 -Subject: [PATCH v41 09/13] crypto: provide access to a static Jitter RNG state -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -To support the LRNG operation which uses the Jitter RNG separately -from the kernel crypto API, at a time where potentially the regular -memory management is not yet initialized, the Jitter RNG needs to -provide a state whose memory is defined at compile time. As only once -instance will ever be needed by the LRNG, define once static memory -block which is solely to be used by the LRNG. - -CC: Torsten Duwe -CC: "Eric W. Biederman" -CC: "Alexander E. Patrakov" -CC: "Ahmed S. Darwish" -CC: "Theodore Y. Ts'o" -CC: Willy Tarreau -CC: Matthew Garrett -CC: Vito Caputo -CC: Andreas Dilger -CC: Jan Kara -CC: Ray Strode -CC: William Jon McCann -CC: zhangjs -CC: Andy Lutomirski -CC: Florian Weimer -CC: Lennart Poettering -CC: Nicolai Stange -CC: Alexander Lobakin -Reviewed-by: Roman Drahtmueller -Tested-by: Roman Drahtmüller -Tested-by: Marcelo Henrique Cerri -Tested-by: Neil Horman -Signed-off-by: Stephan Mueller ---- - crypto/jitterentropy-kcapi.c | 3 +- - crypto/jitterentropy.c | 31 ++++++++++++++++++- - .../crypto/internal}/jitterentropy.h | 3 ++ - 3 files changed, 34 insertions(+), 3 deletions(-) - rename {crypto => include/crypto/internal}/jitterentropy.h (84%) - ---- a/crypto/jitterentropy-kcapi.c -+++ b/crypto/jitterentropy-kcapi.c -@@ -43,8 +43,7 @@ - #include - #include - #include -- --#include "jitterentropy.h" -+#include - - /*************************************************************************** - * Helper function ---- a/crypto/jitterentropy.c -+++ b/crypto/jitterentropy.c -@@ -103,7 +103,7 @@ struct rand_data { - * Helper functions - ***************************************************************************/ - --#include "jitterentropy.h" -+#include - - /** - * Update of the loop count used for the next round of -@@ -639,3 +639,32 @@ int jent_entropy_init(void) - - return 0; - } -+ -+struct rand_data *jent_lrng_entropy_collector(void) -+{ -+ static unsigned char lrng_jent_mem[JENT_MEMORY_SIZE]; -+ static struct rand_data lrng_jent_state = { -+ .data = 0, -+ .old_data = 0, -+ .prev_time = 0, -+ .last_delta = 0, -+ .last_delta2 = 0, -+ .osr = 1, -+ .mem = lrng_jent_mem, -+ .memlocation = 0, -+ .memblocks = JENT_MEMORY_BLOCKSIZE, -+ .memblocksize = JENT_MEMORY_BLOCKS, -+ .memaccessloops = JENT_MEMORY_ACCESSLOOPS, -+ .rct_count = 0, -+ .apt_observations = 0, -+ .apt_count = 0, -+ .apt_base = 0, -+ .apt_base_set = 0, -+ .health_failure = 0 -+ }; -+ -+ if (jent_entropy_init()) -+ return NULL; -+ -+ return &lrng_jent_state; -+} ---- a/crypto/jitterentropy.h -+++ /dev/null -@@ -1,19 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0-or-later -- --typedef unsigned long long __u64; -- --extern void *jent_zalloc(unsigned int len); --extern void jent_zfree(void *ptr); --extern int jent_fips_enabled(void); --extern void jent_panic(char *s); --extern void jent_memcpy(void *dest, const void *src, unsigned int n); --extern void jent_get_nstime(__u64 *out); -- --struct rand_data; --extern int jent_entropy_init(void); --extern int jent_read_entropy(struct rand_data *ec, unsigned char *data, -- unsigned int len); -- --extern struct rand_data *jent_entropy_collector_alloc(unsigned int osr, -- unsigned int flags); --extern void jent_entropy_collector_free(struct rand_data *entropy_collector); ---- /dev/null -+++ b/include/crypto/internal/jitterentropy.h -@@ -0,0 +1,22 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+ -+typedef unsigned long long __u64; -+ -+extern void *jent_zalloc(unsigned int len); -+extern void jent_zfree(void *ptr); -+extern int jent_fips_enabled(void); -+extern void jent_panic(char *s); -+extern void jent_memcpy(void *dest, const void *src, unsigned int n); -+extern void jent_get_nstime(__u64 *out); -+ -+struct rand_data; -+extern int jent_entropy_init(void); -+extern int jent_read_entropy(struct rand_data *ec, unsigned char *data, -+ unsigned int len); -+ -+extern struct rand_data *jent_entropy_collector_alloc(unsigned int osr, -+ unsigned int flags); -+extern void jent_entropy_collector_free(struct rand_data *entropy_collector); -+ -+/* Access to statically allocated Jitter RNG instance */ -+extern struct rand_data *jent_lrng_entropy_collector(void); diff --git a/PATCH/LRNG/696-12-v42-0009-crypto-move-Jitter-RNG-header-include-dir.patch b/PATCH/LRNG/696-12-v42-0009-crypto-move-Jitter-RNG-header-include-dir.patch new file mode 100644 index 000000000..7871b9388 --- /dev/null +++ b/PATCH/LRNG/696-12-v42-0009-crypto-move-Jitter-RNG-header-include-dir.patch @@ -0,0 +1,77 @@ +From 84c82faba86da8fc9ecd7ccbf7e85322dda009d3 Mon Sep 17 00:00:00 2001 +From: Stephan Mueller +Date: Wed, 16 Sep 2020 09:50:27 +0200 +Subject: [PATCH v42 09/13] crypto: move Jitter RNG header include dir +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +To support the LRNG operation which uses the Jitter RNG separately +from the kernel crypto API, the header file must be accessible to +the LRNG code. + +CC: Torsten Duwe +CC: "Eric W. Biederman" +CC: "Alexander E. Patrakov" +CC: "Ahmed S. Darwish" +CC: "Theodore Y. Ts'o" +CC: Willy Tarreau +CC: Matthew Garrett +CC: Vito Caputo +CC: Andreas Dilger +CC: Jan Kara +CC: Ray Strode +CC: William Jon McCann +CC: zhangjs +CC: Andy Lutomirski +CC: Florian Weimer +CC: Lennart Poettering +CC: Nicolai Stange +Reviewed-by: Alexander Lobakin +Tested-by: Alexander Lobakin +Reviewed-by: Roman Drahtmueller +Tested-by: Roman Drahtmüller +Tested-by: Marcelo Henrique Cerri +Tested-by: Neil Horman +Signed-off-by: Stephan Mueller +--- + crypto/jitterentropy-kcapi.c | 3 +-- + crypto/jitterentropy.c | 2 +- + {crypto => include/crypto/internal}/jitterentropy.h | 0 + 3 files changed, 2 insertions(+), 3 deletions(-) + rename {crypto => include/crypto/internal}/jitterentropy.h (100%) + +diff --git a/crypto/jitterentropy-kcapi.c b/crypto/jitterentropy-kcapi.c +index e8a4165a1874..c90e60910827 100644 +--- a/crypto/jitterentropy-kcapi.c ++++ b/crypto/jitterentropy-kcapi.c +@@ -43,8 +43,7 @@ + #include + #include + #include +- +-#include "jitterentropy.h" ++#include + + /*************************************************************************** + * Helper function +diff --git a/crypto/jitterentropy.c b/crypto/jitterentropy.c +index a11b3208760f..f36a391319e1 100644 +--- a/crypto/jitterentropy.c ++++ b/crypto/jitterentropy.c +@@ -117,7 +117,7 @@ struct rand_data { + #define JENT_EHEALTH 9 /* Health test failed during initialization */ + #define JENT_ERCT 10 /* RCT failed during initialization */ + +-#include "jitterentropy.h" ++#include + + /*************************************************************************** + * Adaptive Proportion Test +diff --git a/crypto/jitterentropy.h b/include/crypto/internal/jitterentropy.h +similarity index 100% +rename from crypto/jitterentropy.h +rename to include/crypto/internal/jitterentropy.h +-- +2.31.1 + diff --git a/PATCH/LRNG/696-13-v41-0010-LRNG-add-Jitter-RNG-fast-noise-source.patch b/PATCH/LRNG/696-13-v42-0010-LRNG-add-Jitter-RNG-fast-noise-source.patch similarity index 82% rename from PATCH/LRNG/696-13-v41-0010-LRNG-add-Jitter-RNG-fast-noise-source.patch rename to PATCH/LRNG/696-13-v42-0010-LRNG-add-Jitter-RNG-fast-noise-source.patch index f64d5f717..386d8367e 100644 --- a/PATCH/LRNG/696-13-v41-0010-LRNG-add-Jitter-RNG-fast-noise-source.patch +++ b/PATCH/LRNG/696-13-v42-0010-LRNG-add-Jitter-RNG-fast-noise-source.patch @@ -1,7 +1,7 @@ -From 44305098f785b82a20285ad47668bacd2a2ee4a8 Mon Sep 17 00:00:00 2001 +From bd786e34db91f6a72788d397625a41d01e1bd7bc Mon Sep 17 00:00:00 2001 From: Stephan Mueller -Date: Fri, 18 Jun 2021 08:13:57 +0200 -Subject: [PATCH v41 10/13] LRNG - add Jitter RNG fast noise source +Date: Mon, 30 Aug 2021 12:32:04 +0200 +Subject: [PATCH v42 10/13] LRNG - add Jitter RNG fast noise source The Jitter RNG fast noise source implemented as part of the kernel crypto API is queried for 256 bits of entropy at the time the seed @@ -24,18 +24,21 @@ CC: Andy Lutomirski CC: Florian Weimer CC: Lennart Poettering CC: Nicolai Stange -CC: Alexander Lobakin +Reviewed-by: Alexander Lobakin +Tested-by: Alexander Lobakin Reviewed-by: Marcelo Henrique Cerri Tested-by: Marcelo Henrique Cerri Tested-by: Neil Horman Signed-off-by: Stephan Mueller --- - drivers/char/lrng/Kconfig | 27 +++++++++++ - drivers/char/lrng/Makefile | 1 + - drivers/char/lrng/lrng_jent.c | 90 +++++++++++++++++++++++++++++++++++ + drivers/char/lrng/Kconfig | 27 ++++++++++ + drivers/char/lrng/Makefile | 1 + + drivers/char/lrng/lrng_es_jent.c | 90 ++++++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+) - create mode 100644 drivers/char/lrng/lrng_jent.c + create mode 100644 drivers/char/lrng/lrng_es_jent.c +diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig +index ffd2df43f2d4..e622b8532e2b 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig @@ -182,6 +182,33 @@ config LRNG_IRQ_ENTROPY_RATE @@ -72,15 +75,20 @@ Signed-off-by: Stephan Mueller comment "CPU Entropy Source" config LRNG_CPU_ENTROPY_RATE +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +index ad7c413cc0d9..01a69172c464 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile -@@ -14,3 +14,4 @@ obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_s +@@ -14,3 +14,4 @@ obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_switch.o obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.o obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o -+obj-$(CONFIG_LRNG_JENT) += lrng_jent.o ++obj-$(CONFIG_LRNG_JENT) += lrng_es_jent.o +diff --git a/drivers/char/lrng/lrng_es_jent.c b/drivers/char/lrng/lrng_es_jent.c +new file mode 100644 +index 000000000000..e98152b4c912 --- /dev/null -+++ b/drivers/char/lrng/lrng_jent.c ++++ b/drivers/char/lrng/lrng_es_jent.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* @@ -115,8 +123,8 @@ Signed-off-by: Stephan Mueller +static int __init lrng_jent_initialize(void) +{ + /* Initialize the Jitter RNG after the clocksources are initialized. */ -+ lrng_jent_state = jent_lrng_entropy_collector(); -+ if (!lrng_jent_state) { ++ if (jent_entropy_init() || ++ (lrng_jent_state = jent_entropy_collector_alloc(1, 0)) == NULL) { + jitterrng = 0; + pr_info("Jitter RNG unusable on current system\n"); + return 0; @@ -172,3 +180,6 @@ Signed-off-by: Stephan Mueller + return lrng_fast_noise_entropylevel((lrng_jent_initialized) ? + jitterrng : 0, requested_bits); +} +-- +2.31.1 + diff --git a/PATCH/LRNG/696-14-v41-0011-LRNG-add-SP800-90B-compliant-health-tests.patch b/PATCH/LRNG/696-14-v42-0011-LRNG-add-SP800-90B-compliant-health-tests.patch similarity index 96% rename from PATCH/LRNG/696-14-v41-0011-LRNG-add-SP800-90B-compliant-health-tests.patch rename to PATCH/LRNG/696-14-v42-0011-LRNG-add-SP800-90B-compliant-health-tests.patch index 951cc6d1b..2b03ccf46 100644 --- a/PATCH/LRNG/696-14-v41-0011-LRNG-add-SP800-90B-compliant-health-tests.patch +++ b/PATCH/LRNG/696-14-v42-0011-LRNG-add-SP800-90B-compliant-health-tests.patch @@ -1,7 +1,7 @@ -From 928e83bd2eb312c68d2e1bbaadd96a5e841eadff Mon Sep 17 00:00:00 2001 +From 0dc6dec5b9ab060d66af8e4abfe09099251b9fdf Mon Sep 17 00:00:00 2001 From: Stephan Mueller -Date: Fri, 18 Jun 2021 08:17:40 +0200 -Subject: [PATCH v41 11/13] LRNG - add SP800-90B compliant health tests +Date: Mon, 2 Aug 2021 21:59:23 +0200 +Subject: [PATCH v42 11/13] LRNG - add SP800-90B compliant health tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -124,7 +124,8 @@ CC: Andy Lutomirski CC: Florian Weimer CC: Lennart Poettering CC: Nicolai Stange -CC: Alexander Lobakin +Reviewed-by: Alexander Lobakin +Tested-by: Alexander Lobakin Reviewed-by: Roman Drahtmueller Tested-by: Marcelo Henrique Cerri Tested-by: Neil Horman @@ -136,6 +137,8 @@ Signed-off-by: Stephan Mueller 3 files changed, 467 insertions(+) create mode 100644 drivers/char/lrng/lrng_health.c +diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig +index e622b8532e2b..931959f75a83 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig @@ -164,6 +164,62 @@ config LRNG_COLLECTION_SIZE @@ -201,13 +204,18 @@ Signed-off-by: Stephan Mueller config LRNG_IRQ_ENTROPY_RATE int "Interrupt Entropy Source Entropy Rate" range 256 4294967295 +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +index 01a69172c464..02513621411b 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile -@@ -15,3 +15,4 @@ obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kc +@@ -15,3 +15,4 @@ obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.o obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o - obj-$(CONFIG_LRNG_JENT) += lrng_jent.o + obj-$(CONFIG_LRNG_JENT) += lrng_es_jent.o +obj-$(CONFIG_LRNG_HEALTH_TESTS) += lrng_health.o +diff --git a/drivers/char/lrng/lrng_health.c b/drivers/char/lrng/lrng_health.c +new file mode 100644 +index 000000000000..a56a0c4261ab --- /dev/null +++ b/drivers/char/lrng/lrng_health.c @@ -0,0 +1,410 @@ @@ -621,3 +629,6 @@ Signed-off-by: Stephan Mueller + + return lrng_health_pass; +} +-- +2.31.1 + diff --git a/PATCH/LRNG/696-15-v41-0012-LRNG-add-interface-for-gathering-of-raw-entropy.patch b/PATCH/LRNG/696-15-v42-0012-LRNG-add-interface-for-gathering-of-raw-entropy.patch similarity index 96% rename from PATCH/LRNG/696-15-v41-0012-LRNG-add-interface-for-gathering-of-raw-entropy.patch rename to PATCH/LRNG/696-15-v42-0012-LRNG-add-interface-for-gathering-of-raw-entropy.patch index f4bf5c423..5068525a1 100644 --- a/PATCH/LRNG/696-15-v41-0012-LRNG-add-interface-for-gathering-of-raw-entropy.patch +++ b/PATCH/LRNG/696-15-v42-0012-LRNG-add-interface-for-gathering-of-raw-entropy.patch @@ -1,7 +1,7 @@ -From 95f1ae07c94a30f083eb24c57bf15b3f0fff12c2 Mon Sep 17 00:00:00 2001 +From 4e03f13da1abe7b547fcc31e0d7bf1888663fb7d Mon Sep 17 00:00:00 2001 From: Stephan Mueller -Date: Fri, 18 Jun 2021 08:23:31 +0200 -Subject: [PATCH v41 12/13] LRNG - add interface for gathering of raw entropy +Date: Mon, 2 Aug 2021 22:08:30 +0200 +Subject: [PATCH v42 12/13] LRNG - add interface for gathering of raw entropy The test interface allows a privileged process to capture the raw unconditioned noise that is collected by the LRNG for statistical @@ -74,21 +74,24 @@ CC: Andy Lutomirski CC: Florian Weimer CC: Lennart Poettering CC: Nicolai Stange -CC: Alexander Lobakin +Reviewed-by: Alexander Lobakin +Tested-by: Alexander Lobakin Reviewed-by: Roman Drahtmueller Tested-by: Marcelo Henrique Cerri Tested-by: Neil Horman Signed-off-by: Stephan Mueller --- - drivers/char/lrng/Kconfig | 162 ++++++++ + drivers/char/lrng/Kconfig | 170 ++++++++ drivers/char/lrng/Makefile | 1 + drivers/char/lrng/lrng_testing.c | 689 +++++++++++++++++++++++++++++++ - 3 files changed, 852 insertions(+) + 3 files changed, 860 insertions(+) create mode 100644 drivers/char/lrng/lrng_testing.c +diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig +index 931959f75a83..32692aff9774 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig -@@ -323,4 +323,166 @@ config LRNG_KCAPI +@@ -323,4 +323,174 @@ config LRNG_KCAPI provided by the selected kernel crypto API RNG. endif # LRNG_DRNG_SWITCH @@ -248,6 +251,14 @@ Signed-off-by: Stephan Mueller + lrng_jent.jitterrng for the Jitter RNG entropy source, and + lrng_sw_noise.irq_entropy for the interrupt entropy source. + ++config LRNG_RUNTIME_MAX_WO_RESEED_CONFIG ++ bool "Enable runtime configuration of max reseed threshold" ++ help ++ When enabling this option, the LRNG provides an interface ++ allowing the setting of the maximum number of DRNG generate ++ operations without a reseed that has full entropy. The ++ interface is lrng_drng.max_wo_reseed. ++ +config LRNG_TESTING + bool + default y if (LRNG_RAW_HIRES_ENTROPY || LRNG_RAW_JIFFIES_ENTROPY ||LRNG_RAW_IRQ_ENTROPY || LRNG_RAW_IRQFLAGS_ENTROPY || LRNG_RAW_RETIP_ENTROPY || LRNG_RAW_REGS_ENTROPY || LRNG_RAW_ARRAY || LRNG_IRQ_PERF || LRNG_ACVT_HASH) @@ -255,13 +266,18 @@ Signed-off-by: Stephan Mueller +endif #LRNG_TESTING_MENU + endif # LRNG +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +index 02513621411b..919c85cd103a 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile @@ -16,3 +16,4 @@ obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o - obj-$(CONFIG_LRNG_JENT) += lrng_jent.o + obj-$(CONFIG_LRNG_JENT) += lrng_es_jent.o obj-$(CONFIG_LRNG_HEALTH_TESTS) += lrng_health.o +obj-$(CONFIG_LRNG_TESTING) += lrng_testing.o +diff --git a/drivers/char/lrng/lrng_testing.c b/drivers/char/lrng/lrng_testing.c +new file mode 100644 +index 000000000000..99cc35abf45c --- /dev/null +++ b/drivers/char/lrng/lrng_testing.c @@ -0,0 +1,689 @@ @@ -954,3 +970,6 @@ Signed-off-by: Stephan Mueller +} + +module_init(lrng_raw_init); +-- +2.31.1 + diff --git a/PATCH/LRNG/696-16-v41-0013-LRNG-add-power-on-and-runtime-self-tests.patch b/PATCH/LRNG/696-16-v42-0013-LRNG-add-power-on-and-runtime-self-tests.patch similarity index 92% rename from PATCH/LRNG/696-16-v41-0013-LRNG-add-power-on-and-runtime-self-tests.patch rename to PATCH/LRNG/696-16-v42-0013-LRNG-add-power-on-and-runtime-self-tests.patch index 3d37618a8..49a3c183e 100644 --- a/PATCH/LRNG/696-16-v41-0013-LRNG-add-power-on-and-runtime-self-tests.patch +++ b/PATCH/LRNG/696-16-v42-0013-LRNG-add-power-on-and-runtime-self-tests.patch @@ -1,7 +1,7 @@ -From 142c1cde7b3e57796ff5ed0bc17e3f9d92f123d5 Mon Sep 17 00:00:00 2001 +From 23983cc15570a566e4f095dadcbc9353f7d892eb Mon Sep 17 00:00:00 2001 From: Stephan Mueller -Date: Fri, 18 Jun 2021 08:26:24 +0200 -Subject: [PATCH v41 13/13] LRNG - add power-on and runtime self-tests +Date: Mon, 2 Aug 2021 22:01:09 +0200 +Subject: [PATCH v42 13/13] LRNG - add power-on and runtime self-tests Parts of the LRNG are already covered by self-tests, including: @@ -64,15 +64,18 @@ CC: Lennart Poettering CC: Nicolai Stange CC: Marcelo Henrique Cerri CC: Neil Horman -CC: Alexander Lobakin +Reviewed-by: Alexander Lobakin +Tested-by: Alexander Lobakin Signed-off-by: Stephan Mueller --- drivers/char/lrng/Kconfig | 43 +++- drivers/char/lrng/Makefile | 1 + - drivers/char/lrng/lrng_selftest.c | 351 ++++++++++++++++++++++++++++++ - 3 files changed, 387 insertions(+), 8 deletions(-) + drivers/char/lrng/lrng_selftest.c | 369 ++++++++++++++++++++++++++++++ + 3 files changed, 405 insertions(+), 8 deletions(-) create mode 100644 drivers/char/lrng/lrng_selftest.c +diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig +index 32692aff9774..de50abaf53cb 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig @@ -165,15 +165,16 @@ config LRNG_COLLECTION_SIZE @@ -100,7 +103,7 @@ Signed-off-by: Stephan Mueller If unsure, say Y. -@@ -485,4 +486,30 @@ config LRNG_TESTING +@@ -493,4 +494,30 @@ config LRNG_TESTING endif #LRNG_TESTING_MENU @@ -131,16 +134,21 @@ Signed-off-by: Stephan Mueller +endif # LRNG_SELFTEST + endif # LRNG +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +index 919c85cd103a..623813764aca 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o - obj-$(CONFIG_LRNG_JENT) += lrng_jent.o + obj-$(CONFIG_LRNG_JENT) += lrng_es_jent.o obj-$(CONFIG_LRNG_HEALTH_TESTS) += lrng_health.o obj-$(CONFIG_LRNG_TESTING) += lrng_testing.o +obj-$(CONFIG_LRNG_SELFTEST) += lrng_selftest.o +diff --git a/drivers/char/lrng/lrng_selftest.c b/drivers/char/lrng/lrng_selftest.c +new file mode 100644 +index 000000000000..e219f7ea832b --- /dev/null +++ b/drivers/char/lrng/lrng_selftest.c -@@ -0,0 +1,351 @@ +@@ -0,0 +1,369 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* + * LRNG power-on and on-demand self-test @@ -173,12 +181,13 @@ Signed-off-by: Stephan Mueller + +#include "lrng_chacha20.h" +#include "lrng_internal.h" -+#include "lrng_sw_noise.h" ++#include "lrng_es_irq.h" + +#define LRNG_SELFTEST_PASSED 0 +#define LRNG_SEFLTEST_ERROR_TIME (1 << 0) +#define LRNG_SEFLTEST_ERROR_CHACHA20 (1 << 1) +#define LRNG_SEFLTEST_ERROR_HASH (1 << 2) ++#define LRNG_SEFLTEST_ERROR_GCD (1 << 3) +#define LRNG_SELFTEST_NOT_EXECUTED 0xffffffff + +static u32 lrng_data_selftest_ptr = 0; @@ -449,12 +458,29 @@ Signed-off-by: Stephan Mueller + return LRNG_SEFLTEST_ERROR_CHACHA20; +} + ++static unsigned int lrng_gcd_selftest(void) ++{ ++ u32 history[10]; ++ unsigned int i; ++ ++#define LRNG_GCD_SELFTEST 3 ++ for (i = 0; i < ARRAY_SIZE(history); i++) ++ history[i] = i * LRNG_GCD_SELFTEST; ++ ++ if (lrng_gcd_analyze(history, ARRAY_SIZE(history)) == LRNG_GCD_SELFTEST) ++ return LRNG_SELFTEST_PASSED; ++ ++ pr_err("LRNG GCD self-test FAILED\n"); ++ return LRNG_SEFLTEST_ERROR_GCD; ++} ++ +static int lrng_selftest(void) +{ + unsigned int ret = lrng_data_process_selftest(); + + ret |= lrng_chacha20_drng_selftest(); + ret |= lrng_hash_selftest(); ++ ret |= lrng_gcd_selftest(); + + if (ret) { + if (IS_ENABLED(CONFIG_LRNG_SELFTEST_PANIC)) @@ -492,3 +518,6 @@ Signed-off-by: Stephan Mueller +} + +module_init(lrng_selftest_init); +-- +2.31.1 + diff --git a/PATCH/LRNG/696-17-v41-01-remove_compat_ioctl.patch b/PATCH/LRNG/696-17-v42-01-remove_compat_ioctl.patch similarity index 100% rename from PATCH/LRNG/696-17-v41-01-remove_compat_ioctl.patch rename to PATCH/LRNG/696-17-v42-01-remove_compat_ioctl.patch diff --git a/PATCH/LRNG/696-18-v41-02-jitterentropy_remove_RCT_APT.patch b/PATCH/LRNG/696-18-v41-02-jitterentropy_remove_RCT_APT.patch deleted file mode 100644 index 80b85e462..000000000 --- a/PATCH/LRNG/696-18-v41-02-jitterentropy_remove_RCT_APT.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- a/crypto/jitterentropy.c -+++ b/crypto/jitterentropy.c -@@ -655,12 +655,6 @@ struct rand_data *jent_lrng_entropy_coll - .memblocks = JENT_MEMORY_BLOCKSIZE, - .memblocksize = JENT_MEMORY_BLOCKS, - .memaccessloops = JENT_MEMORY_ACCESSLOOPS, -- .rct_count = 0, -- .apt_observations = 0, -- .apt_count = 0, -- .apt_base = 0, -- .apt_base_set = 0, -- .health_failure = 0 - }; - - if (jent_entropy_init()) diff --git a/PATCH/LRNG/696-19-v41-03-arch_random_early.patch b/PATCH/LRNG/696-18-v42-03-arch_random_early.patch similarity index 85% rename from PATCH/LRNG/696-19-v41-03-arch_random_early.patch rename to PATCH/LRNG/696-18-v42-03-arch_random_early.patch index 73fa9f53e..156bbbf46 100644 --- a/PATCH/LRNG/696-19-v41-03-arch_random_early.patch +++ b/PATCH/LRNG/696-18-v42-03-arch_random_early.patch @@ -1,5 +1,5 @@ ---- a/drivers/char/lrng/lrng_pool.c -+++ b/drivers/char/lrng/lrng_pool.c +--- a/drivers/char/lrng/lrng_es_mgr.c ++++ b/drivers/char/lrng/lrng_es_mgr.c @@ -324,8 +324,8 @@ int __init rand_initialize(void) seed.time = ktime_get_real(); diff --git a/PATCH/LRNG/696-20-v41-04-net_rand_state.patch b/PATCH/LRNG/696-19-v42-04-net_rand_state.patch similarity index 59% rename from PATCH/LRNG/696-20-v41-04-net_rand_state.patch rename to PATCH/LRNG/696-19-v42-04-net_rand_state.patch index f066f1e4e..c3e2392c9 100644 --- a/PATCH/LRNG/696-20-v41-04-net_rand_state.patch +++ b/PATCH/LRNG/696-19-v42-04-net_rand_state.patch @@ -1,5 +1,5 @@ ---- a/drivers/char/lrng/lrng_sw_noise.c -+++ b/drivers/char/lrng/lrng_sw_noise.c +--- a/drivers/char/lrng/lrng_es_irq.c ++++ b/drivers/char/lrng/lrng_es_irq.c @@ -12,6 +12,7 @@ #include #include @@ -7,4 +7,4 @@ +#include #include "lrng_internal.h" - #include "lrng_sw_noise.h" + #include "lrng_es_irq.h" diff --git a/PATCH/LRNG/696-21-v41-05-kzfree.patch b/PATCH/LRNG/696-20-v42-05-kzfree.patch similarity index 100% rename from PATCH/LRNG/696-21-v41-05-kzfree.patch rename to PATCH/LRNG/696-20-v42-05-kzfree.patch diff --git a/PATCH/LRNG/696-22-v41-06-sha-includes.patch b/PATCH/LRNG/696-21-v42-06-sha-includes.patch similarity index 100% rename from PATCH/LRNG/696-22-v41-06-sha-includes.patch rename to PATCH/LRNG/696-21-v42-06-sha-includes.patch diff --git a/PATCH/LRNG/696-22-v42-07-chacha_constants.patch b/PATCH/LRNG/696-22-v42-07-chacha_constants.patch new file mode 100644 index 000000000..572fbab8c --- /dev/null +++ b/PATCH/LRNG/696-22-v42-07-chacha_constants.patch @@ -0,0 +1,13 @@ +--- linux-5.10/drivers/char/lrng/lrng_chacha20.h.orig 2021-08-20 21:16:45.569017375 +0200 ++++ linux-5.10/drivers/char/lrng/lrng_chacha20.h 2021-08-20 21:18:21.255462479 +0200 +@@ -21,5 +21,9 @@ struct chacha20_block { + + static inline void lrng_cc20_init_rfc7539(struct chacha20_block *chacha20) + { +- chacha_init_consts(chacha20->constants); ++ /* String "expand 32-byte k" */ ++ chacha20->constants[0] = 0x61707865; ++ chacha20->constants[1] = 0x3320646e; ++ chacha20->constants[2] = 0x79622d32; ++ chacha20->constants[3] = 0x6b206574; + } From a7d95d6de76b7969fc37c39dc1e4402627da16a7 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Fri, 17 Sep 2021 23:40:34 +0800 Subject: [PATCH 197/244] Adapt to upstream change --- .github/workflows/R2C-OpenWrt.yml | 4 --- SCRIPTS/01_get_ready.sh | 35 +++++++++++++---------- SCRIPTS/02_prepare_package.sh | 46 +++++++++++++++++-------------- SCRIPTS/X86/02_target_only.sh | 8 ++++-- SEED/R2C/config.seed | 2 ++ SEED/R2S/config.seed | 2 ++ SEED/R4S/config.seed | 2 ++ SEED/X86/config.seed | 2 ++ 8 files changed, 59 insertions(+), 42 deletions(-) diff --git a/.github/workflows/R2C-OpenWrt.yml b/.github/workflows/R2C-OpenWrt.yml index d9d848f2c..104958eaf 100644 --- a/.github/workflows/R2C-OpenWrt.yml +++ b/.github/workflows/R2C-OpenWrt.yml @@ -56,10 +56,6 @@ jobs: - name: Prepare Package run: | cd openwrt - rm -rf target/linux/rockchip - svn co https://github.com/immortalwrt/immortalwrt/branches/master/target/linux/rockchip target/linux/rockchip - rm -rf package/boot - svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/boot package/boot cp -r ../SCRIPTS/. ./ /bin/bash 02_prepare_package.sh /bin/bash 02_target_only.sh diff --git a/SCRIPTS/01_get_ready.sh b/SCRIPTS/01_get_ready.sh index 89a283398..b007dd7e4 100644 --- a/SCRIPTS/01_get_ready.sh +++ b/SCRIPTS/01_get_ready.sh @@ -1,24 +1,29 @@ #!/bin/bash -latest_release="$(curl -s https://github.com/openwrt/openwrt/releases |grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" |sed -n '/21/p' |sed -n 1p |sed 's/.tar.gz//g')" -git clone --single-branch -b ${latest_release} https://github.com/openwrt/openwrt openwrt_back -git clone --single-branch -b openwrt-21.02 https://github.com/openwrt/openwrt openwrt_new -rm -f ./openwrt_new/include/version.mk -rm -f ./openwrt_new/include/kernel-version.mk -rm -f ./openwrt_new/package/base-files/image-config.in -rm -rf ./openwrt_new/target/linux/* -cp -f ./openwrt_back/include/version.mk ./openwrt_new/include/version.mk -cp -f ./openwrt_back/include/kernel-version.mk ./openwrt_new/include/kernel-version.mk -cp -f ./openwrt_back/package/base-files/image-config.in ./openwrt_new/package/base-files/image-config.in -cp -rf ./openwrt_back/target/linux/* ./openwrt_new/target/linux/ -mkdir openwrt -cp -rf ./openwrt_new/* ./openwrt/ +latest_release="$(curl -s https://github.com/openwrt/openwrt/releases | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/21/p' | sed -n 1p | sed 's/.tar.gz//g')" +git clone --single-branch -b ${latest_release} https://github.com/openwrt/openwrt openwrt_release +git clone --single-branch -b openwrt-21.02 https://github.com/openwrt/openwrt openwrt +rm -f ./openwrt/include/version.mk +rm -f ./openwrt/include/kernel.mk +rm -f ./openwrt/include/kernel-version.mk +rm -f ./openwrt/include/toolchain-build.mk +rm -f ./openwrt/include/kernel-defaults.mk +rm -f ./openwrt/package/base-files/image-config.in +rm -rf ./openwrt/target/linux/* +cp -f ./openwrt_release/include/version.mk ./openwrt/include/version.mk +cp -f ./openwrt_release/include/kernel.mk ./openwrt/include/kernel.mk +cp -f ./openwrt_release/include/kernel-version.mk ./openwrt/include/kernel-version.mk +cp -f ./openwrt_release/include/toolchain-build.mk ./openwrt/include/toolchain-build.mk +cp -f ./openwrt_release/include/kernel-defaults.mk ./openwrt/include/kernel-defaults.mk +cp -f ./openwrt_release/package/base-files/image-config.in ./openwrt/package/base-files/image-config.in +cp -f ./openwrt_release/version ./openwrt/version +cp -f ./openwrt_release/version.date ./openwrt/version.date +cp -rf ./openwrt_release/target/linux/* ./openwrt/target/linux/ # 获取源代码 -#git clone --single-branch -b openwrt-21.02 https://github.com/openwrt/openwrt openwrt #git clone -b main --depth 1 https://github.com/Lienol/openwrt.git openwrt-lienol #git clone -b main --depth 1 https://github.com/Lienol/openwrt-packages packages-lienol #git clone -b main --depth 1 https://github.com/Lienol/openwrt-luci luci-lienol #git clone -b linksys-ea6350v3-mastertrack --depth 1 https://github.com/NoTengoBattery/openwrt NoTengoBattery -exit 0 +exit 0 \ No newline at end of file diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 342c0b04a..ed1ceb8bc 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -23,7 +23,7 @@ echo "net.netfilter.nf_conntrack_helper = 1" >> ./package/kernel/linux/files/sys ### 必要的 Patches ### # Patch arm64 型号名称 -wget -P target/linux/generic/hack-5.4/ https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/generic/hack-5.4/312-arm64-cpuinfo-Add-model-name-in-proc-cpuinfo-for-64bit-ta.patch +wget -P target/linux/generic/hack-5.4/ https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/target/linux/generic/hack-5.4/312-arm64-cpuinfo-Add-model-name-in-proc-cpuinfo-for-64bit-ta.patch # Patch jsonc patch -p1 < ../PATCH/jsonc/use_json_object_new_int64.patch # Patch dnsmasq @@ -59,7 +59,7 @@ wget -qO - https://github.com/mj22226/openwrt/commit/5e10633.patch | patch -p1 ### Fullcone-NAT 部分 ### # Patch Kernel 以解决 FullCone 冲突 pushd target/linux/generic/hack-5.4 -wget https://github.com/immortalwrt/immortalwrt/raw/master/target/linux/generic/hack-5.4/952-net-conntrack-events-support-multiple-registrant.patch +wget https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/target/linux/generic/hack-5.4/952-net-conntrack-events-support-multiple-registrant.patch popd # Patch FireWall 以增添 FullCone 功能 mkdir package/network/config/firewall/patches @@ -73,18 +73,17 @@ svn co https://github.com/Lienol/openwrt/trunk/package/network/fullconenat packa ### 获取额外的基础软件包 ### # 更换为 ImmortalWrt Uboot 以及 Target rm -rf ./target/linux/rockchip -svn co https://github.com/immortalwrt/immortalwrt/branches/master/target/linux/rockchip target/linux/rockchip +svn co https://github.com/immortalwrt/immortalwrt/branches/openwrt-21.02/target/linux/rockchip target/linux/rockchip rm -rf ./package/boot/uboot-rockchip -svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/boot/uboot-rockchip package/boot/uboot-rockchip -svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/boot/arm-trusted-firmware-rockchip-vendor package/boot/arm-trusted-firmware-rockchip-vendor +svn co https://github.com/immortalwrt/immortalwrt/branches/openwrt-21.02/package/boot/uboot-rockchip package/boot/uboot-rockchip +svn co https://github.com/immortalwrt/immortalwrt/branches/openwrt-21.02/package/boot/arm-trusted-firmware-rockchip-vendor package/boot/arm-trusted-firmware-rockchip-vendor rm -rf ./package/kernel/linux/modules/video.mk -wget -P package/kernel/linux/modules/ https://github.com/immortalwrt/immortalwrt/raw/master/package/kernel/linux/modules/video.mk +wget -P package/kernel/linux/modules/ https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/package/kernel/linux/modules/video.mk # R4S超频到 2.2/1.8 GHz rm -rf ./target/linux/rockchip/patches-5.4/992-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch cp -f ../PATCH/target_r4s/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch ./target/linux/rockchip/patches-5.4/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch cp -f ../PATCH/target_r4s/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch ./target/linux/rockchip/patches-5.4/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch # Disable Mitigations -https://github.com/immortalwrt/immortalwrt/tree/master/target/linux/rockchip/image sed -i 's,rootwait,rootwait mitigations=off,g' target/linux/rockchip/image/mmc.bootscript sed -i 's,rootwait,rootwait mitigations=off,g' target/linux/rockchip/image/nanopi-r2s.bootscript sed -i 's,rootwait,rootwait mitigations=off,g' target/linux/rockchip/image/nanopi-r4s.bootscript @@ -92,7 +91,7 @@ sed -i 's,noinitrd,noinitrd mitigations=off,g' target/linux/x86/image/grub-efi.c sed -i 's,noinitrd,noinitrd mitigations=off,g' target/linux/x86/image/grub-iso.cfg sed -i 's,noinitrd,noinitrd mitigations=off,g' target/linux/x86/image/grub-pc.cfg # AutoCore -svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/emortal/autocore package/lean/autocore +svn co https://github.com/immortalwrt/immortalwrt/branches/openwrt-21.02/package/emortal/autocore package/lean/autocore rm -rf ./feeds/packages/utils/coremark svn co https://github.com/immortalwrt/packages/trunk/utils/coremark feeds/packages/utils/coremark # 更换 Nodejs 版本 @@ -138,7 +137,10 @@ svn co https://github.com/openwrt/packages/trunk/net/adguardhome feeds/packages/ sed -i '/\t)/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/AdGuardHome' ./feeds/packages/net/adguardhome/Makefile sed -i '/init/d' feeds/packages/net/adguardhome/Makefile # Argon 主题 -git clone -b master --depth 1 https://github.com/jerrykuku/luci-theme-argon.git package/new/luci-theme-argon +git clone https://github.com/jerrykuku/luci-theme-argon.git package/new/luci-theme-argon +pushd package/new/luci-theme-argon +git checkout 3b15d06 +popd git clone -b master --depth 1 https://github.com/jerrykuku/luci-app-argon-config.git package/new/luci-app-argon-config # MAC 地址与 IP 绑定 svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-arpbind feeds/luci/applications/luci-app-arpbind @@ -162,8 +164,8 @@ svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/luci-app-cpulimit package/ svn co https://github.com/immortalwrt/packages/trunk/utils/cpulimit feeds/packages/utils/cpulimit ln -sf ../../../feeds/packages/utils/cpulimit ./package/feeds/packages/cpulimit # 动态DNS -git clone --depth 1 https://github.com/small-5/ddns-scripts-dnspod package/lean/ddns-scripts_dnspod -git clone --depth 1 https://github.com/small-5/ddns-scripts-aliyun package/lean/ddns-scripts_aliyun +svn co https://github.com/kiddin9/openwrt-packages/trunk/ddns-scripts-aliyun package/lean/ddns-scripts_dnspod +svn co https://github.com/kiddin9/openwrt-packages/trunk/ddns-scripts-dnspod package/lean/ddns-scripts_aliyun svn co https://github.com/QiuSimons/OpenWrt_luci-app/trunk/luci-app-tencentddns package/lean/luci-app-tencentddns svn co https://github.com/kenzok8/openwrt-packages/trunk/luci-app-aliddns feeds/luci/applications/luci-app-aliddns ln -sf ../../../feeds/luci/applications/luci-app-aliddns ./package/feeds/luci/luci-app-aliddns @@ -200,7 +202,10 @@ git clone --depth 1 https://github.com/KyleRicardo/MentoHUST-OpenWrt-ipk package svn co https://github.com/QiuSimons/openwrt-packages/branches/main/mos-chinadns package/new/mos-chinadns svn co https://github.com/QiuSimons/openwrt-packages/branches/main/luci-app-moschinadns package/new/luci-app-moschinadns # Mosdns -svn co https://github.com/QiuSimons/openwrt-mos/trunk/mosdns package/new/mosdns +svn co https://github.com/immortalwrt/packages/trunk/net/mosdns feeds/packages/net/mosdns +ln -sf ../../../feeds/packages/net/mosdns ./package/feeds/packages/mosdns +sed -i '/config.yaml/d' feeds/packages/net/mosdns/Makefile +sed -i '/mosdns-init-openwrt/d' feeds/packages/net/mosdns/Makefile svn co https://github.com/QiuSimons/openwrt-mos/trunk/luci-app-mosdns package/new/luci-app-mosdns # 流量监管 svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-netdata package/lean/luci-app-netdata @@ -219,8 +224,9 @@ svn co https://github.com/QiuSimons/dragino2-teasiu/trunk/package/teasiu/luci-ap # Passwall svn co https://github.com/xiaorouji/openwrt-passwall/trunk/luci-app-passwall package/new/luci-app-passwall sed -i 's,default n,default y,g' package/new/luci-app-passwall/Makefile -sed -i '/V2ray:v2ray/d' package/new/luci-app-passwall/Makefile -sed -i '/plugin:v2ray/d' package/new/luci-app-passwall/Makefile +sed -i '/Trojan_GO:/d' package/new/luci-app-passwall/Makefile +sed -i '/V2ray:/d' package/new/luci-app-passwall/Makefile +sed -i '/V2ray_Plugin:/d' package/new/luci-app-passwall/Makefile wget -P package/new/luci-app-passwall/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/move_2_services.sh chmod -R 755 ./package/new/luci-app-passwall/move_2_services.sh pushd package/new/luci-app-passwall @@ -277,15 +283,13 @@ ln -sf ../../../feeds/packages/net/kcptun ./package/feeds/packages/kcptun svn co https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/lean/luci-app-ssr-plus rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans pushd package/lean -wget -qO - https://github.com/fw876/helloworld/pull/645.patch | patch -p1 +wget -qO - https://github.com/fw876/helloworld/pull/656.patch | patch -p1 wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/5bbf6e7.patch | patch -p1 wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/323fbf0.patch | patch -p1 popd pushd package/lean/luci-app-ssr-plus sed -i 's,default n,default y,g' Makefile -sed -i 's,Xray:xray ,Xray:xray-core ,g' Makefile -sed -i '/V2ray:v2ray/d' Makefile -sed -i '/plugin:v2ray/d' Makefile +sed -i '/Plugin:/d' Makefile sed -i '/result.encrypt_method/a\result.fast_open = "1"' root/usr/share/shadowsocksr/subscribe.lua sed -i 's,ispip.clang.cn/all_cn,cdn.jsdelivr.net/gh/QiuSimons/Chnroute@master/dist/chnroute/chnroute,' root/etc/init.d/shadowsocksr sed -i 's,YW5vbnltb3Vz/domain-list-community/release/gfwlist.txt,Loyalsoldier/v2ray-rules-dat/release/gfw.txt,' root/etc/init.d/shadowsocksr @@ -304,6 +308,8 @@ svn co https://github.com/immortalwrt/packages/trunk/libs/libcron feeds/packages ln -sf ../../../feeds/packages/libs/libcron ./package/feeds/packages/libcron svn co https://github.com/immortalwrt/packages/trunk/libs/quickjspp feeds/packages/libs/quickjspp ln -sf ../../../feeds/packages/libs/quickjspp ./package/feeds/packages/quickjspp +svn co https://github.com/immortalwrt/packages/trunk/libs/toml11 feeds/packages/libs/toml11 +ln -sf ../../../feeds/packages/libs/toml11 ./package/feeds/packages/toml11 # 网易云音乐解锁 git clone --depth 1 https://github.com/immortalwrt/luci-app-unblockneteasemusic.git package/new/UnblockNeteaseMusic # USB 打印机 @@ -318,8 +324,8 @@ svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/vlmcsd package/le git clone -b master --depth 1 https://github.com/jerrykuku/luci-app-vssr.git package/lean/luci-app-vssr git clone -b master --depth 1 https://github.com/jerrykuku/lua-maxminddb.git package/lean/lua-maxminddb sed -i 's,default n,default y,g' package/lean/luci-app-vssr/Makefile -sed -i '/V2ray:v2ray/d' package/lean/luci-app-vssr/Makefile -sed -i '/plugin:v2ray/d' package/lean/luci-app-vssr/Makefile +sed -i '/Xray_plugin:/d' package/lean/luci-app-vssr/Makefile +#sed -i '/plugin:v2ray/d' package/lean/luci-app-vssr/Makefile sed -i '/result.encrypt_method/a\result.fast_open = "1"' package/lean/luci-app-vssr/root/usr/share/vssr/subscribe.lua sed -i 's,ispip.clang.cn/all_cn.txt,raw.sevencdn.com/QiuSimons/Chnroute/master/dist/chnroute/chnroute.txt,g' package/lean/luci-app-vssr/luasrc/controller/vssr.lua sed -i 's,ispip.clang.cn/all_cn.txt,raw.sevencdn.com/QiuSimons/Chnroute/master/dist/chnroute/chnroute.txt,g' package/lean/luci-app-vssr/root/usr/share/vssr/update.lua diff --git a/SCRIPTS/X86/02_target_only.sh b/SCRIPTS/X86/02_target_only.sh index a513cfa69..7fc74d84c 100644 --- a/SCRIPTS/X86/02_target_only.sh +++ b/SCRIPTS/X86/02_target_only.sh @@ -1,9 +1,11 @@ #!/bin/bash # 在 X86 架构下移除 Shadowsocks-rust -sed -i '/Rust:/d' package/lean/luci-app-ssr-plus/Makefile -sed -i '/Rust:/d' package/new/luci-app-passwall/Makefile -sed -i '/Rust:/d' package/lean/luci-app-vssr/Makefile +sed -i '/Rust_Client:/d' package/lean/luci-app-ssr-plus/Makefile +sed -i '/Rust_Server:/d' package/lean/luci-app-ssr-plus/Makefile +sed -i '/Rust_Client:/d' package/new/luci-app-passwall/Makefile +sed -i '/Rust_Server:/d' package/new/luci-app-passwall/Makefile +#sed -i '/Rust:/d' package/lean/luci-app-vssr/Makefile # 内核加解密组件 echo ' diff --git a/SEED/R2C/config.seed b/SEED/R2C/config.seed index d691b5cdc..b43ba95f1 100644 --- a/SEED/R2C/config.seed +++ b/SEED/R2C/config.seed @@ -117,6 +117,8 @@ CONFIG_PACKAGE_luci-app-sqm=y CONFIG_PACKAGE_luci-app-vlmcsd=y CONFIG_PACKAGE_luci-app-vssr=y CONFIG_PACKAGE_luci-app-ssr-plus=y +# CONFIG_PACKAGE_luci-app-ssr-plus_INCLUDE_libustream-wolfssl is not set +CONFIG_PACKAGE_luci-app-ssr-plus_INCLUDE_libustream-openssl=y CONFIG_PACKAGE_luci-app-passwall=y CONFIG_PACKAGE_luci-app-unblockneteasemusic=y CONFIG_PACKAGE_luci-app-upnp=y diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index ba87c0067..51ec413ad 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -117,6 +117,8 @@ CONFIG_PACKAGE_luci-app-sqm=y CONFIG_PACKAGE_luci-app-vlmcsd=y CONFIG_PACKAGE_luci-app-vssr=y CONFIG_PACKAGE_luci-app-ssr-plus=y +# CONFIG_PACKAGE_luci-app-ssr-plus_INCLUDE_libustream-wolfssl is not set +CONFIG_PACKAGE_luci-app-ssr-plus_INCLUDE_libustream-openssl=y CONFIG_PACKAGE_luci-app-passwall=y CONFIG_PACKAGE_luci-app-unblockneteasemusic=y CONFIG_PACKAGE_luci-app-upnp=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index c1133c676..e8f322737 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -117,6 +117,8 @@ CONFIG_PACKAGE_luci-app-sqm=y CONFIG_PACKAGE_luci-app-vlmcsd=y CONFIG_PACKAGE_luci-app-vssr=y CONFIG_PACKAGE_luci-app-ssr-plus=y +# CONFIG_PACKAGE_luci-app-ssr-plus_INCLUDE_libustream-wolfssl is not set +CONFIG_PACKAGE_luci-app-ssr-plus_INCLUDE_libustream-openssl=y CONFIG_PACKAGE_luci-app-passwall=y CONFIG_PACKAGE_luci-app-unblockneteasemusic=y CONFIG_PACKAGE_luci-app-upnp=y diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index 093345927..9dcdcf87f 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -117,6 +117,8 @@ CONFIG_PACKAGE_luci-app-sqm=y CONFIG_PACKAGE_luci-app-vlmcsd=y CONFIG_PACKAGE_luci-app-vssr=y CONFIG_PACKAGE_luci-app-ssr-plus=y +# CONFIG_PACKAGE_luci-app-ssr-plus_INCLUDE_libustream-wolfssl is not set +CONFIG_PACKAGE_luci-app-ssr-plus_INCLUDE_libustream-openssl=y CONFIG_PACKAGE_luci-app-passwall=y CONFIG_PACKAGE_luci-app-unblockneteasemusic=y CONFIG_PACKAGE_luci-app-upnp=y From 4d9a058aa55b26cd7cd187f731d4b8d4f7e619a1 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 28 Sep 2021 12:36:24 +0800 Subject: [PATCH 198/244] Patche refresh --- ...Rv2_congestion_control_for_Linux_TCP.patch | 113 +++++++----------- ...2-0001-Linux-Random-Number-Generator.patch | 57 +-------- ...cate-one-DRNG-instance-per-NUMA-node.patch | 8 -- ...0003-LRNG-sysctls-and-proc-interface.patch | 12 +- ...004-LRNG-add-switchable-DRNG-support.patch | 10 -- ...LRNG-add-common-generic-hash-support.patch | 13 -- ...-externalize-DRBG-functions-for-LRNG.patch | 27 ++--- ...07-LRNG-add-SP800-90A-DRBG-extension.patch | 10 -- ...add-kernel-crypto-API-PRNG-extension.patch | 10 -- ...o-move-Jitter-RNG-header-include-dir.patch | 67 ++++++++--- ...RNG-add-Jitter-RNG-fast-noise-source.patch | 12 +- ...add-SP800-90B-compliant-health-tests.patch | 12 +- ...terface-for-gathering-of-raw-entropy.patch | 10 -- ...-add-power-on-and-runtime-self-tests.patch | 10 -- .../696-18-v42-03-arch_random_early.patch | 2 +- PATCH/LRNG/696-19-v42-04-net_rand_state.patch | 4 +- .../LRNG/696-22-v42-07-chacha_constants.patch | 4 +- PATCH/UKSM/695-uksm-5.4.patch | 109 +++++------------ .../dnsmasq/900-add-filter-aaaa-option.patch | 25 ++-- ...and-GCM-with-ARMv8-Crypto-Extensions.patch | 65 +++++----- ...U-temperature-for-thermal-throttling.patch | 6 +- ...overclock-to-2.2-1.8-GHz-for-NanoPi4.patch | 2 +- SCRIPTS/02_prepare_package.sh | 16 ++- SEED/R2C/config.seed | 2 +- SEED/R2S/config.seed | 2 +- SEED/R4S/config.seed | 2 +- SEED/X86/config.seed | 2 +- 27 files changed, 198 insertions(+), 414 deletions(-) diff --git a/PATCH/BBRv2/693-Add_BBRv2_congestion_control_for_Linux_TCP.patch b/PATCH/BBRv2/693-Add_BBRv2_congestion_control_for_Linux_TCP.patch index 902bbfc1b..ede293434 100644 --- a/PATCH/BBRv2/693-Add_BBRv2_congestion_control_for_Linux_TCP.patch +++ b/PATCH/BBRv2/693-Add_BBRv2_congestion_control_for_Linux_TCP.patch @@ -40,11 +40,9 @@ Effort: net-tcp_bbr Origin-9xx-SHA1: 2c84098e60bed6d67dde23cd7538c51dee273102 Change-Id: I125cf26ba2a7a686f2fa5e87f4c2afceb65f7a05 --- -diff --git a/include/linux/tcp.h b/include/linux/tcp.h -index ca6f01531e64..145b15f5d07e 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h -@@ -218,6 +218,7 @@ +@@ -218,6 +218,7 @@ struct tcp_sock { u8 compressed_ack; u8 tlp_retrans:1, /* TLP is a retransmission */ unused_1:7; @@ -52,11 +50,9 @@ index ca6f01531e64..145b15f5d07e 100644 u32 chrono_start; /* Start time in jiffies of a TCP chrono */ u32 chrono_stat[3]; /* Time in jiffies for chrono_stat stats */ u8 chrono_type:2, /* current chronograph type */ -diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h -index 895546058a20..1038f192cd09 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h -@@ -138,8 +138,9 @@ +@@ -138,8 +138,9 @@ struct inet_connection_sock { u32 icsk_probes_tstamp; u32 icsk_user_timeout; @@ -68,11 +64,9 @@ index 895546058a20..1038f192cd09 100644 }; #define ICSK_TIME_RETRANS 1 /* Retransmit timer */ -diff --git a/include/net/tcp.h b/include/net/tcp.h -index 36f195fb576a..c28000be002a 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h -@@ -362,6 +362,7 @@ +@@ -362,6 +362,7 @@ static inline void tcp_dec_quickack_mode #define TCP_ECN_QUEUE_CWR 2 #define TCP_ECN_DEMAND_CWR 4 #define TCP_ECN_SEEN 8 @@ -80,7 +74,7 @@ index 36f195fb576a..c28000be002a 100644 enum tcp_tw_status { TCP_TW_SUCCESS = 0, -@@ -782,6 +783,11 @@ +@@ -782,6 +783,11 @@ static inline u32 tcp_stamp_us_delta(u64 return max_t(s64, t1 - t0, 0); } @@ -92,7 +86,7 @@ index 36f195fb576a..c28000be002a 100644 static inline u32 tcp_skb_timestamp(const struct sk_buff *skb) { return div_u64(skb->skb_mstamp_ns, NSEC_PER_SEC / TCP_TS_HZ); -@@ -849,16 +855,22 @@ +@@ -849,16 +855,22 @@ struct tcp_skb_cb { __u32 ack_seq; /* Sequence number ACK'd */ union { struct { @@ -120,7 +114,7 @@ index 36f195fb576a..c28000be002a 100644 } tx; /* only used for outgoing skbs */ union { struct inet_skb_parm h4; -@@ -1002,6 +1014,8 @@ +@@ -1002,6 +1014,8 @@ enum tcp_ca_ack_event_flags { #define TCP_CONG_NON_RESTRICTED 0x1 /* Requires ECN/ECT set on all packets */ #define TCP_CONG_NEEDS_ECN 0x2 @@ -129,7 +123,7 @@ index 36f195fb576a..c28000be002a 100644 union tcp_cc_info; -@@ -1021,8 +1035,13 @@ +@@ -1021,8 +1035,13 @@ struct ack_sample { */ struct rate_sample { u64 prior_mstamp; /* starting timestamp for interval */ @@ -143,7 +137,7 @@ index 36f195fb576a..c28000be002a 100644 long interval_us; /* time for tp->delivered to incr "delivered" */ u32 snd_interval_us; /* snd interval for delivered packets */ u32 rcv_interval_us; /* rcv interval for delivered packets */ -@@ -1033,6 +1052,7 @@ +@@ -1033,6 +1052,7 @@ struct rate_sample { bool is_app_limited; /* is sample from packet with bubble in pipe? */ bool is_retrans; /* is sample from retransmission? */ bool is_ack_delayed; /* is this (likely) a delayed ACK? */ @@ -151,7 +145,7 @@ index 36f195fb576a..c28000be002a 100644 }; struct tcp_congestion_ops { -@@ -1059,10 +1079,12 @@ +@@ -1059,10 +1079,12 @@ struct tcp_congestion_ops { u32 (*undo_cwnd)(struct sock *sk); /* hook for packet ack accounting (optional) */ void (*pkts_acked)(struct sock *sk, const struct ack_sample *sample); @@ -166,7 +160,7 @@ index 36f195fb576a..c28000be002a 100644 /* call when packets are delivered to update cwnd and pacing rate, * after all the ca_state processing. (optional) */ -@@ -1107,6 +1129,14 @@ +@@ -1107,6 +1129,14 @@ static inline char *tcp_ca_get_name_by_k } #endif @@ -181,7 +175,7 @@ index 36f195fb576a..c28000be002a 100644 static inline bool tcp_ca_needs_ecn(const struct sock *sk) { const struct inet_connection_sock *icsk = inet_csk(sk); -@@ -1132,6 +1162,7 @@ +@@ -1132,6 +1162,7 @@ static inline void tcp_ca_event(struct s } /* From tcp_rate.c */ @@ -189,11 +183,9 @@ index 36f195fb576a..c28000be002a 100644 void tcp_rate_skb_sent(struct sock *sk, struct sk_buff *skb); void tcp_rate_skb_delivered(struct sock *sk, struct sk_buff *skb, struct rate_sample *rs); -diff --git a/include/uapi/linux/inet_diag.h b/include/uapi/linux/inet_diag.h -index a1ff345b3f33..ffc88b01868d 100644 --- a/include/uapi/linux/inet_diag.h +++ b/include/uapi/linux/inet_diag.h -@@ -206,9 +206,42 @@ +@@ -206,9 +206,42 @@ struct tcp_bbr_info { __u32 bbr_cwnd_gain; /* cwnd gain shifted left 8 bits */ }; @@ -236,11 +228,9 @@ index a1ff345b3f33..ffc88b01868d 100644 + struct tcp_bbr2_info bbr2; }; #endif /* _UAPI_INET_DIAG_H_ */ -diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig -index 03381f3e12ba..a638dee76e8b 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig -@@ -655,6 +655,24 @@ +@@ -655,6 +655,24 @@ config TCP_CONG_BBR bufferbloat, policers, or AQM schemes that do not provide a delay signal. It requires the fq ("Fair Queue") pacing packet scheduler. @@ -265,7 +255,7 @@ index 03381f3e12ba..a638dee76e8b 100644 choice prompt "Default TCP congestion control" default DEFAULT_CUBIC -@@ -692,6 +710,9 @@ +@@ -692,6 +710,9 @@ choice config DEFAULT_BBR bool "BBR" if TCP_CONG_BBR=y @@ -275,7 +265,7 @@ index 03381f3e12ba..a638dee76e8b 100644 config DEFAULT_RENO bool "Reno" endchoice -@@ -716,6 +737,7 @@ +@@ -716,6 +737,7 @@ config DEFAULT_TCP_CONG default "dctcp" if DEFAULT_DCTCP default "cdg" if DEFAULT_CDG default "bbr" if DEFAULT_BBR @@ -283,11 +273,9 @@ index 03381f3e12ba..a638dee76e8b 100644 default "cubic" config TCP_MD5SIG -diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile -index d57ecfaf89d4..7f187a52156c 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile -@@ -45,6 +45,7 @@ +@@ -45,6 +45,7 @@ obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag. obj-$(CONFIG_INET_UDP_DIAG) += udp_diag.o obj-$(CONFIG_INET_RAW_DIAG) += raw_diag.o obj-$(CONFIG_TCP_CONG_BBR) += tcp_bbr.o @@ -295,9 +283,6 @@ index d57ecfaf89d4..7f187a52156c 100644 obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o obj-$(CONFIG_TCP_CONG_CDG) += tcp_cdg.o obj-$(CONFIG_TCP_CONG_CUBIC) += tcp_cubic.o -diff --git a/net/ipv4/tcp_bbr2.c b/net/ipv4/tcp_bbr2.c -new file mode 100644 -index 000000000000..875ebfef5a03 --- /dev/null +++ b/net/ipv4/tcp_bbr2.c @@ -0,0 +1,2674 @@ @@ -2975,11 +2960,9 @@ index 000000000000..875ebfef5a03 + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DESCRIPTION("TCP BBR (Bottleneck Bandwidth and RTT)"); -diff --git a/net/ipv4/tcp_bbr.c b/net/ipv4/tcp_bbr.c -index 32772d6ded4e..2d6677521575 100644 --- a/net/ipv4/tcp_bbr.c +++ b/net/ipv4/tcp_bbr.c -@@ -292,26 +292,40 @@ +@@ -292,26 +292,40 @@ static void bbr_set_pacing_rate(struct s sk->sk_pacing_rate = rate; } @@ -3032,7 +3015,7 @@ index 32772d6ded4e..2d6677521575 100644 } /* Save "last known good" cwnd so we can restore it after losses or PROBE_RTT */ -@@ -1147,7 +1161,7 @@ +@@ -1147,7 +1161,7 @@ static struct tcp_congestion_ops tcp_bbr .undo_cwnd = bbr_undo_cwnd, .cwnd_event = bbr_cwnd_event, .ssthresh = bbr_ssthresh, @@ -3041,11 +3024,9 @@ index 32772d6ded4e..2d6677521575 100644 .get_info = bbr_get_info, .set_state = bbr_set_state, }; -diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c -index 9b48aec29aca..5d41c97d9c5e 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c -@@ -2682,6 +2682,7 @@ +@@ -2682,6 +2682,7 @@ int tcp_disconnect(struct sock *sk, int tp->rx_opt.dsack = 0; tp->rx_opt.num_sacks = 0; tp->rcv_ooopack = 0; @@ -3053,11 +3034,9 @@ index 9b48aec29aca..5d41c97d9c5e 100644 /* Clean up fastopen related fields */ -diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c -index c445a81d144e..4a9a6b20d1e7 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c -@@ -179,6 +179,7 @@ +@@ -179,6 +179,7 @@ void tcp_init_congestion_control(struct const struct inet_connection_sock *icsk = inet_csk(sk); tcp_sk(sk)->prior_ssthresh = 0; @@ -3065,11 +3044,9 @@ index c445a81d144e..4a9a6b20d1e7 100644 if (icsk->icsk_ca_ops->init) icsk->icsk_ca_ops->init(sk); if (tcp_ca_needs_ecn(sk)) -diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c -index 88b987ca9ebb..c3538bd0d008 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c -@@ -284,7 +284,7 @@ +@@ -284,7 +284,7 @@ static void __tcp_ecn_check_ce(struct so tcp_enter_quickack_mode(sk, 2); break; case INET_ECN_CE: @@ -3078,7 +3055,7 @@ index 88b987ca9ebb..c3538bd0d008 100644 tcp_ca_event(sk, CA_EVENT_ECN_IS_CE); if (!(tp->ecn_flags & TCP_ECN_DEMAND_CWR)) { -@@ -295,7 +295,7 @@ +@@ -295,7 +295,7 @@ static void __tcp_ecn_check_ce(struct so tp->ecn_flags |= TCP_ECN_SEEN; break; default: @@ -3087,7 +3064,7 @@ index 88b987ca9ebb..c3538bd0d008 100644 tcp_ca_event(sk, CA_EVENT_ECN_NO_CE); tp->ecn_flags |= TCP_ECN_SEEN; break; -@@ -957,8 +957,14 @@ +@@ -957,8 +957,14 @@ void tcp_skb_mark_lost_uncond_verify(str tcp_sum_lost(tp, skb); if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_LOST|TCPCB_SACKED_ACKED))) { @@ -3102,7 +3079,7 @@ index 88b987ca9ebb..c3538bd0d008 100644 } } -@@ -1314,6 +1320,17 @@ +@@ -1314,6 +1320,17 @@ static bool tcp_shifted_skb(struct sock WARN_ON_ONCE(tcp_skb_pcount(skb) < pcount); tcp_skb_pcount_add(skb, -pcount); @@ -3120,7 +3097,7 @@ index 88b987ca9ebb..c3538bd0d008 100644 /* When we're adding to gso_segs == 1, gso_size will be zero, * in theory this shouldn't be necessary but as long as DSACK * code can come after this skb later on it's better to keep -@@ -3087,7 +3104,6 @@ +@@ -3087,7 +3104,6 @@ static int tcp_clean_rtx_queue(struct so long seq_rtt_us = -1L; long ca_rtt_us = -1L; u32 pkts_acked = 0; @@ -3128,7 +3105,7 @@ index 88b987ca9ebb..c3538bd0d008 100644 bool rtt_update; int flag = 0; -@@ -3125,7 +3141,6 @@ +@@ -3125,7 +3141,6 @@ static int tcp_clean_rtx_queue(struct so if (!first_ackt) first_ackt = last_ackt; @@ -3136,7 +3113,7 @@ index 88b987ca9ebb..c3538bd0d008 100644 if (before(start_seq, reord)) reord = start_seq; if (!after(scb->end_seq, tp->high_seq)) -@@ -3186,8 +3201,8 @@ +@@ -3186,8 +3201,8 @@ static int tcp_clean_rtx_queue(struct so seq_rtt_us = tcp_stamp_us_delta(tp->tcp_mstamp, first_ackt); ca_rtt_us = tcp_stamp_us_delta(tp->tcp_mstamp, last_ackt); @@ -3147,7 +3124,7 @@ index 88b987ca9ebb..c3538bd0d008 100644 sack->rate->prior_delivered + 1 == tp->delivered && !(flag & (FLAG_CA_ALERT | FLAG_SYN_ACKED))) { /* Conservatively mark a delayed ACK. It's typically -@@ -3244,9 +3259,10 @@ +@@ -3244,9 +3259,10 @@ static int tcp_clean_rtx_queue(struct so if (icsk->icsk_ca_ops->pkts_acked) { struct ack_sample sample = { .pkts_acked = pkts_acked, @@ -3160,7 +3137,7 @@ index 88b987ca9ebb..c3538bd0d008 100644 icsk->icsk_ca_ops->pkts_acked(sk, &sample); } -@@ -3645,6 +3661,7 @@ +@@ -3645,6 +3661,7 @@ static int tcp_ack(struct sock *sk, cons prior_fack = tcp_is_sack(tp) ? tcp_highest_sack_seq(tp) : tp->snd_una; rs.prior_in_flight = tcp_packets_in_flight(tp); @@ -3168,7 +3145,7 @@ index 88b987ca9ebb..c3538bd0d008 100644 /* ts_recent update must be made after we are sure that the packet * is in window. -@@ -3737,6 +3754,7 @@ +@@ -3737,6 +3754,7 @@ static int tcp_ack(struct sock *sk, cons delivered = tcp_newly_delivered(sk, delivered, flag); lost = tp->lost - lost; /* freshly marked lost */ rs.is_ack_delayed = !!(flag & FLAG_ACK_MAYBE_DELAYED); @@ -3176,7 +3153,7 @@ index 88b987ca9ebb..c3538bd0d008 100644 tcp_rate_gen(sk, delivered, lost, is_sack_reneg, sack_state.rate); tcp_cong_control(sk, ack, delivered, flag, sack_state.rate); tcp_xmit_recovery(sk, rexmit); -@@ -5261,13 +5279,14 @@ +@@ -5261,13 +5279,14 @@ static void __tcp_ack_snd_check(struct s /* More than one full frame received... */ if (((tp->rcv_nxt - tp->rcv_wup) > inet_csk(sk)->icsk_ack.rcv_mss && @@ -3192,11 +3169,9 @@ index 88b987ca9ebb..c3538bd0d008 100644 /* We ACK each frame or... */ tcp_in_quickack_mode(sk) || /* Protocol state mandates a one-time immediate ACK */ -diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c -index be6d22b8190f..4943f96aade8 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c -@@ -376,7 +376,8 @@ +@@ -376,7 +376,8 @@ static void tcp_ecn_send(struct sock *sk th->cwr = 1; skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN; } @@ -3206,7 +3181,7 @@ index be6d22b8190f..4943f96aade8 100644 /* ACK or retransmitted segment: clear ECT|CE */ INET_ECN_dontxmit(sk); } -@@ -1037,8 +1038,6 @@ +@@ -1037,8 +1038,6 @@ static int __tcp_transmit_skb(struct soc tp->tcp_wstamp_ns = max(tp->tcp_wstamp_ns, tp->tcp_clock_cache); skb->skb_mstamp_ns = tp->tcp_wstamp_ns; if (clone_it) { @@ -3215,7 +3190,7 @@ index be6d22b8190f..4943f96aade8 100644 oskb = skb; tcp_skb_tsorted_save(oskb) { -@@ -1308,7 +1307,7 @@ +@@ -1308,7 +1307,7 @@ int tcp_fragment(struct sock *sk, enum t { struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *buff; @@ -3224,7 +3199,7 @@ index be6d22b8190f..4943f96aade8 100644 long limit; int nlen; u8 flags; -@@ -1386,6 +1385,15 @@ +@@ -1386,6 +1385,15 @@ int tcp_fragment(struct sock *sk, enum t if (diff) tcp_adjust_pcount(sk, skb, diff); @@ -3240,7 +3215,7 @@ index be6d22b8190f..4943f96aade8 100644 } /* Link BUFF into the send queue. */ -@@ -1754,13 +1762,12 @@ +@@ -1755,13 +1763,12 @@ static u32 tcp_tso_autosize(const struct static u32 tcp_tso_segs(struct sock *sk, unsigned int mss_now) { const struct tcp_congestion_ops *ca_ops = inet_csk(sk)->icsk_ca_ops; @@ -3259,7 +3234,7 @@ index be6d22b8190f..4943f96aade8 100644 return min_t(u32, tso_segs, sk->sk_gso_max_segs); } -@@ -2398,6 +2405,7 @@ +@@ -2399,6 +2406,7 @@ static bool tcp_write_xmit(struct sock * skb->skb_mstamp_ns = tp->tcp_wstamp_ns = tp->tcp_clock_cache; list_move_tail(&skb->tcp_tsorted_anchor, &tp->tsorted_sent_queue); tcp_init_tso_segs(skb, mss_now); @@ -3267,8 +3242,6 @@ index be6d22b8190f..4943f96aade8 100644 goto repair; /* Skip network transmission */ } -diff --git a/net/ipv4/tcp_rate.c b/net/ipv4/tcp_rate.c -index 0de693565963..796fa6e5310c 100644 --- a/net/ipv4/tcp_rate.c +++ b/net/ipv4/tcp_rate.c @@ -34,6 +34,24 @@ @@ -3296,7 +3269,7 @@ index 0de693565963..796fa6e5310c 100644 /* Snapshot the current delivery information in the skb, to generate * a rate sample later when the skb is (s)acked in tcp_rate_skb_delivered(). */ -@@ -65,7 +83,10 @@ +@@ -65,7 +83,10 @@ void tcp_rate_skb_sent(struct sock *sk, TCP_SKB_CB(skb)->tx.first_tx_mstamp = tp->first_tx_mstamp; TCP_SKB_CB(skb)->tx.delivered_mstamp = tp->delivered_mstamp; TCP_SKB_CB(skb)->tx.delivered = tp->delivered; @@ -3307,7 +3280,7 @@ index 0de693565963..796fa6e5310c 100644 } /* When an skb is sacked or acked, we fill in the rate sample with the (prior) -@@ -86,15 +107,19 @@ +@@ -86,15 +107,19 @@ void tcp_rate_skb_delivered(struct sock if (!rs->prior_delivered || after(scb->tx.delivered, rs->prior_delivered)) { @@ -3328,7 +3301,7 @@ index 0de693565963..796fa6e5310c 100644 scb->tx.first_tx_mstamp); } -@@ -137,6 +162,11 @@ +@@ -137,6 +162,11 @@ void tcp_rate_gen(struct sock *sk, u32 d return; } rs->delivered = tp->delivered - rs->prior_delivered; @@ -3340,7 +3313,7 @@ index 0de693565963..796fa6e5310c 100644 /* Model sending data and receiving ACKs as separate pipeline phases * for a window. Usually the ACK phase is longer, but with ACK -@@ -144,7 +174,7 @@ +@@ -144,7 +174,7 @@ void tcp_rate_gen(struct sock *sk, u32 d * longer phase. */ snd_us = rs->interval_us; /* send phase */ @@ -3349,11 +3322,9 @@ index 0de693565963..796fa6e5310c 100644 rs->prior_mstamp); /* ack phase */ rs->interval_us = max(snd_us, ack_us); -diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c -index dd5a6317a801..1da66d4bbb08 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c -@@ -602,6 +602,7 @@ +@@ -602,6 +602,7 @@ void tcp_write_timer_handler(struct sock goto out; } diff --git a/PATCH/LRNG/696-04-v42-0001-Linux-Random-Number-Generator.patch b/PATCH/LRNG/696-04-v42-0001-Linux-Random-Number-Generator.patch index 36f1bc80d..dcd6c1ad3 100644 --- a/PATCH/LRNG/696-04-v42-0001-Linux-Random-Number-Generator.patch +++ b/PATCH/LRNG/696-04-v42-0001-Linux-Random-Number-Generator.patch @@ -324,13 +324,11 @@ Signed-off-by: Stephan Mueller create mode 100644 drivers/char/lrng/lrng_internal.h create mode 100644 include/linux/lrng.h -diff --git a/MAINTAINERS b/MAINTAINERS -index d7b4f32875a9..f609786d1d1d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -10737,6 +10737,13 @@ F: Documentation/litmus-tests/ +@@ -9494,6 +9494,13 @@ F: Documentation/core-api/atomic_ops.rst + F: Documentation/core-api/refcount-vs-atomic.rst F: Documentation/memory-barriers.txt - F: tools/memory-model/ +LINUX RANDOM NUMBER GENERATOR (LRNG) DRIVER +M: Stephan Mueller @@ -342,11 +340,9 @@ index d7b4f32875a9..f609786d1d1d 100644 LIS3LV02D ACCELEROMETER DRIVER M: Eric Piel S: Maintained -diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig -index ea3ead00f30f..10d1a41a01d2 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig -@@ -427,6 +427,8 @@ config ADI +@@ -535,6 +535,8 @@ config ADI and SSM (Silicon Secured Memory). Intended consumers of this driver include crash and makedumpfile. @@ -355,8 +351,6 @@ index ea3ead00f30f..10d1a41a01d2 100644 endmenu config RANDOM_TRUST_CPU -diff --git a/drivers/char/Makefile b/drivers/char/Makefile -index 264eb398fdd4..7371f7464a49 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -3,7 +3,14 @@ @@ -375,9 +369,6 @@ index 264eb398fdd4..7371f7464a49 100644 obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o obj-y += misc.o obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o -diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig -new file mode 100644 -index 000000000000..1cb2f55666ac --- /dev/null +++ b/drivers/char/lrng/Kconfig @@ -0,0 +1,205 @@ @@ -586,9 +577,6 @@ index 000000000000..1cb2f55666ac +endmenu # "Entropy Source Configuration" + +endif # LRNG -diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile -new file mode 100644 -index 000000000000..c26f932628d7 --- /dev/null +++ b/drivers/char/lrng/Makefile @@ -0,0 +1,9 @@ @@ -601,9 +589,6 @@ index 000000000000..c26f932628d7 + lrng_es_irq.o lrng_es_archrandom.o \ + lrng_drng.o lrng_chacha20.o \ + lrng_interfaces.o lrng_es_aux.o -diff --git a/drivers/char/lrng/lrng_aux.c b/drivers/char/lrng/lrng_aux.c -new file mode 100644 -index 000000000000..a970bbc879ed --- /dev/null +++ b/drivers/char/lrng/lrng_aux.c @@ -0,0 +1,136 @@ @@ -743,9 +728,6 @@ index 000000000000..a970bbc879ed + + return start + (get_random_long() % range << PAGE_SHIFT); +} -diff --git a/drivers/char/lrng/lrng_chacha20.c b/drivers/char/lrng/lrng_chacha20.c -new file mode 100644 -index 000000000000..ebbd67b600e0 --- /dev/null +++ b/drivers/char/lrng/lrng_chacha20.c @@ -0,0 +1,321 @@ @@ -1070,9 +1052,6 @@ index 000000000000..ebbd67b600e0 + .lrng_hash_final = lrng_cc20_hash_final, + .lrng_hash_desc_zero = lrng_cc20_hash_desc_zero, +}; -diff --git a/drivers/char/lrng/lrng_chacha20.h b/drivers/char/lrng/lrng_chacha20.h -new file mode 100644 -index 000000000000..bd0c0bee38f3 --- /dev/null +++ b/drivers/char/lrng/lrng_chacha20.h @@ -0,0 +1,25 @@ @@ -1101,9 +1080,6 @@ index 000000000000..bd0c0bee38f3 +{ + chacha_init_consts(chacha20->constants); +} -diff --git a/drivers/char/lrng/lrng_drng.c b/drivers/char/lrng/lrng_drng.c -new file mode 100644 -index 000000000000..701fb26c699a --- /dev/null +++ b/drivers/char/lrng/lrng_drng.c @@ -0,0 +1,444 @@ @@ -1551,9 +1527,6 @@ index 000000000000..701fb26c699a +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Stephan Mueller "); +MODULE_DESCRIPTION("Linux Random Number Generator"); -diff --git a/drivers/char/lrng/lrng_es_archrandom.c b/drivers/char/lrng/lrng_es_archrandom.c -new file mode 100644 -index 000000000000..ae87fa9bae58 --- /dev/null +++ b/drivers/char/lrng/lrng_es_archrandom.c @@ -0,0 +1,91 @@ @@ -1648,9 +1621,6 @@ index 000000000000..ae87fa9bae58 + ent_bits); + return ent_bits; +} -diff --git a/drivers/char/lrng/lrng_es_aux.c b/drivers/char/lrng/lrng_es_aux.c -new file mode 100644 -index 000000000000..9a12f7f79866 --- /dev/null +++ b/drivers/char/lrng/lrng_es_aux.c @@ -0,0 +1,274 @@ @@ -1928,9 +1898,6 @@ index 000000000000..9a12f7f79866 + + spin_unlock_irqrestore(&pool->lock, flags); +} -diff --git a/drivers/char/lrng/lrng_es_irq.c b/drivers/char/lrng/lrng_es_irq.c -new file mode 100644 -index 000000000000..675425d87481 --- /dev/null +++ b/drivers/char/lrng/lrng_es_irq.c @@ -0,0 +1,796 @@ @@ -2730,9 +2697,6 @@ index 000000000000..675425d87481 + } +} +EXPORT_SYMBOL(add_interrupt_randomness); -diff --git a/drivers/char/lrng/lrng_es_irq.h b/drivers/char/lrng/lrng_es_irq.h -new file mode 100644 -index 000000000000..00b16b1aa45f --- /dev/null +++ b/drivers/char/lrng/lrng_es_irq.h @@ -0,0 +1,71 @@ @@ -2807,9 +2771,6 @@ index 000000000000..00b16b1aa45f + *mask = ((1 << (*pre_ptr & (LRNG_DATA_SLOTS_PER_UINT - 1)) * + LRNG_DATA_SLOTSIZE_BITS)) - 1; +} -diff --git a/drivers/char/lrng/lrng_es_mgr.c b/drivers/char/lrng/lrng_es_mgr.c -new file mode 100644 -index 000000000000..d0d66ff36de2 --- /dev/null +++ b/drivers/char/lrng/lrng_es_mgr.c @@ -0,0 +1,375 @@ @@ -3188,9 +3149,6 @@ index 000000000000..d0d66ff36de2 + */ + lrng_writer_wakeup(); +} -diff --git a/drivers/char/lrng/lrng_interfaces.c b/drivers/char/lrng/lrng_interfaces.c -new file mode 100644 -index 000000000000..3a56bfdca01e --- /dev/null +++ b/drivers/char/lrng/lrng_interfaces.c @@ -0,0 +1,650 @@ @@ -3844,9 +3802,6 @@ index 000000000000..3a56bfdca01e + + return lrng_read_common_block(flags & GRND_NONBLOCK, buf, count); +} -diff --git a/drivers/char/lrng/lrng_internal.h b/drivers/char/lrng/lrng_internal.h -new file mode 100644 -index 000000000000..a21e5be716b0 --- /dev/null +++ b/drivers/char/lrng/lrng_internal.h @@ -0,0 +1,446 @@ @@ -4296,9 +4251,6 @@ index 000000000000..a21e5be716b0 +#endif /*CONFIG_LRNG_IRQ_PERF */ + +#endif /* _LRNG_INTERNAL_H */ -diff --git a/include/linux/lrng.h b/include/linux/lrng.h -new file mode 100644 -index 000000000000..e9dc860a1ebb --- /dev/null +++ b/include/linux/lrng.h @@ -0,0 +1,81 @@ @@ -4383,6 +4335,3 @@ index 000000000000..e9dc860a1ebb +#endif /* CONFIG_LRNG_DRNG_SWITCH */ + +#endif /* _LRNG_H */ --- -2.31.1 - diff --git a/PATCH/LRNG/696-05-v42-0002-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch b/PATCH/LRNG/696-05-v42-0002-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch index 926dea3ca..757560a19 100644 --- a/PATCH/LRNG/696-05-v42-0002-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch +++ b/PATCH/LRNG/696-05-v42-0002-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch @@ -50,8 +50,6 @@ Signed-off-by: Stephan Mueller 2 files changed, 124 insertions(+) create mode 100644 drivers/char/lrng/lrng_numa.c -diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile -index c26f932628d7..80b152059598 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile @@ -7,3 +7,5 @@ obj-y += lrng_es_mgr.o lrng_aux.o \ @@ -60,9 +58,6 @@ index c26f932628d7..80b152059598 100644 lrng_interfaces.o lrng_es_aux.o + +obj-$(CONFIG_NUMA) += lrng_numa.o -diff --git a/drivers/char/lrng/lrng_numa.c b/drivers/char/lrng/lrng_numa.c -new file mode 100644 -index 000000000000..fbfb40a5fb8d --- /dev/null +++ b/drivers/char/lrng/lrng_numa.c @@ -0,0 +1,122 @@ @@ -188,6 +183,3 @@ index 000000000000..fbfb40a5fb8d +{ + schedule_work(&lrng_drngs_numa_alloc_work); +} --- -2.31.1 - diff --git a/PATCH/LRNG/696-06-v42-0003-LRNG-sysctls-and-proc-interface.patch b/PATCH/LRNG/696-06-v42-0003-LRNG-sysctls-and-proc-interface.patch index 5ec5f3c54..b31804d87 100644 --- a/PATCH/LRNG/696-06-v42-0003-LRNG-sysctls-and-proc-interface.patch +++ b/PATCH/LRNG/696-06-v42-0003-LRNG-sysctls-and-proc-interface.patch @@ -65,8 +65,6 @@ Signed-off-by: Stephan Mueller 3 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 drivers/char/lrng/lrng_proc.c -diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile -index 80b152059598..3144e87c2166 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile @@ -9,3 +9,4 @@ obj-y += lrng_es_mgr.o lrng_aux.o \ @@ -74,11 +72,9 @@ index 80b152059598..3144e87c2166 100644 obj-$(CONFIG_NUMA) += lrng_numa.o +obj-$(CONFIG_SYSCTL) += lrng_proc.o -diff --git a/drivers/char/lrng/lrng_interfaces.c b/drivers/char/lrng/lrng_interfaces.c -index 3a56bfdca01e..4b8c56849112 100644 --- a/drivers/char/lrng/lrng_interfaces.c +++ b/drivers/char/lrng/lrng_interfaces.c -@@ -38,8 +38,6 @@ static DECLARE_WAIT_QUEUE_HEAD(lrng_write_wait); +@@ -38,8 +38,6 @@ static DECLARE_WAIT_QUEUE_HEAD(lrng_writ static DECLARE_WAIT_QUEUE_HEAD(lrng_init_wait); static struct fasync_struct *fasync; @@ -87,9 +83,6 @@ index 3a56bfdca01e..4b8c56849112 100644 /********************************** Helper ***********************************/ /* Is the DRNG seed level too low? */ -diff --git a/drivers/char/lrng/lrng_proc.c b/drivers/char/lrng/lrng_proc.c -new file mode 100644 -index 000000000000..a842c6c897f2 --- /dev/null +++ b/drivers/char/lrng/lrng_proc.c @@ -0,0 +1,185 @@ @@ -278,6 +271,3 @@ index 000000000000..a842c6c897f2 +} + +module_init(lrng_proc_type_init); --- -2.31.1 - diff --git a/PATCH/LRNG/696-07-v42-0004-LRNG-add-switchable-DRNG-support.patch b/PATCH/LRNG/696-07-v42-0004-LRNG-add-switchable-DRNG-support.patch index 9a88d1d4f..f884de9c8 100644 --- a/PATCH/LRNG/696-07-v42-0004-LRNG-add-switchable-DRNG-support.patch +++ b/PATCH/LRNG/696-07-v42-0004-LRNG-add-switchable-DRNG-support.patch @@ -70,8 +70,6 @@ Signed-off-by: Stephan Mueller 3 files changed, 234 insertions(+) create mode 100644 drivers/char/lrng/lrng_switch.c -diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig -index 1cb2f55666ac..c10a0c3f2015 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig @@ -202,4 +202,11 @@ config LRNG_CPU_ENTROPY_RATE @@ -86,8 +84,6 @@ index 1cb2f55666ac..c10a0c3f2015 100644 + option other DRNGs can be selected and loaded at runtime. + endif # LRNG -diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile -index 3144e87c2166..dc3ef329b2c4 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile @@ -10,3 +10,4 @@ obj-y += lrng_es_mgr.o lrng_aux.o \ @@ -95,9 +91,6 @@ index 3144e87c2166..dc3ef329b2c4 100644 obj-$(CONFIG_NUMA) += lrng_numa.o obj-$(CONFIG_SYSCTL) += lrng_proc.o +obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_switch.o -diff --git a/drivers/char/lrng/lrng_switch.c b/drivers/char/lrng/lrng_switch.c -new file mode 100644 -index 000000000000..f3b2f30d1c21 --- /dev/null +++ b/drivers/char/lrng/lrng_switch.c @@ -0,0 +1,226 @@ @@ -327,6 +320,3 @@ index 000000000000..f3b2f30d1c21 + return ret; +} +EXPORT_SYMBOL(lrng_set_drng_cb); --- -2.31.1 - diff --git a/PATCH/LRNG/696-08-v42-0005-LRNG-add-common-generic-hash-support.patch b/PATCH/LRNG/696-08-v42-0005-LRNG-add-common-generic-hash-support.patch index f61ba6959..e822b53ea 100644 --- a/PATCH/LRNG/696-08-v42-0005-LRNG-add-common-generic-hash-support.patch +++ b/PATCH/LRNG/696-08-v42-0005-LRNG-add-common-generic-hash-support.patch @@ -46,8 +46,6 @@ Signed-off-by: Stephan Mueller create mode 100644 drivers/char/lrng/lrng_kcapi_hash.c create mode 100644 drivers/char/lrng/lrng_kcapi_hash.h -diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig -index c10a0c3f2015..ab17c45a356b 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig @@ -209,4 +209,12 @@ menuconfig LRNG_DRNG_SWITCH @@ -63,8 +61,6 @@ index c10a0c3f2015..ab17c45a356b 100644 +endif # LRNG_DRNG_SWITCH + endif # LRNG -diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile -index dc3ef329b2c4..299715bb0ec2 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile @@ -11,3 +11,4 @@ obj-y += lrng_es_mgr.o lrng_aux.o \ @@ -72,9 +68,6 @@ index dc3ef329b2c4..299715bb0ec2 100644 obj-$(CONFIG_SYSCTL) += lrng_proc.o obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_switch.o +obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.o -diff --git a/drivers/char/lrng/lrng_kcapi_hash.c b/drivers/char/lrng/lrng_kcapi_hash.c -new file mode 100644 -index 000000000000..9647d980e468 --- /dev/null +++ b/drivers/char/lrng/lrng_kcapi_hash.c @@ -0,0 +1,103 @@ @@ -181,9 +174,6 @@ index 000000000000..9647d980e468 + shash_desc_zero(shash); +} +EXPORT_SYMBOL(lrng_kcapi_hash_zero); -diff --git a/drivers/char/lrng/lrng_kcapi_hash.h b/drivers/char/lrng/lrng_kcapi_hash.h -new file mode 100644 -index 000000000000..2f94558d2dd6 --- /dev/null +++ b/drivers/char/lrng/lrng_kcapi_hash.h @@ -0,0 +1,20 @@ @@ -207,6 +197,3 @@ index 000000000000..2f94558d2dd6 +void lrng_kcapi_hash_zero(struct shash_desc *shash); + +#endif /* _LRNG_KCAPI_HASH_H */ --- -2.31.1 - diff --git a/PATCH/LRNG/696-09-v42-0006-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch b/PATCH/LRNG/696-09-v42-0006-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch index e63392caf..ae58f06de 100644 --- a/PATCH/LRNG/696-09-v42-0006-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch +++ b/PATCH/LRNG/696-09-v42-0006-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch @@ -38,11 +38,9 @@ Signed-off-by: Stephan Mueller include/crypto/drbg.h | 7 +++++++ 2 files changed, 17 insertions(+), 6 deletions(-) -diff --git a/crypto/drbg.c b/crypto/drbg.c -index ea85d4a0fe9e..74a9dca67698 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c -@@ -114,7 +114,7 @@ +@@ -113,7 +113,7 @@ * the SHA256 / AES 256 over other ciphers. Thus, the favored * DRBGs are the latest entries in this array. */ @@ -51,7 +49,7 @@ index ea85d4a0fe9e..74a9dca67698 100644 #ifdef CONFIG_CRYPTO_DRBG_CTR { .flags = DRBG_CTR | DRBG_STRENGTH128, -@@ -191,6 +191,7 @@ static const struct drbg_core drbg_cores[] = { +@@ -190,6 +190,7 @@ static const struct drbg_core drbg_cores }, #endif /* CONFIG_CRYPTO_DRBG_HMAC */ }; @@ -59,7 +57,7 @@ index ea85d4a0fe9e..74a9dca67698 100644 static int drbg_uninstantiate(struct drbg_state *drbg); -@@ -206,7 +207,7 @@ static int drbg_uninstantiate(struct drbg_state *drbg); +@@ -205,7 +206,7 @@ static int drbg_uninstantiate(struct drb * Return: normalized strength in *bytes* value or 32 as default * to counter programming errors */ @@ -68,7 +66,7 @@ index ea85d4a0fe9e..74a9dca67698 100644 { switch (flags & DRBG_STRENGTH_MASK) { case DRBG_STRENGTH128: -@@ -219,6 +220,7 @@ static inline unsigned short drbg_sec_strength(drbg_flag_t flags) +@@ -218,6 +219,7 @@ static inline unsigned short drbg_sec_st return 32; } } @@ -76,7 +74,7 @@ index ea85d4a0fe9e..74a9dca67698 100644 /* * FIPS 140-2 continuous self test for the noise source -@@ -1215,7 +1217,7 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers, +@@ -1202,7 +1204,7 @@ out: } /* Free all substructures in a DRBG state without the DRBG state structure */ @@ -85,7 +83,7 @@ index ea85d4a0fe9e..74a9dca67698 100644 { if (!drbg) return; -@@ -1236,12 +1238,13 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg) +@@ -1223,12 +1225,13 @@ static inline void drbg_dealloc_state(st drbg->fips_primed = false; } } @@ -100,7 +98,7 @@ index ea85d4a0fe9e..74a9dca67698 100644 { int ret = -ENOMEM; unsigned int sb_size = 0; -@@ -1322,6 +1325,7 @@ static inline int drbg_alloc_state(struct drbg_state *drbg) +@@ -1309,6 +1312,7 @@ err: drbg_dealloc_state(drbg); return ret; } @@ -108,7 +106,7 @@ index ea85d4a0fe9e..74a9dca67698 100644 /************************************************************************* * DRBG interface functions -@@ -1891,8 +1895,7 @@ static int drbg_kcapi_sym_ctr(struct drbg_state *drbg, +@@ -1876,8 +1880,7 @@ out: * * return: flags */ @@ -118,7 +116,7 @@ index ea85d4a0fe9e..74a9dca67698 100644 { int i = 0; size_t start = 0; -@@ -1919,6 +1922,7 @@ static inline void drbg_convert_tfm_core(const char *cra_driver_name, +@@ -1904,6 +1907,7 @@ static inline void drbg_convert_tfm_core } } } @@ -126,11 +124,9 @@ index ea85d4a0fe9e..74a9dca67698 100644 static int drbg_kcapi_init(struct crypto_tfm *tfm) { -diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h -index c4165126937e..71d53e028e6d 100644 --- a/include/crypto/drbg.h +++ b/include/crypto/drbg.h -@@ -278,4 +278,11 @@ enum drbg_prefixes { +@@ -282,4 +282,11 @@ enum drbg_prefixes { DRBG_PREFIX3 }; @@ -142,6 +138,3 @@ index c4165126937e..71d53e028e6d 100644 +extern unsigned short drbg_sec_strength(drbg_flag_t flags); + #endif /* _DRBG_H */ --- -2.31.1 - diff --git a/PATCH/LRNG/696-10-v42-0007-LRNG-add-SP800-90A-DRBG-extension.patch b/PATCH/LRNG/696-10-v42-0007-LRNG-add-SP800-90A-DRBG-extension.patch index 96d12d6c2..5d100b3ff 100644 --- a/PATCH/LRNG/696-10-v42-0007-LRNG-add-SP800-90A-DRBG-extension.patch +++ b/PATCH/LRNG/696-10-v42-0007-LRNG-add-SP800-90A-DRBG-extension.patch @@ -50,8 +50,6 @@ Signed-off-by: Stephan Mueller 3 files changed, 209 insertions(+) create mode 100644 drivers/char/lrng/lrng_drbg.c -diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig -index ab17c45a356b..aa611363b97e 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig @@ -215,6 +215,16 @@ config LRNG_KCAPI_HASH @@ -71,8 +69,6 @@ index ab17c45a356b..aa611363b97e 100644 endif # LRNG_DRNG_SWITCH endif # LRNG -diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile -index 299715bb0ec2..7e5acb8cac3d 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_NUMA) += lrng_numa.o @@ -80,9 +76,6 @@ index 299715bb0ec2..7e5acb8cac3d 100644 obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_switch.o obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.o +obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o -diff --git a/drivers/char/lrng/lrng_drbg.c b/drivers/char/lrng/lrng_drbg.c -new file mode 100644 -index 000000000000..6ca6b05eccf4 --- /dev/null +++ b/drivers/char/lrng/lrng_drbg.c @@ -0,0 +1,198 @@ @@ -284,6 +277,3 @@ index 000000000000..6ca6b05eccf4 +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Stephan Mueller "); +MODULE_DESCRIPTION("Linux Random Number Generator - SP800-90A DRBG backend"); --- -2.31.1 - diff --git a/PATCH/LRNG/696-11-v42-0008-LRNG-add-kernel-crypto-API-PRNG-extension.patch b/PATCH/LRNG/696-11-v42-0008-LRNG-add-kernel-crypto-API-PRNG-extension.patch index 98e72a232..f727ec613 100644 --- a/PATCH/LRNG/696-11-v42-0008-LRNG-add-kernel-crypto-API-PRNG-extension.patch +++ b/PATCH/LRNG/696-11-v42-0008-LRNG-add-kernel-crypto-API-PRNG-extension.patch @@ -47,8 +47,6 @@ Signed-off-by: Stephan Mueller 3 files changed, 241 insertions(+) create mode 100644 drivers/char/lrng/lrng_kcapi.c -diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig -index aa611363b97e..ffd2df43f2d4 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig @@ -225,6 +225,19 @@ config LRNG_DRBG @@ -71,8 +69,6 @@ index aa611363b97e..ffd2df43f2d4 100644 endif # LRNG_DRNG_SWITCH endif # LRNG -diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile -index 7e5acb8cac3d..ad7c413cc0d9 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_SYSCTL) += lrng_proc.o @@ -80,9 +76,6 @@ index 7e5acb8cac3d..ad7c413cc0d9 100644 obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.o obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o +obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o -diff --git a/drivers/char/lrng/lrng_kcapi.c b/drivers/char/lrng/lrng_kcapi.c -new file mode 100644 -index 000000000000..b06449cb2365 --- /dev/null +++ b/drivers/char/lrng/lrng_kcapi.c @@ -0,0 +1,227 @@ @@ -313,6 +306,3 @@ index 000000000000..b06449cb2365 +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Stephan Mueller "); +MODULE_DESCRIPTION("Linux Random Number Generator - kernel crypto API DRNG backend"); --- -2.31.1 - diff --git a/PATCH/LRNG/696-12-v42-0009-crypto-move-Jitter-RNG-header-include-dir.patch b/PATCH/LRNG/696-12-v42-0009-crypto-move-Jitter-RNG-header-include-dir.patch index 7871b9388..36fe316ee 100644 --- a/PATCH/LRNG/696-12-v42-0009-crypto-move-Jitter-RNG-header-include-dir.patch +++ b/PATCH/LRNG/696-12-v42-0009-crypto-move-Jitter-RNG-header-include-dir.patch @@ -41,13 +41,11 @@ Signed-off-by: Stephan Mueller 3 files changed, 2 insertions(+), 3 deletions(-) rename {crypto => include/crypto/internal}/jitterentropy.h (100%) -diff --git a/crypto/jitterentropy-kcapi.c b/crypto/jitterentropy-kcapi.c -index e8a4165a1874..c90e60910827 100644 --- a/crypto/jitterentropy-kcapi.c +++ b/crypto/jitterentropy-kcapi.c @@ -43,8 +43,7 @@ - #include #include + #include #include - -#include "jitterentropy.h" @@ -55,23 +53,58 @@ index e8a4165a1874..c90e60910827 100644 /*************************************************************************** * Helper function -diff --git a/crypto/jitterentropy.c b/crypto/jitterentropy.c -index a11b3208760f..f36a391319e1 100644 --- a/crypto/jitterentropy.c +++ b/crypto/jitterentropy.c -@@ -117,7 +117,7 @@ struct rand_data { - #define JENT_EHEALTH 9 /* Health test failed during initialization */ - #define JENT_ERCT 10 /* RCT failed during initialization */ +@@ -103,7 +103,7 @@ struct rand_data { + * Helper functions + ***************************************************************************/ -#include "jitterentropy.h" +#include - /*************************************************************************** - * Adaptive Proportion Test -diff --git a/crypto/jitterentropy.h b/include/crypto/internal/jitterentropy.h -similarity index 100% -rename from crypto/jitterentropy.h -rename to include/crypto/internal/jitterentropy.h --- -2.31.1 - + /** + * Update of the loop count used for the next round of +--- a/crypto/jitterentropy.h ++++ /dev/null +@@ -1,19 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0-or-later +- +-typedef unsigned long long __u64; +- +-extern void *jent_zalloc(unsigned int len); +-extern void jent_zfree(void *ptr); +-extern int jent_fips_enabled(void); +-extern void jent_panic(char *s); +-extern void jent_memcpy(void *dest, const void *src, unsigned int n); +-extern void jent_get_nstime(__u64 *out); +- +-struct rand_data; +-extern int jent_entropy_init(void); +-extern int jent_read_entropy(struct rand_data *ec, unsigned char *data, +- unsigned int len); +- +-extern struct rand_data *jent_entropy_collector_alloc(unsigned int osr, +- unsigned int flags); +-extern void jent_entropy_collector_free(struct rand_data *entropy_collector); +--- /dev/null ++++ b/include/crypto/internal/jitterentropy.h +@@ -0,0 +1,19 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++ ++typedef unsigned long long __u64; ++ ++extern void *jent_zalloc(unsigned int len); ++extern void jent_zfree(void *ptr); ++extern int jent_fips_enabled(void); ++extern void jent_panic(char *s); ++extern void jent_memcpy(void *dest, const void *src, unsigned int n); ++extern void jent_get_nstime(__u64 *out); ++ ++struct rand_data; ++extern int jent_entropy_init(void); ++extern int jent_read_entropy(struct rand_data *ec, unsigned char *data, ++ unsigned int len); ++ ++extern struct rand_data *jent_entropy_collector_alloc(unsigned int osr, ++ unsigned int flags); ++extern void jent_entropy_collector_free(struct rand_data *entropy_collector); diff --git a/PATCH/LRNG/696-13-v42-0010-LRNG-add-Jitter-RNG-fast-noise-source.patch b/PATCH/LRNG/696-13-v42-0010-LRNG-add-Jitter-RNG-fast-noise-source.patch index 386d8367e..57a6feb58 100644 --- a/PATCH/LRNG/696-13-v42-0010-LRNG-add-Jitter-RNG-fast-noise-source.patch +++ b/PATCH/LRNG/696-13-v42-0010-LRNG-add-Jitter-RNG-fast-noise-source.patch @@ -37,8 +37,6 @@ Signed-off-by: Stephan Mueller 3 files changed, 118 insertions(+) create mode 100644 drivers/char/lrng/lrng_es_jent.c -diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig -index ffd2df43f2d4..e622b8532e2b 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig @@ -182,6 +182,33 @@ config LRNG_IRQ_ENTROPY_RATE @@ -75,18 +73,13 @@ index ffd2df43f2d4..e622b8532e2b 100644 comment "CPU Entropy Source" config LRNG_CPU_ENTROPY_RATE -diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile -index ad7c413cc0d9..01a69172c464 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile -@@ -14,3 +14,4 @@ obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_switch.o +@@ -14,3 +14,4 @@ obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_s obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.o obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o +obj-$(CONFIG_LRNG_JENT) += lrng_es_jent.o -diff --git a/drivers/char/lrng/lrng_es_jent.c b/drivers/char/lrng/lrng_es_jent.c -new file mode 100644 -index 000000000000..e98152b4c912 --- /dev/null +++ b/drivers/char/lrng/lrng_es_jent.c @@ -0,0 +1,90 @@ @@ -180,6 +173,3 @@ index 000000000000..e98152b4c912 + return lrng_fast_noise_entropylevel((lrng_jent_initialized) ? + jitterrng : 0, requested_bits); +} --- -2.31.1 - diff --git a/PATCH/LRNG/696-14-v42-0011-LRNG-add-SP800-90B-compliant-health-tests.patch b/PATCH/LRNG/696-14-v42-0011-LRNG-add-SP800-90B-compliant-health-tests.patch index 2b03ccf46..9944c0afd 100644 --- a/PATCH/LRNG/696-14-v42-0011-LRNG-add-SP800-90B-compliant-health-tests.patch +++ b/PATCH/LRNG/696-14-v42-0011-LRNG-add-SP800-90B-compliant-health-tests.patch @@ -137,8 +137,6 @@ Signed-off-by: Stephan Mueller 3 files changed, 467 insertions(+) create mode 100644 drivers/char/lrng/lrng_health.c -diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig -index e622b8532e2b..931959f75a83 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig @@ -164,6 +164,62 @@ config LRNG_COLLECTION_SIZE @@ -204,18 +202,13 @@ index e622b8532e2b..931959f75a83 100644 config LRNG_IRQ_ENTROPY_RATE int "Interrupt Entropy Source Entropy Rate" range 256 4294967295 -diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile -index 01a69172c464..02513621411b 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile -@@ -15,3 +15,4 @@ obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.o +@@ -15,3 +15,4 @@ obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kc obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o obj-$(CONFIG_LRNG_JENT) += lrng_es_jent.o +obj-$(CONFIG_LRNG_HEALTH_TESTS) += lrng_health.o -diff --git a/drivers/char/lrng/lrng_health.c b/drivers/char/lrng/lrng_health.c -new file mode 100644 -index 000000000000..a56a0c4261ab --- /dev/null +++ b/drivers/char/lrng/lrng_health.c @@ -0,0 +1,410 @@ @@ -629,6 +622,3 @@ index 000000000000..a56a0c4261ab + + return lrng_health_pass; +} --- -2.31.1 - diff --git a/PATCH/LRNG/696-15-v42-0012-LRNG-add-interface-for-gathering-of-raw-entropy.patch b/PATCH/LRNG/696-15-v42-0012-LRNG-add-interface-for-gathering-of-raw-entropy.patch index 5068525a1..bf5cecd71 100644 --- a/PATCH/LRNG/696-15-v42-0012-LRNG-add-interface-for-gathering-of-raw-entropy.patch +++ b/PATCH/LRNG/696-15-v42-0012-LRNG-add-interface-for-gathering-of-raw-entropy.patch @@ -87,8 +87,6 @@ Signed-off-by: Stephan Mueller 3 files changed, 860 insertions(+) create mode 100644 drivers/char/lrng/lrng_testing.c -diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig -index 931959f75a83..32692aff9774 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig @@ -323,4 +323,174 @@ config LRNG_KCAPI @@ -266,8 +264,6 @@ index 931959f75a83..32692aff9774 100644 +endif #LRNG_TESTING_MENU + endif # LRNG -diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile -index 02513621411b..919c85cd103a 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile @@ -16,3 +16,4 @@ obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o @@ -275,9 +271,6 @@ index 02513621411b..919c85cd103a 100644 obj-$(CONFIG_LRNG_JENT) += lrng_es_jent.o obj-$(CONFIG_LRNG_HEALTH_TESTS) += lrng_health.o +obj-$(CONFIG_LRNG_TESTING) += lrng_testing.o -diff --git a/drivers/char/lrng/lrng_testing.c b/drivers/char/lrng/lrng_testing.c -new file mode 100644 -index 000000000000..99cc35abf45c --- /dev/null +++ b/drivers/char/lrng/lrng_testing.c @@ -0,0 +1,689 @@ @@ -970,6 +963,3 @@ index 000000000000..99cc35abf45c +} + +module_init(lrng_raw_init); --- -2.31.1 - diff --git a/PATCH/LRNG/696-16-v42-0013-LRNG-add-power-on-and-runtime-self-tests.patch b/PATCH/LRNG/696-16-v42-0013-LRNG-add-power-on-and-runtime-self-tests.patch index 49a3c183e..d8d60f0ab 100644 --- a/PATCH/LRNG/696-16-v42-0013-LRNG-add-power-on-and-runtime-self-tests.patch +++ b/PATCH/LRNG/696-16-v42-0013-LRNG-add-power-on-and-runtime-self-tests.patch @@ -74,8 +74,6 @@ Signed-off-by: Stephan Mueller 3 files changed, 405 insertions(+), 8 deletions(-) create mode 100644 drivers/char/lrng/lrng_selftest.c -diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig -index 32692aff9774..de50abaf53cb 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig @@ -165,15 +165,16 @@ config LRNG_COLLECTION_SIZE @@ -134,8 +132,6 @@ index 32692aff9774..de50abaf53cb 100644 +endif # LRNG_SELFTEST + endif # LRNG -diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile -index 919c85cd103a..623813764aca 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o @@ -143,9 +139,6 @@ index 919c85cd103a..623813764aca 100644 obj-$(CONFIG_LRNG_HEALTH_TESTS) += lrng_health.o obj-$(CONFIG_LRNG_TESTING) += lrng_testing.o +obj-$(CONFIG_LRNG_SELFTEST) += lrng_selftest.o -diff --git a/drivers/char/lrng/lrng_selftest.c b/drivers/char/lrng/lrng_selftest.c -new file mode 100644 -index 000000000000..e219f7ea832b --- /dev/null +++ b/drivers/char/lrng/lrng_selftest.c @@ -0,0 +1,369 @@ @@ -518,6 +511,3 @@ index 000000000000..e219f7ea832b +} + +module_init(lrng_selftest_init); --- -2.31.1 - diff --git a/PATCH/LRNG/696-18-v42-03-arch_random_early.patch b/PATCH/LRNG/696-18-v42-03-arch_random_early.patch index 156bbbf46..d9e52ac77 100644 --- a/PATCH/LRNG/696-18-v42-03-arch_random_early.patch +++ b/PATCH/LRNG/696-18-v42-03-arch_random_early.patch @@ -1,6 +1,6 @@ --- a/drivers/char/lrng/lrng_es_mgr.c +++ b/drivers/char/lrng/lrng_es_mgr.c -@@ -324,8 +324,8 @@ int __init rand_initialize(void) +@@ -276,8 +276,8 @@ int __init rand_initialize(void) seed.time = ktime_get_real(); for (i = 0; i < ARRAY_SIZE(seed.data); i++) { diff --git a/PATCH/LRNG/696-19-v42-04-net_rand_state.patch b/PATCH/LRNG/696-19-v42-04-net_rand_state.patch index c3e2392c9..eb5dd0b3b 100644 --- a/PATCH/LRNG/696-19-v42-04-net_rand_state.patch +++ b/PATCH/LRNG/696-19-v42-04-net_rand_state.patch @@ -1,7 +1,7 @@ --- a/drivers/char/lrng/lrng_es_irq.c +++ b/drivers/char/lrng/lrng_es_irq.c -@@ -12,6 +12,7 @@ - #include +@@ -13,6 +13,7 @@ + #include #include #include +#include diff --git a/PATCH/LRNG/696-22-v42-07-chacha_constants.patch b/PATCH/LRNG/696-22-v42-07-chacha_constants.patch index 572fbab8c..1649a9f55 100644 --- a/PATCH/LRNG/696-22-v42-07-chacha_constants.patch +++ b/PATCH/LRNG/696-22-v42-07-chacha_constants.patch @@ -1,5 +1,5 @@ ---- linux-5.10/drivers/char/lrng/lrng_chacha20.h.orig 2021-08-20 21:16:45.569017375 +0200 -+++ linux-5.10/drivers/char/lrng/lrng_chacha20.h 2021-08-20 21:18:21.255462479 +0200 +--- a/drivers/char/lrng/lrng_chacha20.h ++++ b/drivers/char/lrng/lrng_chacha20.h @@ -21,5 +21,9 @@ struct chacha20_block { static inline void lrng_cc20_init_rfc7539(struct chacha20_block *chacha20) diff --git a/PATCH/UKSM/695-uksm-5.4.patch b/PATCH/UKSM/695-uksm-5.4.patch index e558144b6..9f5a206a4 100644 --- a/PATCH/UKSM/695-uksm-5.4.patch +++ b/PATCH/UKSM/695-uksm-5.4.patch @@ -1,6 +1,3 @@ -diff --git a/Documentation/vm/uksm.txt b/Documentation/vm/uksm.txt -new file mode 100644 -index 000000000000..be19a3127001 --- /dev/null +++ b/Documentation/vm/uksm.txt @@ -0,0 +1,61 @@ @@ -65,8 +62,6 @@ index 000000000000..be19a3127001 +2015-04-22 UKSM 0.1.2.4 Fix a race condition that can sometimes trigger anonying warnings. +2016-09-10 UKSM 0.1.2.5 Fix a bug in dedup ratio calculation. +2017-02-26 UKSM 0.1.2.6 Fix a bug in hugetlbpage handling and a race bug with page migration. -diff --git a/fs/exec.c b/fs/exec.c -index 555e93c7dec8..7e1cfd568e6c 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -63,6 +63,7 @@ @@ -77,11 +72,9 @@ index 555e93c7dec8..7e1cfd568e6c 100644 #include #include -diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c -index 8c1f1bb1a5ce..62e28cf10bbf 100644 --- a/fs/proc/meminfo.c +++ b/fs/proc/meminfo.c -@@ -105,7 +105,10 @@ static int meminfo_proc_show(struct seq_file *m, void *v) +@@ -105,7 +105,10 @@ static int meminfo_proc_show(struct seq_ global_zone_page_state(NR_KERNEL_STACK_KB)); show_val_kb(m, "PageTables: ", global_zone_page_state(NR_PAGETABLE)); @@ -93,11 +86,9 @@ index 8c1f1bb1a5ce..62e28cf10bbf 100644 show_val_kb(m, "NFS_Unstable: ", global_node_page_state(NR_UNSTABLE_NFS)); show_val_kb(m, "Bounce: ", -diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h -index 818691846c90..b2169f37c696 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h -@@ -855,12 +855,25 @@ extern void untrack_pfn(struct vm_area_struct *vma, unsigned long pfn, +@@ -855,12 +855,25 @@ extern void untrack_pfn(struct vm_area_s extern void untrack_pfn_moved(struct vm_area_struct *vma); #endif @@ -124,7 +115,7 @@ index 818691846c90..b2169f37c696 100644 } #define my_zero_pfn(addr) page_to_pfn(ZERO_PAGE(addr)) -@@ -869,7 +882,7 @@ static inline int is_zero_pfn(unsigned long pfn) +@@ -869,7 +882,7 @@ static inline int is_zero_pfn(unsigned l static inline int is_zero_pfn(unsigned long pfn) { extern unsigned long zero_pfn; @@ -133,8 +124,6 @@ index 818691846c90..b2169f37c696 100644 } static inline unsigned long my_zero_pfn(unsigned long addr) -diff --git a/include/linux/ksm.h b/include/linux/ksm.h -index e48b1e453ff5..095d59310ce0 100644 --- a/include/linux/ksm.h +++ b/include/linux/ksm.h @@ -1,4 +1,4 @@ @@ -169,7 +158,7 @@ index e48b1e453ff5..095d59310ce0 100644 } /* -@@ -56,6 +52,33 @@ void ksm_migrate_page(struct page *newpage, struct page *oldpage); +@@ -56,6 +52,33 @@ void ksm_migrate_page(struct page *newpa bool reuse_ksm_page(struct page *page, struct vm_area_struct *vma, unsigned long address); @@ -203,15 +192,13 @@ index e48b1e453ff5..095d59310ce0 100644 #else /* !CONFIG_KSM */ static inline int ksm_fork(struct mm_struct *mm, struct mm_struct *oldmm) -@@ -96,4 +119,6 @@ static inline bool reuse_ksm_page(struct page *page, +@@ -96,4 +119,6 @@ static inline bool reuse_ksm_page(struct #endif /* CONFIG_MMU */ #endif /* !CONFIG_KSM */ +#include + #endif /* __LINUX_KSM_H */ -diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h -index 270aa8fd2800..8e1eaf6a2de3 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -353,6 +353,9 @@ struct vm_area_struct { @@ -224,8 +211,6 @@ index 270aa8fd2800..8e1eaf6a2de3 100644 } __randomize_layout; struct core_thread { -diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h -index bda20282746b..dab82e7cc3df 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -206,6 +206,9 @@ enum zone_stat_item { @@ -238,9 +223,6 @@ index bda20282746b..dab82e7cc3df 100644 NR_VM_ZONE_STAT_ITEMS }; enum node_stat_item { -diff --git a/include/linux/sradix-tree.h b/include/linux/sradix-tree.h -new file mode 100644 -index 000000000000..d71edba6b63f --- /dev/null +++ b/include/linux/sradix-tree.h @@ -0,0 +1,77 @@ @@ -321,9 +303,6 @@ index 000000000000..d71edba6b63f +extern void *sradix_tree_lookup(struct sradix_tree_root *root, unsigned long index); + +#endif /* _LINUX_SRADIX_TREE_H */ -diff --git a/include/linux/uksm.h b/include/linux/uksm.h -new file mode 100644 -index 000000000000..bb8651f534f2 --- /dev/null +++ b/include/linux/uksm.h @@ -0,0 +1,149 @@ @@ -476,11 +455,9 @@ index 000000000000..bb8651f534f2 +} +#endif /* !CONFIG_UKSM */ +#endif /* __LINUX_UKSM_H */ -diff --git a/kernel/fork.c b/kernel/fork.c -index 13b38794efb5..acb562745f1c 100644 --- a/kernel/fork.c +++ b/kernel/fork.c -@@ -595,7 +595,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm, +@@ -595,7 +595,7 @@ static __latent_entropy int dup_mmap(str __vma_link_rb(mm, tmp, rb_link, rb_parent); rb_link = &tmp->vm_rb.rb_right; rb_parent = &tmp->vm_rb; @@ -489,11 +466,9 @@ index 13b38794efb5..acb562745f1c 100644 mm->map_count++; if (!(tmp->vm_flags & VM_WIPEONFORK)) retval = copy_page_range(mm, oldmm, mpnt); -diff --git a/lib/Makefile b/lib/Makefile -index c5892807e06f..4b0d37da9fa0 100644 --- a/lib/Makefile +++ b/lib/Makefile -@@ -25,7 +25,7 @@ CFLAGS_string.o := $(call cc-option, -fno-stack-protector) +@@ -35,7 +35,7 @@ CFLAGS_string.o := $(call cc-option, -fn endif lib-y := ctype.o string.o vsprintf.o cmdline.o \ @@ -502,9 +477,6 @@ index c5892807e06f..4b0d37da9fa0 100644 idr.o extable.o sha1.o irq_regs.o argv_split.o \ flex_proportions.o ratelimit.o show_mem.o \ is_single_threaded.o plist.o decompress.o kobject_uevent.o \ -diff --git a/lib/sradix-tree.c b/lib/sradix-tree.c -new file mode 100644 -index 000000000000..ab21e6309b93 --- /dev/null +++ b/lib/sradix-tree.c @@ -0,0 +1,476 @@ @@ -984,8 +956,6 @@ index 000000000000..ab21e6309b93 + + return 0; +} -diff --git a/mm/Kconfig b/mm/Kconfig -index a5dae9a7eb51..eda3a78226b0 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -299,6 +299,32 @@ config KSM @@ -1021,8 +991,6 @@ index a5dae9a7eb51..eda3a78226b0 100644 config DEFAULT_MMAP_MIN_ADDR int "Low address space to protect from user allocation" -diff --git a/mm/Makefile b/mm/Makefile -index d996846697ef..786cb9fad4b9 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -66,7 +66,8 @@ obj-$(CONFIG_SPARSEMEM) += sparse.o @@ -1035,11 +1003,9 @@ index d996846697ef..786cb9fad4b9 100644 obj-$(CONFIG_PAGE_POISONING) += page_poison.o obj-$(CONFIG_SLAB) += slab.o obj-$(CONFIG_SLUB) += slub.o -diff --git a/mm/ksm.c b/mm/ksm.c -index 7905934cd3ad..3e9d0064eaf2 100644 --- a/mm/ksm.c +++ b/mm/ksm.c -@@ -857,17 +857,6 @@ static int unmerge_ksm_pages(struct vm_area_struct *vma, +@@ -858,17 +858,6 @@ static int unmerge_ksm_pages(struct vm_a return err; } @@ -1057,11 +1023,9 @@ index 7905934cd3ad..3e9d0064eaf2 100644 #ifdef CONFIG_SYSFS /* * Only called through the sysfs control interface: -diff --git a/mm/memory.c b/mm/memory.c -index 45442d9a4f52..9beaa229bb0d 100644 --- a/mm/memory.c +++ b/mm/memory.c -@@ -144,6 +144,25 @@ EXPORT_SYMBOL(zero_pfn); +@@ -142,6 +142,25 @@ EXPORT_SYMBOL(zero_pfn); unsigned long highest_memmap_pfn __read_mostly; @@ -1087,15 +1051,15 @@ index 45442d9a4f52..9beaa229bb0d 100644 /* * CONFIG_MMU architectures set up ZERO_PAGE in their paging_init() */ -@@ -159,6 +178,7 @@ void mm_trace_rss_stat(struct mm_struct *mm, int member, long count) - trace_rss_stat(mm, member, count); - } +@@ -153,6 +172,7 @@ static int __init init_zero_pfn(void) + early_initcall(init_zero_pfn); + + #if defined(SPLIT_RSS_COUNTING) void sync_mm_rss(struct mm_struct *mm) -@@ -790,8 +810,13 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, +@@ -784,8 +804,13 @@ copy_one_pte(struct mm_struct *dst_mm, s get_page(page); page_dup_rmap(page, false); rss[mm_counter(page)]++; @@ -1109,7 +1073,7 @@ index 45442d9a4f52..9beaa229bb0d 100644 } out_set_pte: -@@ -1064,8 +1089,10 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb, +@@ -1058,8 +1083,10 @@ again: ptent = ptep_get_and_clear_full(mm, addr, pte, tlb->fullmm); tlb_remove_tlb_entry(tlb, pte, addr); @@ -1121,7 +1085,7 @@ index 45442d9a4f52..9beaa229bb0d 100644 if (!PageAnon(page)) { if (pte_dirty(ptent)) { -@@ -2230,6 +2257,7 @@ static inline bool cow_user_page(struct page *dst, struct page *src, +@@ -2183,6 +2210,7 @@ static inline bool cow_user_page(struct if (likely(src)) { copy_user_highpage(dst, src, addr, vma); @@ -1129,7 +1093,7 @@ index 45442d9a4f52..9beaa229bb0d 100644 return true; } -@@ -2457,6 +2485,7 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf) +@@ -2429,6 +2457,7 @@ static vm_fault_t wp_page_copy(struct vm vmf->address); if (!new_page) goto oom; @@ -1137,7 +1101,7 @@ index 45442d9a4f52..9beaa229bb0d 100644 } else { new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vmf->address); -@@ -2498,7 +2527,9 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf) +@@ -2470,7 +2499,9 @@ static vm_fault_t wp_page_copy(struct vm mm_counter_file(old_page)); inc_mm_counter_fast(mm, MM_ANONPAGES); } @@ -1147,8 +1111,6 @@ index 45442d9a4f52..9beaa229bb0d 100644 inc_mm_counter_fast(mm, MM_ANONPAGES); } flush_cache_page(vma, vmf->address, pte_pfn(vmf->orig_pte)); -diff --git a/mm/mmap.c b/mm/mmap.c -index a7d8c84d19b7..797582240047 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -46,6 +46,7 @@ @@ -1159,7 +1121,7 @@ index a7d8c84d19b7..797582240047 100644 #include #include -@@ -184,6 +185,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma) +@@ -178,6 +179,7 @@ static struct vm_area_struct *remove_vma if (vma->vm_file) fput(vma->vm_file); mpol_put(vma_policy(vma)); @@ -1167,7 +1129,7 @@ index a7d8c84d19b7..797582240047 100644 vm_area_free(vma); return next; } -@@ -736,9 +738,16 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, +@@ -728,9 +730,16 @@ int __vma_adjust(struct vm_area_struct * long adjust_next = 0; int remove_next = 0; @@ -1184,7 +1146,7 @@ index a7d8c84d19b7..797582240047 100644 if (end >= next->vm_end) { /* * vma expands, overlapping all the next, and -@@ -871,6 +880,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, +@@ -863,6 +872,7 @@ again: end_changed = true; } vma->vm_pgoff = pgoff; @@ -1192,7 +1154,7 @@ index a7d8c84d19b7..797582240047 100644 if (adjust_next) { next->vm_start += adjust_next << PAGE_SHIFT; next->vm_pgoff += adjust_next; -@@ -976,6 +986,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, +@@ -968,6 +978,7 @@ again: if (remove_next == 2) { remove_next = 1; end = next->vm_end; @@ -1200,7 +1162,7 @@ index a7d8c84d19b7..797582240047 100644 goto again; } else if (next) -@@ -1002,10 +1013,14 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, +@@ -994,10 +1005,14 @@ again: */ VM_WARN_ON(mm->highest_vm_end != vm_end_gap(vma)); } @@ -1215,7 +1177,7 @@ index a7d8c84d19b7..797582240047 100644 validate_mm(mm); return 0; -@@ -1465,6 +1480,9 @@ unsigned long do_mmap(struct file *file, unsigned long addr, +@@ -1457,6 +1472,9 @@ unsigned long do_mmap(struct file *file, vm_flags |= calc_vm_prot_bits(prot, pkey) | calc_vm_flag_bits(flags) | mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; @@ -1225,7 +1187,7 @@ index a7d8c84d19b7..797582240047 100644 if (flags & MAP_LOCKED) if (!can_do_mlock()) return -EPERM; -@@ -1835,6 +1853,7 @@ unsigned long mmap_region(struct file *file, unsigned long addr, +@@ -1825,6 +1843,7 @@ unsigned long mmap_region(struct file *f allow_write_access(file); } file = vma->vm_file; @@ -1233,7 +1195,7 @@ index a7d8c84d19b7..797582240047 100644 out: perf_event_mmap(vma); -@@ -1877,6 +1896,7 @@ unsigned long mmap_region(struct file *file, unsigned long addr, +@@ -1867,6 +1886,7 @@ allow_write_and_free_vma: if (vm_flags & VM_DENYWRITE) allow_write_access(file); free_vma: @@ -1241,7 +1203,7 @@ index a7d8c84d19b7..797582240047 100644 vm_area_free(vma); unacct_error: if (charged) -@@ -2706,6 +2726,8 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -2709,6 +2729,8 @@ int __split_vma(struct mm_struct *mm, st else err = vma_adjust(vma, vma->vm_start, addr, vma->vm_pgoff, new); @@ -1250,7 +1212,7 @@ index a7d8c84d19b7..797582240047 100644 /* Success. */ if (!err) return 0; -@@ -3011,6 +3033,7 @@ static int do_brk_flags(unsigned long addr, unsigned long len, unsigned long fla +@@ -3015,6 +3037,7 @@ static int do_brk_flags(unsigned long ad if ((flags & (~VM_EXEC)) != 0) return -EINVAL; flags |= VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; @@ -1258,7 +1220,7 @@ index a7d8c84d19b7..797582240047 100644 error = get_unmapped_area(NULL, addr, len, 0, MAP_FIXED); if (offset_in_page(error)) -@@ -3061,6 +3084,7 @@ static int do_brk_flags(unsigned long addr, unsigned long len, unsigned long fla +@@ -3065,6 +3088,7 @@ static int do_brk_flags(unsigned long ad vma->vm_flags = flags; vma->vm_page_prot = vm_get_page_prot(flags); vma_link(mm, vma, prev, rb_link, rb_parent); @@ -1266,7 +1228,7 @@ index a7d8c84d19b7..797582240047 100644 out: perf_event_mmap(vma); mm->total_vm += len >> PAGE_SHIFT; -@@ -3138,6 +3162,12 @@ void exit_mmap(struct mm_struct *mm) +@@ -3142,6 +3166,12 @@ void exit_mmap(struct mm_struct *mm) up_write(&mm->mmap_sem); } @@ -1279,8 +1241,8 @@ index a7d8c84d19b7..797582240047 100644 if (mm->locked_vm) { vma = mm->mmap; while (vma) { -@@ -3172,6 +3202,11 @@ void exit_mmap(struct mm_struct *mm) - vma = remove_vma(vma); +@@ -3177,6 +3207,11 @@ void exit_mmap(struct mm_struct *mm) + cond_resched(); } vm_unacct_memory(nr_accounted); + @@ -1291,7 +1253,7 @@ index a7d8c84d19b7..797582240047 100644 } /* Insert vm structure into process list sorted by address -@@ -3279,6 +3314,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, +@@ -3284,6 +3319,7 @@ struct vm_area_struct *copy_vma(struct v new_vma->vm_ops->open(new_vma); vma_link(mm, new_vma, prev, rb_link, rb_parent); *need_rmap_locks = false; @@ -1299,7 +1261,7 @@ index a7d8c84d19b7..797582240047 100644 } return new_vma; -@@ -3429,6 +3465,7 @@ static struct vm_area_struct *__install_special_mapping( +@@ -3434,6 +3470,7 @@ static struct vm_area_struct *__install_ vm_stat_account(mm, vma->vm_flags, len >> PAGE_SHIFT); perf_event_mmap(vma); @@ -1307,9 +1269,6 @@ index a7d8c84d19b7..797582240047 100644 return vma; -diff --git a/mm/uksm.c b/mm/uksm.c -new file mode 100644 -index 000000000000..ef068d5dc307 --- /dev/null +++ b/mm/uksm.c @@ -0,0 +1,5613 @@ @@ -6926,8 +6885,6 @@ index 000000000000..ef068d5dc307 +late_initcall(uksm_init); +#endif + -diff --git a/mm/vmstat.c b/mm/vmstat.c -index a8222041bd44..7058e8322cbd 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -1168,6 +1168,9 @@ const char * const vmstat_text[] = { diff --git a/PATCH/dnsmasq/900-add-filter-aaaa-option.patch b/PATCH/dnsmasq/900-add-filter-aaaa-option.patch index 4995b593c..4c9bbe62a 100644 --- a/PATCH/dnsmasq/900-add-filter-aaaa-option.patch +++ b/PATCH/dnsmasq/900-add-filter-aaaa-option.patch @@ -1,7 +1,6 @@ -diff -rNEZbwBdu3 a/src/dnsmasq.h b/src/dnsmasq.h ---- a/src/dnsmasq.h 2020-04-09 00:32:53.000000000 +0800 -+++ b/src/dnsmasq.h 2020-06-05 23:03:45.941176855 +0800 -@@ -269,7 +269,8 @@ +--- a/src/dnsmasq.h ++++ b/src/dnsmasq.h +@@ -270,7 +270,8 @@ struct event_desc { #define OPT_SINGLE_PORT 60 #define OPT_LEASE_RENEW 61 #define OPT_LOG_DEBUG 62 @@ -11,10 +10,9 @@ diff -rNEZbwBdu3 a/src/dnsmasq.h b/src/dnsmasq.h #define OPTION_BITS (sizeof(unsigned int)*8) #define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) ) -diff -rNEZbwBdu3 a/src/option.c b/src/option.c ---- a/src/option.c 2020-04-09 00:32:53.000000000 +0800 -+++ b/src/option.c 2020-06-05 23:06:29.880350271 +0800 -@@ -167,6 +167,7 @@ +--- a/src/option.c ++++ b/src/option.c +@@ -170,6 +170,7 @@ struct myoption { #define LOPT_PXE_VENDOR 361 #define LOPT_DYNHOST 362 #define LOPT_LOG_DEBUG 363 @@ -22,7 +20,7 @@ diff -rNEZbwBdu3 a/src/option.c b/src/option.c #ifdef HAVE_GETOPT_LONG static const struct option opts[] = -@@ -339,6 +340,7 @@ +@@ -345,6 +346,7 @@ static const struct myoption opts[] = { "dhcp-ignore-clid", 0, 0, LOPT_IGNORE_CLID }, { "dynamic-host", 1, 0, LOPT_DYNHOST }, { "log-debug", 0, 0, LOPT_LOG_DEBUG }, @@ -30,7 +28,7 @@ diff -rNEZbwBdu3 a/src/option.c b/src/option.c { NULL, 0, 0, 0 } }; -@@ -518,6 +520,7 @@ +@@ -527,6 +529,7 @@ static struct { { LOPT_DUMPFILE, ARG_ONE, "", gettext_noop("Path to debug packet dump file"), NULL }, { LOPT_DUMPMASK, ARG_ONE, "", gettext_noop("Mask which packets to dump"), NULL }, { LOPT_SCRIPT_TIME, OPT_LEASE_RENEW, NULL, gettext_noop("Call dhcp-script when lease expiry changes."), NULL }, @@ -38,10 +36,9 @@ diff -rNEZbwBdu3 a/src/option.c b/src/option.c { 0, 0, NULL, NULL, NULL } }; -diff -rNEZbwBdu3 a/src/rfc1035.c b/src/rfc1035.c ---- a/src/rfc1035.c 2020-04-09 00:32:53.000000000 +0800 -+++ b/src/rfc1035.c 2020-06-05 23:08:46.476106541 +0800 -@@ -1955,6 +1955,15 @@ +--- a/src/rfc1035.c ++++ b/src/rfc1035.c +@@ -1895,6 +1895,15 @@ size_t answer_request(struct dns_header } } diff --git a/PATCH/mbedtls/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch b/PATCH/mbedtls/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch index 22e5b9793..579c32486 100644 --- a/PATCH/mbedtls/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch +++ b/PATCH/mbedtls/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.patch @@ -27,15 +27,13 @@ QEMU seems to also need Then run normal make or cmake etc. --- -diff -ruNa --binary a/ChangeLog.d/armv8_crypto_extensions.txt b/ChangeLog.d/armv8_crypto_extensions.txt ---- a/ChangeLog.d/armv8_crypto_extensions.txt 1970-01-01 08:00:00.000000000 +0800 -+++ b/ChangeLog.d/armv8_crypto_extensions.txt 2021-03-07 15:07:17.781911791 +0800 +--- /dev/null ++++ b/ChangeLog.d/armv8_crypto_extensions.txt @@ -0,0 +1,2 @@ +Features + * Support ARMv8 Cryptography Extensions for AES and GCM. -diff -ruNa --binary a/include/mbedtls/armv8ce_aes.h b/include/mbedtls/armv8ce_aes.h ---- a/include/mbedtls/armv8ce_aes.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/include/mbedtls/armv8ce_aes.h 2021-03-07 15:07:17.781911791 +0800 +--- /dev/null ++++ b/include/mbedtls/armv8ce_aes.h @@ -0,0 +1,63 @@ +/** + * \file armv8ce_aes.h @@ -100,9 +98,8 @@ diff -ruNa --binary a/include/mbedtls/armv8ce_aes.h b/include/mbedtls/armv8ce_ae + const unsigned char b[16] ); + +#endif /* MBEDTLS_ARMV8CE_AES_H */ -diff -ruNa --binary a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h ---- a/include/mbedtls/check_config.h 2020-12-10 20:54:15.000000000 +0800 -+++ b/include/mbedtls/check_config.h 2021-03-07 15:06:45.625543309 +0800 +--- a/include/mbedtls/check_config.h ++++ b/include/mbedtls/check_config.h @@ -95,6 +95,10 @@ #error "MBEDTLS_AESNI_C defined, but not all prerequisites" #endif @@ -119,9 +116,8 @@ diff -ruNa --binary a/include/mbedtls/check_config.h b/include/mbedtls/check_con #endif /* MBEDTLS_CHECK_CONFIG_H */ + -diff -ruNa --binary a/include/mbedtls/config.h b/include/mbedtls/config.h ---- a/include/mbedtls/config.h 2020-12-10 20:54:15.000000000 +0800 -+++ b/include/mbedtls/config.h 2021-03-07 15:14:27.957855484 +0800 +--- a/include/mbedtls/config.h ++++ b/include/mbedtls/config.h @@ -73,6 +73,7 @@ * Requires support for asm() in compiler. * @@ -130,7 +126,7 @@ diff -ruNa --binary a/include/mbedtls/config.h b/include/mbedtls/config.h * library/aria.c * library/timing.c * include/mbedtls/bn_mul.h -@@ -1888,6 +1889,21 @@ +@@ -1905,6 +1906,21 @@ #define MBEDTLS_AESNI_C /** @@ -152,9 +148,8 @@ diff -ruNa --binary a/include/mbedtls/config.h b/include/mbedtls/config.h * \def MBEDTLS_AES_C * * Enable the AES block cipher. -diff -ruNa --binary a/library/aes.c b/library/aes.c ---- a/library/aes.c 2020-12-10 20:54:15.000000000 +0800 -+++ b/library/aes.c 2021-03-07 15:06:45.625543309 +0800 +--- a/library/aes.c ++++ b/library/aes.c @@ -69,7 +69,9 @@ #if defined(MBEDTLS_AESNI_C) #include "mbedtls/aesni.h" @@ -166,7 +161,7 @@ diff -ruNa --binary a/library/aes.c b/library/aes.c #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" -@@ -1052,6 +1054,11 @@ +@@ -1052,6 +1054,11 @@ int mbedtls_aes_crypt_ecb( mbedtls_aes_c return( mbedtls_aesni_crypt_ecb( ctx, mode, input, output ) ); #endif @@ -178,9 +173,8 @@ diff -ruNa --binary a/library/aes.c b/library/aes.c #if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) if( aes_padlock_ace ) { -diff -ruNa --binary a/library/armv8ce_aes.c b/library/armv8ce_aes.c ---- a/library/armv8ce_aes.c 1970-01-01 08:00:00.000000000 +0800 -+++ b/library/armv8ce_aes.c 2021-03-07 15:07:17.781911791 +0800 +--- /dev/null ++++ b/library/armv8ce_aes.c @@ -0,0 +1,142 @@ +/* + * ARMv8 Cryptography Extensions -- Optimized code for AES and GCM @@ -324,10 +318,9 @@ diff -ruNa --binary a/library/armv8ce_aes.c b/library/armv8ce_aes.c +#endif /* MBEDTLS_GCM_C */ + +#endif /* MBEDTLS_ARMV8CE_AES_C */ -diff -ruNa --binary a/library/CMakeLists.txt b/library/CMakeLists.txt ---- a/library/CMakeLists.txt 2020-12-10 20:54:15.000000000 +0800 -+++ b/library/CMakeLists.txt 2021-03-07 15:06:45.625543309 +0800 -@@ -7,6 +7,7 @@ +--- a/library/CMakeLists.txt ++++ b/library/CMakeLists.txt +@@ -7,6 +7,7 @@ set(src_crypto aesni.c arc4.c aria.c @@ -335,9 +328,8 @@ diff -ruNa --binary a/library/CMakeLists.txt b/library/CMakeLists.txt asn1parse.c asn1write.c base64.c -diff -ruNa --binary a/library/gcm.c b/library/gcm.c ---- a/library/gcm.c 2020-12-10 20:54:15.000000000 +0800 -+++ b/library/gcm.c 2021-03-07 15:06:45.625543309 +0800 +--- a/library/gcm.c ++++ b/library/gcm.c @@ -71,6 +71,10 @@ #include "mbedtls/aesni.h" #endif @@ -349,7 +341,7 @@ diff -ruNa --binary a/library/gcm.c b/library/gcm.c #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) #include "mbedtls/aes.h" #include "mbedtls/platform.h" -@@ -140,6 +144,12 @@ +@@ -140,6 +144,12 @@ static int gcm_gen_table( mbedtls_gcm_co if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 ) return( ret ); @@ -362,7 +354,7 @@ diff -ruNa --binary a/library/gcm.c b/library/gcm.c /* pack h as two 64-bits ints, big-endian */ GET_UINT32_BE( hi, h, 0 ); GET_UINT32_BE( lo, h, 4 ); -@@ -248,6 +258,11 @@ +@@ -248,6 +258,11 @@ static void gcm_mult( mbedtls_gcm_contex unsigned char lo, hi, rem; uint64_t zh, zl; @@ -374,10 +366,9 @@ diff -ruNa --binary a/library/gcm.c b/library/gcm.c #if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) { unsigned char h[16]; -diff -ruNa --binary a/library/Makefile b/library/Makefile ---- a/library/Makefile 2020-12-10 20:54:15.000000000 +0800 -+++ b/library/Makefile 2021-03-07 15:12:49.277078224 +0800 -@@ -65,6 +65,7 @@ +--- a/library/Makefile ++++ b/library/Makefile +@@ -65,6 +65,7 @@ endif OBJS_CRYPTO= aes.o aesni.o arc4.o \ aria.o asn1parse.o asn1write.o \ @@ -385,10 +376,9 @@ diff -ruNa --binary a/library/Makefile b/library/Makefile base64.o bignum.o blowfish.o \ camellia.o ccm.o chacha20.o \ chachapoly.o cipher.o cipher_wrap.o \ -diff -ruNa --binary a/library/version_features.c b/library/version_features.c ---- a/library/version_features.c 2020-12-10 20:54:15.000000000 +0800 -+++ b/library/version_features.c 2021-03-07 15:06:45.625543309 +0800 -@@ -583,6 +583,9 @@ +--- a/library/version_features.c ++++ b/library/version_features.c +@@ -586,6 +586,9 @@ static const char *features[] = { #if defined(MBEDTLS_AESNI_C) "MBEDTLS_AESNI_C", #endif /* MBEDTLS_AESNI_C */ @@ -398,4 +388,3 @@ diff -ruNa --binary a/library/version_features.c b/library/version_features.c #if defined(MBEDTLS_AES_C) "MBEDTLS_AES_C", #endif /* MBEDTLS_AES_C */ - diff --git a/PATCH/target_r4s/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch b/PATCH/target_r4s/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch index c4ba0dfed..a49b0fede 100644 --- a/PATCH/target_r4s/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch +++ b/PATCH/target_r4s/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch @@ -7,11 +7,9 @@ Subject: [PATCH] rk3399: reset thermal throttling temp arch/arm64/boot/dts/rockchip/rk3399.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) -diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi -index 2551b238b97c6..a53ff24d92bad 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi -@@ -772,12 +772,12 @@ +@@ -777,12 +777,12 @@ trips { cpu_alert0: cpu_alert0 { @@ -26,7 +24,7 @@ index 2551b238b97c6..a53ff24d92bad 100644 hysteresis = <2000>; type = "passive"; }; -@@ -816,7 +816,7 @@ +@@ -821,7 +821,7 @@ trips { gpu_alert0: gpu_alert0 { diff --git a/PATCH/target_r4s/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch b/PATCH/target_r4s/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch index 75fda5ca0..37ac2c3b7 100644 --- a/PATCH/target_r4s/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch +++ b/PATCH/target_r4s/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch @@ -174,6 +174,6 @@ Co-authored-by: gzelvis #include "rk3399.dtsi" -#include "rk3399-opp.dtsi" +#include "rk3399-nanopi4-opp.dtsi" - + / { chosen { diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index ed1ceb8bc..df289265c 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -51,7 +51,7 @@ wget -qO - https://github.com/QiuSimons/openwrt-NoTengoBattery/commit/afed16a.pa rm -rf ./feeds/packages/net/haproxy svn co https://github.com/openwrt/packages/trunk/net/haproxy feeds/packages/net/haproxy pushd feeds/packages -wget -qO - https://github.com/QiuSimons/packages/commit/e365bd2.patch | patch -p1 +wget -qO - https://github.com/QiuSimons/packages/commit/7ffbfbe.patch | patch -p1 popd # OPENSSL wget -qO - https://github.com/mj22226/openwrt/commit/5e10633.patch | patch -p1 @@ -198,14 +198,12 @@ git clone --depth 1 https://github.com/jerrykuku/luci-app-jd-dailybonus.git pack # MentoHUST git clone --depth 1 https://github.com/BoringCat/luci-app-mentohust package/new/luci-app-mentohust git clone --depth 1 https://github.com/KyleRicardo/MentoHUST-OpenWrt-ipk package/new/MentoHUST -# Moschinadns -svn co https://github.com/QiuSimons/openwrt-packages/branches/main/mos-chinadns package/new/mos-chinadns -svn co https://github.com/QiuSimons/openwrt-packages/branches/main/luci-app-moschinadns package/new/luci-app-moschinadns # Mosdns -svn co https://github.com/immortalwrt/packages/trunk/net/mosdns feeds/packages/net/mosdns -ln -sf ../../../feeds/packages/net/mosdns ./package/feeds/packages/mosdns -sed -i '/config.yaml/d' feeds/packages/net/mosdns/Makefile -sed -i '/mosdns-init-openwrt/d' feeds/packages/net/mosdns/Makefile +#svn co https://github.com/immortalwrt/packages/trunk/net/mosdns feeds/packages/net/mosdns +#ln -sf ../../../feeds/packages/net/mosdns ./package/feeds/packages/mosdns +#sed -i '/config.yaml/d' feeds/packages/net/mosdns/Makefile +#sed -i '/mosdns-init-openwrt/d' feeds/packages/net/mosdns/Makefile +svn co https://github.com/QiuSimons/openwrt-mos/trunk/mosdns package/new/mosdns svn co https://github.com/QiuSimons/openwrt-mos/trunk/luci-app-mosdns package/new/luci-app-mosdns # 流量监管 svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-netdata package/lean/luci-app-netdata @@ -283,7 +281,7 @@ ln -sf ../../../feeds/packages/net/kcptun ./package/feeds/packages/kcptun svn co https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/lean/luci-app-ssr-plus rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans pushd package/lean -wget -qO - https://github.com/fw876/helloworld/pull/656.patch | patch -p1 +#wget -qO - https://github.com/fw876/helloworld/pull/656.patch | patch -p1 wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/5bbf6e7.patch | patch -p1 wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/323fbf0.patch | patch -p1 popd diff --git a/SEED/R2C/config.seed b/SEED/R2C/config.seed index b43ba95f1..3807dff60 100644 --- a/SEED/R2C/config.seed +++ b/SEED/R2C/config.seed @@ -13,7 +13,7 @@ CONFIG_NODEJS_14=y CONFIG_NODEJS_ICU_NONE=y CONFIG_DEVEL=y CONFIG_TOOLCHAINOPTS=y -CONFIG_GCC_USE_VERSION_7=y +CONFIG_GCC_USE_VERSION_8=y ### BASIC ### CONFIG_PACKAGE_r8169-firmware=y diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 51ec413ad..dfdfd402f 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -13,7 +13,7 @@ CONFIG_NODEJS_14=y CONFIG_NODEJS_ICU_NONE=y CONFIG_DEVEL=y CONFIG_TOOLCHAINOPTS=y -CONFIG_GCC_USE_VERSION_7=y +CONFIG_GCC_USE_VERSION_8=y ### BASIC ### CONFIG_PACKAGE_r8169-firmware=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index e8f322737..9c1df3b54 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -13,7 +13,7 @@ CONFIG_NODEJS_14=y CONFIG_NODEJS_ICU_NONE=y CONFIG_DEVEL=y CONFIG_TOOLCHAINOPTS=y -CONFIG_GCC_USE_VERSION_7=y +CONFIG_GCC_USE_VERSION_8=y ### BASIC ### CONFIG_PACKAGE_r8169-firmware=y diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index 9dcdcf87f..f1f388646 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -14,7 +14,7 @@ CONFIG_NODEJS_14=y CONFIG_NODEJS_ICU_NONE=y CONFIG_DEVEL=y CONFIG_TOOLCHAINOPTS=y -CONFIG_GCC_USE_VERSION_7=y +CONFIG_GCC_USE_VERSION_8=y ### BASIC ### CONFIG_PACKAGE_addition-trans-zh=y From a63c98ac2285b67b45a48dbd7d6f58452caaf738 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 12 Oct 2021 16:35:10 +0800 Subject: [PATCH 199/244] klever1988/cachewrtbuild/tree/test --- .github/workflows/R2C-OpenWrt.yml | 15 ++++++--------- .github/workflows/R2S-OpenWrt.yml | 15 ++++++--------- .github/workflows/R4S-OpenWrt.yml | 15 ++++++--------- .github/workflows/X86-OpenWrt.yml | 15 ++++++--------- 4 files changed, 24 insertions(+), 36 deletions(-) diff --git a/.github/workflows/R2C-OpenWrt.yml b/.github/workflows/R2C-OpenWrt.yml index 104958eaf..6236a384a 100644 --- a/.github/workflows/R2C-OpenWrt.yml +++ b/.github/workflows/R2C-OpenWrt.yml @@ -73,19 +73,16 @@ jobs: mv ../SEED/R2C/config.seed .config #echo -e 'CONFIG_DEVEL=y\nCONFIG_CCACHE=y' >> .config make defconfig - - name: Smart chmod + - name: Get Architecture + working-directory: ${{ github.workspace }}/openwrt run: | - MY_Filter=$(mktemp) - echo '/\.git' > ${MY_Filter} - echo '/\.svn' >> ${MY_Filter} - find ./ -maxdepth 1 | grep -v '\./$' | grep -v '/\.git' | xargs -s1024 chmod -R u=rwX,og=rX - find ./ -type f | grep -v -f ${MY_Filter} | xargs -s1024 file | grep 'executable\|ELF' | cut -d ':' -f1 | xargs -s1024 chmod 755 - rm -f ${MY_Filter} - unset MY_Filter + TARGET_DEVICE_ARCH="$(grep "^CONFIG_TARGET_.*_.*=y$" ".config" | head -n 1 | sed 's/^CONFIG_TARGET_//g' | awk -F '_' '{print $1}')" + echo "TARGET_DEVICE_ARCH=${TARGET_DEVICE_ARCH}-" >>$GITHUB_ENV - name: Cache - uses: klever1988/cachewrtbuild@main + uses: klever1988/cachewrtbuild@test with: ccache: 'true' + mixkey: ${{ env.TARGET_DEVICE_ARCH }} prefix: ${{ github.workspace }}/openwrt - name: Make Download run: | diff --git a/.github/workflows/R2S-OpenWrt.yml b/.github/workflows/R2S-OpenWrt.yml index a4e704ae9..39d0e210f 100644 --- a/.github/workflows/R2S-OpenWrt.yml +++ b/.github/workflows/R2S-OpenWrt.yml @@ -73,19 +73,16 @@ jobs: mv ../SEED/R2S/config.seed .config #echo -e 'CONFIG_DEVEL=y\nCONFIG_CCACHE=y' >> .config make defconfig - - name: Smart chmod + - name: Get Architecture + working-directory: ${{ github.workspace }}/openwrt run: | - MY_Filter=$(mktemp) - echo '/\.git' > ${MY_Filter} - echo '/\.svn' >> ${MY_Filter} - find ./ -maxdepth 1 | grep -v '\./$' | grep -v '/\.git' | xargs -s1024 chmod -R u=rwX,og=rX - find ./ -type f | grep -v -f ${MY_Filter} | xargs -s1024 file | grep 'executable\|ELF' | cut -d ':' -f1 | xargs -s1024 chmod 755 - rm -f ${MY_Filter} - unset MY_Filter + TARGET_DEVICE_ARCH="$(grep "^CONFIG_TARGET_.*_.*=y$" ".config" | head -n 1 | sed 's/^CONFIG_TARGET_//g' | awk -F '_' '{print $1}')" + echo "TARGET_DEVICE_ARCH=${TARGET_DEVICE_ARCH}-" >>$GITHUB_ENV - name: Cache - uses: klever1988/cachewrtbuild@main + uses: klever1988/cachewrtbuild@test with: ccache: 'true' + mixkey: ${{ env.TARGET_DEVICE_ARCH }} prefix: ${{ github.workspace }}/openwrt - name: Make Download run: | diff --git a/.github/workflows/R4S-OpenWrt.yml b/.github/workflows/R4S-OpenWrt.yml index 5b11a9e5c..32b4d94ed 100644 --- a/.github/workflows/R4S-OpenWrt.yml +++ b/.github/workflows/R4S-OpenWrt.yml @@ -73,19 +73,16 @@ jobs: mv ../SEED/R4S/config.seed .config #echo -e 'CONFIG_DEVEL=y\nCONFIG_CCACHE=y' >> .config make defconfig - - name: Smart chmod + - name: Get Architecture + working-directory: ${{ github.workspace }}/openwrt run: | - MY_Filter=$(mktemp) - echo '/\.git' > ${MY_Filter} - echo '/\.svn' >> ${MY_Filter} - find ./ -maxdepth 1 | grep -v '\./$' | grep -v '/\.git' | xargs -s1024 chmod -R u=rwX,og=rX - find ./ -type f | grep -v -f ${MY_Filter} | xargs -s1024 file | grep 'executable\|ELF' | cut -d ':' -f1 | xargs -s1024 chmod 755 - rm -f ${MY_Filter} - unset MY_Filter + TARGET_DEVICE_ARCH="$(grep "^CONFIG_TARGET_.*_.*=y$" ".config" | head -n 1 | sed 's/^CONFIG_TARGET_//g' | awk -F '_' '{print $1}')" + echo "TARGET_DEVICE_ARCH=${TARGET_DEVICE_ARCH}-" >>$GITHUB_ENV - name: Cache - uses: klever1988/cachewrtbuild@main + uses: klever1988/cachewrtbuild@test with: ccache: 'true' + mixkey: ${{ env.TARGET_DEVICE_ARCH }} prefix: ${{ github.workspace }}/openwrt - name: Make Download run: | diff --git a/.github/workflows/X86-OpenWrt.yml b/.github/workflows/X86-OpenWrt.yml index 02b01d220..c86cd0bcd 100644 --- a/.github/workflows/X86-OpenWrt.yml +++ b/.github/workflows/X86-OpenWrt.yml @@ -73,19 +73,16 @@ jobs: mv ../SEED/X86/config.seed .config #echo -e 'CONFIG_DEVEL=y\nCONFIG_CCACHE=y' >> .config make defconfig - - name: Smart chmod + - name: Get Architecture + working-directory: ${{ github.workspace }}/openwrt run: | - MY_Filter=$(mktemp) - echo '/\.git' > ${MY_Filter} - echo '/\.svn' >> ${MY_Filter} - find ./ -maxdepth 1 | grep -v '\./$' | grep -v '/\.git' | xargs -s1024 chmod -R u=rwX,og=rX - find ./ -type f | grep -v -f ${MY_Filter} | xargs -s1024 file | grep 'executable\|ELF' | cut -d ':' -f1 | xargs -s1024 chmod 755 - rm -f ${MY_Filter} - unset MY_Filter + TARGET_DEVICE_ARCH="$(grep "^CONFIG_TARGET_.*_.*=y$" ".config" | head -n 1 | sed 's/^CONFIG_TARGET_//g' | awk -F '_' '{print $1}')" + echo "TARGET_DEVICE_ARCH=${TARGET_DEVICE_ARCH}-" >>$GITHUB_ENV - name: Cache - uses: klever1988/cachewrtbuild@main + uses: klever1988/cachewrtbuild@test with: ccache: 'true' + mixkey: ${{ env.TARGET_DEVICE_ARCH }} prefix: ${{ github.workspace }}/openwrt - name: Make Download run: | From 5820496552fb03ece30b717a906378300b62b934 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 12 Oct 2021 16:55:21 +0800 Subject: [PATCH 200/244] auto format code --- SCRIPTS/02_prepare_package.sh | 18 ++-- SCRIPTS/03_convert_translation.sh | 58 ++++++------ SCRIPTS/04_remove_upx.sh | 9 +- SCRIPTS/05_create_acl_for_luci.sh | 142 +++++++++++++++--------------- SCRIPTS/06_cleaning.sh | 2 +- SCRIPTS/R2S/02_target_only.sh | 8 +- SCRIPTS/R4S/02_target_only.sh | 8 +- SCRIPTS/X86/02_target_only.sh | 8 +- 8 files changed, 122 insertions(+), 131 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index df289265c..ef1f48b1d 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -19,19 +19,19 @@ wget -P scripts/ https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/sc wget -P include/ https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/include/download.mk sed -i '/unshift/d' scripts/download.pl sed -i '/mirror02/d' scripts/download.pl -echo "net.netfilter.nf_conntrack_helper = 1" >> ./package/kernel/linux/files/sysctl-nf-conntrack.conf +echo "net.netfilter.nf_conntrack_helper = 1" >>./package/kernel/linux/files/sysctl-nf-conntrack.conf ### 必要的 Patches ### # Patch arm64 型号名称 wget -P target/linux/generic/hack-5.4/ https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/target/linux/generic/hack-5.4/312-arm64-cpuinfo-Add-model-name-in-proc-cpuinfo-for-64bit-ta.patch # Patch jsonc -patch -p1 < ../PATCH/jsonc/use_json_object_new_int64.patch +patch -p1 <../PATCH/jsonc/use_json_object_new_int64.patch # Patch dnsmasq -patch -p1 < ../PATCH/dnsmasq/dnsmasq-add-filter-aaaa-option.patch -patch -p1 < ../PATCH/dnsmasq/luci-add-filter-aaaa-option.patch +patch -p1 <../PATCH/dnsmasq/dnsmasq-add-filter-aaaa-option.patch +patch -p1 <../PATCH/dnsmasq/luci-add-filter-aaaa-option.patch cp -f ../PATCH/dnsmasq/900-add-filter-aaaa-option.patch ./package/network/services/dnsmasq/patches/900-add-filter-aaaa-option.patch # BBRv2 -patch -p1 < ../PATCH/BBRv2/openwrt-kmod-bbr2.patch +patch -p1 <../PATCH/BBRv2/openwrt-kmod-bbr2.patch cp -f ../PATCH/BBRv2/693-Add_BBRv2_congestion_control_for_Linux_TCP.patch ./target/linux/generic/hack-5.4/693-Add_BBRv2_congestion_control_for_Linux_TCP.patch wget -qO - https://github.com/openwrt/openwrt/commit/cfaf039.patch | patch -p1 # CacULE @@ -44,7 +44,7 @@ cp -rf ../PATCH/LRNG/* ./target/linux/generic/hack-5.4/ echo ' CONFIG_LRNG=y CONFIG_LRNG_JENT=y -' >> ./target/linux/generic/config-5.4 +' >>./target/linux/generic/config-5.4 # Grub 2 wget -qO - https://github.com/QiuSimons/openwrt-NoTengoBattery/commit/afed16a.patch | patch -p1 # Haproxy @@ -61,12 +61,12 @@ wget -qO - https://github.com/mj22226/openwrt/commit/5e10633.patch | patch -p1 pushd target/linux/generic/hack-5.4 wget https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/target/linux/generic/hack-5.4/952-net-conntrack-events-support-multiple-registrant.patch popd -# Patch FireWall 以增添 FullCone 功能 +# Patch FireWall 以增添 FullCone 功能 mkdir package/network/config/firewall/patches wget -P package/network/config/firewall/patches/ https://github.com/immortalwrt/immortalwrt/raw/master/package/network/config/firewall/patches/fullconenat.patch wget -qO- https://github.com/msylgj/R2S-R4S-OpenWrt/raw/21.02/PATCHES/001-fix-firewall-flock.patch | patch -p1 # Patch LuCI 以增添 FullCone 开关 -patch -p1 < ../PATCH/firewall/luci-app-firewall_add_fullcone.patch +patch -p1 <../PATCH/firewall/luci-app-firewall_add_fullcone.patch # FullCone 相关组件 svn co https://github.com/Lienol/openwrt/trunk/package/network/fullconenat package/network/fullconenat @@ -114,7 +114,7 @@ svn co https://github.com/nxhack/openwrt-node-packages/trunk/node-yarn feeds/pac ln -sf ../../../feeds/packages/lang/node-yarn ./package/feeds/packages/node-yarn # R8168驱动 git clone -b master --depth 1 https://github.com/BROBIRD/openwrt-r8168.git package/new/r8168 -patch -p1 < ../PATCH/r8168/r8168-fix_LAN_led-for_r4s-from_TL.patch +patch -p1 <../PATCH/r8168/r8168-fix_LAN_led-for_r4s-from_TL.patch # R8152驱动 svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/kernel/r8152 package/new/r8152 # UPX 可执行软件压缩 diff --git a/SCRIPTS/03_convert_translation.sh b/SCRIPTS/03_convert_translation.sh index 23232a7e4..b301fd872 100644 --- a/SCRIPTS/03_convert_translation.sh +++ b/SCRIPTS/03_convert_translation.sh @@ -5,47 +5,41 @@ # Convert translation files zh-cn to zh_Hans # The script is still in testing, welcome to report bugs. -po_file="$({ find |grep -E "[a-z0-9]+\.zh\-cn.+po"; } 2>"/dev/null")" -for a in ${po_file} -do - [ -n "$(grep "Language: zh_CN" "$a")" ] && sed -i "s/Language: zh_CN/Language: zh_Hans/g" "$a" - po_new_file="$(echo -e "$a"|sed "s/zh-cn/zh_Hans/g")" - mv "$a" "${po_new_file}" 2>"/dev/null" +po_file="$({ find | grep -E "[a-z0-9]+\.zh\-cn.+po"; } 2>"/dev/null")" +for a in ${po_file}; do + [ -n "$(grep "Language: zh_CN" "$a")" ] && sed -i "s/Language: zh_CN/Language: zh_Hans/g" "$a" + po_new_file="$(echo -e "$a" | sed "s/zh-cn/zh_Hans/g")" + mv "$a" "${po_new_file}" 2>"/dev/null" done -po_file2="$({ find |grep "/zh-cn/" |grep "\.po"; } 2>"/dev/null")" -for b in ${po_file2} -do - [ -n "$(grep "Language: zh_CN" "$b")" ] && sed -i "s/Language: zh_CN/Language: zh_Hans/g" "$b" - po_new_file2="$(echo -e "$b"|sed "s/zh-cn/zh_Hans/g")" - mv "$b" "${po_new_file2}" 2>"/dev/null" +po_file2="$({ find | grep "/zh-cn/" | grep "\.po"; } 2>"/dev/null")" +for b in ${po_file2}; do + [ -n "$(grep "Language: zh_CN" "$b")" ] && sed -i "s/Language: zh_CN/Language: zh_Hans/g" "$b" + po_new_file2="$(echo -e "$b" | sed "s/zh-cn/zh_Hans/g")" + mv "$b" "${po_new_file2}" 2>"/dev/null" done -lmo_file="$({ find |grep -E "[a-z0-9]+\.zh_Hans.+lmo"; } 2>"/dev/null")" -for c in ${lmo_file} -do - lmo_new_file="$(echo -e "$c"|sed "s/zh_Hans/zh-cn/g")" - mv "$c" "${lmo_new_file}" 2>"/dev/null" +lmo_file="$({ find | grep -E "[a-z0-9]+\.zh_Hans.+lmo"; } 2>"/dev/null")" +for c in ${lmo_file}; do + lmo_new_file="$(echo -e "$c" | sed "s/zh_Hans/zh-cn/g")" + mv "$c" "${lmo_new_file}" 2>"/dev/null" done -lmo_file2="$({ find |grep "/zh_Hans/" |grep "\.lmo"; } 2>"/dev/null")" -for d in ${lmo_file2} -do - lmo_new_file2="$(echo -e "$d"|sed "s/zh_Hans/zh-cn/g")" - mv "$d" "${lmo_new_file2}" 2>"/dev/null" +lmo_file2="$({ find | grep "/zh_Hans/" | grep "\.lmo"; } 2>"/dev/null")" +for d in ${lmo_file2}; do + lmo_new_file2="$(echo -e "$d" | sed "s/zh_Hans/zh-cn/g")" + mv "$d" "${lmo_new_file2}" 2>"/dev/null" done -po_dir="$({ find |grep "/zh-cn" |sed "/\.po/d" |sed "/\.lmo/d"; } 2>"/dev/null")" -for e in ${po_dir} -do - po_new_dir="$(echo -e "$e"|sed "s/zh-cn/zh_Hans/g")" - mv "$e" "${po_new_dir}" 2>"/dev/null" +po_dir="$({ find | grep "/zh-cn" | sed "/\.po/d" | sed "/\.lmo/d"; } 2>"/dev/null")" +for e in ${po_dir}; do + po_new_dir="$(echo -e "$e" | sed "s/zh-cn/zh_Hans/g")" + mv "$e" "${po_new_dir}" 2>"/dev/null" done -makefile_file="$({ find|grep Makefile |sed "/Makefile./d"; } 2>"/dev/null")" -for f in ${makefile_file} -do - [ -n "$(grep "zh-cn" "$f")" ] && sed -i "s/zh-cn/zh_Hans/g" "$f" - [ -n "$(grep "zh_Hans.lmo" "$f")" ] && sed -i "s/zh_Hans.lmo/zh-cn.lmo/g" "$f" +makefile_file="$({ find | grep Makefile | sed "/Makefile./d"; } 2>"/dev/null")" +for f in ${makefile_file}; do + [ -n "$(grep "zh-cn" "$f")" ] && sed -i "s/zh-cn/zh_Hans/g" "$f" + [ -n "$(grep "zh_Hans.lmo" "$f")" ] && sed -i "s/zh_Hans.lmo/zh-cn.lmo/g" "$f" done exit 0 diff --git a/SCRIPTS/04_remove_upx.sh b/SCRIPTS/04_remove_upx.sh index fe438a5ad..26fb7e6d3 100644 --- a/SCRIPTS/04_remove_upx.sh +++ b/SCRIPTS/04_remove_upx.sh @@ -4,9 +4,8 @@ # -------------------------------------------------------- # Remove upx commands -makefile_file="$({ find package|grep Makefile |sed "/Makefile./d"; } 2>"/dev/null")" -for a in ${makefile_file} -do - [ -n "$(grep "upx" "$a")" ] && sed -i "/upx/d" "$a" +makefile_file="$({ find package | grep Makefile | sed "/Makefile./d"; } 2>"/dev/null")" +for a in ${makefile_file}; do + [ -n "$(grep "upx" "$a")" ] && sed -i "/upx/d" "$a" done -exit 0 \ No newline at end of file +exit 0 diff --git a/SCRIPTS/05_create_acl_for_luci.sh b/SCRIPTS/05_create_acl_for_luci.sh index a0138ea11..2e1c24103 100644 --- a/SCRIPTS/05_create_acl_for_luci.sh +++ b/SCRIPTS/05_create_acl_for_luci.sh @@ -8,37 +8,37 @@ error_font="\033[31m[Error]$\033[0m " success_font="\033[32m[Success]\033[0m " info_font="\033[36m[Info]\033[0m " -function echo_green_bg(){ - echo -e "\033[42;37m$1\033[0m" +function echo_green_bg() { + echo -e "\033[42;37m$1\033[0m" } -function echo_yellow_bg(){ - echo -e "\033[43;37m$1\033[0m" +function echo_yellow_bg() { + echo -e "\033[43;37m$1\033[0m" } -function echo_red_bg(){ - echo -e "\033[41;37m$1\033[0m" +function echo_red_bg() { + echo -e "\033[41;37m$1\033[0m" } -function clean_outdated_files(){ - rm -f "create_acl_for_luci.err" "create_acl_for_luci.warn" "create_acl_for_luci.ok" +function clean_outdated_files() { + rm -f "create_acl_for_luci.err" "create_acl_for_luci.warn" "create_acl_for_luci.ok" } -function check_if_acl_exist(){ - ls "$1"/root/usr/share/rpcd/acl.d/*.json >/dev/null 2>&1 && return 0 || return 1 +function check_if_acl_exist() { + ls "$1"/root/usr/share/rpcd/acl.d/*.json >/dev/null 2>&1 && return 0 || return 1 } -function check_config_files(){ - [ "$(ls "$1"/root/etc/config/* 2>/dev/null | wc -l)" -ne "1" ] && return 0 || return 1 +function check_config_files() { + [ "$(ls "$1"/root/etc/config/* 2>/dev/null | wc -l)" -ne "1" ] && return 0 || return 1 } -function get_config_name(){ - ls "$1"/root/etc/config/* 2>/dev/null | awk -F '/' '{print $NF}' +function get_config_name() { + ls "$1"/root/etc/config/* 2>/dev/null | awk -F '/' '{print $NF}' } -function create_acl_file(){ - mkdir -p "$1" - echo -e "{ +function create_acl_file() { + mkdir -p "$1" + echo -e "{ \"$2\": { \"description\": \"Grant UCI access for $2\", \"read\": { @@ -48,70 +48,68 @@ function create_acl_file(){ \"uci\": [ \"$3\" ] } } -}" > "$1/$2.json" +}" >"$1/$2.json" } -function auto_create_acl(){ - luci_app_list="$(find package -maxdepth 2 | grep -Eo "package/.+/luci-app-[a-zA-Z0-9_-]+" | sort -s)" +function auto_create_acl() { + luci_app_list="$(find package -maxdepth 2 | grep -Eo "package/.+/luci-app-[a-zA-Z0-9_-]+" | sort -s)" - [ "$(echo -e "${luci_app_list}" | wc -l)" -gt "0" ] && for i in ${luci_app_list} - do - if check_if_acl_exist "$i"; then - echo_yellow_bg "$i: has ACL file already, skipping..." | tee -a create_acl_for_luci.warn - elif check_config_files "$i"; then - echo_red_bg "$i: has no/multi config file(s), skipping..." | tee -a create_acl_for_luci.err - else - create_acl_file "$i/root/usr/share/rpcd/acl.d" "${i##*/}" "$(get_config_name "$i")" - echo_green_bg "$i: ACL file has been generated." | tee -a create_acl_for_luci.ok - fi - done + [ "$(echo -e "${luci_app_list}" | wc -l)" -gt "0" ] && for i in ${luci_app_list}; do + if check_if_acl_exist "$i"; then + echo_yellow_bg "$i: has ACL file already, skipping..." | tee -a create_acl_for_luci.warn + elif check_config_files "$i"; then + echo_red_bg "$i: has no/multi config file(s), skipping..." | tee -a create_acl_for_luci.err + else + create_acl_file "$i/root/usr/share/rpcd/acl.d" "${i##*/}" "$(get_config_name "$i")" + echo_green_bg "$i: ACL file has been generated." | tee -a create_acl_for_luci.ok + fi + done } -while getopts "achml:n:p:" input_arg -do - case $input_arg in - a) - clean_outdated_files - auto_create_acl - exit - ;; - m) - manual_mode=1 - ;; - p) - acl_path="$OPTARG" - ;; - l) - luci_name="$OPTARG" - ;; - n) - conf_name="$OPTARG" - ;; - c) - clean_outdated_files - exit - ;; - h|?|*) - echo -e "${info_font}Usage: $0 [-a|-m (-p ) -l -n |-c]" - exit 2 - ;; - esac +while getopts "achml:n:p:" input_arg; do + case $input_arg in + a) + clean_outdated_files + auto_create_acl + exit + ;; + m) + manual_mode=1 + ;; + p) + acl_path="$OPTARG" + ;; + l) + luci_name="$OPTARG" + ;; + n) + conf_name="$OPTARG" + ;; + c) + clean_outdated_files + exit + ;; + h | ? | *) + echo -e "${info_font}Usage: $0 [-a|-m (-p ) -l -n |-c]" + exit 2 + ;; + esac done [ "$?" -ne "0" ] && exit if [ "*${manual_mode}*" == "*1*" ]; then - acl_path="${acl_path:-root/usr/share/rpcd/acl.d}" - if create_acl_file "${acl_path}" "${luci_name}" "${conf_name}"; then - echo -e "${success_font}Output file: $(ls "${acl_path}/${luci_name}.json")" - echo_green_bg "$(cat "${acl_path}/${luci_name}.json")" - echo_green_bg "${luci_name}: ACL file has been generated." >> "create_acl_for_luci.ok" - [ -e "create_acl_for_luci.err" ] && sed -i "/${luci_name}/d" "create_acl_for_luci.err" - else - echo -e "${error_font}Failed to create file ${acl_path}/${luci_name}.json" - echo_red_bg "${luci_name}: Failed to create ACL file." >> "create_acl_for_luci.err" - fi + acl_path="${acl_path:-root/usr/share/rpcd/acl.d}" + if create_acl_file "${acl_path}" "${luci_name}" "${conf_name}"; then + echo -e "${success_font}Output file: $(ls "${acl_path}/${luci_name}.json")" + echo_green_bg "$(cat "${acl_path}/${luci_name}.json")" + echo_green_bg "${luci_name}: ACL file has been generated." >>"create_acl_for_luci.ok" + [ -e "create_acl_for_luci.err" ] && sed -i "/${luci_name}/d" "create_acl_for_luci.err" + else + echo -e "${error_font}Failed to create file ${acl_path}/${luci_name}.json" + echo_red_bg "${luci_name}: Failed to create ACL file." >>"create_acl_for_luci.err" + fi else - echo -e "${info_font}Usage: $0 [-a|-m -p -l -n |-c]" - exit 2 + echo -e "${info_font}Usage: $0 [-a|-m -p -l -n |-c]" + exit 2 fi diff --git a/SCRIPTS/06_cleaning.sh b/SCRIPTS/06_cleaning.sh index 1319e4be4..5fcedfc15 100644 --- a/SCRIPTS/06_cleaning.sh +++ b/SCRIPTS/06_cleaning.sh @@ -1,6 +1,6 @@ #!/bin/bash -rm -rf `ls | grep -v "squashfs"` +rm -rf $(ls | grep -v "squashfs") gzip -d *.gz gzip *.img diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index 8962db65f..f1a8f46e3 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -13,13 +13,13 @@ wget -P target/linux/rockchip/armv8/base-files/usr/bin/ https://github.com/frien sed -i '/CONFIG_NR_CPUS/d' ./target/linux/rockchip/armv8/config-5.4 echo ' CONFIG_NR_CPUS=4 -' >> ./target/linux/rockchip/armv8/config-5.4 +' >>./target/linux/rockchip/armv8/config-5.4 # UKSM echo ' CONFIG_KSM=y CONFIG_UKSM=y -' >> ./target/linux/rockchip/armv8/config-5.4 +' >>./target/linux/rockchip/armv8/config-5.4 # 配置 IRQ 并默认关闭 eth0 offloading rx/rx sed -i '/set_interface_core 4 "eth1"/a\set_interface_core 8 "ff160000" "ff160000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity @@ -31,9 +31,9 @@ sed -i 's,"eth1" "eth0","eth0" "eth1",g' target/linux/rockchip/armv8/base-files/ sed -i "s,'eth1' 'eth0','eth0' 'eth1',g" target/linux/rockchip/armv8/base-files/etc/board.d/02_network #Vermagic -latest_version="$(curl -s https://github.com/openwrt/openwrt/releases |grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" |sed -n '/21/p' |sed -n 1p |sed 's/v//g' |sed 's/.tar.gz//g')" +latest_version="$(curl -s https://github.com/openwrt/openwrt/releases | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/21/p' | sed -n 1p | sed 's/v//g' | sed 's/.tar.gz//g')" wget https://downloads.openwrt.org/releases/${latest_version}/targets/rockchip/armv8/packages/Packages.gz -zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' > .vermagic +zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' >.vermagic sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic/' include/kernel-defaults.mk # 预配置一些插件 diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index 6ff03f3e2..79b5f6800 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -14,22 +14,22 @@ wget -P target/linux/rockchip/armv8/base-files/usr/bin/ https://github.com/frien sed -i '/CONFIG_NR_CPUS/d' ./target/linux/rockchip/armv8/config-5.4 echo ' CONFIG_NR_CPUS=6 -' >> ./target/linux/rockchip/armv8/config-5.4 +' >>./target/linux/rockchip/armv8/config-5.4 # UKSM echo ' CONFIG_KSM=y CONFIG_UKSM=y -' >> ./target/linux/rockchip/armv8/config-5.4 +' >>./target/linux/rockchip/armv8/config-5.4 # IRQ 调优 sed -i '/set_interface_core 20 "eth1"/a\set_interface_core 8 "ff3c0000" "ff3c0000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity sed -i '/set_interface_core 20 "eth1"/a\ethtool -C eth0 rx-usecs 1000 rx-frames 25 tx-usecs 100 tx-frames 25' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity #Vermagic -latest_version="$(curl -s https://github.com/openwrt/openwrt/releases |grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" |sed -n '/21/p' |sed -n 1p |sed 's/v//g' |sed 's/.tar.gz//g')" +latest_version="$(curl -s https://github.com/openwrt/openwrt/releases | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/21/p' | sed -n 1p | sed 's/v//g' | sed 's/.tar.gz//g')" wget https://downloads.openwrt.org/releases/${latest_version}/targets/rockchip/armv8/packages/Packages.gz -zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' > .vermagic +zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' >.vermagic sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic/' include/kernel-defaults.mk # 预配置一些插件 diff --git a/SCRIPTS/X86/02_target_only.sh b/SCRIPTS/X86/02_target_only.sh index 7fc74d84c..778495859 100644 --- a/SCRIPTS/X86/02_target_only.sh +++ b/SCRIPTS/X86/02_target_only.sh @@ -10,18 +10,18 @@ sed -i '/Rust_Server:/d' package/new/luci-app-passwall/Makefile # 内核加解密组件 echo ' CONFIG_CRYPTO_AES_NI_INTEL=y -' >> ./target/linux/x86/64/config-5.4 +' >>./target/linux/x86/64/config-5.4 # UKSM echo ' CONFIG_KSM=y CONFIG_UKSM=y -' >> ./target/linux/x86/64/config-5.4 +' >>./target/linux/x86/64/config-5.4 #Vermagic -latest_version="$(curl -s https://github.com/openwrt/openwrt/releases |grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" |sed -n '/21/p' |sed -n 1p |sed 's/v//g' |sed 's/.tar.gz//g')" +latest_version="$(curl -s https://github.com/openwrt/openwrt/releases | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/21/p' | sed -n 1p | sed 's/v//g' | sed 's/.tar.gz//g')" wget https://downloads.openwrt.org/releases/${latest_version}/targets/x86/64/packages/Packages.gz -zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' > .vermagic +zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' >.vermagic sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic/' include/kernel-defaults.mk # 预配置一些插件 From 4d0c8a2d16fa5551d0f365d5b4fd9141e3f25d62 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 18 Oct 2021 14:04:22 +0800 Subject: [PATCH 201/244] Adapt to upstream change --- SCRIPTS/02_prepare_package.sh | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index ef1f48b1d..cae38b591 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -54,7 +54,9 @@ pushd feeds/packages wget -qO - https://github.com/QiuSimons/packages/commit/7ffbfbe.patch | patch -p1 popd # OPENSSL -wget -qO - https://github.com/mj22226/openwrt/commit/5e10633.patch | patch -p1 +wget -P package/libs/openssl/patches/ https://github.com/openssl/openssl/pull/11895.patch +wget -P package/libs/openssl/patches/ https://github.com/openssl/openssl/pull/14578.patch +wget -P package/libs/openssl/patches/ https://github.com/openssl/openssl/pull/16575.patch ### Fullcone-NAT 部分 ### # Patch Kernel 以解决 FullCone 冲突 @@ -80,9 +82,9 @@ svn co https://github.com/immortalwrt/immortalwrt/branches/openwrt-21.02/package rm -rf ./package/kernel/linux/modules/video.mk wget -P package/kernel/linux/modules/ https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/package/kernel/linux/modules/video.mk # R4S超频到 2.2/1.8 GHz -rm -rf ./target/linux/rockchip/patches-5.4/992-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch -cp -f ../PATCH/target_r4s/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch ./target/linux/rockchip/patches-5.4/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch -cp -f ../PATCH/target_r4s/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch ./target/linux/rockchip/patches-5.4/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch +#rm -rf ./target/linux/rockchip/patches-5.4/992-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch +#cp -f ../PATCH/target_r4s/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch ./target/linux/rockchip/patches-5.4/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch +#cp -f ../PATCH/target_r4s/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch ./target/linux/rockchip/patches-5.4/213-RK3399-set-critical-CPU-temperature-for-thermal-throttling.patch # Disable Mitigations sed -i 's,rootwait,rootwait mitigations=off,g' target/linux/rockchip/image/mmc.bootscript sed -i 's,rootwait,rootwait mitigations=off,g' target/linux/rockchip/image/nanopi-r2s.bootscript @@ -97,6 +99,7 @@ svn co https://github.com/immortalwrt/packages/trunk/utils/coremark feeds/packag # 更换 Nodejs 版本 rm -rf ./feeds/packages/lang/node svn co https://github.com/nxhack/openwrt-node-packages/trunk/node feeds/packages/lang/node +sed -i '\/bin\/node/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $(1)/usr/bin/node' feeds/packages/lang/node/Makefile rm -rf ./feeds/packages/lang/node-arduino-firmata svn co https://github.com/nxhack/openwrt-node-packages/trunk/node-arduino-firmata feeds/packages/lang/node-arduino-firmata rm -rf ./feeds/packages/lang/node-cylon @@ -138,9 +141,9 @@ sed -i '/\t)/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DI sed -i '/init/d' feeds/packages/net/adguardhome/Makefile # Argon 主题 git clone https://github.com/jerrykuku/luci-theme-argon.git package/new/luci-theme-argon -pushd package/new/luci-theme-argon -git checkout 3b15d06 -popd +#pushd package/new/luci-theme-argon +#git checkout 3b15d06 +#popd git clone -b master --depth 1 https://github.com/jerrykuku/luci-app-argon-config.git package/new/luci-app-argon-config # MAC 地址与 IP 绑定 svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-arpbind feeds/luci/applications/luci-app-arpbind @@ -209,8 +212,10 @@ svn co https://github.com/QiuSimons/openwrt-mos/trunk/luci-app-mosdns package/ne svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-netdata package/lean/luci-app-netdata # 上网 APP 过滤 git clone -b master --depth 1 https://github.com/destan19/OpenAppFilter.git package/new/OpenAppFilter -sed -i 's,先关闭ACC加速,在防火墙中关闭 FullCone 及 流量分载 ,g' package/new/OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/appfilter.lua -sed -i 's,flowoffload.@flow[0],firewall.@defaults[0],g' package/new/OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/appfilter.lua +pushd package/new/OpenAppFilter +wget -qO - https://github.com/QiuSimons/OpenAppFilter-destan19/commit/9088cc2.patch | patch -p1 +wget https://github.com/destan19/destan19.github.io/raw/main/assets/oaf/open_feature/feature-06-18.cfg -O ./open-app-filter/files/feature.cfg +popd # OLED 驱动程序 git clone -b master --depth 1 https://github.com/NateLol/luci-app-oled.git package/new/luci-app-oled # OpenClash @@ -224,7 +229,7 @@ svn co https://github.com/xiaorouji/openwrt-passwall/trunk/luci-app-passwall pac sed -i 's,default n,default y,g' package/new/luci-app-passwall/Makefile sed -i '/Trojan_GO:/d' package/new/luci-app-passwall/Makefile sed -i '/V2ray:/d' package/new/luci-app-passwall/Makefile -sed -i '/V2ray_Plugin:/d' package/new/luci-app-passwall/Makefile +sed -i '/Plugin:/d' package/new/luci-app-passwall/Makefile wget -P package/new/luci-app-passwall/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/move_2_services.sh chmod -R 755 ./package/new/luci-app-passwall/move_2_services.sh pushd package/new/luci-app-passwall @@ -274,6 +279,7 @@ svn co https://github.com/fw876/helloworld/trunk/xray-core package/lean/xray-cor svn co https://github.com/fw876/helloworld/trunk/v2ray-plugin package/lean/v2ray-plugin svn co https://github.com/fw876/helloworld/trunk/xray-plugin package/lean/xray-plugin svn co https://github.com/immortalwrt/packages/trunk/net/shadowsocks-rust feeds/packages/net/shadowsocks-rust +sed -i '/Build\/Compile/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $$(PKG_BUILD_DIR)/$(component)' feeds/packages/net/shadowsocks-rust/Makefile ln -sf ../../../feeds/packages/net/shadowsocks-rust ./package/feeds/packages/shadowsocks-rust svn co https://github.com/immortalwrt/packages/trunk/net/kcptun feeds/packages/net/kcptun ln -sf ../../../feeds/packages/net/kcptun ./package/feeds/packages/kcptun @@ -297,6 +303,7 @@ popd svn co https://github.com/Lienol/openwrt-package/trunk/luci-app-socat package/new/luci-app-socat # 订阅转换 svn co https://github.com/immortalwrt/packages/trunk/net/subconverter feeds/packages/net/subconverter +sed -i '\/bin\/subconverter/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $(1)/usr/bin/subconverter' feeds/packages/net/subconverter/Makefile ln -sf ../../../feeds/packages/net/subconverter ./package/feeds/packages/subconverter svn co https://github.com/immortalwrt/packages/trunk/libs/jpcre2 feeds/packages/libs/jpcre2 ln -sf ../../../feeds/packages/libs/jpcre2 ./package/feeds/packages/jpcre2 @@ -322,7 +329,7 @@ svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/vlmcsd package/le git clone -b master --depth 1 https://github.com/jerrykuku/luci-app-vssr.git package/lean/luci-app-vssr git clone -b master --depth 1 https://github.com/jerrykuku/lua-maxminddb.git package/lean/lua-maxminddb sed -i 's,default n,default y,g' package/lean/luci-app-vssr/Makefile -sed -i '/Xray_plugin:/d' package/lean/luci-app-vssr/Makefile +sed -i '/plugin:/d' package/lean/luci-app-vssr/Makefile #sed -i '/plugin:v2ray/d' package/lean/luci-app-vssr/Makefile sed -i '/result.encrypt_method/a\result.fast_open = "1"' package/lean/luci-app-vssr/root/usr/share/vssr/subscribe.lua sed -i 's,ispip.clang.cn/all_cn.txt,raw.sevencdn.com/QiuSimons/Chnroute/master/dist/chnroute/chnroute.txt,g' package/lean/luci-app-vssr/luasrc/controller/vssr.lua @@ -343,6 +350,7 @@ bash move_2_services.sh popd ln -sf ../../../feeds/luci/applications/luci-app-zerotier ./package/feeds/luci/luci-app-zerotier rm -rf ./feeds/packages/net/zerotier/files/etc/init.d/zerotier +sed -i '/Default,one/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $(PKG_BUILD_DIR)/zerotier-one' feeds/packages/net/zerotier/Makefile # 翻译及部分功能优化 svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/addition-trans-zh package/lean/lean-translate From dd908b41a0fa91a42160da41d34909b068093cfe Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sat, 23 Oct 2021 18:45:42 +0800 Subject: [PATCH 202/244] Follow openwrt upstream changes (#298) --- PATCH/dnsmasq/dnsmasq-add-filter-aaaa-option.patch | 4 ++-- PATCH/dnsmasq/luci-add-filter-aaaa-option.patch | 2 +- SCRIPTS/01_get_ready.sh | 4 ++-- SCRIPTS/02_prepare_package.sh | 4 ++-- SCRIPTS/R2S/02_target_only.sh | 2 +- SCRIPTS/R4S/02_target_only.sh | 2 +- SCRIPTS/X86/02_target_only.sh | 2 +- SEED/R2C/config.seed | 2 -- SEED/R2S/config.seed | 2 -- SEED/R4S/config.seed | 2 -- SEED/X86/config.seed | 2 -- 11 files changed, 10 insertions(+), 18 deletions(-) mode change 100644 => 100755 SCRIPTS/01_get_ready.sh diff --git a/PATCH/dnsmasq/dnsmasq-add-filter-aaaa-option.patch b/PATCH/dnsmasq/dnsmasq-add-filter-aaaa-option.patch index 5de320343..1cd9e6f20 100644 --- a/PATCH/dnsmasq/dnsmasq-add-filter-aaaa-option.patch +++ b/PATCH/dnsmasq/dnsmasq-add-filter-aaaa-option.patch @@ -17,7 +17,7 @@ index 360c7d79eee..c9407f5e649 100644 #list notinterface lo #list bogusnxdomain '64.94.110.11' option localservice 1 # disable to allow DNS requests from non-local subnets -+ option filteraaaa 1 ++ option filter_aaaa 1 option ednspacket_max 1232 config dhcp lan @@ -30,7 +30,7 @@ index 06d83b06deb..08ff64d659f 100644 append_bool "$cfg" sequential_ip "--dhcp-sequential-ip" append_bool "$cfg" allservers "--all-servers" append_bool "$cfg" noping "--no-ping" -+ append_bool "$cfg" filteraaaa "--filter-aaaa" ++ append_bool "$cfg" filter_aaaa "--filter-aaaa" append_bool "$cfg" rapidcommit "--dhcp-rapid-commit" append_bool "$cfg" scriptarp "--script-arp" diff --git a/PATCH/dnsmasq/luci-add-filter-aaaa-option.patch b/PATCH/dnsmasq/luci-add-filter-aaaa-option.patch index 1dd6e24bd..3d0230178 100644 --- a/PATCH/dnsmasq/luci-add-filter-aaaa-option.patch +++ b/PATCH/dnsmasq/luci-add-filter-aaaa-option.patch @@ -16,7 +16,7 @@ index 6693dc0eac..1c8f943758 100644 s.taboption('files', form.DynamicList, 'addnhosts', _('Additional Hosts files')).optional = true; -+ o = s.taboption('advanced', form.Flag, 'filteraaaa', ++ o = s.taboption('advanced', form.Flag, 'filter_aaaa', + _('Filter IPv6 Records'), + _('Filter IPv6(AAAA) Records during DNS resolution')); + o.optional = true; diff --git a/SCRIPTS/01_get_ready.sh b/SCRIPTS/01_get_ready.sh old mode 100644 new mode 100755 index b007dd7e4..e3da6b293 --- a/SCRIPTS/01_get_ready.sh +++ b/SCRIPTS/01_get_ready.sh @@ -1,6 +1,6 @@ #!/bin/bash -latest_release="$(curl -s https://github.com/openwrt/openwrt/releases | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/21/p' | sed -n 1p | sed 's/.tar.gz//g')" +latest_release="$(curl -s https://github.com/openwrt/openwrt/tags | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/21/p' | sed -n 1p | sed 's/.tar.gz//g')" git clone --single-branch -b ${latest_release} https://github.com/openwrt/openwrt openwrt_release git clone --single-branch -b openwrt-21.02 https://github.com/openwrt/openwrt openwrt rm -f ./openwrt/include/version.mk @@ -26,4 +26,4 @@ cp -rf ./openwrt_release/target/linux/* ./openwrt/target/linux/ #git clone -b main --depth 1 https://github.com/Lienol/openwrt-luci luci-lienol #git clone -b linksys-ea6350v3-mastertrack --depth 1 https://github.com/NoTengoBattery/openwrt NoTengoBattery -exit 0 \ No newline at end of file +exit 0 diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index cae38b591..585aeabc0 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -270,9 +270,9 @@ svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/microsocks packag svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/dns2socks package/lean/dns2socks svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/redsocks2 package/lean/redsocks2 svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/ipt2socks package/lean/ipt2socks -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/simple-obfs package/lean/simple-obfs svn co https://github.com/coolsnowwolf/packages/trunk/net/shadowsocks-libev package/lean/shadowsocks-libev -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/trojan package/lean/trojan +svn co https://github.com/fw876/helloworld/trunk/trojan package/lean/trojan +svn co https://github.com/fw876/helloworld/trunk/simple-obfs package/lean/simple-obfs svn co https://github.com/fw876/helloworld/trunk/naiveproxy package/lean/naiveproxy svn co https://github.com/fw876/helloworld/trunk/v2ray-core package/lean/v2ray-core svn co https://github.com/fw876/helloworld/trunk/xray-core package/lean/xray-core diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index f1a8f46e3..4f955591a 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -31,7 +31,7 @@ sed -i 's,"eth1" "eth0","eth0" "eth1",g' target/linux/rockchip/armv8/base-files/ sed -i "s,'eth1' 'eth0','eth0' 'eth1',g" target/linux/rockchip/armv8/base-files/etc/board.d/02_network #Vermagic -latest_version="$(curl -s https://github.com/openwrt/openwrt/releases | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/21/p' | sed -n 1p | sed 's/v//g' | sed 's/.tar.gz//g')" +latest_version="$(curl -s https://github.com/openwrt/openwrt/tags | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/21/p' | sed -n 1p | sed 's/v//g' | sed 's/.tar.gz//g')" wget https://downloads.openwrt.org/releases/${latest_version}/targets/rockchip/armv8/packages/Packages.gz zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' >.vermagic sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic/' include/kernel-defaults.mk diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index 79b5f6800..8f6b5cb5c 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -27,7 +27,7 @@ sed -i '/set_interface_core 20 "eth1"/a\set_interface_core 8 "ff3c0000" "ff3c000 sed -i '/set_interface_core 20 "eth1"/a\ethtool -C eth0 rx-usecs 1000 rx-frames 25 tx-usecs 100 tx-frames 25' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity #Vermagic -latest_version="$(curl -s https://github.com/openwrt/openwrt/releases | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/21/p' | sed -n 1p | sed 's/v//g' | sed 's/.tar.gz//g')" +latest_version="$(curl -s https://github.com/openwrt/openwrt/tags | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/21/p' | sed -n 1p | sed 's/v//g' | sed 's/.tar.gz//g')" wget https://downloads.openwrt.org/releases/${latest_version}/targets/rockchip/armv8/packages/Packages.gz zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' >.vermagic sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic/' include/kernel-defaults.mk diff --git a/SCRIPTS/X86/02_target_only.sh b/SCRIPTS/X86/02_target_only.sh index 778495859..2521f996c 100644 --- a/SCRIPTS/X86/02_target_only.sh +++ b/SCRIPTS/X86/02_target_only.sh @@ -19,7 +19,7 @@ CONFIG_UKSM=y ' >>./target/linux/x86/64/config-5.4 #Vermagic -latest_version="$(curl -s https://github.com/openwrt/openwrt/releases | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/21/p' | sed -n 1p | sed 's/v//g' | sed 's/.tar.gz//g')" +latest_version="$(curl -s https://github.com/openwrt/openwrt/tags | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/21/p' | sed -n 1p | sed 's/v//g' | sed 's/.tar.gz//g')" wget https://downloads.openwrt.org/releases/${latest_version}/targets/x86/64/packages/Packages.gz zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' >.vermagic sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic/' include/kernel-defaults.mk diff --git a/SEED/R2C/config.seed b/SEED/R2C/config.seed index 3807dff60..c934df712 100644 --- a/SEED/R2C/config.seed +++ b/SEED/R2C/config.seed @@ -117,8 +117,6 @@ CONFIG_PACKAGE_luci-app-sqm=y CONFIG_PACKAGE_luci-app-vlmcsd=y CONFIG_PACKAGE_luci-app-vssr=y CONFIG_PACKAGE_luci-app-ssr-plus=y -# CONFIG_PACKAGE_luci-app-ssr-plus_INCLUDE_libustream-wolfssl is not set -CONFIG_PACKAGE_luci-app-ssr-plus_INCLUDE_libustream-openssl=y CONFIG_PACKAGE_luci-app-passwall=y CONFIG_PACKAGE_luci-app-unblockneteasemusic=y CONFIG_PACKAGE_luci-app-upnp=y diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index dfdfd402f..7313b3f5f 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -117,8 +117,6 @@ CONFIG_PACKAGE_luci-app-sqm=y CONFIG_PACKAGE_luci-app-vlmcsd=y CONFIG_PACKAGE_luci-app-vssr=y CONFIG_PACKAGE_luci-app-ssr-plus=y -# CONFIG_PACKAGE_luci-app-ssr-plus_INCLUDE_libustream-wolfssl is not set -CONFIG_PACKAGE_luci-app-ssr-plus_INCLUDE_libustream-openssl=y CONFIG_PACKAGE_luci-app-passwall=y CONFIG_PACKAGE_luci-app-unblockneteasemusic=y CONFIG_PACKAGE_luci-app-upnp=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index 9c1df3b54..b8d756fc1 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -117,8 +117,6 @@ CONFIG_PACKAGE_luci-app-sqm=y CONFIG_PACKAGE_luci-app-vlmcsd=y CONFIG_PACKAGE_luci-app-vssr=y CONFIG_PACKAGE_luci-app-ssr-plus=y -# CONFIG_PACKAGE_luci-app-ssr-plus_INCLUDE_libustream-wolfssl is not set -CONFIG_PACKAGE_luci-app-ssr-plus_INCLUDE_libustream-openssl=y CONFIG_PACKAGE_luci-app-passwall=y CONFIG_PACKAGE_luci-app-unblockneteasemusic=y CONFIG_PACKAGE_luci-app-upnp=y diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index f1f388646..0548aca2f 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -117,8 +117,6 @@ CONFIG_PACKAGE_luci-app-sqm=y CONFIG_PACKAGE_luci-app-vlmcsd=y CONFIG_PACKAGE_luci-app-vssr=y CONFIG_PACKAGE_luci-app-ssr-plus=y -# CONFIG_PACKAGE_luci-app-ssr-plus_INCLUDE_libustream-wolfssl is not set -CONFIG_PACKAGE_luci-app-ssr-plus_INCLUDE_libustream-openssl=y CONFIG_PACKAGE_luci-app-passwall=y CONFIG_PACKAGE_luci-app-unblockneteasemusic=y CONFIG_PACKAGE_luci-app-upnp=y From 3b3abef3bac643b2e7051d00ffdefe8909951ce0 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sun, 24 Oct 2021 20:29:57 +0800 Subject: [PATCH 203/244] Remove upx --- .github/workflows/R2C-OpenWrt.yml | 1 + .github/workflows/R2S-OpenWrt.yml | 1 + .github/workflows/R4S-OpenWrt.yml | 1 + .github/workflows/X86-OpenWrt.yml | 1 + 4 files changed, 4 insertions(+) diff --git a/.github/workflows/R2C-OpenWrt.yml b/.github/workflows/R2C-OpenWrt.yml index 6236a384a..135869733 100644 --- a/.github/workflows/R2C-OpenWrt.yml +++ b/.github/workflows/R2C-OpenWrt.yml @@ -59,6 +59,7 @@ jobs: cp -r ../SCRIPTS/. ./ /bin/bash 02_prepare_package.sh /bin/bash 02_target_only.sh + /bin/bash 04_remove_upx.sh - name: Convert Translation run: | cd openwrt diff --git a/.github/workflows/R2S-OpenWrt.yml b/.github/workflows/R2S-OpenWrt.yml index 39d0e210f..b04854f17 100644 --- a/.github/workflows/R2S-OpenWrt.yml +++ b/.github/workflows/R2S-OpenWrt.yml @@ -59,6 +59,7 @@ jobs: cp -r ../SCRIPTS/. ./ /bin/bash 02_prepare_package.sh /bin/bash 02_target_only.sh + /bin/bash 04_remove_upx.sh - name: Convert Translation run: | cd openwrt diff --git a/.github/workflows/R4S-OpenWrt.yml b/.github/workflows/R4S-OpenWrt.yml index 32b4d94ed..d2295e144 100644 --- a/.github/workflows/R4S-OpenWrt.yml +++ b/.github/workflows/R4S-OpenWrt.yml @@ -59,6 +59,7 @@ jobs: cp -r ../SCRIPTS/. ./ /bin/bash 02_prepare_package.sh /bin/bash 02_target_only.sh + /bin/bash 04_remove_upx.sh - name: Convert Translation run: | cd openwrt diff --git a/.github/workflows/X86-OpenWrt.yml b/.github/workflows/X86-OpenWrt.yml index c86cd0bcd..e9e60e4bd 100644 --- a/.github/workflows/X86-OpenWrt.yml +++ b/.github/workflows/X86-OpenWrt.yml @@ -59,6 +59,7 @@ jobs: cp -r ../SCRIPTS/. ./ /bin/bash 02_prepare_package.sh /bin/bash 02_target_only.sh + /bin/bash 04_remove_upx.sh - name: Convert Translation run: | cd openwrt From a4ac9607a95a62b91f082173c7992b3540845095 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 26 Oct 2021 16:40:03 +0800 Subject: [PATCH 204/244] Sync with OpenWrt v21.02.1 --- .github/workflows/R2C-OpenWrt.yml | 14 ++++++++------ .github/workflows/R2S-OpenWrt.yml | 14 ++++++++------ .github/workflows/R4S-OpenWrt.yml | 14 ++++++++------ .github/workflows/X86-OpenWrt.yml | 14 ++++++++------ SCRIPTS/01_get_ready.sh | 2 +- SCRIPTS/R2S/02_target_only.sh | 2 +- SCRIPTS/R4S/02_target_only.sh | 2 +- SCRIPTS/X86/02_target_only.sh | 2 +- 8 files changed, 36 insertions(+), 28 deletions(-) diff --git a/.github/workflows/R2C-OpenWrt.yml b/.github/workflows/R2C-OpenWrt.yml index 135869733..5d27b768c 100644 --- a/.github/workflows/R2C-OpenWrt.yml +++ b/.github/workflows/R2C-OpenWrt.yml @@ -79,6 +79,8 @@ jobs: run: | TARGET_DEVICE_ARCH="$(grep "^CONFIG_TARGET_.*_.*=y$" ".config" | head -n 1 | sed 's/^CONFIG_TARGET_//g' | awk -F '_' '{print $1}')" echo "TARGET_DEVICE_ARCH=${TARGET_DEVICE_ARCH}-" >>$GITHUB_ENV + latest_release="$(curl -s https://github.com/openwrt/openwrt/tags | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/[2-9][0-9]/p' | sed -n 1p | sed 's/.tar.gz//g' | sed 's/v//g')" + echo "latest_release=${latest_release}" >>$GITHUB_ENV - name: Cache uses: klever1988/cachewrtbuild@test with: @@ -117,23 +119,23 @@ jobs: gzip -d *.gz && exit 0 gzip --best *.img ls -Ahl - sha256sum openwrt*r2c* | tee R2C-GC404-$(date +%Y-%m-%d)-21.02.sha256sum - zip R2C-GC404-$(date +%Y-%m-%d)-21.02-ext4.zip *r2c*ext4* - zip R2C-GC404-$(date +%Y-%m-%d)-21.02-sfs.zip *r2c*squashfs* + sha256sum openwrt*r2c* | tee R2C-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}.sha256sum + zip R2C-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}-ext4.zip *r2c*ext4* + zip R2C-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}-sfs.zip *r2c*squashfs* ls -Ahl - name: Upload artifact uses: actions/upload-artifact@main with: - name: OpenWRT_21.02 + name: OpenWRT_${{ env.latest_release }} path: ./artifact/ - name: Create release id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-21.02.0 + name: OpenWRT-${{ env.latest_release }} allowUpdates: true - tag: 21.02.0 + tag: ${{ env.latest_release }} commit: master replacesArtifacts: true token: ${{ secrets.workflow_token }} diff --git a/.github/workflows/R2S-OpenWrt.yml b/.github/workflows/R2S-OpenWrt.yml index b04854f17..eb06007df 100644 --- a/.github/workflows/R2S-OpenWrt.yml +++ b/.github/workflows/R2S-OpenWrt.yml @@ -79,6 +79,8 @@ jobs: run: | TARGET_DEVICE_ARCH="$(grep "^CONFIG_TARGET_.*_.*=y$" ".config" | head -n 1 | sed 's/^CONFIG_TARGET_//g' | awk -F '_' '{print $1}')" echo "TARGET_DEVICE_ARCH=${TARGET_DEVICE_ARCH}-" >>$GITHUB_ENV + latest_release="$(curl -s https://github.com/openwrt/openwrt/tags | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/[2-9][0-9]/p' | sed -n 1p | sed 's/.tar.gz//g' | sed 's/v//g')" + echo "latest_release=${latest_release}" >>$GITHUB_ENV - name: Cache uses: klever1988/cachewrtbuild@test with: @@ -117,23 +119,23 @@ jobs: gzip -d *.gz && exit 0 gzip --best *.img ls -Ahl - sha256sum openwrt*r2s* | tee R2S-GC404-$(date +%Y-%m-%d)-21.02.sha256sum - zip R2S-GC404-$(date +%Y-%m-%d)-21.02-ext4.zip *r2s*ext4* - zip R2S-GC404-$(date +%Y-%m-%d)-21.02-sfs.zip *r2s*squashfs* + sha256sum openwrt*r2s* | tee R2S-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}.sha256sum + zip R2S-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}-ext4.zip *r2s*ext4* + zip R2S-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}-sfs.zip *r2s*squashfs* ls -Ahl - name: Upload artifact uses: actions/upload-artifact@main with: - name: OpenWRT_21.02 + name: OpenWRT_${{ env.latest_release }} path: ./artifact/ - name: Create release id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-21.02.0 + name: OpenWRT-${{ env.latest_release }} allowUpdates: true - tag: 21.02.0 + tag: ${{ env.latest_release }} commit: master replacesArtifacts: true token: ${{ secrets.workflow_token }} diff --git a/.github/workflows/R4S-OpenWrt.yml b/.github/workflows/R4S-OpenWrt.yml index d2295e144..d1c637fe5 100644 --- a/.github/workflows/R4S-OpenWrt.yml +++ b/.github/workflows/R4S-OpenWrt.yml @@ -79,6 +79,8 @@ jobs: run: | TARGET_DEVICE_ARCH="$(grep "^CONFIG_TARGET_.*_.*=y$" ".config" | head -n 1 | sed 's/^CONFIG_TARGET_//g' | awk -F '_' '{print $1}')" echo "TARGET_DEVICE_ARCH=${TARGET_DEVICE_ARCH}-" >>$GITHUB_ENV + latest_release="$(curl -s https://github.com/openwrt/openwrt/tags | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/[2-9][0-9]/p' | sed -n 1p | sed 's/.tar.gz//g' | sed 's/v//g')" + echo "latest_release=${latest_release}" >>$GITHUB_ENV - name: Cache uses: klever1988/cachewrtbuild@test with: @@ -117,23 +119,23 @@ jobs: gzip -d *.gz && exit 0 gzip --best *.img ls -Ahl - sha256sum openwrt*r4s* | tee R4S-GC404-$(date +%Y-%m-%d)-21.02.sha256sum - zip R4S-GC404-$(date +%Y-%m-%d)-21.02-ext4.zip *r4s*ext4* - zip R4S-GC404-$(date +%Y-%m-%d)-21.02-sfs.zip *r4s*squashfs* + sha256sum openwrt*r4s* | tee R4S-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}.sha256sum + zip R4S-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}-ext4.zip *r4s*ext4* + zip R4S-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}-sfs.zip *r4s*squashfs* ls -Ahl - name: Upload artifact uses: actions/upload-artifact@main with: - name: OpenWRT_21.02 + name: OpenWRT_${{ env.latest_release }} path: ./artifact/ - name: Create release id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-21.02.0 + name: OpenWRT-${{ env.latest_release }} allowUpdates: true - tag: 21.02.0 + tag: ${{ env.latest_release }} commit: master replacesArtifacts: true token: ${{ secrets.workflow_token }} diff --git a/.github/workflows/X86-OpenWrt.yml b/.github/workflows/X86-OpenWrt.yml index e9e60e4bd..aed1361b0 100644 --- a/.github/workflows/X86-OpenWrt.yml +++ b/.github/workflows/X86-OpenWrt.yml @@ -79,6 +79,8 @@ jobs: run: | TARGET_DEVICE_ARCH="$(grep "^CONFIG_TARGET_.*_.*=y$" ".config" | head -n 1 | sed 's/^CONFIG_TARGET_//g' | awk -F '_' '{print $1}')" echo "TARGET_DEVICE_ARCH=${TARGET_DEVICE_ARCH}-" >>$GITHUB_ENV + latest_release="$(curl -s https://github.com/openwrt/openwrt/tags | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/[2-9][0-9]/p' | sed -n 1p | sed 's/.tar.gz//g' | sed 's/v//g')" + echo "latest_release=${latest_release}" >>$GITHUB_ENV - name: Cache uses: klever1988/cachewrtbuild@test with: @@ -117,23 +119,23 @@ jobs: gzip -d *.gz && exit 0 gzip --best *.img ls -Ahl - sha256sum openwrt*x86* | tee X86-GC404-$(date +%Y-%m-%d)-21.02.sha256sum - zip X86-GC404-$(date +%Y-%m-%d)-21.02-ext4.zip *ext4-combined* - zip X86-GC404-$(date +%Y-%m-%d)-21.02-sfs.zip *squashfs-combined* + sha256sum openwrt*x86* | tee X86-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}.sha256sum + zip X86-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}-ext4.zip *ext4-combined* + zip X86-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}-sfs.zip *squashfs-combined* ls -Ahl - name: Upload artifact uses: actions/upload-artifact@main with: - name: OpenWRT_21.02 + name: OpenWRT_${{ env.latest_release }} path: ./artifact/ - name: Create release id: create_release uses: ncipollo/release-action@v1.8.0 with: - name: OpenWRT-21.02.0 + name: OpenWRT-${{ env.latest_release }} allowUpdates: true - tag: 21.02.0 + tag: ${{ env.latest_release }} commit: master replacesArtifacts: true token: ${{ secrets.workflow_token }} diff --git a/SCRIPTS/01_get_ready.sh b/SCRIPTS/01_get_ready.sh index e3da6b293..904e70306 100755 --- a/SCRIPTS/01_get_ready.sh +++ b/SCRIPTS/01_get_ready.sh @@ -1,6 +1,6 @@ #!/bin/bash -latest_release="$(curl -s https://github.com/openwrt/openwrt/tags | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/21/p' | sed -n 1p | sed 's/.tar.gz//g')" +latest_release="$(curl -s https://github.com/openwrt/openwrt/tags | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/[2-9][0-9]/p' | sed -n 1p | sed 's/.tar.gz//g')" git clone --single-branch -b ${latest_release} https://github.com/openwrt/openwrt openwrt_release git clone --single-branch -b openwrt-21.02 https://github.com/openwrt/openwrt openwrt rm -f ./openwrt/include/version.mk diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index 4f955591a..f0b1eff76 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -31,7 +31,7 @@ sed -i 's,"eth1" "eth0","eth0" "eth1",g' target/linux/rockchip/armv8/base-files/ sed -i "s,'eth1' 'eth0','eth0' 'eth1',g" target/linux/rockchip/armv8/base-files/etc/board.d/02_network #Vermagic -latest_version="$(curl -s https://github.com/openwrt/openwrt/tags | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/21/p' | sed -n 1p | sed 's/v//g' | sed 's/.tar.gz//g')" +latest_version="$(curl -s https://github.com/openwrt/openwrt/tags | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/[2-9][0-9]/p' | sed -n 1p | sed 's/v//g' | sed 's/.tar.gz//g')" wget https://downloads.openwrt.org/releases/${latest_version}/targets/rockchip/armv8/packages/Packages.gz zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' >.vermagic sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic/' include/kernel-defaults.mk diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index 8f6b5cb5c..b69f273ef 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -27,7 +27,7 @@ sed -i '/set_interface_core 20 "eth1"/a\set_interface_core 8 "ff3c0000" "ff3c000 sed -i '/set_interface_core 20 "eth1"/a\ethtool -C eth0 rx-usecs 1000 rx-frames 25 tx-usecs 100 tx-frames 25' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity #Vermagic -latest_version="$(curl -s https://github.com/openwrt/openwrt/tags | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/21/p' | sed -n 1p | sed 's/v//g' | sed 's/.tar.gz//g')" +latest_version="$(curl -s https://github.com/openwrt/openwrt/tags | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/[2-9][0-9]/p' | sed -n 1p | sed 's/v//g' | sed 's/.tar.gz//g')" wget https://downloads.openwrt.org/releases/${latest_version}/targets/rockchip/armv8/packages/Packages.gz zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' >.vermagic sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic/' include/kernel-defaults.mk diff --git a/SCRIPTS/X86/02_target_only.sh b/SCRIPTS/X86/02_target_only.sh index 2521f996c..fd44a90eb 100644 --- a/SCRIPTS/X86/02_target_only.sh +++ b/SCRIPTS/X86/02_target_only.sh @@ -19,7 +19,7 @@ CONFIG_UKSM=y ' >>./target/linux/x86/64/config-5.4 #Vermagic -latest_version="$(curl -s https://github.com/openwrt/openwrt/tags | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/21/p' | sed -n 1p | sed 's/v//g' | sed 's/.tar.gz//g')" +latest_version="$(curl -s https://github.com/openwrt/openwrt/tags | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/[2-9][0-9]/p' | sed -n 1p | sed 's/v//g' | sed 's/.tar.gz//g')" wget https://downloads.openwrt.org/releases/${latest_version}/targets/x86/64/packages/Packages.gz zgrep -m 1 "Depends: kernel (=.*)$" Packages.gz | sed -e 's/.*-\(.*\))/\1/' >.vermagic sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic/' include/kernel-defaults.mk From 1ab0cc83c4e96a9d80f492a7847f822ab339a011 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 23 Nov 2021 13:44:05 +0800 Subject: [PATCH 205/244] Update 02_prepare_package.sh --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 585aeabc0..06b041ac8 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -214,7 +214,7 @@ svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-netdata git clone -b master --depth 1 https://github.com/destan19/OpenAppFilter.git package/new/OpenAppFilter pushd package/new/OpenAppFilter wget -qO - https://github.com/QiuSimons/OpenAppFilter-destan19/commit/9088cc2.patch | patch -p1 -wget https://github.com/destan19/destan19.github.io/raw/main/assets/oaf/open_feature/feature-06-18.cfg -O ./open-app-filter/files/feature.cfg +wget https://destan19.github.io/assets/oaf/open_feature/feature-06-18.cfg -O ./open-app-filter/files/feature.cfg popd # OLED 驱动程序 git clone -b master --depth 1 https://github.com/NateLol/luci-app-oled.git package/new/luci-app-oled From 0b4173ee6c5b199508bb78dbe82d81780f882c67 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 25 Nov 2021 10:25:19 +0800 Subject: [PATCH 206/244] LRNG: patch series for v43 --- ...ha1.patch => 696-01-v43-000001-sha1.patch} | 4 +- ... => 696-02-v43-000002-GRND_INSECURE.patch} | 6 +- ... => 696-03-v43-000003-jent-backport.patch} | 7 + ...-0001-Linux-Random-Number-Generator.patch} | 1526 +++-------------- ...-05-v43-0002-LRNG-IRQ-entropy-source.patch | 1155 +++++++++++++ ...003-LRNG-sysctls-and-proc-interface.patch} | 78 +- ...ate-one-DRNG-instance-per-NUMA-node.patch} | 29 +- ...-08-v43-0005-LRNG-CPU-entropy-source.patch | 336 ++++ ...06-LRNG-add-switchable-DRNG-support.patch} | 28 +- ...RNG-add-common-generic-hash-support.patch} | 25 +- ...externalize-DRBG-functions-for-LRNG.patch} | 33 +- ...9-LRNG-add-SP800-90A-DRBG-extension.patch} | 22 +- ...dd-kernel-crypto-API-PRNG-extension.patch} | 20 +- ...-move-Jitter-RNG-header-include-dir.patch} | 73 +- ...NG-add-Jitter-RNG-fast-noise-source.patch} | 49 +- ...dd-SP800-90B-compliant-health-tests.patch} | 46 +- ...erface-for-gathering-of-raw-entropy.patch} | 36 +- ...add-power-on-and-runtime-self-tests.patch} | 136 +- PATCH/LRNG/696-19-v42-04-net_rand_state.patch | 10 - ...> 696-19-v43-01-remove_compat_ioctl.patch} | 8 +- PATCH/LRNG/696-20-v42-05-kzfree.patch | 44 - ... => 696-20-v43-03-arch_random_early.patch} | 6 +- PATCH/LRNG/696-21-v43-04-net_rand_state.patch | 10 + PATCH/LRNG/696-22-v43-05-kzfree.patch | 44 + ...patch => 696-23-v43-06-sha-includes.patch} | 12 +- ...h => 696-24-v43-07-chacha_constants.patch} | 4 +- 26 files changed, 2180 insertions(+), 1567 deletions(-) rename PATCH/LRNG/{696-01-v42-000001-sha1.patch => 696-01-v43-000001-sha1.patch} (79%) rename PATCH/LRNG/{696-02-v42-000002-GRND_INSECURE.patch => 696-02-v43-000002-GRND_INSECURE.patch} (63%) rename PATCH/LRNG/{696-03-v42-000003-jent-backport.patch => 696-03-v43-000003-jent-backport.patch} (91%) rename PATCH/LRNG/{696-04-v42-0001-Linux-Random-Number-Generator.patch => 696-04-v43-0001-Linux-Random-Number-Generator.patch} (69%) create mode 100644 PATCH/LRNG/696-05-v43-0002-LRNG-IRQ-entropy-source.patch rename PATCH/LRNG/{696-06-v42-0003-LRNG-sysctls-and-proc-interface.patch => 696-06-v43-0003-LRNG-sysctls-and-proc-interface.patch} (79%) rename PATCH/LRNG/{696-05-v42-0002-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch => 696-07-v43-0004-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch} (87%) create mode 100644 PATCH/LRNG/696-08-v43-0005-LRNG-CPU-entropy-source.patch rename PATCH/LRNG/{696-07-v42-0004-LRNG-add-switchable-DRNG-support.patch => 696-09-v43-0006-LRNG-add-switchable-DRNG-support.patch} (93%) rename PATCH/LRNG/{696-08-v42-0005-LRNG-add-common-generic-hash-support.patch => 696-10-v43-0007-LRNG-add-common-generic-hash-support.patch} (86%) rename PATCH/LRNG/{696-09-v42-0006-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch => 696-11-v43-0008-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch} (77%) rename PATCH/LRNG/{696-10-v42-0007-LRNG-add-SP800-90A-DRBG-extension.patch => 696-12-v43-0009-LRNG-add-SP800-90A-DRBG-extension.patch} (92%) rename PATCH/LRNG/{696-11-v42-0008-LRNG-add-kernel-crypto-API-PRNG-extension.patch => 696-13-v43-0010-LRNG-add-kernel-crypto-API-PRNG-extension.patch} (93%) rename PATCH/LRNG/{696-12-v42-0009-crypto-move-Jitter-RNG-header-include-dir.patch => 696-14-v43-0011-crypto-move-Jitter-RNG-header-include-dir.patch} (52%) rename PATCH/LRNG/{696-13-v42-0010-LRNG-add-Jitter-RNG-fast-noise-source.patch => 696-15-v43-0012-LRNG-add-Jitter-RNG-fast-noise-source.patch} (79%) rename PATCH/LRNG/{696-14-v42-0011-LRNG-add-SP800-90B-compliant-health-tests.patch => 696-16-v43-0013-LRNG-add-SP800-90B-compliant-health-tests.patch} (93%) rename PATCH/LRNG/{696-15-v42-0012-LRNG-add-interface-for-gathering-of-raw-entropy.patch => 696-17-v43-0014-LRNG-add-interface-for-gathering-of-raw-entropy.patch} (96%) rename PATCH/LRNG/{696-16-v42-0013-LRNG-add-power-on-and-runtime-self-tests.patch => 696-18-v43-0015-LRNG-add-power-on-and-runtime-self-tests.patch} (91%) delete mode 100644 PATCH/LRNG/696-19-v42-04-net_rand_state.patch rename PATCH/LRNG/{696-17-v42-01-remove_compat_ioctl.patch => 696-19-v43-01-remove_compat_ioctl.patch} (54%) delete mode 100644 PATCH/LRNG/696-20-v42-05-kzfree.patch rename PATCH/LRNG/{696-18-v42-03-arch_random_early.patch => 696-20-v43-03-arch_random_early.patch} (64%) create mode 100644 PATCH/LRNG/696-21-v43-04-net_rand_state.patch create mode 100644 PATCH/LRNG/696-22-v43-05-kzfree.patch rename PATCH/LRNG/{696-21-v42-06-sha-includes.patch => 696-23-v43-06-sha-includes.patch} (51%) rename PATCH/LRNG/{696-22-v42-07-chacha_constants.patch => 696-24-v43-07-chacha_constants.patch} (67%) diff --git a/PATCH/LRNG/696-01-v42-000001-sha1.patch b/PATCH/LRNG/696-01-v43-000001-sha1.patch similarity index 79% rename from PATCH/LRNG/696-01-v42-000001-sha1.patch rename to PATCH/LRNG/696-01-v43-000001-sha1.patch index f4f5010e4..7797b9c73 100644 --- a/PATCH/LRNG/696-01-v42-000001-sha1.patch +++ b/PATCH/LRNG/696-01-v43-000001-sha1.patch @@ -1,5 +1,5 @@ ---- a/include/crypto/sha.h -+++ b/include/crypto/sha.h +--- linux-5.4/include/crypto/sha.h.orig 2020-12-05 15:55:05.834664069 +0100 ++++ linux-5.4/include/crypto/sha.h 2020-12-05 15:57:51.631948082 +0100 @@ -159,4 +159,14 @@ extern int sha224_update(struct sha256_s unsigned int length); extern int sha224_final(struct sha256_state *sctx, u8 *hash); diff --git a/PATCH/LRNG/696-02-v42-000002-GRND_INSECURE.patch b/PATCH/LRNG/696-02-v43-000002-GRND_INSECURE.patch similarity index 63% rename from PATCH/LRNG/696-02-v42-000002-GRND_INSECURE.patch rename to PATCH/LRNG/696-02-v43-000002-GRND_INSECURE.patch index 268235d11..37cf6a858 100644 --- a/PATCH/LRNG/696-02-v42-000002-GRND_INSECURE.patch +++ b/PATCH/LRNG/696-02-v43-000002-GRND_INSECURE.patch @@ -1,6 +1,6 @@ ---- a/include/uapi/linux/random.h -+++ b/include/uapi/linux/random.h -@@ -49,8 +49,10 @@ struct rand_pool_info { +--- linux-5.4/include/uapi/linux/random.h.lrng 2020-08-13 20:42:05.900054630 -0600 ++++ linux-5.4/include/uapi/linux/random.h 2020-08-13 20:43:53.375216798 -0600 +@@ -49,8 +49,10 @@ * * GRND_NONBLOCK Don't block and return EAGAIN instead * GRND_RANDOM Use the /dev/random pool instead of /dev/urandom diff --git a/PATCH/LRNG/696-03-v42-000003-jent-backport.patch b/PATCH/LRNG/696-03-v43-000003-jent-backport.patch similarity index 91% rename from PATCH/LRNG/696-03-v42-000003-jent-backport.patch rename to PATCH/LRNG/696-03-v43-000003-jent-backport.patch index 0feef6dfe..258c263d3 100644 --- a/PATCH/LRNG/696-03-v42-000003-jent-backport.patch +++ b/PATCH/LRNG/696-03-v43-000003-jent-backport.patch @@ -23,6 +23,8 @@ Date: Wed Oct 9 10:12:56 2019 +0100 Reviewed-by: Stephan Mueller +diff --git a/crypto/jitterentropy-kcapi.c b/crypto/jitterentropy-kcapi.c +index 701b8d86ab49..a5ce8f96790f 100644 --- a/crypto/jitterentropy-kcapi.c +++ b/crypto/jitterentropy-kcapi.c @@ -44,13 +44,7 @@ @@ -40,6 +42,8 @@ Date: Wed Oct 9 10:12:56 2019 +0100 /*************************************************************************** * Helper function +diff --git a/crypto/jitterentropy.c b/crypto/jitterentropy.c +index 9597f9f5723d..042157f0d28b 100644 --- a/crypto/jitterentropy.c +++ b/crypto/jitterentropy.c @@ -103,12 +103,7 @@ struct rand_data { @@ -56,6 +60,9 @@ Date: Wed Oct 9 10:12:56 2019 +0100 /** * Update of the loop count used for the next round of +diff --git a/crypto/jitterentropy.h b/crypto/jitterentropy.h +new file mode 100644 +index 000000000000..c83fff32d130 --- /dev/null +++ b/crypto/jitterentropy.h @@ -0,0 +1,19 @@ diff --git a/PATCH/LRNG/696-04-v42-0001-Linux-Random-Number-Generator.patch b/PATCH/LRNG/696-04-v43-0001-Linux-Random-Number-Generator.patch similarity index 69% rename from PATCH/LRNG/696-04-v42-0001-Linux-Random-Number-Generator.patch rename to PATCH/LRNG/696-04-v43-0001-Linux-Random-Number-Generator.patch index dcd6c1ad3..6b4773ef6 100644 --- a/PATCH/LRNG/696-04-v42-0001-Linux-Random-Number-Generator.patch +++ b/PATCH/LRNG/696-04-v43-0001-Linux-Random-Number-Generator.patch @@ -1,7 +1,7 @@ -From 4c05d448e19e351788d6baaaf5356f4905e11486 Mon Sep 17 00:00:00 2001 +From 535a4c6d35e1b8297b2f742b1cacbf860af096e9 Mon Sep 17 00:00:00 2001 From: Stephan Mueller -Date: Wed, 4 Aug 2021 21:27:54 +0200 -Subject: [PATCH v42 01/13] Linux Random Number Generator +Date: Sun, 17 Oct 2021 20:23:04 +0200 +Subject: [PATCH v43 01/15] Linux Random Number Generator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -13,29 +13,33 @@ implement the various components in separate code for easier maintenance, and provide compliance to SP800-90[A|B|C], introduce the Linux Random Number Generator (LRNG) framework. +The LRNG framework provides a flexible random number generator which +allows developers and system integrators to achieve different goals +by ensuring that each solution establishes a secure state. + The general design is as follows. Additional implementation details are given in [1]. The LRNG consists of the following components: 1. The LRNG implements a DRNG. The DRNG always generates the requested amount of output. When using the SP800-90A terminology -it operates without prediction resistance. The secondary DRNG -maintains a counter of how many bytes were generated since last -re-seed and a timer of the elapsed time since last re-seed. If either -the counter or the timer reaches a threshold, the secondary DRNG is -seeded from the entropy pool. +it operates without prediction resistance. The DRNG maintains a counter +of how many bytes were generated since last re-seed and a timer of the +elapsed time since last re-seed. If either the counter or the timer reaches +a threshold, the DRNG is seeded from the entropy pool. + +In case the Linux kernel detects a NUMA system, one DRNG instance per NUMA +node is maintained. -In case the Linux kernel detects a NUMA system, one secondary DRNG -instance per NUMA node is maintained. +2. The DRNG is seeded by concatenating the data from the following sources + which deliver data and are credited with entropy if enabled: -2. The DRNG is seeded by concatenating the data from the -following sources: +(a) the output of the IRQ per-CPU entropy pools, -(a) the output of the entropy pool, +(b) the auxiliary entropy pool, -(b) the Jitter RNG if available and enabled, and +(c) the Jitter RNG if available and enabled, and -(c) the CPU-based noise source such as Intel RDRAND if available and -enabled. +(d) the CPU-based noise source such as Intel RDSEED. The entropy estimate of the data of all noise sources are added to form the entropy estimate of the data used to seed the DRNG with. @@ -46,36 +50,34 @@ The LRNG is designed such that none of these noise sources can dominate the other noise sources to provide seed data to the DRNG during due to the following: -(a) During boot time, the amount of received interrupts are the trigger -points to (re)seed the DRNG. +(a) During boot time, the amount of received entropy at the different +entropy sources are the trigger points to (re)seed the DRNG. (b) At runtime, the available entropy from the slow noise source is concatenated with a pre-defined amount of data from the fast noise sources. In addition, each DRNG reseed operation triggers external noise source providers to deliver one block of data. -3. The entropy pool accumulates entropy obtained from certain events, -which will henceforth be collectively called "slow noise sources". -The entropy pool collects noise data from slow noise sources. Any data -received by the LRNG from the slow noise sources is inserted into a -per-CPU entropy pool using a hash operation that can be changed during -runtime. Per default, SHA-256 is used. +3. The IRQ entropy pool collects noise data from interrupt timing. +Any data received by the LRNG from the interrupt noise sources is +inserted into a per-CPU entropy pool using a hash operation that can +be changed during runtime. Per default, SHA-256 is used. - (a) When an interrupt occurs, the high-resolution time stamp is mixed -into the per-CPU entropy pool. This time stamp is credited with -heuristically implied entropy. + (a) When an interrupt occurs, the 8 least significant bits of the + high-resolution time stamp divided by the greatest common divisor (GCD) + is mixed into the per-CPU entropy pool. This time stamp is credited with + heuristically implied entropy. (b) HID event data like the key stroke or the mouse coordinates are -mixed into the per-CPU entropy pool. This data is not credited with -entropy by the LRNG. + mixed into the per-CPU entropy pool. This data is not credited with + entropy by the LRNG. - (c) Device drivers may provide data that is mixed into an auxiliary -pool using the same hash that is used to process the per-CPU entropy -pool. This data is not credited with entropy by the LRNG. - -Any data provided from user space by either writing to /dev/random, +5. Any data provided from user space by either writing to /dev/random, /dev/urandom or the IOCTL of RNDADDENTROPY on both device files -are always injected into the auxiliary pool. +are always injected into the auxiliary pool. Also, device drivers may +provide data that is mixed into an auxiliary pool using the same hash +that is used to process the per-CPU entropy pool. This data is not +credited with entropy by the LRNG. In addition, when a hardware random number generator covered by the Linux kernel HW generator framework wants to deliver random numbers, @@ -87,17 +89,17 @@ LRNG operation. Similarly any user space provided data is inserted into the entropy pool. When seed data for the DRNG is to be generated, all per-CPU -entropy pools and the auxiliary pool are hashed. The message digest -forms the new auxiliary pool state. At the same time, this data -is used for seeding the DRNG. +entropy pools are hashed. The message digest forms the data used for +seeding the DRNG. To speed up the interrupt handling code of the LRNG, the time stamp -collected for an interrupt event is truncated to the 8 least -significant bits. 64 truncated time stamps are concatenated and then +collected for an interrupt event is divided by the greatest common +divisor to eliminate fixed low bits and then truncated to the 8 least +significant bits. 1024 truncated time stamps are concatenated and then jointly inserted into the per-CPU entropy pool. During boot time, until the fully seeded stage is reached, each time stamp with its -32 least significant bits is are concatenated. When 16 such events -are received, they are injected into the per-CPU entropy pool. +32 least significant bits is are concatenated. When 1024/32 = 32 such +events are received, they are injected into the per-CPU entropy pool. The LRNG allows the DRNG mechanism to be changed at runtime. Per default, a ChaCha20-based DRNG is used. The ChaCha20-DRNG implemented for the @@ -109,8 +111,9 @@ The processing of entropic data from the noise source before injecting them into the DRNG is performed with the following mathematical operations: -1. Truncation: The received time stamps are truncated to 8 least -significant bits (or 32 least significant bits during boot time) +1. Truncation: The received time stamps divided by the GCD are +truncated to 8 least significant bits (or 32 least significant bits +during boot time) 2. Concatenation: The received and truncated time stamps as well as auxiliary 32 bit words are concatenated to fill the per-CPU data @@ -126,9 +129,7 @@ is hashed together with the auxiliary pool to form a new auxiliary pool state. 5. Hashing: A message digest of all per-CPU entropy pools and the -auxiliary pool is calculated which forms the new auxiliary pool -state. At the same time, this message digest is used to fill the -slow noise source output buffer discussed in the following. +is calculated which forms the new auxiliary pool state. 6. Truncation: The most-significant bits (MSB) defined by the requested number of bits (commonly equal to the security strength @@ -151,39 +152,29 @@ transferred to the DRNG, the hash_df function always generates 256 data bits during boot to seed the DRNG. During boot, the DRNG is seeded as follows: -1. The DRNG is reseeded from the entropy pool and potentially the fast -noise sources if the entropy pool has collected at least 32 bits of -entropy from the interrupt noise source. The goal of this step is to -ensure that the DRNG receives some initial entropy as early as -possible. In addition it receives the entropy available from -the fast noise sources. +1. The DRNG is reseeded from the entropy sources if the entropy sources +collectively have at least 32 bits of entropy. The goal of this step is +to ensure that the DRNG receives some initial entropy as early as +possible. -2. The DRNG is reseeded from the entropy pool and potentially the fast -noise sources if all noise sources collectively can provide at least -128 bits of entropy. +2. The DRNG is reseeded from the entropy sources if all entropy sources +collectively can provide at least 128 bits of entropy. -3. The DRNG is reseeded from the entropy pool and potentially the fast -noise sources if all noise sources collectivel can provide at least 256 -bits. +3. The DRNG is reseeded from the entropy sources if all entropy sources +collectively can provide at least 256 bits. At the time of the reseeding steps, the DRNG requests as much entropy as is available in order to skip certain steps and reach the seeding level of 256 bits. This may imply that one or more of the aforementioned steps are skipped. -In all listed steps, the DRNG is (re)seeded with a number of random -bytes from the entropy pool that is at most the amount of entropy -present in the entropy pool. This means that when the entropy pool -contains 128 or 256 bits of entropy, the DRNG is seeded with that -amount of entropy as well. - Before the DRNG is seeded with 256 bits of entropy in step 3, requests of random data from /dev/random and the getrandom system call are not processed. -The hash operation providing random data from the entropy pools will -always require that all entropy sources collectively can deliver at -least 128 entropy bits. +The reseeding of the DRNG always ensures that all entropy sources +collectively can deliver at least 128 entropy bits during runtime once +the DRNG is fully seeded. The DRNG operates as deterministic random number generator with the following properties: @@ -195,20 +186,24 @@ The ChaCha20 DRNG as well as the SP800-90A DRBGs implement an update of their state after completing a generate request for backtracking resistance. -* The secondary DRNG is reseeded with whatever entropy is available – +* The DRNG is reseeded with whatever entropy is available - in the worst case where no additional entropy can be provided by the -noise sources, the DRNG is not re-seeded and continues its operation +entropy sources, the DRNG is not re-seeded and continues its operation to try to reseed again after again the expiry of one of these thresholds: - - If the last reseeding of the secondary DRNG is more than 600 seconds + - If the last reseeding of the DRNG is more than 600 seconds ago, or - 2^20 DRNG generate operations are performed, whatever comes first, or - - the secondary DRNG is forced to reseed before the next generation of + - the DRNG is forced to reseed before the next generation of random numbers if data has been injected into the LRNG by writing data into /dev/random or /dev/urandom. + - If the DRNG was not successfully reseeded after 2^30 generate requests, + the DRNG reverts back to an unseeded stage implying that the blocking + interfaces of /dev/random and getrandom will block again. + The chosen values prevent high-volume requests from user space to cause frequent reseeding operations which drag down the performance of the DRNG. @@ -263,6 +258,10 @@ In addition, the documentation explains the conducted regression tests to verify that the LRNG is API and ABI compatible with the existing /dev/random implementation. +Note, this patch covers the entropy sources manager, the API +implementation, the built-in ChaCha20 DRNG and the auxiliary entropy +pool. + [1] https://www.chronox.de/lrng.html CC: Torsten Duwe @@ -289,46 +288,44 @@ Reviewed-by: Marcelo Henrique Cerri Reviewed-by: Roman Drahtmueller Tested-by: Marcelo Henrique Cerri Tested-by: Neil Horman +Tested-by: Jirka Hladky +Reviewed-by: Jirka Hladky Signed-off-by: Stephan Mueller --- - MAINTAINERS | 7 + - drivers/char/Kconfig | 2 + - drivers/char/Makefile | 9 +- - drivers/char/lrng/Kconfig | 205 +++++++ - drivers/char/lrng/Makefile | 9 + - drivers/char/lrng/lrng_aux.c | 136 +++++ - drivers/char/lrng/lrng_chacha20.c | 321 ++++++++++ - drivers/char/lrng/lrng_chacha20.h | 25 + - drivers/char/lrng/lrng_drng.c | 444 ++++++++++++++ - drivers/char/lrng/lrng_es_archrandom.c | 91 +++ - drivers/char/lrng/lrng_es_aux.c | 274 +++++++++ - drivers/char/lrng/lrng_es_irq.c | 796 +++++++++++++++++++++++++ - drivers/char/lrng/lrng_es_irq.h | 71 +++ - drivers/char/lrng/lrng_es_mgr.c | 375 ++++++++++++ - drivers/char/lrng/lrng_interfaces.c | 650 ++++++++++++++++++++ - drivers/char/lrng/lrng_internal.h | 446 ++++++++++++++ - include/linux/lrng.h | 81 +++ - 17 files changed, 3941 insertions(+), 1 deletion(-) + MAINTAINERS | 7 + + drivers/char/Kconfig | 2 + + drivers/char/Makefile | 9 +- + drivers/char/lrng/Kconfig | 58 +++ + drivers/char/lrng/Makefile | 8 + + drivers/char/lrng/lrng_aux.c | 136 ++++++ + drivers/char/lrng/lrng_chacha20.c | 321 ++++++++++++++ + drivers/char/lrng/lrng_chacha20.h | 25 ++ + drivers/char/lrng/lrng_drng.c | 451 +++++++++++++++++++ + drivers/char/lrng/lrng_es_aux.c | 294 +++++++++++++ + drivers/char/lrng/lrng_es_mgr.c | 373 ++++++++++++++++ + drivers/char/lrng/lrng_interfaces.c | 656 ++++++++++++++++++++++++++++ + drivers/char/lrng/lrng_internal.h | 485 ++++++++++++++++++++ + include/linux/lrng.h | 81 ++++ + 14 files changed, 2905 insertions(+), 1 deletion(-) create mode 100644 drivers/char/lrng/Kconfig create mode 100644 drivers/char/lrng/Makefile create mode 100644 drivers/char/lrng/lrng_aux.c create mode 100644 drivers/char/lrng/lrng_chacha20.c create mode 100644 drivers/char/lrng/lrng_chacha20.h create mode 100644 drivers/char/lrng/lrng_drng.c - create mode 100644 drivers/char/lrng/lrng_es_archrandom.c create mode 100644 drivers/char/lrng/lrng_es_aux.c - create mode 100644 drivers/char/lrng/lrng_es_irq.c - create mode 100644 drivers/char/lrng/lrng_es_irq.h create mode 100644 drivers/char/lrng/lrng_es_mgr.c create mode 100644 drivers/char/lrng/lrng_interfaces.c create mode 100644 drivers/char/lrng/lrng_internal.h create mode 100644 include/linux/lrng.h +diff --git a/MAINTAINERS b/MAINTAINERS +index c79388b78818..ea4f88da1601 100644 --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -9494,6 +9494,13 @@ F: Documentation/core-api/atomic_ops.rst - F: Documentation/core-api/refcount-vs-atomic.rst +@@ -10817,6 +10817,13 @@ F: Documentation/litmus-tests/ F: Documentation/memory-barriers.txt + F: tools/memory-model/ +LINUX RANDOM NUMBER GENERATOR (LRNG) DRIVER +M: Stephan Mueller @@ -340,17 +337,19 @@ Signed-off-by: Stephan Mueller LIS3LV02D ACCELEROMETER DRIVER M: Eric Piel S: Maintained +diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig +index 740811893c57..a52d575ca756 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig -@@ -535,6 +535,8 @@ config ADI - and SSM (Silicon Secured Memory). Intended consumers of this - driver include crash and makedumpfile. +@@ -451,4 +451,6 @@ config RANDOM_TRUST_BOOTLOADER + pool. Otherwise, say N here so it will be regarded as device input that + only mixes the entropy pool. +source "drivers/char/lrng/Kconfig" + endmenu - - config RANDOM_TRUST_CPU +diff --git a/drivers/char/Makefile b/drivers/char/Makefile +index 264eb398fdd4..7371f7464a49 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -3,7 +3,14 @@ @@ -369,9 +368,12 @@ Signed-off-by: Stephan Mueller obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o obj-y += misc.o obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o +diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig +new file mode 100644 +index 000000000000..655d873480b0 --- /dev/null +++ b/drivers/char/lrng/Kconfig -@@ -0,0 +1,205 @@ +@@ -0,0 +1,58 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Linux Random Number Generator configuration @@ -429,166 +431,24 @@ Signed-off-by: Stephan Mueller + +endmenu # "Specific DRNG seeding strategies" + -+menu "Entropy Source Configuration" -+ -+comment "Interrupt Entropy Source" -+ -+choice -+ prompt "Continuous entropy compression boot time setting" -+ default LRNG_CONTINUOUS_COMPRESSION_ENABLED -+ help -+ Select the default behavior of the interrupt entropy source -+ continuous compression operation. -+ -+ The Linux RNG collects entropy data during each interrupt. -+ For performance reasons, a amount of entropy data defined by -+ the LRNG entropy collection pool size is concatenated into -+ an array. When that array is filled up, a hash is calculated -+ to compress the entropy. That hash is calculated in -+ interrupt context. -+ -+ In case such hash calculation in interrupt context is deemed -+ too time-consuming, the continuous compression operation -+ can be disabled. If disabled, the collection of entropy will -+ not trigger a hash compression operation in interrupt context. -+ The compression happens only when the DRNG is reseeded which is -+ in process context. This implies that old entropy data -+ collected after the last DRNG-reseed is overwritten with newer -+ entropy data once the collection pool is full instead of -+ retaining its entropy with the compression operation. -+ -+ config LRNG_CONTINUOUS_COMPRESSION_ENABLED -+ bool "Enable continuous compression (default)" -+ -+ config LRNG_CONTINUOUS_COMPRESSION_DISABLED -+ bool "Disable continuous compression" -+endchoice -+ -+config LRNG_ENABLE_CONTINUOUS_COMPRESSION -+ bool -+ default y if LRNG_CONTINUOUS_COMPRESSION_ENABLED -+ default n if LRNG_CONTINUOUS_COMPRESSION_DISABLED -+ -+config LRNG_SWITCHABLE_CONTINUOUS_COMPRESSION -+ bool "Runtime-switchable continuous entropy compression" -+ help -+ Per default, the interrupt entropy source continuous -+ compression operation behavior is hard-wired into the kernel. -+ Enable this option to allow it to be configurable at boot time. -+ -+ To modify the default behavior of the continuous -+ compression operation, use the kernel command line option -+ of lrng_sw_noise.lrng_pcpu_continuous_compression. -+ -+ If unsure, say N. -+ -+choice -+ prompt "LRNG Entropy Collection Pool Size" -+ default LRNG_COLLECTION_SIZE_1024 -+ help -+ Select the size of the LRNG entropy collection pool -+ storing data for the interrupt entropy source without -+ performing a compression operation. The larger the -+ collection size is, the faster the average interrupt -+ handling will be. The collection size represents the -+ number of bytes of the per-CPU memory used to batch -+ up entropy event data. -+ -+ The default value is good for regular operations. Choose -+ larger sizes for servers that have no memory limitations. -+ If runtime memory is precious, choose a smaller size. -+ -+ The collection size is unrelated to the entropy rate -+ or the amount of entropy the LRNG can process. -+ -+ config LRNG_COLLECTION_SIZE_32 -+ depends on LRNG_CONTINUOUS_COMPRESSION_ENABLED -+ depends on !LRNG_SWITCHABLE_CONTINUOUS_COMPRESSION -+ depends on !LRNG_OVERSAMPLE_ENTROPY_SOURCES -+ bool "32 interrupt events" -+ -+ config LRNG_COLLECTION_SIZE_256 -+ depends on !LRNG_OVERSAMPLE_ENTROPY_SOURCES -+ bool "256 interrupt events" -+ -+ config LRNG_COLLECTION_SIZE_512 -+ bool "512 interrupt events" -+ -+ config LRNG_COLLECTION_SIZE_1024 -+ bool "1024 interrupt events (default)" -+ -+ config LRNG_COLLECTION_SIZE_2048 -+ bool "2048 interrupt events" -+ -+ config LRNG_COLLECTION_SIZE_4096 -+ bool "4096 interrupt events" -+ -+ config LRNG_COLLECTION_SIZE_8192 -+ bool "8192 interrupt events" -+ -+endchoice -+ -+config LRNG_COLLECTION_SIZE -+ int -+ default 32 if LRNG_COLLECTION_SIZE_32 -+ default 256 if LRNG_COLLECTION_SIZE_256 -+ default 512 if LRNG_COLLECTION_SIZE_512 -+ default 1024 if LRNG_COLLECTION_SIZE_1024 -+ default 2048 if LRNG_COLLECTION_SIZE_2048 -+ default 4096 if LRNG_COLLECTION_SIZE_4096 -+ default 8192 if LRNG_COLLECTION_SIZE_8192 -+ -+config LRNG_IRQ_ENTROPY_RATE -+ int "Interrupt Entropy Source Entropy Rate" -+ range 256 4294967295 -+ default 256 -+ help -+ The LRNG will collect the configured number of interrupts to -+ obtain 256 bits of entropy. This value can be set to any between -+ 256 and 4294967295. The LRNG guarantees that this value is not -+ lower than 256. This lower limit implies that one interrupt event -+ is credited with one bit of entropy. This value is subject to the -+ increase by the oversampling factor, if no high-resolution timer -+ is found. -+ -+ In order to effectively disable the interrupt entropy source, -+ the option has to be set to 4294967295. In this case, the -+ interrupt entropy source will still deliver data but without -+ being credited with entropy. -+ -+comment "CPU Entropy Source" -+ -+config LRNG_CPU_ENTROPY_RATE -+ int "CPU Entropy Source Entropy Rate" -+ range 0 256 -+ default 8 -+ help -+ The option defines the amount of entropy the LRNG applies to 256 -+ bits of data obtained from the CPU entropy source. The LRNG -+ enforces the limit that this value must be in the range between -+ 0 and 256. -+ -+ In order to disable the CPU entropy source, the option has to -+ be set to 0. -+ -+ Note, this option is overwritten when the option -+ CONFIG_RANDOM_TRUST_CPU is set. -+ -+endmenu # "Entropy Source Configuration" -+ +endif # LRNG +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +new file mode 100644 +index 000000000000..6f4603f897cd --- /dev/null +++ b/drivers/char/lrng/Makefile -@@ -0,0 +1,9 @@ +@@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for the Linux Random Number Generator. +# + +obj-y += lrng_es_mgr.o lrng_aux.o \ -+ lrng_es_irq.o lrng_es_archrandom.o \ + lrng_drng.o lrng_chacha20.o \ + lrng_interfaces.o lrng_es_aux.o +diff --git a/drivers/char/lrng/lrng_aux.c b/drivers/char/lrng/lrng_aux.c +new file mode 100644 +index 000000000000..e3b994f6e4c1 --- /dev/null +++ b/drivers/char/lrng/lrng_aux.c @@ -0,0 +1,136 @@ @@ -697,7 +557,7 @@ Signed-off-by: Stephan Mueller + } +} + -+/** ++/* + * randomize_page - Generate a random, page aligned address + * @start: The smallest acceptable address the caller will take. + * @range: The size of the area, starting at @start, within which the @@ -728,6 +588,9 @@ Signed-off-by: Stephan Mueller + + return start + (get_random_long() % range << PAGE_SHIFT); +} +diff --git a/drivers/char/lrng/lrng_chacha20.c b/drivers/char/lrng/lrng_chacha20.c +new file mode 100644 +index 000000000000..51f693c2971f --- /dev/null +++ b/drivers/char/lrng/lrng_chacha20.c @@ -0,0 +1,321 @@ @@ -764,7 +627,7 @@ Signed-off-by: Stephan Mueller + */ +struct chacha20_state chacha20 __latent_entropy; + -+/** ++/* + * Update of the ChaCha20 state by either using an unused buffer part or by + * generating one ChaCha20 block which is half of the state of the ChaCha20. + * The block is XORed into the key part of the state. This shall ensure @@ -1052,6 +915,9 @@ Signed-off-by: Stephan Mueller + .lrng_hash_final = lrng_cc20_hash_final, + .lrng_hash_desc_zero = lrng_cc20_hash_desc_zero, +}; +diff --git a/drivers/char/lrng/lrng_chacha20.h b/drivers/char/lrng/lrng_chacha20.h +new file mode 100644 +index 000000000000..bd0c0bee38f3 --- /dev/null +++ b/drivers/char/lrng/lrng_chacha20.h @@ -0,0 +1,25 @@ @@ -1080,9 +946,12 @@ Signed-off-by: Stephan Mueller +{ + chacha_init_consts(chacha20->constants); +} +diff --git a/drivers/char/lrng/lrng_drng.c b/drivers/char/lrng/lrng_drng.c +new file mode 100644 +index 000000000000..1ab533263239 --- /dev/null +++ b/drivers/char/lrng/lrng_drng.c -@@ -0,0 +1,444 @@ +@@ -0,0 +1,451 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* + * LRNG DRNG processing @@ -1378,7 +1247,14 @@ Signed-off-by: Stephan Mueller + struct lrng_drng **lrng_drng = lrng_drng_instances(); + u32 node; + -+ if (!lrng_drng) { ++ /* ++ * If the initial DRNG is over the reseed threshold, allow a forced ++ * reseed only for the initial DRNG as this is the fallback for all. It ++ * must be kept seeded before all others to keep the LRNG operational. ++ */ ++ if (!lrng_drng || ++ (atomic_read_u32(&lrng_drng_init.requests_since_fully_seeded) > ++ LRNG_DRNG_RESEED_THRESH)) { + lrng_drng_init.force_reseed = lrng_drng_init.fully_seeded; + pr_debug("force reseed of initial DRNG\n"); + return; @@ -1395,7 +1271,7 @@ Signed-off-by: Stephan Mueller + lrng_drng_atomic.force_reseed = lrng_drng_atomic.fully_seeded; +} + -+/** ++/* + * lrng_drng_get() - Get random data out of the DRNG which is reseeded + * frequently. + * @@ -1527,103 +1403,12 @@ Signed-off-by: Stephan Mueller +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Stephan Mueller "); +MODULE_DESCRIPTION("Linux Random Number Generator"); ---- /dev/null -+++ b/drivers/char/lrng/lrng_es_archrandom.c -@@ -0,0 +1,91 @@ -+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause -+/* -+ * LRNG Fast Entropy Source: CPU-based entropy source -+ * -+ * Copyright (C) 2016 - 2021, Stephan Mueller -+ */ -+ -+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+#include -+ -+#include "lrng_internal.h" -+ -+/* -+ * Estimated entropy of data is a 32th of LRNG_DRNG_SECURITY_STRENGTH_BITS. -+ * As we have no ability to review the implementation of those noise sources, -+ * it is prudent to have a conservative estimate here. -+ */ -+#define LRNG_ARCHRANDOM_DEFAULT_STRENGTH CONFIG_LRNG_CPU_ENTROPY_RATE -+#define LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH LRNG_DRNG_SECURITY_STRENGTH_BITS -+#ifdef CONFIG_RANDOM_TRUST_CPU -+static u32 archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH; -+#else -+static u32 archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH; -+#endif -+#ifdef CONFIG_LRNG_RUNTIME_ES_CONFIG -+module_param(archrandom, uint, 0644); -+MODULE_PARM_DESC(archrandom, "Entropy in bits of 256 data bits from CPU noise source (e.g. RDRAND)"); -+#endif -+ -+static int __init lrng_parse_trust_cpu(char *arg) -+{ -+ int ret; -+ bool trust_cpu = false; -+ -+ ret = kstrtobool(arg, &trust_cpu); -+ if (ret) -+ return ret; -+ -+ if (trust_cpu) { -+ archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH; -+ lrng_pool_add_entropy(); -+ } else { -+ archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH; -+ } -+ -+ return 0; -+} -+early_param("random.trust_cpu", lrng_parse_trust_cpu); -+ -+u32 lrng_archrandom_entropylevel(u32 requested_bits) -+{ -+ return lrng_fast_noise_entropylevel(archrandom, requested_bits); -+} -+ -+/** -+ * lrng_get_arch() - Get CPU noise source entropy -+ * -+ * @outbuf: buffer to store entropy of size LRNG_DRNG_SECURITY_STRENGTH_BYTES -+ * -+ * Return: -+ * * > 0 on success where value provides the added entropy in bits -+ * * 0 if no fast source was available -+ */ -+u32 lrng_get_arch(u8 *outbuf, u32 requested_bits) -+{ -+ u32 i, ent_bits = lrng_archrandom_entropylevel(requested_bits); -+ -+ /* operate on full blocks */ -+ BUILD_BUG_ON(LRNG_DRNG_SECURITY_STRENGTH_BYTES % sizeof(unsigned long)); -+ BUILD_BUG_ON(CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS % -+ sizeof(unsigned long)); -+ /* ensure we have aligned buffers */ -+ BUILD_BUG_ON(LRNG_KCAPI_ALIGN % sizeof(unsigned long)); -+ -+ if (!ent_bits) -+ return 0; -+ -+ for (i = 0; i < (requested_bits >> 3); -+ i += sizeof(unsigned long)) { -+ if (!arch_get_random_seed_long((unsigned long *)(outbuf + i)) && -+ !arch_get_random_long((unsigned long *)(outbuf + i))) { -+ archrandom = 0; -+ return 0; -+ } -+ } -+ -+ pr_debug("obtained %u bits of entropy from CPU RNG noise source\n", -+ ent_bits); -+ return ent_bits; -+} +diff --git a/drivers/char/lrng/lrng_es_aux.c b/drivers/char/lrng/lrng_es_aux.c +new file mode 100644 +index 000000000000..cd51c7311feb --- /dev/null +++ b/drivers/char/lrng/lrng_es_aux.c -@@ -0,0 +1,274 @@ +@@ -0,0 +1,294 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* + * LRNG Slow Entropy Source: Auxiliary entropy pool @@ -1686,6 +1471,15 @@ Signed-off-by: Stephan Mueller + atomic_set(&lrng_pool.digestsize, digestsize); + + /* ++ * Update the /proc/.../write_wakeup_threshold which must not be larger ++ * than the digest size of the curent conditioning hash. ++ */ ++ digestsize <<= 3; ++ lrng_proc_update_max_write_thresh(digestsize); ++ if (lrng_write_wakeup_bits > digestsize) ++ lrng_write_wakeup_bits = digestsize; ++ ++ /* + * In case the new digest is larger than the old one, cap the available + * entropy to the old message digest used to process the existing data. + */ @@ -1760,7 +1554,7 @@ Signed-off-by: Stephan Mueller + + entropy_bits = min_t(u32, entropy_bits, inbuflen << 3); + -+ read_lock_irqsave(&drng->hash_lock, flags); ++ lrng_hash_lock(drng, &flags); + + crypto_cb = drng->crypto_cb; + hash = drng->hash; @@ -1786,7 +1580,7 @@ Signed-off-by: Stephan Mueller + crypto_cb->lrng_hash_digestsize(hash) << 3)); + +out: -+ read_unlock_irqrestore(&drng->hash_lock, flags); ++ lrng_hash_unlock(drng, flags); + return ret; +} + @@ -1807,7 +1601,7 @@ Signed-off-by: Stephan Mueller + +/************************* Get data from entropy pool *************************/ + -+/** ++/* + * Get auxiliary entropy pool and its entropy content for seed buffer. + * Caller must hold lrng_pool.pool->lock. + * @outbuf: buffer to store data in with size requested_bits @@ -1829,7 +1623,7 @@ Signed-off-by: Stephan Mueller + if (unlikely(!pool->initialized)) + return 0; + -+ read_lock_irqsave(&drng->hash_lock, flags); ++ lrng_hash_lock(drng, &flags); + + crypto_cb = drng->crypto_cb; + hash = drng->hash; @@ -1876,7 +1670,7 @@ Signed-off-by: Stephan Mueller + memcpy(outbuf, aux_output, requested_bits >> 3); + } + -+ read_unlock_irqrestore(&drng->hash_lock, flags); ++ lrng_hash_unlock(drng, flags); + memzero_explicit(aux_output, digestsize); + return returned_ent_bits; +} @@ -1898,882 +1692,23 @@ Signed-off-by: Stephan Mueller + + spin_unlock_irqrestore(&pool->lock, flags); +} ---- /dev/null -+++ b/drivers/char/lrng/lrng_es_irq.c -@@ -0,0 +1,796 @@ -+// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause -+/* -+ * LRNG Slow Entropy Source: Interrupt data collection -+ * -+ * Copyright (C) 2016 - 2021, Stephan Mueller -+ */ -+ -+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "lrng_internal.h" -+#include "lrng_es_irq.h" -+ -+/* Number of interrupts required for LRNG_DRNG_SECURITY_STRENGTH_BITS entropy */ -+static u32 lrng_irq_entropy_bits = LRNG_IRQ_ENTROPY_BITS; -+/* Is high-resolution timer present? */ -+static bool lrng_irq_highres_timer = false; -+ -+static u32 irq_entropy __read_mostly = LRNG_IRQ_ENTROPY_BITS; -+#ifdef CONFIG_LRNG_RUNTIME_ES_CONFIG -+module_param(irq_entropy, uint, 0444); -+MODULE_PARM_DESC(irq_entropy, -+ "How many interrupts must be collected for obtaining 256 bits of entropy\n"); -+#endif -+ -+/* Per-CPU array holding concatenated entropy events */ -+static DEFINE_PER_CPU(u32 [LRNG_DATA_ARRAY_SIZE], lrng_pcpu_array) -+ __aligned(LRNG_KCAPI_ALIGN); -+static DEFINE_PER_CPU(u32, lrng_pcpu_array_ptr) = 0; -+static DEFINE_PER_CPU(atomic_t, lrng_pcpu_array_irqs) = ATOMIC_INIT(0); -+ -+/* -+ * The entropy collection is performed by executing the following steps: -+ * 1. fill up the per-CPU array holding the time stamps -+ * 2. once the per-CPU array is full, a compression of the data into -+ * the entropy pool is performed - this happens in interrupt context -+ * -+ * If step 2 is not desired in interrupt context, the following boolean -+ * needs to be set to false. This implies that old entropy data in the -+ * per-CPU array collected since the last DRNG reseed is overwritten with -+ * new entropy data instead of retaining the entropy with the compression -+ * operation. -+ * -+ * Impact on entropy: -+ * -+ * If continuous compression is enabled, the maximum entropy that is collected -+ * per CPU between DRNG reseeds is equal to the digest size of the used hash. -+ * -+ * If continuous compression is disabled, the maximum number of entropy events -+ * that can be collected per CPU is equal to LRNG_DATA_ARRAY_SIZE. This amount -+ * of events is converted into an entropy statement which then represents the -+ * maximum amount of entropy collectible per CPU between DRNG reseeds. -+ */ -+static bool lrng_pcpu_continuous_compression __read_mostly = -+ IS_ENABLED(CONFIG_LRNG_ENABLE_CONTINUOUS_COMPRESSION); -+ -+#ifdef CONFIG_LRNG_SWITCHABLE_CONTINUOUS_COMPRESSION -+module_param(lrng_pcpu_continuous_compression, bool, 0444); -+MODULE_PARM_DESC(lrng_pcpu_continuous_compression, -+ "Perform entropy compression if per-CPU entropy data array is full\n"); -+#endif -+ -+/* -+ * Per-CPU entropy pool with compressed entropy event -+ * -+ * The per-CPU entropy pool is defined as the hash state. New data is simply -+ * inserted into the entropy pool by performing a hash update operation. -+ * To read the entropy pool, a hash final must be invoked. However, before -+ * the entropy pool is released again after a hash final, the hash init must -+ * be performed. -+ */ -+static DEFINE_PER_CPU(u8 [LRNG_POOL_SIZE], lrng_pcpu_pool) -+ __aligned(LRNG_KCAPI_ALIGN); -+/* -+ * Lock to allow other CPUs to read the pool - as this is only done during -+ * reseed which is infrequent, this lock is hardly contended. -+ */ -+static DEFINE_PER_CPU(spinlock_t, lrng_pcpu_lock); -+static DEFINE_PER_CPU(bool, lrng_pcpu_lock_init) = false; -+ -+/* Number of time stamps analyzed to calculate a GCD */ -+#define LRNG_GCD_WINDOW_SIZE 100 -+static u32 lrng_gcd_history[LRNG_GCD_WINDOW_SIZE]; -+static atomic_t lrng_gcd_history_ptr = ATOMIC_INIT(-1); -+ -+/* The common divisor for all timestamps */ -+static u32 lrng_gcd_timer = 0; -+ -+static inline bool lrng_gcd_tested(void) -+{ -+ return (lrng_gcd_timer != 0); -+} -+ -+/* Set the GCD for use in IRQ ES - if 0, the GCD calculation is restarted. */ -+static inline void _lrng_gcd_set(u32 running_gcd) -+{ -+ lrng_gcd_timer = running_gcd; -+ mb(); -+} -+ -+static void lrng_gcd_set(u32 running_gcd) -+{ -+ if (!lrng_gcd_tested()) { -+ _lrng_gcd_set(running_gcd); -+ pr_debug("Setting GCD to %u\n", running_gcd); -+ } -+} -+ -+u32 lrng_gcd_analyze(u32 *history, size_t nelem) -+{ -+ u32 running_gcd = 0; -+ size_t i; -+ -+ /* Now perform the analysis on the accumulated time data. */ -+ for (i = 0; i < nelem; i++) { -+ /* -+ * NOTE: this would be the place to add more analysis on the -+ * appropriateness of the timer like checking the presence -+ * of sufficient variations in the timer. -+ */ -+ -+ /* -+ * This calculates the gcd of all the time values. that is -+ * gcd(time_1, time_2, ..., time_nelem) -+ * -+ * Some timers increment by a fixed (non-1) amount each step. -+ * This code checks for such increments, and allows the library -+ * to output the number of such changes have occurred. -+ */ -+ running_gcd = (u32)gcd(history[i], running_gcd); -+ -+ /* Zeroize data */ -+ history[i] = 0; -+ } -+ -+ return running_gcd; -+} -+ -+static void jent_gcd_add_value(u32 time) -+{ -+ u32 ptr = (u32)atomic_inc_return_relaxed(&lrng_gcd_history_ptr); -+ -+ if (ptr < LRNG_GCD_WINDOW_SIZE) { -+ lrng_gcd_history[ptr] = time; -+ } else if (ptr == LRNG_GCD_WINDOW_SIZE) { -+ u32 gcd = lrng_gcd_analyze(lrng_gcd_history, -+ LRNG_GCD_WINDOW_SIZE); -+ -+ if (!gcd) -+ gcd = 1; -+ -+ /* -+ * Ensure that we have variations in the time stamp below the -+ * given value. This is just a safety measure to prevent the GCD -+ * becoming too large. -+ */ -+ if (gcd >= 1000) { -+ pr_warn("calculated GCD is larger than expected: %u\n", -+ gcd); -+ gcd = 1000; -+ } -+ -+ /* Adjust all deltas by the observed (small) common factor. */ -+ lrng_gcd_set(gcd); -+ atomic_set(&lrng_gcd_history_ptr, 0); -+ } -+} -+ -+/* Return boolean whether LRNG identified presence of high-resolution timer */ -+bool lrng_pool_highres_timer(void) -+{ -+ return lrng_irq_highres_timer; -+} -+ -+/* Convert entropy in bits into number of IRQs with the same entropy content. */ -+static inline u32 lrng_entropy_to_data(u32 entropy_bits) -+{ -+ return ((entropy_bits * lrng_irq_entropy_bits) / -+ LRNG_DRNG_SECURITY_STRENGTH_BITS); -+} -+ -+/* Convert number of IRQs into entropy value. */ -+static inline u32 lrng_data_to_entropy(u32 irqnum) -+{ -+ return ((irqnum * LRNG_DRNG_SECURITY_STRENGTH_BITS) / -+ lrng_irq_entropy_bits); -+} -+ -+static inline bool lrng_pcpu_pool_online(int cpu) -+{ -+ return per_cpu(lrng_pcpu_lock_init, cpu); -+} -+ -+bool lrng_pcpu_continuous_compression_state(void) -+{ -+ return lrng_pcpu_continuous_compression; -+} -+ -+static void lrng_pcpu_check_compression_state(void) -+{ -+ /* One pool must hold sufficient entropy for disabled compression */ -+ if (!lrng_pcpu_continuous_compression) { -+ u32 max_ent = min_t(u32, lrng_get_digestsize(), -+ lrng_data_to_entropy(LRNG_DATA_NUM_VALUES)); -+ if (max_ent < lrng_security_strength()) { -+ pr_warn("Force continuous compression operation to ensure LRNG can hold enough entropy\n"); -+ lrng_pcpu_continuous_compression = true; -+ } -+ } -+} -+ -+static int __init lrng_init_time_source(void) -+{ -+ /* Set a minimum number of interrupts that must be collected */ -+ irq_entropy = max_t(u32, LRNG_IRQ_ENTROPY_BITS, irq_entropy); -+ -+ if ((random_get_entropy() & LRNG_DATA_SLOTSIZE_MASK) || -+ (random_get_entropy() & LRNG_DATA_SLOTSIZE_MASK)) { -+ /* -+ * As the highres timer is identified here, previous interrupts -+ * obtained during boot time are treated like a lowres-timer -+ * would have been present. -+ */ -+ lrng_irq_highres_timer = true; -+ lrng_irq_entropy_bits = irq_entropy; -+ } else { -+ lrng_health_disable(); -+ lrng_irq_highres_timer = false; -+ lrng_irq_entropy_bits = irq_entropy * -+ LRNG_IRQ_OVERSAMPLING_FACTOR; -+ pr_warn("operating without high-resolution timer and applying IRQ oversampling factor %u\n", -+ LRNG_IRQ_OVERSAMPLING_FACTOR); -+ lrng_pcpu_check_compression_state(); -+ } -+ -+ return 0; -+} -+core_initcall(lrng_init_time_source); -+ -+/* -+ * Reset all per-CPU pools - reset entropy estimator but leave the pool data -+ * that may or may not have entropy unchanged. -+ */ -+void lrng_pcpu_reset(void) -+{ -+ int cpu; -+ -+ /* Trigger GCD calculation anew. */ -+ _lrng_gcd_set(0); -+ -+ for_each_online_cpu(cpu) -+ atomic_set(per_cpu_ptr(&lrng_pcpu_array_irqs, cpu), 0); -+} -+ -+u32 lrng_pcpu_avail_pool_size(void) -+{ -+ u32 max_size = 0, max_pool = lrng_get_digestsize(); -+ int cpu; -+ -+ if (!lrng_pcpu_continuous_compression) -+ max_pool = min_t(u32, max_pool, LRNG_DATA_NUM_VALUES); -+ -+ for_each_online_cpu(cpu) { -+ if (lrng_pcpu_pool_online(cpu)) -+ max_size += max_pool; -+ } -+ -+ return max_size; -+} -+ -+/* Return entropy of unused IRQs present in all per-CPU pools. */ -+u32 lrng_pcpu_avail_entropy(void) -+{ -+ u32 digestsize_irqs, irq = 0; -+ int cpu; -+ -+ /* Obtain the cap of maximum numbers of IRQs we count */ -+ digestsize_irqs = lrng_entropy_to_data(lrng_get_digestsize()); -+ if (!lrng_pcpu_continuous_compression) { -+ /* Cap to max. number of IRQs the array can hold */ -+ digestsize_irqs = min_t(u32, digestsize_irqs, -+ LRNG_DATA_NUM_VALUES); -+ } -+ -+ for_each_online_cpu(cpu) { -+ if (!lrng_pcpu_pool_online(cpu)) -+ continue; -+ irq += min_t(u32, digestsize_irqs, -+ atomic_read_u32(per_cpu_ptr(&lrng_pcpu_array_irqs, -+ cpu))); -+ } -+ -+ /* Consider oversampling rate */ -+ return lrng_reduce_by_osr(lrng_data_to_entropy(irq)); -+} -+ -+/** -+ * Trigger a switch of the hash implementation for the per-CPU pool. -+ * -+ * For each per-CPU pool, obtain the message digest with the old hash -+ * implementation, initialize the per-CPU pool again with the new hash -+ * implementation and inject the message digest into the new state. -+ * -+ * Assumption: the caller must guarantee that the new_cb is available during the -+ * entire operation (e.g. it must hold the lock against pointer updating). -+ */ -+int lrng_pcpu_switch_hash(int node, -+ const struct lrng_crypto_cb *new_cb, void *new_hash, -+ const struct lrng_crypto_cb *old_cb) -+{ -+ u8 digest[LRNG_MAX_DIGESTSIZE]; -+ u32 digestsize_irqs, found_irqs; -+ int ret = 0, cpu; -+ -+ if (!IS_ENABLED(CONFIG_LRNG_DRNG_SWITCH)) -+ return -EOPNOTSUPP; -+ -+ for_each_online_cpu(cpu) { -+ struct shash_desc *pcpu_shash; -+ -+ /* -+ * Only switch the per-CPU pools for the current node because -+ * the crypto_cb only applies NUMA-node-wide. -+ */ -+ if (cpu_to_node(cpu) != node || !lrng_pcpu_pool_online(cpu)) -+ continue; -+ -+ pcpu_shash = (struct shash_desc *)per_cpu_ptr(lrng_pcpu_pool, -+ cpu); -+ -+ digestsize_irqs = old_cb->lrng_hash_digestsize(pcpu_shash); -+ digestsize_irqs = lrng_entropy_to_data(digestsize_irqs << 3); -+ -+ if (pcpu_shash->tfm == new_hash) -+ continue; -+ -+ /* Get the per-CPU pool hash with old digest ... */ -+ ret = old_cb->lrng_hash_final(pcpu_shash, digest) ?: -+ /* ... re-initialize the hash with the new digest ... */ -+ new_cb->lrng_hash_init(pcpu_shash, new_hash) ?: -+ /* -+ * ... feed the old hash into the new state. We may feed -+ * uninitialized memory into the new state, but this is -+ * considered no issue and even good as we have some more -+ * uncertainty here. -+ */ -+ new_cb->lrng_hash_update(pcpu_shash, digest, -+ sizeof(digest)); -+ if (ret) -+ goto out; -+ -+ /* -+ * In case the new digest is larger than the old one, cap -+ * the available entropy to the old message digest used to -+ * process the existing data. -+ */ -+ found_irqs = atomic_xchg_relaxed( -+ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu), 0); -+ found_irqs = min_t(u32, found_irqs, digestsize_irqs); -+ atomic_add_return_relaxed(found_irqs, -+ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu)); -+ -+ pr_debug("Re-initialize per-CPU entropy pool for CPU %d on NUMA node %d with hash %s\n", -+ cpu, node, new_cb->lrng_hash_name()); -+ } -+ -+out: -+ memzero_explicit(digest, sizeof(digest)); -+ return ret; -+} -+ -+/* -+ * When reading the per-CPU message digest, make sure we use the crypto -+ * callbacks defined for the NUMA node the per-CPU pool is defined for because -+ * the LRNG crypto switch support is only atomic per NUMA node. -+ */ -+static inline u32 -+lrng_pcpu_pool_hash_one(const struct lrng_crypto_cb *pcpu_crypto_cb, -+ void *pcpu_hash, int cpu, u8 *digest, u32 *digestsize) -+{ -+ struct shash_desc *pcpu_shash = -+ (struct shash_desc *)per_cpu_ptr(lrng_pcpu_pool, cpu); -+ spinlock_t *lock = per_cpu_ptr(&lrng_pcpu_lock, cpu); -+ unsigned long flags; -+ u32 digestsize_irqs, found_irqs; -+ -+ /* Lock guarding against reading / writing to per-CPU pool */ -+ spin_lock_irqsave(lock, flags); -+ -+ *digestsize = pcpu_crypto_cb->lrng_hash_digestsize(pcpu_hash); -+ digestsize_irqs = lrng_entropy_to_data(*digestsize << 3); -+ -+ /* Obtain entropy statement like for the entropy pool */ -+ found_irqs = atomic_xchg_relaxed( -+ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu), 0); -+ /* Cap to maximum amount of data we can hold in hash */ -+ found_irqs = min_t(u32, found_irqs, digestsize_irqs); -+ -+ /* Cap to maximum amount of data we can hold in array */ -+ if (!lrng_pcpu_continuous_compression) -+ found_irqs = min_t(u32, found_irqs, LRNG_DATA_NUM_VALUES); -+ -+ /* Store all not-yet compressed data in data array into hash, ... */ -+ if (pcpu_crypto_cb->lrng_hash_update(pcpu_shash, -+ (u8 *)per_cpu_ptr(lrng_pcpu_array, cpu), -+ LRNG_DATA_ARRAY_SIZE * sizeof(u32)) ?: -+ /* ... get the per-CPU pool digest, ... */ -+ pcpu_crypto_cb->lrng_hash_final(pcpu_shash, digest) ?: -+ /* ... re-initialize the hash, ... */ -+ pcpu_crypto_cb->lrng_hash_init(pcpu_shash, pcpu_hash) ?: -+ /* ... feed the old hash into the new state. */ -+ pcpu_crypto_cb->lrng_hash_update(pcpu_shash, digest, *digestsize)) -+ found_irqs = 0; -+ -+ spin_unlock_irqrestore(lock, flags); -+ return found_irqs; -+} -+ -+/** -+ * Hash all per-CPU pools and return the digest to be used as seed data for -+ * seeding a DRNG. The caller must guarantee backtracking resistance. -+ * The function will only copy as much data as entropy is available into the -+ * caller-provided output buffer. -+ * -+ * This function handles the translation from the number of received interrupts -+ * into an entropy statement. The conversion depends on LRNG_IRQ_ENTROPY_BITS -+ * which defines how many interrupts must be received to obtain 256 bits of -+ * entropy. With this value, the function lrng_data_to_entropy converts a given -+ * data size (received interrupts, requested amount of data, etc.) into an -+ * entropy statement. lrng_entropy_to_data does the reverse. -+ * -+ * @outbuf: buffer to store data in with size requested_bits -+ * @requested_bits: Requested amount of entropy -+ * @fully_seeded: indicator whether LRNG is fully seeded -+ * @return: amount of entropy in outbuf in bits. -+ */ -+u32 lrng_pcpu_pool_hash(u8 *outbuf, u32 requested_bits, bool fully_seeded) -+{ -+ SHASH_DESC_ON_STACK(shash, NULL); -+ const struct lrng_crypto_cb *crypto_cb; -+ struct lrng_drng **lrng_drng = lrng_drng_instances(); -+ struct lrng_drng *drng = lrng_drng_init_instance(); -+ u8 digest[LRNG_MAX_DIGESTSIZE]; -+ unsigned long flags, flags2; -+ u32 found_irqs, collected_irqs = 0, collected_ent_bits, requested_irqs, -+ returned_ent_bits; -+ int ret, cpu; -+ void *hash; -+ -+ /* Lock guarding replacement of per-NUMA hash */ -+ read_lock_irqsave(&drng->hash_lock, flags); -+ -+ crypto_cb = drng->crypto_cb; -+ hash = drng->hash; -+ -+ /* The hash state of filled with all per-CPU pool hashes. */ -+ ret = crypto_cb->lrng_hash_init(shash, hash); -+ if (ret) -+ goto err; -+ -+ requested_irqs = lrng_entropy_to_data(requested_bits + -+ lrng_compress_osr()); -+ -+ /* -+ * Harvest entropy from each per-CPU hash state - even though we may -+ * have collected sufficient entropy, we will hash all per-CPU pools. -+ */ -+ for_each_online_cpu(cpu) { -+ struct lrng_drng *pcpu_drng = drng; -+ u32 digestsize, pcpu_unused_irqs = 0; -+ int node = cpu_to_node(cpu); -+ -+ /* If pool is not online, then no entropy is present. */ -+ if (!lrng_pcpu_pool_online(cpu)) -+ continue; -+ -+ if (lrng_drng && lrng_drng[node]) -+ pcpu_drng = lrng_drng[node]; -+ -+ if (pcpu_drng == drng) { -+ found_irqs = lrng_pcpu_pool_hash_one(crypto_cb, hash, -+ cpu, digest, -+ &digestsize); -+ } else { -+ read_lock_irqsave(&pcpu_drng->hash_lock, flags2); -+ found_irqs = -+ lrng_pcpu_pool_hash_one(pcpu_drng->crypto_cb, -+ pcpu_drng->hash, cpu, -+ digest, &digestsize); -+ read_unlock_irqrestore(&pcpu_drng->hash_lock, flags2); -+ } -+ -+ /* Inject the digest into the state of all per-CPU pools */ -+ ret = crypto_cb->lrng_hash_update(shash, digest, digestsize); -+ if (ret) -+ goto err; -+ -+ collected_irqs += found_irqs; -+ if (collected_irqs > requested_irqs) { -+ pcpu_unused_irqs = collected_irqs - requested_irqs; -+ atomic_add_return_relaxed(pcpu_unused_irqs, -+ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu)); -+ collected_irqs = requested_irqs; -+ } -+ pr_debug("%u interrupts used from entropy pool of CPU %d, %u interrupts remain unused\n", -+ found_irqs - pcpu_unused_irqs, cpu, pcpu_unused_irqs); -+ } -+ -+ ret = crypto_cb->lrng_hash_final(shash, digest); -+ if (ret) -+ goto err; -+ -+ collected_ent_bits = lrng_data_to_entropy(collected_irqs); -+ /* Cap to maximum entropy that can ever be generated with given hash */ -+ collected_ent_bits = min_t(u32, collected_ent_bits, -+ crypto_cb->lrng_hash_digestsize(hash) << 3); -+ /* Apply oversampling: discount requested oversampling rate */ -+ returned_ent_bits = lrng_reduce_by_osr(collected_ent_bits); -+ -+ pr_debug("obtained %u bits by collecting %u bits of entropy from entropy pool noise source\n", -+ returned_ent_bits, collected_ent_bits); -+ -+ /* -+ * Truncate to available entropy as implicitly allowed by SP800-90B -+ * section 3.1.5.1.1 table 1 which awards truncated hashes full -+ * entropy. -+ * -+ * During boot time, we read requested_bits data with -+ * returned_ent_bits entropy. In case our conservative entropy -+ * estimate underestimates the available entropy we can transport as -+ * much available entropy as possible. -+ */ -+ memcpy(outbuf, digest, fully_seeded ? returned_ent_bits >> 3 : -+ requested_bits >> 3); -+ -+out: -+ crypto_cb->lrng_hash_desc_zero(shash); -+ read_unlock_irqrestore(&drng->hash_lock, flags); -+ memzero_explicit(digest, sizeof(digest)); -+ return returned_ent_bits; -+ -+err: -+ returned_ent_bits = 0; -+ goto out; -+} + -+/* Compress the lrng_pcpu_array array into lrng_pcpu_pool */ -+static inline void lrng_pcpu_array_compress(void) ++void lrng_aux_es_state(unsigned char *buf, size_t buflen) +{ -+ struct shash_desc *shash = -+ (struct shash_desc *)this_cpu_ptr(lrng_pcpu_pool); -+ struct lrng_drng **lrng_drng = lrng_drng_instances(); -+ struct lrng_drng *drng = lrng_drng_init_instance(); -+ const struct lrng_crypto_cb *crypto_cb; -+ spinlock_t *lock = this_cpu_ptr(&lrng_pcpu_lock); -+ unsigned long flags, flags2; -+ int node = numa_node_id(); -+ void *hash; -+ bool init = false; -+ -+ /* Get NUMA-node local hash instance */ -+ if (lrng_drng && lrng_drng[node]) -+ drng = lrng_drng[node]; -+ -+ read_lock_irqsave(&drng->hash_lock, flags); -+ crypto_cb = drng->crypto_cb; -+ hash = drng->hash; -+ -+ if (unlikely(!this_cpu_read(lrng_pcpu_lock_init))) { -+ init = true; -+ spin_lock_init(lock); -+ this_cpu_write(lrng_pcpu_lock_init, true); -+ pr_debug("Initializing per-CPU entropy pool for CPU %d on NUMA node %d with hash %s\n", -+ raw_smp_processor_id(), node, -+ crypto_cb->lrng_hash_name()); -+ } ++ const struct lrng_drng *lrng_drng_init = lrng_drng_init_instance(); + -+ spin_lock_irqsave(lock, flags2); -+ -+ if (unlikely(init) && crypto_cb->lrng_hash_init(shash, hash)) { -+ this_cpu_write(lrng_pcpu_lock_init, false); -+ pr_warn("Initialization of hash failed\n"); -+ } else if (lrng_pcpu_continuous_compression) { -+ /* Add entire per-CPU data array content into entropy pool. */ -+ if (crypto_cb->lrng_hash_update(shash, -+ (u8 *)this_cpu_ptr(lrng_pcpu_array), -+ LRNG_DATA_ARRAY_SIZE * sizeof(u32))) -+ pr_warn_ratelimited("Hashing of entropy data failed\n"); -+ } -+ -+ spin_unlock_irqrestore(lock, flags2); -+ read_unlock_irqrestore(&drng->hash_lock, flags); -+} -+ -+/* Compress data array into hash */ -+static inline void lrng_pcpu_array_to_hash(u32 ptr) -+{ -+ u32 *array = this_cpu_ptr(lrng_pcpu_array); -+ -+ /* -+ * During boot time the hash operation is triggered more often than -+ * during regular operation. -+ */ -+ if (unlikely(!lrng_state_fully_seeded())) { -+ if ((ptr & 31) && (ptr < LRNG_DATA_WORD_MASK)) -+ return; -+ } else if (ptr < LRNG_DATA_WORD_MASK) { -+ return; -+ } -+ -+ if (lrng_raw_array_entropy_store(*array)) { -+ u32 i; -+ -+ /* -+ * If we fed even a part of the array to external analysis, we -+ * mark that the entire array and the per-CPU pool to have no -+ * entropy. This is due to the non-IID property of the data as -+ * we do not fully know whether the existing dependencies -+ * diminish the entropy beyond to what we expect it has. -+ */ -+ atomic_set(this_cpu_ptr(&lrng_pcpu_array_irqs), 0); -+ -+ for (i = 1; i < LRNG_DATA_ARRAY_SIZE; i++) -+ lrng_raw_array_entropy_store(*(array + i)); -+ } else { -+ lrng_pcpu_array_compress(); -+ /* Ping pool handler about received entropy */ -+ lrng_pool_add_entropy(); -+ } -+} -+ -+/* -+ * Concatenate full 32 bit word at the end of time array even when current -+ * ptr is not aligned to sizeof(data). -+ */ -+static inline void _lrng_pcpu_array_add_u32(u32 data) -+{ -+ /* Increment pointer by number of slots taken for input value */ -+ u32 pre_ptr, mask, ptr = this_cpu_add_return(lrng_pcpu_array_ptr, -+ LRNG_DATA_SLOTS_PER_UINT); -+ unsigned int pre_array; -+ -+ /* -+ * This function injects a unit into the array - guarantee that -+ * array unit size is equal to data type of input data. -+ */ -+ BUILD_BUG_ON(LRNG_DATA_ARRAY_MEMBER_BITS != (sizeof(data) << 3)); -+ -+ /* -+ * The following logic requires at least two units holding -+ * the data as otherwise the pointer would immediately wrap when -+ * injection an u32 word. -+ */ -+ BUILD_BUG_ON(LRNG_DATA_NUM_VALUES <= LRNG_DATA_SLOTS_PER_UINT); -+ -+ lrng_pcpu_split_u32(&ptr, &pre_ptr, &mask); -+ -+ /* MSB of data go into previous unit */ -+ pre_array = lrng_data_idx2array(pre_ptr); -+ /* zeroization of slot to ensure the following OR adds the data */ -+ this_cpu_and(lrng_pcpu_array[pre_array], ~(0xffffffff &~ mask)); -+ this_cpu_or(lrng_pcpu_array[pre_array], data & ~mask); -+ -+ /* Invoke compression as we just filled data array completely */ -+ if (unlikely(pre_ptr > ptr)) -+ lrng_pcpu_array_to_hash(LRNG_DATA_WORD_MASK); -+ -+ /* LSB of data go into current unit */ -+ this_cpu_write(lrng_pcpu_array[lrng_data_idx2array(ptr)], -+ data & mask); -+ -+ if (likely(pre_ptr <= ptr)) -+ lrng_pcpu_array_to_hash(ptr); -+} -+ -+/* Concatenate a 32-bit word at the end of the per-CPU array */ -+void lrng_pcpu_array_add_u32(u32 data) -+{ -+ /* -+ * Disregard entropy-less data without continuous compression to -+ * avoid it overwriting data with entropy when array ptr wraps. -+ */ -+ if (lrng_pcpu_continuous_compression) -+ _lrng_pcpu_array_add_u32(data); -+} -+ -+/* Concatenate data of max LRNG_DATA_SLOTSIZE_MASK at the end of time array */ -+static inline void lrng_pcpu_array_add_slot(u32 data) -+{ -+ /* Get slot */ -+ u32 ptr = this_cpu_inc_return(lrng_pcpu_array_ptr) & -+ LRNG_DATA_WORD_MASK; -+ unsigned int array = lrng_data_idx2array(ptr); -+ unsigned int slot = lrng_data_idx2slot(ptr); -+ -+ BUILD_BUG_ON(LRNG_DATA_ARRAY_MEMBER_BITS % LRNG_DATA_SLOTSIZE_BITS); -+ /* Ensure consistency of values */ -+ BUILD_BUG_ON(LRNG_DATA_ARRAY_MEMBER_BITS != -+ sizeof(lrng_pcpu_array[0]) << 3); -+ -+ /* zeroization of slot to ensure the following OR adds the data */ -+ this_cpu_and(lrng_pcpu_array[array], -+ ~(lrng_data_slot_val(0xffffffff & LRNG_DATA_SLOTSIZE_MASK, -+ slot))); -+ /* Store data into slot */ -+ this_cpu_or(lrng_pcpu_array[array], lrng_data_slot_val(data, slot)); -+ -+ lrng_pcpu_array_to_hash(ptr); -+} -+ -+static inline void -+lrng_time_process_common(u32 time, void(*add_time)(u32 data)) -+{ -+ enum lrng_health_res health_test; -+ -+ if (lrng_raw_hires_entropy_store(time)) -+ return; -+ -+ health_test = lrng_health_test(time); -+ if (health_test > lrng_health_fail_use) -+ return; -+ -+ if (health_test == lrng_health_pass) -+ atomic_inc_return(this_cpu_ptr(&lrng_pcpu_array_irqs)); -+ -+ add_time(time); -+} -+ -+/* -+ * Batching up of entropy in per-CPU array before injecting into entropy pool. -+ */ -+static inline void lrng_time_process(void) -+{ -+ u32 now_time = random_get_entropy(); -+ -+ if (unlikely(!lrng_gcd_tested())) { -+ /* When GCD is unknown, we process the full time stamp */ -+ lrng_time_process_common(now_time, _lrng_pcpu_array_add_u32); -+ jent_gcd_add_value(now_time); -+ } else { -+ /* GCD is known and applied */ -+ lrng_time_process_common((now_time / lrng_gcd_timer) & -+ LRNG_DATA_SLOTSIZE_MASK, -+ lrng_pcpu_array_add_slot); -+ } -+ -+ lrng_perf_time(now_time); -+} -+ -+/* Hot code path - Callback for interrupt handler */ -+void add_interrupt_randomness(int irq, int irq_flg) -+{ -+ if (lrng_pool_highres_timer()) { -+ lrng_time_process(); -+ } else { -+ struct pt_regs *regs = get_irq_regs(); -+ static atomic_t reg_idx = ATOMIC_INIT(0); -+ u64 ip; -+ u32 tmp; -+ -+ if (regs) { -+ u32 *ptr = (u32 *)regs; -+ int reg_ptr = atomic_add_return_relaxed(1, ®_idx); -+ size_t n = (sizeof(struct pt_regs) / sizeof(u32)); -+ -+ ip = instruction_pointer(regs); -+ tmp = *(ptr + (reg_ptr % n)); -+ tmp = lrng_raw_regs_entropy_store(tmp) ? 0 : tmp; -+ _lrng_pcpu_array_add_u32(tmp); -+ } else { -+ ip = _RET_IP_; -+ } -+ -+ lrng_time_process(); -+ -+ /* -+ * The XOR operation combining the different values is not -+ * considered to destroy entropy since the entirety of all -+ * processed values delivers the entropy (and not each -+ * value separately of the other values). -+ */ -+ tmp = lrng_raw_jiffies_entropy_store(jiffies) ? 0 : jiffies; -+ tmp ^= lrng_raw_irq_entropy_store(irq) ? 0 : irq; -+ tmp ^= lrng_raw_irqflags_entropy_store(irq_flg) ? 0 : irq_flg; -+ tmp ^= lrng_raw_retip_entropy_store(ip) ? 0 : ip; -+ tmp ^= ip >> 32; -+ _lrng_pcpu_array_add_u32(tmp); -+ } -+} -+EXPORT_SYMBOL(add_interrupt_randomness); ---- /dev/null -+++ b/drivers/char/lrng/lrng_es_irq.h -@@ -0,0 +1,71 @@ -+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ -+/* -+ * LRNG Slow Noise Source: Time stamp array handling -+ * -+ * Copyright (C) 2016 - 2021, Stephan Mueller -+ */ -+ -+/* -+ * To limit the impact on the interrupt handling, the LRNG concatenates -+ * entropic LSB parts of the time stamps in a per-CPU array and only -+ * injects them into the entropy pool when the array is full. -+ */ -+ -+/* Store multiple integers in one u32 */ -+#define LRNG_DATA_SLOTSIZE_BITS (8) -+#define LRNG_DATA_SLOTSIZE_MASK ((1 << LRNG_DATA_SLOTSIZE_BITS) - 1) -+#define LRNG_DATA_ARRAY_MEMBER_BITS (4 << 3) /* ((sizeof(u32)) << 3) */ -+#define LRNG_DATA_SLOTS_PER_UINT (LRNG_DATA_ARRAY_MEMBER_BITS / \ -+ LRNG_DATA_SLOTSIZE_BITS) -+ -+/* -+ * Number of time values to store in the array - in small environments -+ * only one atomic_t variable per CPU is used. -+ */ -+#define LRNG_DATA_NUM_VALUES (CONFIG_LRNG_COLLECTION_SIZE) -+/* Mask of LSB of time stamp to store */ -+#define LRNG_DATA_WORD_MASK (LRNG_DATA_NUM_VALUES - 1) -+ -+#define LRNG_DATA_SLOTS_MASK (LRNG_DATA_SLOTS_PER_UINT - 1) -+#define LRNG_DATA_ARRAY_SIZE (LRNG_DATA_NUM_VALUES / \ -+ LRNG_DATA_SLOTS_PER_UINT) -+ -+/* Starting bit index of slot */ -+static inline unsigned int lrng_data_slot2bitindex(unsigned int slot) -+{ -+ return (LRNG_DATA_SLOTSIZE_BITS * slot); -+} -+ -+/* Convert index into the array index */ -+static inline unsigned int lrng_data_idx2array(unsigned int idx) -+{ -+ return idx / LRNG_DATA_SLOTS_PER_UINT; -+} -+ -+/* Convert index into the slot of a given array index */ -+static inline unsigned int lrng_data_idx2slot(unsigned int idx) -+{ -+ return idx & LRNG_DATA_SLOTS_MASK; -+} -+ -+/* Convert value into slot value */ -+static inline unsigned int lrng_data_slot_val(unsigned int val, -+ unsigned int slot) -+{ -+ return val << lrng_data_slot2bitindex(slot); -+} -+ -+/* -+ * Return the pointers for the previous and current units to inject a u32 into. -+ * Also return the mask which the u32 word is to be processed. -+ */ -+static inline void lrng_pcpu_split_u32(u32 *ptr, u32 *pre_ptr, u32 *mask) -+{ -+ /* ptr to previous unit */ -+ *pre_ptr = (*ptr - LRNG_DATA_SLOTS_PER_UINT) & LRNG_DATA_WORD_MASK; -+ *ptr &= LRNG_DATA_WORD_MASK; -+ -+ /* mask to split data into the two parts for the two units */ -+ *mask = ((1 << (*pre_ptr & (LRNG_DATA_SLOTS_PER_UINT - 1)) * -+ LRNG_DATA_SLOTSIZE_BITS)) - 1; ++ /* Assume the lrng_drng_init lock is taken by caller */ ++ snprintf(buf, buflen, ++ "Auxiliary ES properties:\n" ++ " Hash for operating entropy pool: %s\n", ++ lrng_drng_init->crypto_cb->lrng_hash_name()); +} +diff --git a/drivers/char/lrng/lrng_es_mgr.c b/drivers/char/lrng/lrng_es_mgr.c +new file mode 100644 +index 000000000000..c0025ad2b54a --- /dev/null +++ b/drivers/char/lrng/lrng_es_mgr.c -@@ -0,0 +1,375 @@ +@@ -0,0 +1,373 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* + * LRNG Entropy sources management @@ -2784,14 +1719,12 @@ Signed-off-by: Stephan Mueller +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include -+#include +#include +#include +#include +#include + +#include "lrng_internal.h" -+#include "lrng_es_irq.h" + +struct lrng_state { + bool can_invalidate; /* Can invalidate batched entropy? */ @@ -2973,7 +1906,7 @@ Signed-off-by: Stephan Mueller + lrng_jent_entropylevel(ent_thresh); +} + -+/** ++/* + * lrng_init_ops() - Set seed stages of LRNG + * + * Set the slow noise source reseed trigger threshold. The initial threshold @@ -3073,7 +2006,7 @@ Signed-off-by: Stephan Mueller + return 0; +} + -+/* Hot code path during boot - mix data into entropy pool during boot */ ++/* Interface requesting a reseed of the DRNG */ +void lrng_pool_add_entropy(void) +{ + /* @@ -3096,7 +2029,7 @@ Signed-off-by: Stephan Mueller + if (lrng_pool_trylock()) + return; + -+ /* Seed the DRNG with IRQ noise. */ ++ /* Seed the DRNG with any available noise. */ + if (lrng_state.perform_seedwork) + schedule_work(&lrng_state.lrng_seed_work); + else @@ -3149,9 +2082,12 @@ Signed-off-by: Stephan Mueller + */ + lrng_writer_wakeup(); +} +diff --git a/drivers/char/lrng/lrng_interfaces.c b/drivers/char/lrng/lrng_interfaces.c +new file mode 100644 +index 000000000000..6316a534bb54 --- /dev/null +++ b/drivers/char/lrng/lrng_interfaces.c -@@ -0,0 +1,650 @@ +@@ -0,0 +1,656 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* + * LRNG User and kernel space interfaces @@ -3183,7 +2119,7 @@ Signed-off-by: Stephan Mueller + * should wake up processes which are selecting or polling on write + * access to /dev/random. + */ -+u32 lrng_write_wakeup_bits = LRNG_WRITE_WAKEUP_ENTROPY; ++u32 lrng_write_wakeup_bits = (LRNG_WRITE_WAKEUP_ENTROPY << 3); + +static LIST_HEAD(lrng_ready_list); +static DEFINE_SPINLOCK(lrng_ready_list_lock); @@ -3264,7 +2200,7 @@ Signed-off-by: Stephan Mueller + +/************************ LRNG kernel input interfaces ************************/ + -+/** ++/* + * add_hwgenerator_randomness() - Interface for in-kernel drivers of true + * hardware RNGs. + * @@ -3293,7 +2229,7 @@ Signed-off-by: Stephan Mueller +} +EXPORT_SYMBOL_GPL(add_hwgenerator_randomness); + -+/** ++/* + * add_bootloader_randomness() - Handle random seed passed by bootloader. + * + * If the seed is trustworthy, it would be regarded as hardware RNGs. Otherwise @@ -3330,7 +2266,7 @@ Signed-off-by: Stephan Mueller +} +EXPORT_SYMBOL_GPL(add_input_randomness); + -+/** ++/* + * add_device_randomness() - Add device- or boot-specific data to the entropy + * pool to help initialize it. + * @@ -3354,7 +2290,12 @@ Signed-off-by: Stephan Mueller +EXPORT_SYMBOL(add_disk_randomness); +#endif + -+/** ++#ifndef CONFIG_LRNG_IRQ ++void add_interrupt_randomness(int irq, int irq_flg) { } ++EXPORT_SYMBOL(add_interrupt_randomness); ++#endif ++ ++/* + * del_random_ready_callback() - Delete a previously registered readiness + * callback function. + * @@ -3376,7 +2317,7 @@ Signed-off-by: Stephan Mueller +} +EXPORT_SYMBOL(del_random_ready_callback); + -+/** ++/* + * add_random_ready_callback() - Add a callback function that will be invoked + * when the DRNG is fully initialized and seeded. + * @@ -3420,7 +2361,7 @@ Signed-off-by: Stephan Mueller + +/*********************** LRNG kernel output interfaces ************************/ + -+/** ++/* + * get_random_bytes() - Provider of cryptographic strong random numbers for + * kernel-internal usage. + * @@ -3437,7 +2378,7 @@ Signed-off-by: Stephan Mueller +} +EXPORT_SYMBOL(get_random_bytes); + -+/** ++/* + * get_random_bytes_full() - Provider of cryptographic strong random numbers + * for kernel-internal usage. + * @@ -3456,7 +2397,7 @@ Signed-off-by: Stephan Mueller +} +EXPORT_SYMBOL(get_random_bytes_full); + -+/** ++/* + * wait_for_random_bytes() - Wait for the LRNG to be seeded and thus + * guaranteed to supply cryptographically secure random numbers. + * @@ -3478,7 +2419,7 @@ Signed-off-by: Stephan Mueller +} +EXPORT_SYMBOL(wait_for_random_bytes); + -+/** ++/* + * get_random_bytes_arch() - This function will use the architecture-specific + * hardware random number generator if it is available. + * @@ -3631,8 +2572,10 @@ Signed-off-by: Stephan Mueller + if (lrng_state_operational()) + mask |= EPOLLIN | EPOLLRDNORM; + if (lrng_need_entropy() || -+ lrng_state_exseed_allow(lrng_noise_source_user)) ++ lrng_state_exseed_allow(lrng_noise_source_user)) { ++ lrng_state_exseed_set(lrng_noise_source_user, false); + mask |= EPOLLOUT | EPOLLWRNORM; ++ } + return mask; +} + @@ -3727,7 +2670,6 @@ Signed-off-by: Stephan Mueller + return -EFAULT; + if (size < 0) + return -EINVAL; -+ lrng_state_exseed_set(lrng_noise_source_user, false); + /* there cannot be more entropy than data */ + ent_count_bits = min(ent_count_bits, size<<3); + return lrng_drng_write_common((const char __user *)p, size, @@ -3802,9 +2744,12 @@ Signed-off-by: Stephan Mueller + + return lrng_read_common_block(flags & GRND_NONBLOCK, buf, count); +} +diff --git a/drivers/char/lrng/lrng_internal.h b/drivers/char/lrng/lrng_internal.h +new file mode 100644 +index 000000000000..d67aa3c335b9 --- /dev/null +++ b/drivers/char/lrng/lrng_internal.h -@@ -0,0 +1,446 @@ +@@ -0,0 +1,485 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ +/* + * Copyright (C) 2018 - 2021, Stephan Mueller @@ -3818,6 +2763,7 @@ Signed-off-by: Stephan Mueller +#include +#include +#include ++#include +#include +#include + @@ -3827,6 +2773,9 @@ Signed-off-by: Stephan Mueller +#define LRNG_DRNG_SECURITY_STRENGTH_BYTES 32 +#define LRNG_DRNG_SECURITY_STRENGTH_BITS (LRNG_DRNG_SECURITY_STRENGTH_BYTES * 8) +#define LRNG_DRNG_BLOCKSIZE 64 /* Maximum of DRNG block sizes */ ++#define LRNG_DRNG_INIT_SEED_SIZE_BITS (LRNG_DRNG_SECURITY_STRENGTH_BITS + \ ++ CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS) ++#define LRNG_DRNG_INIT_SEED_SIZE_BYTES (LRNG_DRNG_INIT_SEED_SIZE_BITS >> 3) + +/* + * SP800-90A defines a maximum request size of 1<<16 bytes. The given value is @@ -3861,17 +2810,6 @@ Signed-off-by: Stephan Mueller +#define LRNG_DRNG_MAX_WITHOUT_RESEED (1<<30) + +/* -+ * Number of interrupts to be recorded to assume that DRNG security strength -+ * bits of entropy are received. -+ * Note: a value below the DRNG security strength should not be defined as this -+ * may imply the DRNG can never be fully seeded in case other noise -+ * sources are unavailable. -+ * -+ * This value is allowed to be changed. -+ */ -+#define LRNG_IRQ_ENTROPY_BITS CONFIG_LRNG_IRQ_ENTROPY_RATE -+ -+/* + * Min required seed entropy is 128 bits covering the minimum entropy + * requirement of SP800-131A and the German BSI's TR02102. + * @@ -3937,8 +2875,10 @@ Signed-off-by: Stephan Mueller + +#ifdef CONFIG_SYSCTL +void lrng_pool_inc_numa_node(void); ++void lrng_proc_update_max_write_thresh(u32 new_digestsize); +#else +static inline void lrng_pool_inc_numa_node(void) { } ++static inline void lrng_proc_update_max_write_thresh(u32 new_digestsize) { } +#endif + +/****************************** LRNG interfaces *******************************/ @@ -3959,10 +2899,12 @@ Signed-off-by: Stephan Mueller +#ifdef CONFIG_LRNG_JENT +u32 lrng_get_jent(u8 *outbuf, u32 requested_bits); +u32 lrng_jent_entropylevel(u32 requested_bits); -+#else /* CONFIG_CRYPTO_JITTERENTROPY */ ++void lrng_jent_es_state(unsigned char *buf, size_t buflen); ++#else /* CONFIG_LRNG_JENT */ +static inline u32 lrng_get_jent(u8 *outbuf, u32 requested_bits) { return 0; } +static inline u32 lrng_jent_entropylevel(u32 requested_bits) { return 0; } -+#endif /* CONFIG_CRYPTO_JITTERENTROPY */ ++static inline void lrng_jent_es_state(unsigned char *buf, size_t buflen) { } ++#endif /* CONFIG_LRNG_JENT */ + +/************************** CPU-based Entropy Source **************************/ + @@ -3975,12 +2917,19 @@ Signed-off-by: Stephan Mueller + return ent_bits; +} + ++#ifdef CONFIG_LRNG_CPU +u32 lrng_get_arch(u8 *outbuf, u32 requested_bits); +u32 lrng_archrandom_entropylevel(u32 requested_bits); ++void lrng_arch_es_state(unsigned char *buf, size_t buflen); ++#else /* CONFIG_LRNG_CPU */ ++static inline u32 lrng_get_arch(u8 *outbuf, u32 requested_bits) { return 0; } ++static inline u32 lrng_archrandom_entropylevel(u32 requested_bits) { return 0; } ++static inline void lrng_arch_es_state(unsigned char *buf, size_t buflen) { } ++#endif /* CONFIG_LRNG_CPU */ + +/************************** Interrupt Entropy Source **************************/ + -+bool lrng_pcpu_continuous_compression_state(void); ++#ifdef CONFIG_LRNG_IRQ +void lrng_pcpu_reset(void); +u32 lrng_pcpu_avail_pool_size(void); +u32 lrng_pcpu_avail_entropy(void); @@ -3990,6 +2939,25 @@ Signed-off-by: Stephan Mueller +u32 lrng_pcpu_pool_hash(u8 *outbuf, u32 requested_bits, bool fully_seeded); +void lrng_pcpu_array_add_u32(u32 data); +u32 lrng_gcd_analyze(u32 *history, size_t nelem); ++void lrng_irq_es_state(unsigned char *buf, size_t buflen); ++#else /* CONFIG_LRNG_IRQ */ ++static inline void lrng_pcpu_reset(void) { } ++static inline u32 lrng_pcpu_avail_pool_size(void) { return 0; } ++static inline u32 lrng_pcpu_avail_entropy(void) { return 0; } ++static inline int lrng_pcpu_switch_hash(int node, ++ const struct lrng_crypto_cb *new_cb, void *new_hash, ++ const struct lrng_crypto_cb *old_cb) ++{ ++ return 0; ++} ++static inline u32 lrng_pcpu_pool_hash(u8 *outbuf, u32 requested_bits, ++ bool fully_seeded) ++{ ++ return 0; ++} ++static inline void lrng_pcpu_array_add_u32(u32 data) { } ++static inline void lrng_irq_es_state(unsigned char *buf, size_t buflen) { } ++#endif /* CONFIG_LRNG_IRQ */ + +/****************************** DRNG processing *******************************/ + @@ -4110,18 +3078,13 @@ Signed-off-by: Stephan Mueller +int lrng_pool_trylock(void); +void lrng_pool_unlock(void); +void lrng_pool_all_numa_nodes_seeded(bool set); -+bool lrng_pool_highres_timer(void); +void lrng_pool_add_entropy(void); + +struct entropy_buf { -+ u8 a[LRNG_DRNG_SECURITY_STRENGTH_BYTES + -+ (CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS >> 3)]; -+ u8 b[LRNG_DRNG_SECURITY_STRENGTH_BYTES + -+ (CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS >> 3)]; -+ u8 c[LRNG_DRNG_SECURITY_STRENGTH_BYTES + -+ (CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS >> 3)]; -+ u8 d[LRNG_DRNG_SECURITY_STRENGTH_BYTES + -+ (CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS >> 3)]; ++ u8 a[LRNG_DRNG_INIT_SEED_SIZE_BYTES]; ++ u8 b[LRNG_DRNG_INIT_SEED_SIZE_BYTES]; ++ u8 c[LRNG_DRNG_INIT_SEED_SIZE_BYTES]; ++ u8 d[LRNG_DRNG_INIT_SEED_SIZE_BYTES]; + u32 now, a_bits, b_bits, c_bits, d_bits; +}; + @@ -4133,6 +3096,7 @@ Signed-off-by: Stephan Mueller +/*********************** Auxiliary Pool Entropy Source ************************/ + +u32 lrng_avail_aux_entropy(void); ++void lrng_aux_es_state(unsigned char *buf, size_t buflen); +u32 lrng_get_digestsize(void); +void lrng_pool_set_entropy(u32 entropy_bits); +int lrng_aux_switch_hash(const struct lrng_crypto_cb *new_cb, void *new_hash, @@ -4196,6 +3160,26 @@ Signed-off-by: Stephan Mueller + return (u32)atomic_read(v); +} + ++/******************** Crypto Primitive Switching Support **********************/ ++ ++#ifdef CONFIG_LRNG_DRNG_SWITCH ++static inline void lrng_hash_lock(struct lrng_drng *drng, unsigned long *flags) ++{ ++ read_lock_irqsave(&drng->hash_lock, *flags); ++} ++ ++static inline void lrng_hash_unlock(struct lrng_drng *drng, unsigned long flags) ++{ ++ read_unlock_irqrestore(&drng->hash_lock, flags); ++} ++#else /* CONFIG_LRNG_DRNG_SWITCH */ ++static inline void lrng_hash_lock(struct lrng_drng *drng, unsigned long *flags) ++{ } ++ ++static inline void lrng_hash_unlock(struct lrng_drng *drng, unsigned long flags) ++{ } ++#endif /* CONFIG_LRNG_DRNG_SWITCH */ ++ +/*************************** Auxiliary functions ******************************/ + +void invalidate_batched_entropy(void); @@ -4251,6 +3235,9 @@ Signed-off-by: Stephan Mueller +#endif /*CONFIG_LRNG_IRQ_PERF */ + +#endif /* _LRNG_INTERNAL_H */ +diff --git a/include/linux/lrng.h b/include/linux/lrng.h +new file mode 100644 +index 000000000000..3e8f93b53c84 --- /dev/null +++ b/include/linux/lrng.h @@ -0,0 +1,81 @@ @@ -4266,7 +3253,7 @@ Signed-off-by: Stephan Mueller +#include +#include + -+/** ++/* + * struct lrng_crypto_cb - cryptographic callback functions + * @lrng_drng_name Name of DRNG + * @lrng_hash_name Name of Hash used for reading entropy pool @@ -4335,3 +3322,6 @@ Signed-off-by: Stephan Mueller +#endif /* CONFIG_LRNG_DRNG_SWITCH */ + +#endif /* _LRNG_H */ +-- +2.31.1 + diff --git a/PATCH/LRNG/696-05-v43-0002-LRNG-IRQ-entropy-source.patch b/PATCH/LRNG/696-05-v43-0002-LRNG-IRQ-entropy-source.patch new file mode 100644 index 000000000..e5124ee9d --- /dev/null +++ b/PATCH/LRNG/696-05-v43-0002-LRNG-IRQ-entropy-source.patch @@ -0,0 +1,1155 @@ +From bf7029b326477fdbfc7fed2f63dcd34f06077452 Mon Sep 17 00:00:00 2001 +From: Stephan Mueller +Date: Wed, 13 Oct 2021 22:49:22 +0200 +Subject: [PATCH v43 02/15] LRNG - IRQ entropy source + +The interrupt entropy source hooks into the interrupt handler via the +add_interrupt_randomness function callback. Every interrupt received by +the kernel is also sent to the LRNG for processing. + +The IRQ entropy source performs the following processing: + +1. Record a time stamp + +2. Divide the time stamp by its greatest common divisor to eliminate + fixed least significant bits. + +3. Insert the 8 LSB of the result from step 2 into the collection pool. + +4. When the collection pool is full, it is hashed into the per-CPU + entropy pool (if continuous compression is enabled) or the latest + time stamps overwrite the oldest entries in the collection pool. + +If entropy is requested from the IRQ entropy pool, a message digest over +all per-CPU entropy pool digests is calculated. + +The GCD calculation is performed for the first 100 interupt time stamps. +Until the GCD value is calculated, the full 32 bit time stamp is +inserted into the collection pool. + +CC: Torsten Duwe +CC: "Eric W. Biederman" +CC: "Alexander E. Patrakov" +CC: "Ahmed S. Darwish" +CC: "Theodore Y. Ts'o" +CC: Willy Tarreau +CC: Matthew Garrett +CC: Vito Caputo +CC: Andreas Dilger +CC: Jan Kara +CC: Ray Strode +CC: William Jon McCann +CC: zhangjs +CC: Andy Lutomirski +CC: Florian Weimer +CC: Lennart Poettering +CC: Nicolai Stange +Reviewed-by: Alexander Lobakin +Tested-by: Alexander Lobakin +Mathematical aspects Reviewed-by: "Peter, Matthias" +Reviewed-by: Marcelo Henrique Cerri +Reviewed-by: Roman Drahtmueller +Tested-by: Marcelo Henrique Cerri +Tested-by: Neil Horman +Tested-by: Jirka Hladky +Reviewed-by: Jirka Hladky +Signed-off-by: Stephan Mueller +--- + drivers/char/lrng/Kconfig | 162 +++++++ + drivers/char/lrng/Makefile | 2 + + drivers/char/lrng/lrng_es_irq.c | 823 ++++++++++++++++++++++++++++++++ + drivers/char/lrng/lrng_es_irq.h | 71 +++ + 4 files changed, 1058 insertions(+) + create mode 100644 drivers/char/lrng/lrng_es_irq.c + create mode 100644 drivers/char/lrng/lrng_es_irq.h + +diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig +index 655d873480b0..a9ae35d9f648 100644 +--- a/drivers/char/lrng/Kconfig ++++ b/drivers/char/lrng/Kconfig +@@ -55,4 +55,166 @@ config LRNG_SEED_BUFFER_INIT_ADD_BITS + + endmenu # "Specific DRNG seeding strategies" + ++menu "Entropy Source Configuration" ++ ++comment "Interrupt Entropy Source" ++ ++config LRNG_IRQ ++ bool "Enable Interrupt Entropy Source as LRNG Seed Source" ++ default y ++ help ++ The LRNG models an entropy source based on the timing of the ++ occurrence of interrupts. Enable this option to enable this ++ IRQ entropy source. ++ ++ The IRQ entropy source is triggered every time an interrupt ++ arrives and thus causes the interrupt handler to execute ++ slightly longer. Disabling the IRQ entropy source implies ++ that the performance penalty on the interrupt handler added ++ by the LRNG is eliminated. Yet, this entropy source is ++ considered to be the internal entropy source of the LRNG. ++ Thus, only disable it if you ensured that other entropy ++ sources are available that supply the LRNG with entropy. ++ ++ If you disable the IRQ entropy source, you MUST ensure ++ one or more entropy sources collectively have the ++ capability to deliver sufficient entropy with one invocation ++ at a rate compliant to the security strength of the DRNG ++ (usually 256 bits of entropy). In addition, if those ++ entropy sources do not deliver sufficient entropy during ++ first request, the reseed must be triggered from user ++ space or kernel space when sufficient entropy is considered ++ to be present. ++ ++ If unsure, say Y. ++ ++choice ++ prompt "Continuous entropy compression boot time setting" ++ default LRNG_CONTINUOUS_COMPRESSION_ENABLED ++ depends on LRNG_IRQ ++ help ++ Select the default behavior of the interrupt entropy source ++ continuous compression operation. ++ ++ The Linux RNG collects entropy data during each interrupt. ++ For performance reasons, a amount of entropy data defined by ++ the LRNG entropy collection pool size is concatenated into ++ an array. When that array is filled up, a hash is calculated ++ to compress the entropy. That hash is calculated in ++ interrupt context. ++ ++ In case such hash calculation in interrupt context is deemed ++ too time-consuming, the continuous compression operation ++ can be disabled. If disabled, the collection of entropy will ++ not trigger a hash compression operation in interrupt context. ++ The compression happens only when the DRNG is reseeded which is ++ in process context. This implies that old entropy data ++ collected after the last DRNG-reseed is overwritten with newer ++ entropy data once the collection pool is full instead of ++ retaining its entropy with the compression operation. ++ ++ config LRNG_CONTINUOUS_COMPRESSION_ENABLED ++ bool "Enable continuous compression (default)" ++ ++ config LRNG_CONTINUOUS_COMPRESSION_DISABLED ++ bool "Disable continuous compression" ++endchoice ++ ++config LRNG_ENABLE_CONTINUOUS_COMPRESSION ++ bool ++ default y if LRNG_CONTINUOUS_COMPRESSION_ENABLED ++ default n if LRNG_CONTINUOUS_COMPRESSION_DISABLED ++ ++config LRNG_SWITCHABLE_CONTINUOUS_COMPRESSION ++ bool "Runtime-switchable continuous entropy compression" ++ depends on LRNG_IRQ ++ help ++ Per default, the interrupt entropy source continuous ++ compression operation behavior is hard-wired into the kernel. ++ Enable this option to allow it to be configurable at boot time. ++ ++ To modify the default behavior of the continuous ++ compression operation, use the kernel command line option ++ of lrng_sw_noise.lrng_pcpu_continuous_compression. ++ ++ If unsure, say N. ++ ++choice ++ prompt "LRNG Entropy Collection Pool Size" ++ default LRNG_COLLECTION_SIZE_1024 ++ depends on LRNG_IRQ ++ help ++ Select the size of the LRNG entropy collection pool ++ storing data for the interrupt entropy source without ++ performing a compression operation. The larger the ++ collection size is, the faster the average interrupt ++ handling will be. The collection size represents the ++ number of bytes of the per-CPU memory used to batch ++ up entropy event data. ++ ++ The default value is good for regular operations. Choose ++ larger sizes for servers that have no memory limitations. ++ If runtime memory is precious, choose a smaller size. ++ ++ The collection size is unrelated to the entropy rate ++ or the amount of entropy the LRNG can process. ++ ++ config LRNG_COLLECTION_SIZE_32 ++ depends on LRNG_CONTINUOUS_COMPRESSION_ENABLED ++ depends on !LRNG_SWITCHABLE_CONTINUOUS_COMPRESSION ++ depends on !LRNG_OVERSAMPLE_ENTROPY_SOURCES ++ bool "32 interrupt events" ++ ++ config LRNG_COLLECTION_SIZE_256 ++ depends on !LRNG_OVERSAMPLE_ENTROPY_SOURCES ++ bool "256 interrupt events" ++ ++ config LRNG_COLLECTION_SIZE_512 ++ bool "512 interrupt events" ++ ++ config LRNG_COLLECTION_SIZE_1024 ++ bool "1024 interrupt events (default)" ++ ++ config LRNG_COLLECTION_SIZE_2048 ++ bool "2048 interrupt events" ++ ++ config LRNG_COLLECTION_SIZE_4096 ++ bool "4096 interrupt events" ++ ++ config LRNG_COLLECTION_SIZE_8192 ++ bool "8192 interrupt events" ++ ++endchoice ++ ++config LRNG_COLLECTION_SIZE ++ int ++ default 32 if LRNG_COLLECTION_SIZE_32 ++ default 256 if LRNG_COLLECTION_SIZE_256 ++ default 512 if LRNG_COLLECTION_SIZE_512 ++ default 1024 if LRNG_COLLECTION_SIZE_1024 ++ default 2048 if LRNG_COLLECTION_SIZE_2048 ++ default 4096 if LRNG_COLLECTION_SIZE_4096 ++ default 8192 if LRNG_COLLECTION_SIZE_8192 ++ ++config LRNG_IRQ_ENTROPY_RATE ++ int "Interrupt Entropy Source Entropy Rate" ++ depends on LRNG_IRQ ++ range 256 4294967295 ++ default 256 ++ help ++ The LRNG will collect the configured number of interrupts to ++ obtain 256 bits of entropy. This value can be set to any between ++ 256 and 4294967295. The LRNG guarantees that this value is not ++ lower than 256. This lower limit implies that one interrupt event ++ is credited with one bit of entropy. This value is subject to the ++ increase by the oversampling factor, if no high-resolution timer ++ is found. ++ ++ In order to effectively disable the interrupt entropy source, ++ the option has to be set to 4294967295. In this case, the ++ interrupt entropy source will still deliver data but without ++ being credited with entropy. ++ ++endmenu # "Entropy Source Configuration" ++ + endif # LRNG +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +index 6f4603f897cd..d321d6d21a44 100644 +--- a/drivers/char/lrng/Makefile ++++ b/drivers/char/lrng/Makefile +@@ -6,3 +6,5 @@ + obj-y += lrng_es_mgr.o lrng_aux.o \ + lrng_drng.o lrng_chacha20.o \ + lrng_interfaces.o lrng_es_aux.o ++ ++obj-$(CONFIG_LRNG_IRQ) += lrng_es_irq.o +diff --git a/drivers/char/lrng/lrng_es_irq.c b/drivers/char/lrng/lrng_es_irq.c +new file mode 100644 +index 000000000000..82a73b0426fb +--- /dev/null ++++ b/drivers/char/lrng/lrng_es_irq.c +@@ -0,0 +1,823 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause ++/* ++ * LRNG Slow Entropy Source: Interrupt data collection ++ * ++ * Copyright (C) 2016 - 2021, Stephan Mueller ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "lrng_internal.h" ++#include "lrng_es_irq.h" ++ ++/* ++ * Number of interrupts to be recorded to assume that DRNG security strength ++ * bits of entropy are received. ++ * Note: a value below the DRNG security strength should not be defined as this ++ * may imply the DRNG can never be fully seeded in case other noise ++ * sources are unavailable. ++ */ ++#define LRNG_IRQ_ENTROPY_BITS CONFIG_LRNG_IRQ_ENTROPY_RATE ++ ++ ++/* Number of interrupts required for LRNG_DRNG_SECURITY_STRENGTH_BITS entropy */ ++static u32 lrng_irq_entropy_bits = LRNG_IRQ_ENTROPY_BITS; ++/* Is high-resolution timer present? */ ++static bool lrng_irq_highres_timer = false; ++ ++static u32 irq_entropy __read_mostly = LRNG_IRQ_ENTROPY_BITS; ++#ifdef CONFIG_LRNG_RUNTIME_ES_CONFIG ++module_param(irq_entropy, uint, 0444); ++MODULE_PARM_DESC(irq_entropy, ++ "How many interrupts must be collected for obtaining 256 bits of entropy\n"); ++#endif ++ ++/* Per-CPU array holding concatenated entropy events */ ++static DEFINE_PER_CPU(u32 [LRNG_DATA_ARRAY_SIZE], lrng_pcpu_array) ++ __aligned(LRNG_KCAPI_ALIGN); ++static DEFINE_PER_CPU(u32, lrng_pcpu_array_ptr) = 0; ++static DEFINE_PER_CPU(atomic_t, lrng_pcpu_array_irqs) = ATOMIC_INIT(0); ++ ++/* ++ * The entropy collection is performed by executing the following steps: ++ * 1. fill up the per-CPU array holding the time stamps ++ * 2. once the per-CPU array is full, a compression of the data into ++ * the entropy pool is performed - this happens in interrupt context ++ * ++ * If step 2 is not desired in interrupt context, the following boolean ++ * needs to be set to false. This implies that old entropy data in the ++ * per-CPU array collected since the last DRNG reseed is overwritten with ++ * new entropy data instead of retaining the entropy with the compression ++ * operation. ++ * ++ * Impact on entropy: ++ * ++ * If continuous compression is enabled, the maximum entropy that is collected ++ * per CPU between DRNG reseeds is equal to the digest size of the used hash. ++ * ++ * If continuous compression is disabled, the maximum number of entropy events ++ * that can be collected per CPU is equal to LRNG_DATA_ARRAY_SIZE. This amount ++ * of events is converted into an entropy statement which then represents the ++ * maximum amount of entropy collectible per CPU between DRNG reseeds. ++ */ ++static bool lrng_pcpu_continuous_compression __read_mostly = ++ IS_ENABLED(CONFIG_LRNG_ENABLE_CONTINUOUS_COMPRESSION); ++ ++#ifdef CONFIG_LRNG_SWITCHABLE_CONTINUOUS_COMPRESSION ++module_param(lrng_pcpu_continuous_compression, bool, 0444); ++MODULE_PARM_DESC(lrng_pcpu_continuous_compression, ++ "Perform entropy compression if per-CPU entropy data array is full\n"); ++#endif ++ ++/* ++ * Per-CPU entropy pool with compressed entropy event ++ * ++ * The per-CPU entropy pool is defined as the hash state. New data is simply ++ * inserted into the entropy pool by performing a hash update operation. ++ * To read the entropy pool, a hash final must be invoked. However, before ++ * the entropy pool is released again after a hash final, the hash init must ++ * be performed. ++ */ ++static DEFINE_PER_CPU(u8 [LRNG_POOL_SIZE], lrng_pcpu_pool) ++ __aligned(LRNG_KCAPI_ALIGN); ++/* ++ * Lock to allow other CPUs to read the pool - as this is only done during ++ * reseed which is infrequent, this lock is hardly contended. ++ */ ++static DEFINE_PER_CPU(spinlock_t, lrng_pcpu_lock); ++static DEFINE_PER_CPU(bool, lrng_pcpu_lock_init) = false; ++ ++/* Number of time stamps analyzed to calculate a GCD */ ++#define LRNG_GCD_WINDOW_SIZE 100 ++static u32 lrng_gcd_history[LRNG_GCD_WINDOW_SIZE]; ++static atomic_t lrng_gcd_history_ptr = ATOMIC_INIT(-1); ++ ++/* The common divisor for all timestamps */ ++static u32 lrng_gcd_timer = 0; ++ ++static inline bool lrng_gcd_tested(void) ++{ ++ return (lrng_gcd_timer != 0); ++} ++ ++/* Set the GCD for use in IRQ ES - if 0, the GCD calculation is restarted. */ ++static inline void _lrng_gcd_set(u32 running_gcd) ++{ ++ lrng_gcd_timer = running_gcd; ++ mb(); ++} ++ ++static void lrng_gcd_set(u32 running_gcd) ++{ ++ if (!lrng_gcd_tested()) { ++ _lrng_gcd_set(running_gcd); ++ pr_debug("Setting GCD to %u\n", running_gcd); ++ } ++} ++ ++u32 lrng_gcd_analyze(u32 *history, size_t nelem) ++{ ++ u32 running_gcd = 0; ++ size_t i; ++ ++ /* Now perform the analysis on the accumulated time data. */ ++ for (i = 0; i < nelem; i++) { ++ /* ++ * NOTE: this would be the place to add more analysis on the ++ * appropriateness of the timer like checking the presence ++ * of sufficient variations in the timer. ++ */ ++ ++ /* ++ * This calculates the gcd of all the time values. that is ++ * gcd(time_1, time_2, ..., time_nelem) ++ * ++ * Some timers increment by a fixed (non-1) amount each step. ++ * This code checks for such increments, and allows the library ++ * to output the number of such changes have occurred. ++ */ ++ running_gcd = (u32)gcd(history[i], running_gcd); ++ ++ /* Zeroize data */ ++ history[i] = 0; ++ } ++ ++ return running_gcd; ++} ++ ++static void lrng_gcd_add_value(u32 time) ++{ ++ u32 ptr = (u32)atomic_inc_return_relaxed(&lrng_gcd_history_ptr); ++ ++ if (ptr < LRNG_GCD_WINDOW_SIZE) { ++ lrng_gcd_history[ptr] = time; ++ } else if (ptr == LRNG_GCD_WINDOW_SIZE) { ++ u32 gcd = lrng_gcd_analyze(lrng_gcd_history, ++ LRNG_GCD_WINDOW_SIZE); ++ ++ if (!gcd) ++ gcd = 1; ++ ++ /* ++ * Ensure that we have variations in the time stamp below the ++ * given value. This is just a safety measure to prevent the GCD ++ * becoming too large. ++ */ ++ if (gcd >= 1000) { ++ pr_warn("calculated GCD is larger than expected: %u\n", ++ gcd); ++ gcd = 1000; ++ } ++ ++ /* Adjust all deltas by the observed (small) common factor. */ ++ lrng_gcd_set(gcd); ++ atomic_set(&lrng_gcd_history_ptr, 0); ++ } ++} ++ ++/* Return boolean whether LRNG identified presence of high-resolution timer */ ++static bool lrng_pool_highres_timer(void) ++{ ++ return lrng_irq_highres_timer; ++} ++ ++/* Convert entropy in bits into number of IRQs with the same entropy content. */ ++static inline u32 lrng_entropy_to_data(u32 entropy_bits) ++{ ++ return ((entropy_bits * lrng_irq_entropy_bits) / ++ LRNG_DRNG_SECURITY_STRENGTH_BITS); ++} ++ ++/* Convert number of IRQs into entropy value. */ ++static inline u32 lrng_data_to_entropy(u32 irqnum) ++{ ++ return ((irqnum * LRNG_DRNG_SECURITY_STRENGTH_BITS) / ++ lrng_irq_entropy_bits); ++} ++ ++static inline bool lrng_pcpu_pool_online(int cpu) ++{ ++ return per_cpu(lrng_pcpu_lock_init, cpu); ++} ++ ++static void lrng_pcpu_check_compression_state(void) ++{ ++ /* One pool must hold sufficient entropy for disabled compression */ ++ if (!lrng_pcpu_continuous_compression) { ++ u32 max_ent = min_t(u32, lrng_get_digestsize(), ++ lrng_data_to_entropy(LRNG_DATA_NUM_VALUES)); ++ if (max_ent < lrng_security_strength()) { ++ pr_warn("Force continuous compression operation to ensure LRNG can hold enough entropy\n"); ++ lrng_pcpu_continuous_compression = true; ++ } ++ } ++} ++ ++static int __init lrng_init_time_source(void) ++{ ++ /* Set a minimum number of interrupts that must be collected */ ++ irq_entropy = max_t(u32, LRNG_IRQ_ENTROPY_BITS, irq_entropy); ++ ++ if ((random_get_entropy() & LRNG_DATA_SLOTSIZE_MASK) || ++ (random_get_entropy() & LRNG_DATA_SLOTSIZE_MASK)) { ++ /* ++ * As the highres timer is identified here, previous interrupts ++ * obtained during boot time are treated like a lowres-timer ++ * would have been present. ++ */ ++ lrng_irq_highres_timer = true; ++ lrng_irq_entropy_bits = irq_entropy; ++ } else { ++ u32 new_entropy = irq_entropy * LRNG_IRQ_OVERSAMPLING_FACTOR; ++ ++ lrng_health_disable(); ++ lrng_irq_highres_timer = false; ++ lrng_irq_entropy_bits = (irq_entropy < new_entropy) ? ++ new_entropy : irq_entropy; ++ pr_warn("operating without high-resolution timer and applying IRQ oversampling factor %u\n", ++ LRNG_IRQ_OVERSAMPLING_FACTOR); ++ lrng_pcpu_check_compression_state(); ++ } ++ mb(); ++ ++ return 0; ++} ++core_initcall(lrng_init_time_source); ++ ++/* ++ * Reset all per-CPU pools - reset entropy estimator but leave the pool data ++ * that may or may not have entropy unchanged. ++ */ ++void lrng_pcpu_reset(void) ++{ ++ int cpu; ++ ++ /* Trigger GCD calculation anew. */ ++ _lrng_gcd_set(0); ++ ++ for_each_online_cpu(cpu) ++ atomic_set(per_cpu_ptr(&lrng_pcpu_array_irqs, cpu), 0); ++} ++ ++u32 lrng_pcpu_avail_pool_size(void) ++{ ++ u32 max_size = 0, max_pool = lrng_get_digestsize(); ++ int cpu; ++ ++ if (!lrng_pcpu_continuous_compression) ++ max_pool = min_t(u32, max_pool, LRNG_DATA_NUM_VALUES); ++ ++ for_each_online_cpu(cpu) { ++ if (lrng_pcpu_pool_online(cpu)) ++ max_size += max_pool; ++ } ++ ++ return max_size; ++} ++ ++/* Return entropy of unused IRQs present in all per-CPU pools. */ ++u32 lrng_pcpu_avail_entropy(void) ++{ ++ u32 digestsize_irqs, irq = 0; ++ int cpu; ++ ++ /* Obtain the cap of maximum numbers of IRQs we count */ ++ digestsize_irqs = lrng_entropy_to_data(lrng_get_digestsize()); ++ if (!lrng_pcpu_continuous_compression) { ++ /* Cap to max. number of IRQs the array can hold */ ++ digestsize_irqs = min_t(u32, digestsize_irqs, ++ LRNG_DATA_NUM_VALUES); ++ } ++ ++ for_each_online_cpu(cpu) { ++ if (!lrng_pcpu_pool_online(cpu)) ++ continue; ++ irq += min_t(u32, digestsize_irqs, ++ atomic_read_u32(per_cpu_ptr(&lrng_pcpu_array_irqs, ++ cpu))); ++ } ++ ++ /* Consider oversampling rate */ ++ return lrng_reduce_by_osr(lrng_data_to_entropy(irq)); ++} ++ ++/* ++ * Trigger a switch of the hash implementation for the per-CPU pool. ++ * ++ * For each per-CPU pool, obtain the message digest with the old hash ++ * implementation, initialize the per-CPU pool again with the new hash ++ * implementation and inject the message digest into the new state. ++ * ++ * Assumption: the caller must guarantee that the new_cb is available during the ++ * entire operation (e.g. it must hold the lock against pointer updating). ++ */ ++int lrng_pcpu_switch_hash(int node, ++ const struct lrng_crypto_cb *new_cb, void *new_hash, ++ const struct lrng_crypto_cb *old_cb) ++{ ++ u8 digest[LRNG_MAX_DIGESTSIZE]; ++ u32 digestsize_irqs, found_irqs; ++ int ret = 0, cpu; ++ ++ if (!IS_ENABLED(CONFIG_LRNG_DRNG_SWITCH)) ++ return -EOPNOTSUPP; ++ ++ for_each_online_cpu(cpu) { ++ struct shash_desc *pcpu_shash; ++ ++ /* ++ * Only switch the per-CPU pools for the current node because ++ * the crypto_cb only applies NUMA-node-wide. ++ */ ++ if (cpu_to_node(cpu) != node || !lrng_pcpu_pool_online(cpu)) ++ continue; ++ ++ pcpu_shash = (struct shash_desc *)per_cpu_ptr(lrng_pcpu_pool, ++ cpu); ++ ++ digestsize_irqs = old_cb->lrng_hash_digestsize(pcpu_shash); ++ digestsize_irqs = lrng_entropy_to_data(digestsize_irqs << 3); ++ ++ if (pcpu_shash->tfm == new_hash) ++ continue; ++ ++ /* Get the per-CPU pool hash with old digest ... */ ++ ret = old_cb->lrng_hash_final(pcpu_shash, digest) ?: ++ /* ... re-initialize the hash with the new digest ... */ ++ new_cb->lrng_hash_init(pcpu_shash, new_hash) ?: ++ /* ++ * ... feed the old hash into the new state. We may feed ++ * uninitialized memory into the new state, but this is ++ * considered no issue and even good as we have some more ++ * uncertainty here. ++ */ ++ new_cb->lrng_hash_update(pcpu_shash, digest, ++ sizeof(digest)); ++ if (ret) ++ goto out; ++ ++ /* ++ * In case the new digest is larger than the old one, cap ++ * the available entropy to the old message digest used to ++ * process the existing data. ++ */ ++ found_irqs = atomic_xchg_relaxed( ++ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu), 0); ++ found_irqs = min_t(u32, found_irqs, digestsize_irqs); ++ atomic_add_return_relaxed(found_irqs, ++ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu)); ++ ++ pr_debug("Re-initialize per-CPU entropy pool for CPU %d on NUMA node %d with hash %s\n", ++ cpu, node, new_cb->lrng_hash_name()); ++ } ++ ++out: ++ memzero_explicit(digest, sizeof(digest)); ++ return ret; ++} ++ ++/* ++ * When reading the per-CPU message digest, make sure we use the crypto ++ * callbacks defined for the NUMA node the per-CPU pool is defined for because ++ * the LRNG crypto switch support is only atomic per NUMA node. ++ */ ++static inline u32 ++lrng_pcpu_pool_hash_one(const struct lrng_crypto_cb *pcpu_crypto_cb, ++ void *pcpu_hash, int cpu, u8 *digest, u32 *digestsize) ++{ ++ struct shash_desc *pcpu_shash = ++ (struct shash_desc *)per_cpu_ptr(lrng_pcpu_pool, cpu); ++ spinlock_t *lock = per_cpu_ptr(&lrng_pcpu_lock, cpu); ++ unsigned long flags; ++ u32 digestsize_irqs, found_irqs; ++ ++ /* Lock guarding against reading / writing to per-CPU pool */ ++ spin_lock_irqsave(lock, flags); ++ ++ *digestsize = pcpu_crypto_cb->lrng_hash_digestsize(pcpu_hash); ++ digestsize_irqs = lrng_entropy_to_data(*digestsize << 3); ++ ++ /* Obtain entropy statement like for the entropy pool */ ++ found_irqs = atomic_xchg_relaxed( ++ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu), 0); ++ /* Cap to maximum amount of data we can hold in hash */ ++ found_irqs = min_t(u32, found_irqs, digestsize_irqs); ++ ++ /* Cap to maximum amount of data we can hold in array */ ++ if (!lrng_pcpu_continuous_compression) ++ found_irqs = min_t(u32, found_irqs, LRNG_DATA_NUM_VALUES); ++ ++ /* Store all not-yet compressed data in data array into hash, ... */ ++ if (pcpu_crypto_cb->lrng_hash_update(pcpu_shash, ++ (u8 *)per_cpu_ptr(lrng_pcpu_array, cpu), ++ LRNG_DATA_ARRAY_SIZE * sizeof(u32)) ?: ++ /* ... get the per-CPU pool digest, ... */ ++ pcpu_crypto_cb->lrng_hash_final(pcpu_shash, digest) ?: ++ /* ... re-initialize the hash, ... */ ++ pcpu_crypto_cb->lrng_hash_init(pcpu_shash, pcpu_hash) ?: ++ /* ... feed the old hash into the new state. */ ++ pcpu_crypto_cb->lrng_hash_update(pcpu_shash, digest, *digestsize)) ++ found_irqs = 0; ++ ++ spin_unlock_irqrestore(lock, flags); ++ return found_irqs; ++} ++ ++/* ++ * Hash all per-CPU pools and return the digest to be used as seed data for ++ * seeding a DRNG. The caller must guarantee backtracking resistance. ++ * The function will only copy as much data as entropy is available into the ++ * caller-provided output buffer. ++ * ++ * This function handles the translation from the number of received interrupts ++ * into an entropy statement. The conversion depends on LRNG_IRQ_ENTROPY_BITS ++ * which defines how many interrupts must be received to obtain 256 bits of ++ * entropy. With this value, the function lrng_data_to_entropy converts a given ++ * data size (received interrupts, requested amount of data, etc.) into an ++ * entropy statement. lrng_entropy_to_data does the reverse. ++ * ++ * @outbuf: buffer to store data in with size requested_bits ++ * @requested_bits: Requested amount of entropy ++ * @fully_seeded: indicator whether LRNG is fully seeded ++ * @return: amount of entropy in outbuf in bits. ++ */ ++u32 lrng_pcpu_pool_hash(u8 *outbuf, u32 requested_bits, bool fully_seeded) ++{ ++ SHASH_DESC_ON_STACK(shash, NULL); ++ const struct lrng_crypto_cb *crypto_cb; ++ struct lrng_drng **lrng_drng = lrng_drng_instances(); ++ struct lrng_drng *drng = lrng_drng_init_instance(); ++ u8 digest[LRNG_MAX_DIGESTSIZE]; ++ unsigned long flags, flags2; ++ u32 found_irqs, collected_irqs = 0, collected_ent_bits, requested_irqs, ++ returned_ent_bits; ++ int ret, cpu; ++ void *hash; ++ ++ /* Lock guarding replacement of per-NUMA hash */ ++ lrng_hash_lock(drng, &flags); ++ ++ crypto_cb = drng->crypto_cb; ++ hash = drng->hash; ++ ++ /* The hash state of filled with all per-CPU pool hashes. */ ++ ret = crypto_cb->lrng_hash_init(shash, hash); ++ if (ret) ++ goto err; ++ ++ requested_irqs = lrng_entropy_to_data(requested_bits + ++ lrng_compress_osr()); ++ ++ /* ++ * Harvest entropy from each per-CPU hash state - even though we may ++ * have collected sufficient entropy, we will hash all per-CPU pools. ++ */ ++ for_each_online_cpu(cpu) { ++ struct lrng_drng *pcpu_drng = drng; ++ u32 digestsize, pcpu_unused_irqs = 0; ++ int node = cpu_to_node(cpu); ++ ++ /* If pool is not online, then no entropy is present. */ ++ if (!lrng_pcpu_pool_online(cpu)) ++ continue; ++ ++ if (lrng_drng && lrng_drng[node]) ++ pcpu_drng = lrng_drng[node]; ++ ++ if (pcpu_drng == drng) { ++ found_irqs = lrng_pcpu_pool_hash_one(crypto_cb, hash, ++ cpu, digest, ++ &digestsize); ++ } else { ++ lrng_hash_lock(pcpu_drng, &flags2); ++ found_irqs = ++ lrng_pcpu_pool_hash_one(pcpu_drng->crypto_cb, ++ pcpu_drng->hash, cpu, ++ digest, &digestsize); ++ lrng_hash_unlock(pcpu_drng, flags2); ++ } ++ ++ /* Inject the digest into the state of all per-CPU pools */ ++ ret = crypto_cb->lrng_hash_update(shash, digest, digestsize); ++ if (ret) ++ goto err; ++ ++ collected_irqs += found_irqs; ++ if (collected_irqs > requested_irqs) { ++ pcpu_unused_irqs = collected_irqs - requested_irqs; ++ atomic_add_return_relaxed(pcpu_unused_irqs, ++ per_cpu_ptr(&lrng_pcpu_array_irqs, cpu)); ++ collected_irqs = requested_irqs; ++ } ++ pr_debug("%u interrupts used from entropy pool of CPU %d, %u interrupts remain unused\n", ++ found_irqs - pcpu_unused_irqs, cpu, pcpu_unused_irqs); ++ } ++ ++ ret = crypto_cb->lrng_hash_final(shash, digest); ++ if (ret) ++ goto err; ++ ++ collected_ent_bits = lrng_data_to_entropy(collected_irqs); ++ /* Cap to maximum entropy that can ever be generated with given hash */ ++ collected_ent_bits = min_t(u32, collected_ent_bits, ++ crypto_cb->lrng_hash_digestsize(hash) << 3); ++ /* Apply oversampling: discount requested oversampling rate */ ++ returned_ent_bits = lrng_reduce_by_osr(collected_ent_bits); ++ ++ pr_debug("obtained %u bits by collecting %u bits of entropy from entropy pool noise source\n", ++ returned_ent_bits, collected_ent_bits); ++ ++ /* ++ * Truncate to available entropy as implicitly allowed by SP800-90B ++ * section 3.1.5.1.1 table 1 which awards truncated hashes full ++ * entropy. ++ * ++ * During boot time, we read requested_bits data with ++ * returned_ent_bits entropy. In case our conservative entropy ++ * estimate underestimates the available entropy we can transport as ++ * much available entropy as possible. ++ */ ++ memcpy(outbuf, digest, fully_seeded ? returned_ent_bits >> 3 : ++ requested_bits >> 3); ++ ++out: ++ crypto_cb->lrng_hash_desc_zero(shash); ++ lrng_hash_unlock(drng, flags); ++ memzero_explicit(digest, sizeof(digest)); ++ return returned_ent_bits; ++ ++err: ++ returned_ent_bits = 0; ++ goto out; ++} ++ ++/* Compress the lrng_pcpu_array array into lrng_pcpu_pool */ ++static inline void lrng_pcpu_array_compress(void) ++{ ++ struct shash_desc *shash = ++ (struct shash_desc *)this_cpu_ptr(lrng_pcpu_pool); ++ struct lrng_drng **lrng_drng = lrng_drng_instances(); ++ struct lrng_drng *drng = lrng_drng_init_instance(); ++ const struct lrng_crypto_cb *crypto_cb; ++ spinlock_t *lock = this_cpu_ptr(&lrng_pcpu_lock); ++ unsigned long flags, flags2; ++ int node = numa_node_id(); ++ void *hash; ++ bool init = false; ++ ++ /* Get NUMA-node local hash instance */ ++ if (lrng_drng && lrng_drng[node]) ++ drng = lrng_drng[node]; ++ ++ lrng_hash_lock(drng, &flags); ++ crypto_cb = drng->crypto_cb; ++ hash = drng->hash; ++ ++ if (unlikely(!this_cpu_read(lrng_pcpu_lock_init))) { ++ init = true; ++ spin_lock_init(lock); ++ this_cpu_write(lrng_pcpu_lock_init, true); ++ pr_debug("Initializing per-CPU entropy pool for CPU %d on NUMA node %d with hash %s\n", ++ raw_smp_processor_id(), node, ++ crypto_cb->lrng_hash_name()); ++ } ++ ++ spin_lock_irqsave(lock, flags2); ++ ++ if (unlikely(init) && crypto_cb->lrng_hash_init(shash, hash)) { ++ this_cpu_write(lrng_pcpu_lock_init, false); ++ pr_warn("Initialization of hash failed\n"); ++ } else if (lrng_pcpu_continuous_compression) { ++ /* Add entire per-CPU data array content into entropy pool. */ ++ if (crypto_cb->lrng_hash_update(shash, ++ (u8 *)this_cpu_ptr(lrng_pcpu_array), ++ LRNG_DATA_ARRAY_SIZE * sizeof(u32))) ++ pr_warn_ratelimited("Hashing of entropy data failed\n"); ++ } ++ ++ spin_unlock_irqrestore(lock, flags2); ++ lrng_hash_unlock(drng, flags); ++} ++ ++/* Compress data array into hash */ ++static inline void lrng_pcpu_array_to_hash(u32 ptr) ++{ ++ u32 *array = this_cpu_ptr(lrng_pcpu_array); ++ ++ /* ++ * During boot time the hash operation is triggered more often than ++ * during regular operation. ++ */ ++ if (unlikely(!lrng_state_fully_seeded())) { ++ if ((ptr & 31) && (ptr < LRNG_DATA_WORD_MASK)) ++ return; ++ } else if (ptr < LRNG_DATA_WORD_MASK) { ++ return; ++ } ++ ++ if (lrng_raw_array_entropy_store(*array)) { ++ u32 i; ++ ++ /* ++ * If we fed even a part of the array to external analysis, we ++ * mark that the entire array and the per-CPU pool to have no ++ * entropy. This is due to the non-IID property of the data as ++ * we do not fully know whether the existing dependencies ++ * diminish the entropy beyond to what we expect it has. ++ */ ++ atomic_set(this_cpu_ptr(&lrng_pcpu_array_irqs), 0); ++ ++ for (i = 1; i < LRNG_DATA_ARRAY_SIZE; i++) ++ lrng_raw_array_entropy_store(*(array + i)); ++ } else { ++ lrng_pcpu_array_compress(); ++ /* Ping pool handler about received entropy */ ++ lrng_pool_add_entropy(); ++ } ++} ++ ++/* ++ * Concatenate full 32 bit word at the end of time array even when current ++ * ptr is not aligned to sizeof(data). ++ */ ++static inline void _lrng_pcpu_array_add_u32(u32 data) ++{ ++ /* Increment pointer by number of slots taken for input value */ ++ u32 pre_ptr, mask, ptr = this_cpu_add_return(lrng_pcpu_array_ptr, ++ LRNG_DATA_SLOTS_PER_UINT); ++ unsigned int pre_array; ++ ++ /* ++ * This function injects a unit into the array - guarantee that ++ * array unit size is equal to data type of input data. ++ */ ++ BUILD_BUG_ON(LRNG_DATA_ARRAY_MEMBER_BITS != (sizeof(data) << 3)); ++ ++ /* ++ * The following logic requires at least two units holding ++ * the data as otherwise the pointer would immediately wrap when ++ * injection an u32 word. ++ */ ++ BUILD_BUG_ON(LRNG_DATA_NUM_VALUES <= LRNG_DATA_SLOTS_PER_UINT); ++ ++ lrng_pcpu_split_u32(&ptr, &pre_ptr, &mask); ++ ++ /* MSB of data go into previous unit */ ++ pre_array = lrng_data_idx2array(pre_ptr); ++ /* zeroization of slot to ensure the following OR adds the data */ ++ this_cpu_and(lrng_pcpu_array[pre_array], ~(0xffffffff & ~mask)); ++ this_cpu_or(lrng_pcpu_array[pre_array], data & ~mask); ++ ++ /* Invoke compression as we just filled data array completely */ ++ if (unlikely(pre_ptr > ptr)) ++ lrng_pcpu_array_to_hash(LRNG_DATA_WORD_MASK); ++ ++ /* LSB of data go into current unit */ ++ this_cpu_write(lrng_pcpu_array[lrng_data_idx2array(ptr)], ++ data & mask); ++ ++ if (likely(pre_ptr <= ptr)) ++ lrng_pcpu_array_to_hash(ptr); ++} ++ ++/* Concatenate a 32-bit word at the end of the per-CPU array */ ++void lrng_pcpu_array_add_u32(u32 data) ++{ ++ /* ++ * Disregard entropy-less data without continuous compression to ++ * avoid it overwriting data with entropy when array ptr wraps. ++ */ ++ if (lrng_pcpu_continuous_compression) ++ _lrng_pcpu_array_add_u32(data); ++} ++ ++/* Concatenate data of max LRNG_DATA_SLOTSIZE_MASK at the end of time array */ ++static inline void lrng_pcpu_array_add_slot(u32 data) ++{ ++ /* Get slot */ ++ u32 ptr = this_cpu_inc_return(lrng_pcpu_array_ptr) & ++ LRNG_DATA_WORD_MASK; ++ unsigned int array = lrng_data_idx2array(ptr); ++ unsigned int slot = lrng_data_idx2slot(ptr); ++ ++ BUILD_BUG_ON(LRNG_DATA_ARRAY_MEMBER_BITS % LRNG_DATA_SLOTSIZE_BITS); ++ /* Ensure consistency of values */ ++ BUILD_BUG_ON(LRNG_DATA_ARRAY_MEMBER_BITS != ++ sizeof(lrng_pcpu_array[0]) << 3); ++ ++ /* zeroization of slot to ensure the following OR adds the data */ ++ this_cpu_and(lrng_pcpu_array[array], ++ ~(lrng_data_slot_val(0xffffffff & LRNG_DATA_SLOTSIZE_MASK, ++ slot))); ++ /* Store data into slot */ ++ this_cpu_or(lrng_pcpu_array[array], lrng_data_slot_val(data, slot)); ++ ++ lrng_pcpu_array_to_hash(ptr); ++} ++ ++static inline void ++lrng_time_process_common(u32 time, void(*add_time)(u32 data)) ++{ ++ enum lrng_health_res health_test; ++ ++ if (lrng_raw_hires_entropy_store(time)) ++ return; ++ ++ health_test = lrng_health_test(time); ++ if (health_test > lrng_health_fail_use) ++ return; ++ ++ if (health_test == lrng_health_pass) ++ atomic_inc_return(this_cpu_ptr(&lrng_pcpu_array_irqs)); ++ ++ add_time(time); ++} ++ ++/* ++ * Batching up of entropy in per-CPU array before injecting into entropy pool. ++ */ ++static inline void lrng_time_process(void) ++{ ++ u32 now_time = random_get_entropy(); ++ ++ if (unlikely(!lrng_gcd_tested())) { ++ /* When GCD is unknown, we process the full time stamp */ ++ lrng_time_process_common(now_time, _lrng_pcpu_array_add_u32); ++ lrng_gcd_add_value(now_time); ++ } else { ++ /* GCD is known and applied */ ++ lrng_time_process_common((now_time / lrng_gcd_timer) & ++ LRNG_DATA_SLOTSIZE_MASK, ++ lrng_pcpu_array_add_slot); ++ } ++ ++ lrng_perf_time(now_time); ++} ++ ++/* Hot code path - Callback for interrupt handler */ ++void add_interrupt_randomness(int irq, int irq_flg) ++{ ++ if (lrng_pool_highres_timer()) { ++ lrng_time_process(); ++ } else { ++ struct pt_regs *regs = get_irq_regs(); ++ static atomic_t reg_idx = ATOMIC_INIT(0); ++ u64 ip; ++ u32 tmp; ++ ++ if (regs) { ++ u32 *ptr = (u32 *)regs; ++ int reg_ptr = atomic_add_return_relaxed(1, ®_idx); ++ size_t n = (sizeof(struct pt_regs) / sizeof(u32)); ++ ++ ip = instruction_pointer(regs); ++ tmp = *(ptr + (reg_ptr % n)); ++ tmp = lrng_raw_regs_entropy_store(tmp) ? 0 : tmp; ++ _lrng_pcpu_array_add_u32(tmp); ++ } else { ++ ip = _RET_IP_; ++ } ++ ++ lrng_time_process(); ++ ++ /* ++ * The XOR operation combining the different values is not ++ * considered to destroy entropy since the entirety of all ++ * processed values delivers the entropy (and not each ++ * value separately of the other values). ++ */ ++ tmp = lrng_raw_jiffies_entropy_store(jiffies) ? 0 : jiffies; ++ tmp ^= lrng_raw_irq_entropy_store(irq) ? 0 : irq; ++ tmp ^= lrng_raw_irqflags_entropy_store(irq_flg) ? 0 : irq_flg; ++ tmp ^= lrng_raw_retip_entropy_store(ip) ? 0 : ip; ++ tmp ^= ip >> 32; ++ _lrng_pcpu_array_add_u32(tmp); ++ } ++} ++EXPORT_SYMBOL(add_interrupt_randomness); ++ ++void lrng_irq_es_state(unsigned char *buf, size_t buflen) ++{ ++ const struct lrng_drng *lrng_drng_init = lrng_drng_init_instance(); ++ ++ /* Assume the lrng_drng_init lock is taken by caller */ ++ snprintf(buf, buflen, ++ "IRQ ES properties:\n" ++ " Hash for operating entropy pool: %s\n" ++ " per-CPU interrupt collection size: %u\n" ++ " Standards compliance: %s\n" ++ " High-resolution timer: %s\n" ++ " Continuous compression: %s\n", ++ lrng_drng_init->crypto_cb->lrng_hash_name(), ++ LRNG_DATA_NUM_VALUES, ++ lrng_sp80090b_compliant() ? "SP800-90B " : "", ++ lrng_pool_highres_timer() ? "true" : "false", ++ lrng_pcpu_continuous_compression ? "true" : "false"); ++} +diff --git a/drivers/char/lrng/lrng_es_irq.h b/drivers/char/lrng/lrng_es_irq.h +new file mode 100644 +index 000000000000..00b16b1aa45f +--- /dev/null ++++ b/drivers/char/lrng/lrng_es_irq.h +@@ -0,0 +1,71 @@ ++/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ ++/* ++ * LRNG Slow Noise Source: Time stamp array handling ++ * ++ * Copyright (C) 2016 - 2021, Stephan Mueller ++ */ ++ ++/* ++ * To limit the impact on the interrupt handling, the LRNG concatenates ++ * entropic LSB parts of the time stamps in a per-CPU array and only ++ * injects them into the entropy pool when the array is full. ++ */ ++ ++/* Store multiple integers in one u32 */ ++#define LRNG_DATA_SLOTSIZE_BITS (8) ++#define LRNG_DATA_SLOTSIZE_MASK ((1 << LRNG_DATA_SLOTSIZE_BITS) - 1) ++#define LRNG_DATA_ARRAY_MEMBER_BITS (4 << 3) /* ((sizeof(u32)) << 3) */ ++#define LRNG_DATA_SLOTS_PER_UINT (LRNG_DATA_ARRAY_MEMBER_BITS / \ ++ LRNG_DATA_SLOTSIZE_BITS) ++ ++/* ++ * Number of time values to store in the array - in small environments ++ * only one atomic_t variable per CPU is used. ++ */ ++#define LRNG_DATA_NUM_VALUES (CONFIG_LRNG_COLLECTION_SIZE) ++/* Mask of LSB of time stamp to store */ ++#define LRNG_DATA_WORD_MASK (LRNG_DATA_NUM_VALUES - 1) ++ ++#define LRNG_DATA_SLOTS_MASK (LRNG_DATA_SLOTS_PER_UINT - 1) ++#define LRNG_DATA_ARRAY_SIZE (LRNG_DATA_NUM_VALUES / \ ++ LRNG_DATA_SLOTS_PER_UINT) ++ ++/* Starting bit index of slot */ ++static inline unsigned int lrng_data_slot2bitindex(unsigned int slot) ++{ ++ return (LRNG_DATA_SLOTSIZE_BITS * slot); ++} ++ ++/* Convert index into the array index */ ++static inline unsigned int lrng_data_idx2array(unsigned int idx) ++{ ++ return idx / LRNG_DATA_SLOTS_PER_UINT; ++} ++ ++/* Convert index into the slot of a given array index */ ++static inline unsigned int lrng_data_idx2slot(unsigned int idx) ++{ ++ return idx & LRNG_DATA_SLOTS_MASK; ++} ++ ++/* Convert value into slot value */ ++static inline unsigned int lrng_data_slot_val(unsigned int val, ++ unsigned int slot) ++{ ++ return val << lrng_data_slot2bitindex(slot); ++} ++ ++/* ++ * Return the pointers for the previous and current units to inject a u32 into. ++ * Also return the mask which the u32 word is to be processed. ++ */ ++static inline void lrng_pcpu_split_u32(u32 *ptr, u32 *pre_ptr, u32 *mask) ++{ ++ /* ptr to previous unit */ ++ *pre_ptr = (*ptr - LRNG_DATA_SLOTS_PER_UINT) & LRNG_DATA_WORD_MASK; ++ *ptr &= LRNG_DATA_WORD_MASK; ++ ++ /* mask to split data into the two parts for the two units */ ++ *mask = ((1 << (*pre_ptr & (LRNG_DATA_SLOTS_PER_UINT - 1)) * ++ LRNG_DATA_SLOTSIZE_BITS)) - 1; ++} +-- +2.31.1 + diff --git a/PATCH/LRNG/696-06-v42-0003-LRNG-sysctls-and-proc-interface.patch b/PATCH/LRNG/696-06-v43-0003-LRNG-sysctls-and-proc-interface.patch similarity index 79% rename from PATCH/LRNG/696-06-v42-0003-LRNG-sysctls-and-proc-interface.patch rename to PATCH/LRNG/696-06-v43-0003-LRNG-sysctls-and-proc-interface.patch index b31804d87..a0f2d6040 100644 --- a/PATCH/LRNG/696-06-v42-0003-LRNG-sysctls-and-proc-interface.patch +++ b/PATCH/LRNG/696-06-v43-0003-LRNG-sysctls-and-proc-interface.patch @@ -1,7 +1,7 @@ -From 4e3f238b369d19b1b3e9be3b43765ce563626347 Mon Sep 17 00:00:00 2001 +From 4cedc0365b43b7b8ef4220b839f9fc94691a7280 Mon Sep 17 00:00:00 2001 From: Stephan Mueller -Date: Mon, 2 Aug 2021 21:52:37 +0200 -Subject: [PATCH v42 03/13] LRNG - sysctls and /proc interface +Date: Wed, 13 Oct 2021 22:50:53 +0200 +Subject: [PATCH v43 03/15] LRNG - sysctls and /proc interface The LRNG sysctl interface provides the same controls as the existing /dev/random implementation. These sysctls behave identically and are @@ -57,24 +57,30 @@ Reviewed-by: Marcelo Henrique Cerri Reviewed-by: Roman Drahtmueller Tested-by: Marcelo Henrique Cerri Tested-by: Neil Horman +Tested-by: Jirka Hladky +Reviewed-by: Jirka Hladky Signed-off-by: Stephan Mueller --- drivers/char/lrng/Makefile | 1 + drivers/char/lrng/lrng_interfaces.c | 2 - - drivers/char/lrng/lrng_proc.c | 185 ++++++++++++++++++++++++++++ - 3 files changed, 186 insertions(+), 2 deletions(-) + drivers/char/lrng/lrng_proc.c | 199 ++++++++++++++++++++++++++++ + 3 files changed, 200 insertions(+), 2 deletions(-) create mode 100644 drivers/char/lrng/lrng_proc.c +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +index d321d6d21a44..d7df72a702e4 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile -@@ -9,3 +9,4 @@ obj-y += lrng_es_mgr.o lrng_aux.o \ +@@ -8,3 +8,4 @@ obj-y += lrng_es_mgr.o lrng_aux.o \ lrng_interfaces.o lrng_es_aux.o - obj-$(CONFIG_NUMA) += lrng_numa.o + obj-$(CONFIG_LRNG_IRQ) += lrng_es_irq.o +obj-$(CONFIG_SYSCTL) += lrng_proc.o +diff --git a/drivers/char/lrng/lrng_interfaces.c b/drivers/char/lrng/lrng_interfaces.c +index 6316a534bb54..b656aaf0c6cb 100644 --- a/drivers/char/lrng/lrng_interfaces.c +++ b/drivers/char/lrng/lrng_interfaces.c -@@ -38,8 +38,6 @@ static DECLARE_WAIT_QUEUE_HEAD(lrng_writ +@@ -38,8 +38,6 @@ static DECLARE_WAIT_QUEUE_HEAD(lrng_write_wait); static DECLARE_WAIT_QUEUE_HEAD(lrng_init_wait); static struct fasync_struct *fasync; @@ -83,9 +89,12 @@ Signed-off-by: Stephan Mueller /********************************** Helper ***********************************/ /* Is the DRNG seed level too low? */ +diff --git a/drivers/char/lrng/lrng_proc.c b/drivers/char/lrng/lrng_proc.c +new file mode 100644 +index 000000000000..b48094c32b95 --- /dev/null +++ b/drivers/char/lrng/lrng_proc.c -@@ -0,0 +1,185 @@ +@@ -0,0 +1,199 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* + * LRNG proc and sysctl interfaces @@ -100,7 +109,6 @@ Signed-off-by: Stephan Mueller +#include + +#include "lrng_internal.h" -+#include "lrng_es_irq.h" + +/* + * This function is used to return both the bootid UUID, and random @@ -168,10 +176,16 @@ Signed-off-by: Stephan Mueller +} + +static int lrng_min_write_thresh; -+static int lrng_max_write_thresh = LRNG_MAX_DIGESTSIZE; ++static int lrng_max_write_thresh = (LRNG_WRITE_WAKEUP_ENTROPY << 3); +static char lrng_sysctl_bootid[16]; +static int lrng_drng_reseed_max_min; + ++void lrng_proc_update_max_write_thresh(u32 new_digestsize) ++{ ++ lrng_max_write_thresh = (int)new_digestsize; ++ mb(); ++} ++ +struct ctl_table random_table[] = { + { + .procname = "poolsize", @@ -230,36 +244,45 @@ Signed-off-by: Stephan Mueller +{ + struct lrng_drng *lrng_drng_init = lrng_drng_init_instance(); + unsigned long flags = 0; -+ unsigned char buf[390]; ++ unsigned char buf[250], irq[200], aux[100], cpu[90], jent[45]; + + lrng_drng_lock(lrng_drng_init, &flags); + snprintf(buf, sizeof(buf), + "DRNG name: %s\n" -+ "Hash for reading entropy pool: %s\n" -+ "Hash for operating aux entropy pool: %s\n" + "LRNG security strength in bits: %d\n" -+ "per-CPU interrupt collection size: %u\n" + "number of DRNG instances: %u\n" -+ "Standards compliance: %s%s\n" -+ "High-resolution timer: %s\n" ++ "Standards compliance: %s\n" ++ "Entropy Sources: %s%s%sAuxiliary\n" + "LRNG minimally seeded: %s\n" -+ "LRNG fully seeded: %s\n" -+ "Continuous compression: %s\n", ++ "LRNG fully seeded: %s\n", + lrng_drng_init->crypto_cb->lrng_drng_name(), -+ lrng_drng_init->crypto_cb->lrng_hash_name(), -+ lrng_drng_init->crypto_cb->lrng_hash_name(), + lrng_security_strength(), -+ LRNG_DATA_NUM_VALUES, + numa_drngs, -+ lrng_sp80090b_compliant() ? "SP800-90B " : "", + lrng_sp80090c_compliant() ? "SP800-90C " : "", -+ lrng_pool_highres_timer() ? "true" : "false", ++ IS_ENABLED(CONFIG_LRNG_IRQ) ? "IRQ " : "", ++ IS_ENABLED(CONFIG_LRNG_JENT) ? "JitterRNG " : "", ++ IS_ENABLED(CONFIG_LRNG_CPU) ? "CPU " : "", + lrng_state_min_seeded() ? "true" : "false", -+ lrng_state_fully_seeded() ? "true" : "false", -+ lrng_pcpu_continuous_compression_state() ? "true" : "false"); ++ lrng_state_fully_seeded() ? "true" : "false"); ++ ++ lrng_aux_es_state(aux, sizeof(aux)); ++ ++ irq[0] = '\0'; ++ lrng_irq_es_state(irq, sizeof(irq)); ++ ++ jent[0] = '\0'; ++ lrng_jent_es_state(jent, sizeof(jent)); ++ ++ cpu[0] = '\0'; ++ lrng_arch_es_state(cpu, sizeof(cpu)); ++ + lrng_drng_unlock(lrng_drng_init, &flags); + + seq_write(m, buf, strlen(buf)); ++ seq_write(m, aux, strlen(aux)); ++ seq_write(m, irq, strlen(irq)); ++ seq_write(m, jent, strlen(jent)); ++ seq_write(m, cpu, strlen(cpu)); + + return 0; +} @@ -271,3 +294,6 @@ Signed-off-by: Stephan Mueller +} + +module_init(lrng_proc_type_init); +-- +2.31.1 + diff --git a/PATCH/LRNG/696-05-v42-0002-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch b/PATCH/LRNG/696-07-v43-0004-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch similarity index 87% rename from PATCH/LRNG/696-05-v42-0002-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch rename to PATCH/LRNG/696-07-v43-0004-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch index 757560a19..206928b04 100644 --- a/PATCH/LRNG/696-05-v42-0002-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch +++ b/PATCH/LRNG/696-07-v43-0004-LRNG-allocate-one-DRNG-instance-per-NUMA-node.patch @@ -1,7 +1,7 @@ -From 4cb1d63f92167475f34f710802c007ed2b5c7ff2 Mon Sep 17 00:00:00 2001 +From 2e8a913851ace590cd76518040b2bb4cb6f18047 Mon Sep 17 00:00:00 2001 From: Stephan Mueller -Date: Mon, 2 Aug 2021 21:49:21 +0200 -Subject: [PATCH v42 02/13] LRNG - allocate one DRNG instance per NUMA node +Date: Tue, 28 Sep 2021 17:05:50 +0200 +Subject: [PATCH v43 04/15] LRNG - allocate one DRNG instance per NUMA node In order to improve NUMA-locality when serving getrandom(2) requests, allocate one DRNG instance per node. @@ -43,21 +43,27 @@ Reviewed-by: Marcelo Henrique Cerri Reviewed-by: Roman Drahtmueller Tested-by: Marcelo Henrique Cerri Tested-by: Neil Horman +Tested-by: Jirka Hladky +Reviewed-by: Jirka Hladky Signed-off-by: Stephan Mueller --- - drivers/char/lrng/Makefile | 2 + + drivers/char/lrng/Makefile | 1 + drivers/char/lrng/lrng_numa.c | 122 ++++++++++++++++++++++++++++++++++ - 2 files changed, 124 insertions(+) + 2 files changed, 123 insertions(+) create mode 100644 drivers/char/lrng/lrng_numa.c +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +index d7df72a702e4..1e722e0967e0 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile -@@ -7,3 +7,5 @@ obj-y += lrng_es_mgr.o lrng_aux.o \ - lrng_es_irq.o lrng_es_archrandom.o \ - lrng_drng.o lrng_chacha20.o \ - lrng_interfaces.o lrng_es_aux.o -+ +@@ -9,3 +9,4 @@ obj-y += lrng_es_mgr.o lrng_aux.o \ + + obj-$(CONFIG_LRNG_IRQ) += lrng_es_irq.o + obj-$(CONFIG_SYSCTL) += lrng_proc.o +obj-$(CONFIG_NUMA) += lrng_numa.o +diff --git a/drivers/char/lrng/lrng_numa.c b/drivers/char/lrng/lrng_numa.c +new file mode 100644 +index 000000000000..fbfb40a5fb8d --- /dev/null +++ b/drivers/char/lrng/lrng_numa.c @@ -0,0 +1,122 @@ @@ -183,3 +189,6 @@ Signed-off-by: Stephan Mueller +{ + schedule_work(&lrng_drngs_numa_alloc_work); +} +-- +2.31.1 + diff --git a/PATCH/LRNG/696-08-v43-0005-LRNG-CPU-entropy-source.patch b/PATCH/LRNG/696-08-v43-0005-LRNG-CPU-entropy-source.patch new file mode 100644 index 000000000..aa469d8a8 --- /dev/null +++ b/PATCH/LRNG/696-08-v43-0005-LRNG-CPU-entropy-source.patch @@ -0,0 +1,336 @@ +From fcb3d4baf6df0d4e62d706f0ec1dc82b3209affb Mon Sep 17 00:00:00 2001 +From: Stephan Mueller +Date: Mon, 18 Oct 2021 20:52:42 +0200 +Subject: [PATCH v43 05/15] LRNG - CPU entropy source + +Certain CPUs provide instructions giving access to an entropy source +(e.g. RDSEED on Intel/AMD, DARN on POWER, etc.). The LRNG can utilize +the entropy source to seed its DRNG from. + +CC: Torsten Duwe +CC: "Eric W. Biederman" +CC: "Alexander E. Patrakov" +CC: "Ahmed S. Darwish" +CC: "Theodore Y. Ts'o" +CC: Willy Tarreau +CC: Matthew Garrett +CC: Vito Caputo +CC: Andreas Dilger +CC: Jan Kara +CC: Ray Strode +CC: William Jon McCann +CC: zhangjs +CC: Andy Lutomirski +CC: Florian Weimer +CC: Lennart Poettering +CC: Nicolai Stange +Reviewed-by: Alexander Lobakin +Tested-by: Alexander Lobakin +Mathematical aspects Reviewed-by: "Peter, Matthias" +Reviewed-by: Marcelo Henrique Cerri +Reviewed-by: Roman Drahtmueller +Tested-by: Marcelo Henrique Cerri +Tested-by: Neil Horman +Tested-by: Jirka Hladky +Reviewed-by: Jirka Hladky +Signed-off-by: Stephan Mueller +--- + drivers/char/lrng/Kconfig | 38 +++++ + drivers/char/lrng/Makefile | 1 + + drivers/char/lrng/lrng_es_archrandom.c | 226 +++++++++++++++++++++++++ + 3 files changed, 265 insertions(+) + create mode 100644 drivers/char/lrng/lrng_es_archrandom.c + +diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig +index a9ae35d9f648..d3abdfa28493 100644 +--- a/drivers/char/lrng/Kconfig ++++ b/drivers/char/lrng/Kconfig +@@ -215,6 +215,44 @@ config LRNG_IRQ_ENTROPY_RATE + interrupt entropy source will still deliver data but without + being credited with entropy. + ++comment "CPU Entropy Source" ++ ++config LRNG_CPU ++ bool "Enable CPU Entropy Source as LRNG Seed Source" ++ default y ++ help ++ Current CPUs commonly contain entropy sources which can be ++ used to seed the LRNG. For example, the Intel RDSEED ++ instruction, or the POWER DARN instruction will be sourced ++ to seed the LRNG if this option is enabled. ++ ++ Note, if this option is enabled and the underlying CPU ++ does not offer such entropy source, the LRNG will automatically ++ detect this and ignore the hardware. ++ ++config LRNG_CPU_FULL_ENT_MULTIPLIER ++ int ++ default 1 if !LRNG_TEST_CPU_ES_COMPRESSION ++ default 123 if LRNG_TEST_CPU_ES_COMPRESSION ++ ++config LRNG_CPU_ENTROPY_RATE ++ int "CPU Entropy Source Entropy Rate" ++ depends on LRNG_CPU ++ range 0 256 ++ default 8 ++ help ++ The option defines the amount of entropy the LRNG applies to 256 ++ bits of data obtained from the CPU entropy source. The LRNG ++ enforces the limit that this value must be in the range between ++ 0 and 256. ++ ++ When configuring this value to 0, the CPU entropy source will ++ provide 256 bits of data without being credited to contain ++ entropy. ++ ++ Note, this option is overwritten when the option ++ CONFIG_RANDOM_TRUST_CPU is set. ++ + endmenu # "Entropy Source Configuration" + + endif # LRNG +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +index 1e722e0967e0..1e18e2c1016b 100644 +--- a/drivers/char/lrng/Makefile ++++ b/drivers/char/lrng/Makefile +@@ -10,3 +10,4 @@ obj-y += lrng_es_mgr.o lrng_aux.o \ + obj-$(CONFIG_LRNG_IRQ) += lrng_es_irq.o + obj-$(CONFIG_SYSCTL) += lrng_proc.o + obj-$(CONFIG_NUMA) += lrng_numa.o ++obj-$(CONFIG_LRNG_CPU) += lrng_es_archrandom.o +diff --git a/drivers/char/lrng/lrng_es_archrandom.c b/drivers/char/lrng/lrng_es_archrandom.c +new file mode 100644 +index 000000000000..6965f9b8ae50 +--- /dev/null ++++ b/drivers/char/lrng/lrng_es_archrandom.c +@@ -0,0 +1,226 @@ ++// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause ++/* ++ * LRNG Fast Entropy Source: CPU-based entropy source ++ * ++ * Copyright (C) 2016 - 2021, Stephan Mueller ++ */ ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include ++#include ++#include ++ ++#include "lrng_internal.h" ++ ++/* ++ * Estimated entropy of data is a 32th of LRNG_DRNG_SECURITY_STRENGTH_BITS. ++ * As we have no ability to review the implementation of those noise sources, ++ * it is prudent to have a conservative estimate here. ++ */ ++#define LRNG_ARCHRANDOM_DEFAULT_STRENGTH CONFIG_LRNG_CPU_ENTROPY_RATE ++#define LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH LRNG_DRNG_SECURITY_STRENGTH_BITS ++#ifdef CONFIG_RANDOM_TRUST_CPU ++static u32 archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH; ++#else ++static u32 archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH; ++#endif ++#ifdef CONFIG_LRNG_RUNTIME_ES_CONFIG ++module_param(archrandom, uint, 0644); ++MODULE_PARM_DESC(archrandom, "Entropy in bits of 256 data bits from CPU noise source (e.g. RDSEED)"); ++#endif ++ ++static int __init lrng_parse_trust_cpu(char *arg) ++{ ++ int ret; ++ bool trust_cpu = false; ++ ++ ret = kstrtobool(arg, &trust_cpu); ++ if (ret) ++ return ret; ++ ++ if (trust_cpu) { ++ archrandom = LRNG_ARCHRANDOM_TRUST_CPU_STRENGTH; ++ lrng_pool_add_entropy(); ++ } else { ++ archrandom = LRNG_ARCHRANDOM_DEFAULT_STRENGTH; ++ } ++ ++ return 0; ++} ++early_param("random.trust_cpu", lrng_parse_trust_cpu); ++ ++u32 lrng_archrandom_entropylevel(u32 requested_bits) ++{ ++ return lrng_fast_noise_entropylevel(archrandom, requested_bits); ++} ++ ++static u32 lrng_get_arch_data(u8 *outbuf, u32 requested_bits) ++{ ++ u32 i; ++ ++ /* operate on full blocks */ ++ BUILD_BUG_ON(LRNG_DRNG_SECURITY_STRENGTH_BYTES % sizeof(unsigned long)); ++ BUILD_BUG_ON(CONFIG_LRNG_SEED_BUFFER_INIT_ADD_BITS % ++ sizeof(unsigned long)); ++ /* ensure we have aligned buffers */ ++ BUILD_BUG_ON(LRNG_KCAPI_ALIGN % sizeof(unsigned long)); ++ ++ for (i = 0; i < (requested_bits >> 3); ++ i += sizeof(unsigned long)) { ++ if (!arch_get_random_seed_long((unsigned long *)(outbuf + i)) && ++ !arch_get_random_long((unsigned long *)(outbuf + i))) { ++ archrandom = 0; ++ return 0; ++ } ++ } ++ ++ return requested_bits; ++} ++ ++static u32 inline lrng_get_arch_data_compress(u8 *outbuf, u32 requested_bits, ++ u32 data_multiplier) ++{ ++ SHASH_DESC_ON_STACK(shash, NULL); ++ const struct lrng_crypto_cb *crypto_cb; ++ struct lrng_drng *drng = lrng_drng_init_instance(); ++ unsigned long flags; ++ u32 ent_bits = 0, i, partial_bits = 0, ++ full_bits = requested_bits * data_multiplier; ++ void *hash; ++ ++ /* Calculate oversampling for SP800-90C */ ++ if (lrng_sp80090c_compliant()) { ++ /* Complete amount of bits to be pulled */ ++ full_bits += CONFIG_LRNG_OVERSAMPLE_ES_BITS * data_multiplier; ++ /* Full blocks that will be pulled */ ++ data_multiplier = full_bits / requested_bits; ++ /* Partial block in bits to be pulled */ ++ partial_bits = full_bits - (data_multiplier * requested_bits); ++ } ++ ++ lrng_hash_lock(drng, &flags); ++ crypto_cb = drng->crypto_cb; ++ hash = drng->hash; ++ ++ if (crypto_cb->lrng_hash_init(shash, hash)) ++ goto out; ++ ++ /* Hash all data from the CPU entropy source */ ++ for (i = 0; i < data_multiplier; i++) { ++ ent_bits = lrng_get_arch_data(outbuf, requested_bits); ++ if (!ent_bits) ++ goto out; ++ ++ if (crypto_cb->lrng_hash_update(shash, outbuf, ent_bits >> 3)) ++ goto err; ++ } ++ ++ /* Hash partial block, if applicable */ ++ ent_bits = lrng_get_arch_data(outbuf, partial_bits); ++ if (ent_bits && ++ crypto_cb->lrng_hash_update(shash, outbuf, ent_bits >> 3)) ++ goto err; ++ ++ pr_debug("pulled %u bits from CPU RNG entropy source\n", full_bits); ++ ++ /* Generate the compressed data to be returned to the caller */ ++ ent_bits = crypto_cb->lrng_hash_digestsize(hash) << 3; ++ if (requested_bits < ent_bits) { ++ u8 digest[LRNG_MAX_DIGESTSIZE]; ++ ++ if (crypto_cb->lrng_hash_final(shash, digest)) ++ goto err; ++ ++ /* Truncate output data to requested size */ ++ memcpy(outbuf, digest, requested_bits >> 3); ++ memzero_explicit(digest, crypto_cb->lrng_hash_digestsize(hash)); ++ ent_bits = requested_bits; ++ } else { ++ if (crypto_cb->lrng_hash_final(shash, outbuf)) ++ goto err; ++ } ++ ++out: ++ crypto_cb->lrng_hash_desc_zero(shash); ++ lrng_hash_unlock(drng, flags); ++ return ent_bits; ++ ++err: ++ ent_bits = 0; ++ goto out; ++} ++ ++/* ++ * If CPU entropy source requires does not return full entropy, return the ++ * multiplier of how much data shall be sampled from it. ++ */ ++static u32 lrng_arch_multiplier(void) ++{ ++ static u32 data_multiplier = 0; ++ ++ if (data_multiplier > 0) { ++ return data_multiplier; ++ } else { ++ unsigned long v; ++ ++ if (IS_ENABLED(CONFIG_X86) && !arch_get_random_seed_long(&v)) { ++ /* ++ * Intel SPEC: pulling 512 blocks from RDRAND ensures ++ * one reseed making it logically equivalent to RDSEED. ++ */ ++ data_multiplier = 512; ++ } else if (IS_ENABLED(CONFIG_PPC)) { ++ /* ++ * PowerISA defines DARN to deliver at least 0.5 bits of ++ * entropy per data bit. ++ */ ++ data_multiplier = 2; ++ } else { ++ /* CPU provides full entropy */ ++ data_multiplier = CONFIG_LRNG_CPU_FULL_ENT_MULTIPLIER; ++ } ++ } ++ return data_multiplier; ++} ++ ++/* ++ * lrng_get_arch() - Get CPU entropy source entropy ++ * ++ * @outbuf: buffer to store entropy of size requested_bits ++ * ++ * Return: ++ * * > 0 on success where value provides the added entropy in bits ++ * * 0 if no fast source was available ++ */ ++u32 lrng_get_arch(u8 *outbuf, u32 requested_bits) ++{ ++ u32 ent_bits, data_multiplier = lrng_arch_multiplier(); ++ ++ if (data_multiplier <= 1) { ++ ent_bits = lrng_get_arch_data(outbuf, requested_bits); ++ } else { ++ ent_bits = lrng_get_arch_data_compress(outbuf, requested_bits, ++ data_multiplier); ++ } ++ ++ ent_bits = lrng_archrandom_entropylevel(ent_bits); ++ pr_debug("obtained %u bits of entropy from CPU RNG entropy source\n", ++ ent_bits); ++ return ent_bits; ++} ++ ++void lrng_arch_es_state(unsigned char *buf, size_t buflen) ++{ ++ const struct lrng_drng *lrng_drng_init = lrng_drng_init_instance(); ++ u32 data_multiplier = lrng_arch_multiplier(); ++ ++ /* Assume the lrng_drng_init lock is taken by caller */ ++ snprintf(buf, buflen, ++ "CPU ES properties:\n" ++ " Hash for compressing data: %s\n" ++ " Data multiplier: %u\n", ++ (data_multiplier <= 1) ? ++ "N/A" : lrng_drng_init->crypto_cb->lrng_hash_name(), ++ data_multiplier); ++} +-- +2.31.1 + diff --git a/PATCH/LRNG/696-07-v42-0004-LRNG-add-switchable-DRNG-support.patch b/PATCH/LRNG/696-09-v43-0006-LRNG-add-switchable-DRNG-support.patch similarity index 93% rename from PATCH/LRNG/696-07-v42-0004-LRNG-add-switchable-DRNG-support.patch rename to PATCH/LRNG/696-09-v43-0006-LRNG-add-switchable-DRNG-support.patch index f884de9c8..c3d55efcc 100644 --- a/PATCH/LRNG/696-07-v42-0004-LRNG-add-switchable-DRNG-support.patch +++ b/PATCH/LRNG/696-09-v43-0006-LRNG-add-switchable-DRNG-support.patch @@ -1,7 +1,7 @@ -From e26ee3e543f80be93cca6155ea9f861603652f59 Mon Sep 17 00:00:00 2001 +From e0ba1fc91c8e1800210dca1805d8dd0262447955 Mon Sep 17 00:00:00 2001 From: Stephan Mueller -Date: Mon, 2 Aug 2021 21:54:12 +0200 -Subject: [PATCH v42 04/13] LRNG - add switchable DRNG support +Date: Fri, 1 Oct 2021 20:47:30 +0200 +Subject: [PATCH v43 06/15] LRNG - add switchable DRNG support The DRNG switch support allows replacing the DRNG mechanism of the LRNG. The switching support rests on the interface definition of @@ -62,6 +62,8 @@ Reviewed-by: Marcelo Henrique Cerri Reviewed-by: Roman Drahtmueller Tested-by: Marcelo Henrique Cerri Tested-by: Neil Horman +Tested-by: Jirka Hladky +Reviewed-by: Jirka Hladky Signed-off-by: Stephan Mueller --- drivers/char/lrng/Kconfig | 7 + @@ -70,9 +72,11 @@ Signed-off-by: Stephan Mueller 3 files changed, 234 insertions(+) create mode 100644 drivers/char/lrng/lrng_switch.c +diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig +index d3abdfa28493..9fea73b72f88 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig -@@ -202,4 +202,11 @@ config LRNG_CPU_ENTROPY_RATE +@@ -255,4 +255,11 @@ config LRNG_CPU_ENTROPY_RATE endmenu # "Entropy Source Configuration" @@ -84,13 +88,18 @@ Signed-off-by: Stephan Mueller + option other DRNGs can be selected and loaded at runtime. + endif # LRNG +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +index 1e18e2c1016b..2202aa78b63f 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile -@@ -10,3 +10,4 @@ obj-y += lrng_es_mgr.o lrng_aux.o \ - - obj-$(CONFIG_NUMA) += lrng_numa.o +@@ -11,3 +11,4 @@ obj-$(CONFIG_LRNG_IRQ) += lrng_es_irq.o obj-$(CONFIG_SYSCTL) += lrng_proc.o + obj-$(CONFIG_NUMA) += lrng_numa.o + obj-$(CONFIG_LRNG_CPU) += lrng_es_archrandom.o +obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_switch.o +diff --git a/drivers/char/lrng/lrng_switch.c b/drivers/char/lrng/lrng_switch.c +new file mode 100644 +index 000000000000..5fce40149911 --- /dev/null +++ b/drivers/char/lrng/lrng_switch.c @@ -0,0 +1,226 @@ @@ -275,7 +284,7 @@ Signed-off-by: Stephan Mueller + return 0; +} + -+/** ++/* + * lrng_set_drng_cb - Register new cryptographic callback functions for DRNG + * The registering implies that all old DRNG states are replaced with new + * DRNG states. @@ -320,3 +329,6 @@ Signed-off-by: Stephan Mueller + return ret; +} +EXPORT_SYMBOL(lrng_set_drng_cb); +-- +2.31.1 + diff --git a/PATCH/LRNG/696-08-v42-0005-LRNG-add-common-generic-hash-support.patch b/PATCH/LRNG/696-10-v43-0007-LRNG-add-common-generic-hash-support.patch similarity index 86% rename from PATCH/LRNG/696-08-v42-0005-LRNG-add-common-generic-hash-support.patch rename to PATCH/LRNG/696-10-v43-0007-LRNG-add-common-generic-hash-support.patch index e822b53ea..da893a788 100644 --- a/PATCH/LRNG/696-08-v42-0005-LRNG-add-common-generic-hash-support.patch +++ b/PATCH/LRNG/696-10-v43-0007-LRNG-add-common-generic-hash-support.patch @@ -1,7 +1,7 @@ -From 844dc223fc4da1867daf13d7c8ae432fdc6de890 Mon Sep 17 00:00:00 2001 +From f18aea99b5156a952cae5ed789d058b6887ae673 Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Fri, 18 Jun 2021 08:08:20 +0200 -Subject: [PATCH v42 05/13] LRNG - add common generic hash support +Subject: [PATCH v43 07/15] LRNG - add common generic hash support The LRNG switchable DRNG support also allows the replacement of the hash implementation used as conditioning component. The common generic hash @@ -36,6 +36,8 @@ CC: Marcelo Henrique Cerri CC: Neil Horman Reviewed-by: Alexander Lobakin Tested-by: Alexander Lobakin +Tested-by: Jirka Hladky +Reviewed-by: Jirka Hladky Signed-off-by: Stephan Mueller --- drivers/char/lrng/Kconfig | 8 +++ @@ -46,9 +48,11 @@ Signed-off-by: Stephan Mueller create mode 100644 drivers/char/lrng/lrng_kcapi_hash.c create mode 100644 drivers/char/lrng/lrng_kcapi_hash.h +diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig +index 9fea73b72f88..531b34b9ae65 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig -@@ -209,4 +209,12 @@ menuconfig LRNG_DRNG_SWITCH +@@ -262,4 +262,12 @@ menuconfig LRNG_DRNG_SWITCH accessible via the external interfaces. With this configuration option other DRNGs can be selected and loaded at runtime. @@ -61,13 +65,18 @@ Signed-off-by: Stephan Mueller +endif # LRNG_DRNG_SWITCH + endif # LRNG +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +index 2202aa78b63f..cb9b03bdfd00 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile -@@ -11,3 +11,4 @@ obj-y += lrng_es_mgr.o lrng_aux.o \ +@@ -12,3 +12,4 @@ obj-$(CONFIG_SYSCTL) += lrng_proc.o obj-$(CONFIG_NUMA) += lrng_numa.o - obj-$(CONFIG_SYSCTL) += lrng_proc.o + obj-$(CONFIG_LRNG_CPU) += lrng_es_archrandom.o obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_switch.o +obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.o +diff --git a/drivers/char/lrng/lrng_kcapi_hash.c b/drivers/char/lrng/lrng_kcapi_hash.c +new file mode 100644 +index 000000000000..9647d980e468 --- /dev/null +++ b/drivers/char/lrng/lrng_kcapi_hash.c @@ -0,0 +1,103 @@ @@ -174,6 +183,9 @@ Signed-off-by: Stephan Mueller + shash_desc_zero(shash); +} +EXPORT_SYMBOL(lrng_kcapi_hash_zero); +diff --git a/drivers/char/lrng/lrng_kcapi_hash.h b/drivers/char/lrng/lrng_kcapi_hash.h +new file mode 100644 +index 000000000000..2f94558d2dd6 --- /dev/null +++ b/drivers/char/lrng/lrng_kcapi_hash.h @@ -0,0 +1,20 @@ @@ -197,3 +209,6 @@ Signed-off-by: Stephan Mueller +void lrng_kcapi_hash_zero(struct shash_desc *shash); + +#endif /* _LRNG_KCAPI_HASH_H */ +-- +2.31.1 + diff --git a/PATCH/LRNG/696-09-v42-0006-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch b/PATCH/LRNG/696-11-v43-0008-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch similarity index 77% rename from PATCH/LRNG/696-09-v42-0006-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch rename to PATCH/LRNG/696-11-v43-0008-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch index ae58f06de..2fb87016e 100644 --- a/PATCH/LRNG/696-09-v42-0006-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch +++ b/PATCH/LRNG/696-11-v43-0008-crypto-DRBG-externalize-DRBG-functions-for-LRNG.patch @@ -1,7 +1,7 @@ -From 3b4bc70c349cde883e2b2545d65dc37a3ef89050 Mon Sep 17 00:00:00 2001 +From 4448478c27a6586561d93c62c81caebfba54f509 Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Tue, 15 Sep 2020 22:17:43 +0200 -Subject: [PATCH v42 06/13] crypto: DRBG - externalize DRBG functions for LRNG +Subject: [PATCH v43 08/15] crypto: DRBG - externalize DRBG functions for LRNG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -32,15 +32,19 @@ Reviewed-by: Roman Drahtmueller Tested-by: Roman Drahtmüller Tested-by: Marcelo Henrique Cerri Tested-by: Neil Horman +Tested-by: Jirka Hladky +Reviewed-by: Jirka Hladky Signed-off-by: Stephan Mueller --- crypto/drbg.c | 16 ++++++++++------ include/crypto/drbg.h | 7 +++++++ 2 files changed, 17 insertions(+), 6 deletions(-) +diff --git a/crypto/drbg.c b/crypto/drbg.c +index ea85d4a0fe9e..74a9dca67698 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c -@@ -113,7 +113,7 @@ +@@ -114,7 +114,7 @@ * the SHA256 / AES 256 over other ciphers. Thus, the favored * DRBGs are the latest entries in this array. */ @@ -49,7 +53,7 @@ Signed-off-by: Stephan Mueller #ifdef CONFIG_CRYPTO_DRBG_CTR { .flags = DRBG_CTR | DRBG_STRENGTH128, -@@ -190,6 +190,7 @@ static const struct drbg_core drbg_cores +@@ -191,6 +191,7 @@ static const struct drbg_core drbg_cores[] = { }, #endif /* CONFIG_CRYPTO_DRBG_HMAC */ }; @@ -57,7 +61,7 @@ Signed-off-by: Stephan Mueller static int drbg_uninstantiate(struct drbg_state *drbg); -@@ -205,7 +206,7 @@ static int drbg_uninstantiate(struct drb +@@ -206,7 +207,7 @@ static int drbg_uninstantiate(struct drbg_state *drbg); * Return: normalized strength in *bytes* value or 32 as default * to counter programming errors */ @@ -66,7 +70,7 @@ Signed-off-by: Stephan Mueller { switch (flags & DRBG_STRENGTH_MASK) { case DRBG_STRENGTH128: -@@ -218,6 +219,7 @@ static inline unsigned short drbg_sec_st +@@ -219,6 +220,7 @@ static inline unsigned short drbg_sec_strength(drbg_flag_t flags) return 32; } } @@ -74,7 +78,7 @@ Signed-off-by: Stephan Mueller /* * FIPS 140-2 continuous self test for the noise source -@@ -1202,7 +1204,7 @@ out: +@@ -1215,7 +1217,7 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers, } /* Free all substructures in a DRBG state without the DRBG state structure */ @@ -83,7 +87,7 @@ Signed-off-by: Stephan Mueller { if (!drbg) return; -@@ -1223,12 +1225,13 @@ static inline void drbg_dealloc_state(st +@@ -1236,12 +1238,13 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg) drbg->fips_primed = false; } } @@ -98,7 +102,7 @@ Signed-off-by: Stephan Mueller { int ret = -ENOMEM; unsigned int sb_size = 0; -@@ -1309,6 +1312,7 @@ err: +@@ -1322,6 +1325,7 @@ static inline int drbg_alloc_state(struct drbg_state *drbg) drbg_dealloc_state(drbg); return ret; } @@ -106,7 +110,7 @@ Signed-off-by: Stephan Mueller /************************************************************************* * DRBG interface functions -@@ -1876,8 +1880,7 @@ out: +@@ -1891,8 +1895,7 @@ static int drbg_kcapi_sym_ctr(struct drbg_state *drbg, * * return: flags */ @@ -116,7 +120,7 @@ Signed-off-by: Stephan Mueller { int i = 0; size_t start = 0; -@@ -1904,6 +1907,7 @@ static inline void drbg_convert_tfm_core +@@ -1919,6 +1922,7 @@ static inline void drbg_convert_tfm_core(const char *cra_driver_name, } } } @@ -124,9 +128,11 @@ Signed-off-by: Stephan Mueller static int drbg_kcapi_init(struct crypto_tfm *tfm) { +diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h +index c4165126937e..71d53e028e6d 100644 --- a/include/crypto/drbg.h +++ b/include/crypto/drbg.h -@@ -282,4 +282,11 @@ enum drbg_prefixes { +@@ -278,4 +278,11 @@ enum drbg_prefixes { DRBG_PREFIX3 }; @@ -138,3 +144,6 @@ Signed-off-by: Stephan Mueller +extern unsigned short drbg_sec_strength(drbg_flag_t flags); + #endif /* _DRBG_H */ +-- +2.31.1 + diff --git a/PATCH/LRNG/696-10-v42-0007-LRNG-add-SP800-90A-DRBG-extension.patch b/PATCH/LRNG/696-12-v43-0009-LRNG-add-SP800-90A-DRBG-extension.patch similarity index 92% rename from PATCH/LRNG/696-10-v42-0007-LRNG-add-SP800-90A-DRBG-extension.patch rename to PATCH/LRNG/696-12-v43-0009-LRNG-add-SP800-90A-DRBG-extension.patch index 5d100b3ff..e34f6ce0d 100644 --- a/PATCH/LRNG/696-10-v42-0007-LRNG-add-SP800-90A-DRBG-extension.patch +++ b/PATCH/LRNG/696-12-v43-0009-LRNG-add-SP800-90A-DRBG-extension.patch @@ -1,7 +1,7 @@ -From 553e810748bf00be31f1dc6232290cdd70d00e26 Mon Sep 17 00:00:00 2001 +From 5f0699174ef3c0e6050b85f59d311f5a569401fe Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Fri, 18 Jun 2021 08:09:59 +0200 -Subject: [PATCH v42 07/13] LRNG - add SP800-90A DRBG extension +Subject: [PATCH v43 09/15] LRNG - add SP800-90A DRBG extension Using the LRNG switchable DRNG support, the SP800-90A DRBG extension is implemented. @@ -42,6 +42,8 @@ Tested-by: Alexander Lobakin Reviewed-by: Roman Drahtmueller Tested-by: Marcelo Henrique Cerri Tested-by: Neil Horman +Tested-by: Jirka Hladky +Reviewed-by: Jirka Hladky Signed-off-by: Stephan Mueller --- drivers/char/lrng/Kconfig | 10 ++ @@ -50,9 +52,11 @@ Signed-off-by: Stephan Mueller 3 files changed, 209 insertions(+) create mode 100644 drivers/char/lrng/lrng_drbg.c +diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig +index 531b34b9ae65..d06d0417b025 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig -@@ -215,6 +215,16 @@ config LRNG_KCAPI_HASH +@@ -268,6 +268,16 @@ config LRNG_KCAPI_HASH bool select CRYPTO_HASH @@ -69,13 +73,18 @@ Signed-off-by: Stephan Mueller endif # LRNG_DRNG_SWITCH endif # LRNG +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +index cb9b03bdfd00..c00e15b6396e 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile -@@ -12,3 +12,4 @@ obj-$(CONFIG_NUMA) += lrng_numa.o - obj-$(CONFIG_SYSCTL) += lrng_proc.o +@@ -13,3 +13,4 @@ obj-$(CONFIG_NUMA) += lrng_numa.o + obj-$(CONFIG_LRNG_CPU) += lrng_es_archrandom.o obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_switch.o obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.o +obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o +diff --git a/drivers/char/lrng/lrng_drbg.c b/drivers/char/lrng/lrng_drbg.c +new file mode 100644 +index 000000000000..6ca6b05eccf4 --- /dev/null +++ b/drivers/char/lrng/lrng_drbg.c @@ -0,0 +1,198 @@ @@ -277,3 +286,6 @@ Signed-off-by: Stephan Mueller +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Stephan Mueller "); +MODULE_DESCRIPTION("Linux Random Number Generator - SP800-90A DRBG backend"); +-- +2.31.1 + diff --git a/PATCH/LRNG/696-11-v42-0008-LRNG-add-kernel-crypto-API-PRNG-extension.patch b/PATCH/LRNG/696-13-v43-0010-LRNG-add-kernel-crypto-API-PRNG-extension.patch similarity index 93% rename from PATCH/LRNG/696-11-v42-0008-LRNG-add-kernel-crypto-API-PRNG-extension.patch rename to PATCH/LRNG/696-13-v43-0010-LRNG-add-kernel-crypto-API-PRNG-extension.patch index f727ec613..4904c949c 100644 --- a/PATCH/LRNG/696-11-v42-0008-LRNG-add-kernel-crypto-API-PRNG-extension.patch +++ b/PATCH/LRNG/696-13-v43-0010-LRNG-add-kernel-crypto-API-PRNG-extension.patch @@ -1,7 +1,7 @@ -From cfc5387cf2f3226f4543318ec09957571d8ec63e Mon Sep 17 00:00:00 2001 +From efa7aed1263537b0243aa6da8f866d65ab28f40e Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Fri, 18 Jun 2021 08:10:53 +0200 -Subject: [PATCH v42 08/13] LRNG - add kernel crypto API PRNG extension +Subject: [PATCH v43 10/15] LRNG - add kernel crypto API PRNG extension Add runtime-pluggable support for all PRNGs that are accessible via the kernel crypto API, including hardware PRNGs. The PRNG is selected @@ -39,6 +39,8 @@ Reviewed-by: Marcelo Henrique Cerri Reviewed-by: Roman Drahtmueller Tested-by: Marcelo Henrique Cerri Tested-by: Neil Horman +Tested-by: Jirka Hladky +Reviewed-by: Jirka Hladky Signed-off-by: Stephan Mueller --- drivers/char/lrng/Kconfig | 13 ++ @@ -47,9 +49,11 @@ Signed-off-by: Stephan Mueller 3 files changed, 241 insertions(+) create mode 100644 drivers/char/lrng/lrng_kcapi.c +diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig +index d06d0417b025..25684c54d6a9 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig -@@ -225,6 +225,19 @@ config LRNG_DRBG +@@ -278,6 +278,19 @@ config LRNG_DRBG Enable the SP800-90A DRBG support for the LRNG. Once the module is loaded, output from /dev/random, /dev/urandom, getrandom(2), or get_random_bytes_full is provided by a DRBG. @@ -69,13 +73,18 @@ Signed-off-by: Stephan Mueller endif # LRNG_DRNG_SWITCH endif # LRNG +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +index c00e15b6396e..85abeaa68136 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile -@@ -13,3 +13,4 @@ obj-$(CONFIG_SYSCTL) += lrng_proc.o +@@ -14,3 +14,4 @@ obj-$(CONFIG_LRNG_CPU) += lrng_es_archrandom.o obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_switch.o obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.o obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o +obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o +diff --git a/drivers/char/lrng/lrng_kcapi.c b/drivers/char/lrng/lrng_kcapi.c +new file mode 100644 +index 000000000000..b06449cb2365 --- /dev/null +++ b/drivers/char/lrng/lrng_kcapi.c @@ -0,0 +1,227 @@ @@ -306,3 +315,6 @@ Signed-off-by: Stephan Mueller +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Stephan Mueller "); +MODULE_DESCRIPTION("Linux Random Number Generator - kernel crypto API DRNG backend"); +-- +2.31.1 + diff --git a/PATCH/LRNG/696-12-v42-0009-crypto-move-Jitter-RNG-header-include-dir.patch b/PATCH/LRNG/696-14-v43-0011-crypto-move-Jitter-RNG-header-include-dir.patch similarity index 52% rename from PATCH/LRNG/696-12-v42-0009-crypto-move-Jitter-RNG-header-include-dir.patch rename to PATCH/LRNG/696-14-v43-0011-crypto-move-Jitter-RNG-header-include-dir.patch index 36fe316ee..9d51e8b7d 100644 --- a/PATCH/LRNG/696-12-v42-0009-crypto-move-Jitter-RNG-header-include-dir.patch +++ b/PATCH/LRNG/696-14-v43-0011-crypto-move-Jitter-RNG-header-include-dir.patch @@ -1,7 +1,7 @@ -From 84c82faba86da8fc9ecd7ccbf7e85322dda009d3 Mon Sep 17 00:00:00 2001 +From 3b78d3152c0c1368557b2ec1b14ce4b0fadbb606 Mon Sep 17 00:00:00 2001 From: Stephan Mueller Date: Wed, 16 Sep 2020 09:50:27 +0200 -Subject: [PATCH v42 09/13] crypto: move Jitter RNG header include dir +Subject: [PATCH v43 11/15] crypto: move Jitter RNG header include dir MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -33,6 +33,8 @@ Reviewed-by: Roman Drahtmueller Tested-by: Roman Drahtmüller Tested-by: Marcelo Henrique Cerri Tested-by: Neil Horman +Tested-by: Jirka Hladky +Reviewed-by: Jirka Hladky Signed-off-by: Stephan Mueller --- crypto/jitterentropy-kcapi.c | 3 +-- @@ -41,11 +43,13 @@ Signed-off-by: Stephan Mueller 3 files changed, 2 insertions(+), 3 deletions(-) rename {crypto => include/crypto/internal}/jitterentropy.h (100%) +diff --git a/crypto/jitterentropy-kcapi.c b/crypto/jitterentropy-kcapi.c +index e8a4165a1874..c90e60910827 100644 --- a/crypto/jitterentropy-kcapi.c +++ b/crypto/jitterentropy-kcapi.c @@ -43,8 +43,7 @@ + #include #include - #include #include - -#include "jitterentropy.h" @@ -53,58 +57,23 @@ Signed-off-by: Stephan Mueller /*************************************************************************** * Helper function +diff --git a/crypto/jitterentropy.c b/crypto/jitterentropy.c +index a11b3208760f..f36a391319e1 100644 --- a/crypto/jitterentropy.c +++ b/crypto/jitterentropy.c -@@ -103,7 +103,7 @@ struct rand_data { - * Helper functions - ***************************************************************************/ +@@ -117,7 +117,7 @@ struct rand_data { + #define JENT_EHEALTH 9 /* Health test failed during initialization */ + #define JENT_ERCT 10 /* RCT failed during initialization */ -#include "jitterentropy.h" +#include - /** - * Update of the loop count used for the next round of ---- a/crypto/jitterentropy.h -+++ /dev/null -@@ -1,19 +0,0 @@ --// SPDX-License-Identifier: GPL-2.0-or-later -- --typedef unsigned long long __u64; -- --extern void *jent_zalloc(unsigned int len); --extern void jent_zfree(void *ptr); --extern int jent_fips_enabled(void); --extern void jent_panic(char *s); --extern void jent_memcpy(void *dest, const void *src, unsigned int n); --extern void jent_get_nstime(__u64 *out); -- --struct rand_data; --extern int jent_entropy_init(void); --extern int jent_read_entropy(struct rand_data *ec, unsigned char *data, -- unsigned int len); -- --extern struct rand_data *jent_entropy_collector_alloc(unsigned int osr, -- unsigned int flags); --extern void jent_entropy_collector_free(struct rand_data *entropy_collector); ---- /dev/null -+++ b/include/crypto/internal/jitterentropy.h -@@ -0,0 +1,19 @@ -+// SPDX-License-Identifier: GPL-2.0-or-later -+ -+typedef unsigned long long __u64; -+ -+extern void *jent_zalloc(unsigned int len); -+extern void jent_zfree(void *ptr); -+extern int jent_fips_enabled(void); -+extern void jent_panic(char *s); -+extern void jent_memcpy(void *dest, const void *src, unsigned int n); -+extern void jent_get_nstime(__u64 *out); -+ -+struct rand_data; -+extern int jent_entropy_init(void); -+extern int jent_read_entropy(struct rand_data *ec, unsigned char *data, -+ unsigned int len); -+ -+extern struct rand_data *jent_entropy_collector_alloc(unsigned int osr, -+ unsigned int flags); -+extern void jent_entropy_collector_free(struct rand_data *entropy_collector); + /*************************************************************************** + * Adaptive Proportion Test +diff --git a/crypto/jitterentropy.h b/include/crypto/internal/jitterentropy.h +similarity index 100% +rename from crypto/jitterentropy.h +rename to include/crypto/internal/jitterentropy.h +-- +2.31.1 + diff --git a/PATCH/LRNG/696-13-v42-0010-LRNG-add-Jitter-RNG-fast-noise-source.patch b/PATCH/LRNG/696-15-v43-0012-LRNG-add-Jitter-RNG-fast-noise-source.patch similarity index 79% rename from PATCH/LRNG/696-13-v42-0010-LRNG-add-Jitter-RNG-fast-noise-source.patch rename to PATCH/LRNG/696-15-v43-0012-LRNG-add-Jitter-RNG-fast-noise-source.patch index 57a6feb58..09f439695 100644 --- a/PATCH/LRNG/696-13-v42-0010-LRNG-add-Jitter-RNG-fast-noise-source.patch +++ b/PATCH/LRNG/696-15-v43-0012-LRNG-add-Jitter-RNG-fast-noise-source.patch @@ -1,7 +1,7 @@ -From bd786e34db91f6a72788d397625a41d01e1bd7bc Mon Sep 17 00:00:00 2001 +From 58eea410667017b923e559b4a591a9251e95be5f Mon Sep 17 00:00:00 2001 From: Stephan Mueller -Date: Mon, 30 Aug 2021 12:32:04 +0200 -Subject: [PATCH v42 10/13] LRNG - add Jitter RNG fast noise source +Date: Wed, 13 Oct 2021 22:53:51 +0200 +Subject: [PATCH v43 12/15] LRNG - add Jitter RNG fast noise source The Jitter RNG fast noise source implemented as part of the kernel crypto API is queried for 256 bits of entropy at the time the seed @@ -29,17 +29,21 @@ Tested-by: Alexander Lobakin Reviewed-by: Marcelo Henrique Cerri Tested-by: Marcelo Henrique Cerri Tested-by: Neil Horman +Tested-by: Jirka Hladky +Reviewed-by: Jirka Hladky Signed-off-by: Stephan Mueller --- - drivers/char/lrng/Kconfig | 27 ++++++++++ + drivers/char/lrng/Kconfig | 29 ++++++++++ drivers/char/lrng/Makefile | 1 + - drivers/char/lrng/lrng_es_jent.c | 90 ++++++++++++++++++++++++++++++++ - 3 files changed, 118 insertions(+) + drivers/char/lrng/lrng_es_jent.c | 97 ++++++++++++++++++++++++++++++++ + 3 files changed, 127 insertions(+) create mode 100644 drivers/char/lrng/lrng_es_jent.c +diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig +index 25684c54d6a9..478b12839907 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig -@@ -182,6 +182,33 @@ config LRNG_IRQ_ENTROPY_RATE +@@ -215,6 +215,35 @@ config LRNG_IRQ_ENTROPY_RATE interrupt entropy source will still deliver data but without being credited with entropy. @@ -59,6 +63,7 @@ Signed-off-by: Stephan Mueller + +config LRNG_JENT_ENTROPY_RATE + int "Jitter RNG Entropy Source Entropy Rate" ++ depends on LRNG_JENT + range 0 256 + default 16 + help @@ -67,22 +72,28 @@ Signed-off-by: Stephan Mueller + LRNG enforces the limit that this value must be in the range + between 0 and 256. + -+ In order to disable the Jitter RNG entropy source, the option -+ has to be set to 0. ++ When configuring this value to 0, the Jitter RNG entropy source ++ will provide 256 bits of data without being credited to contain ++ entropy. + comment "CPU Entropy Source" - config LRNG_CPU_ENTROPY_RATE + config LRNG_CPU +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +index 85abeaa68136..c797fbd10a98 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile -@@ -14,3 +14,4 @@ obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_s +@@ -15,3 +15,4 @@ obj-$(CONFIG_LRNG_DRNG_SWITCH) += lrng_switch.o obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.o obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o +obj-$(CONFIG_LRNG_JENT) += lrng_es_jent.o +diff --git a/drivers/char/lrng/lrng_es_jent.c b/drivers/char/lrng/lrng_es_jent.c +new file mode 100644 +index 000000000000..2ed221cc9372 --- /dev/null +++ b/drivers/char/lrng/lrng_es_jent.c -@@ -0,0 +1,90 @@ +@@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* + * LRNG Fast Entropy Source: Jitter RNG @@ -130,7 +141,7 @@ Signed-off-by: Stephan Mueller +} +device_initcall(lrng_jent_initialize); + -+/** ++/* + * lrng_get_jent() - Get Jitter RNG entropy + * + * @outbuf: buffer to store entropy @@ -149,7 +160,7 @@ Signed-off-by: Stephan Mueller + + spin_lock_irqsave(&lrng_jent_lock, flags); + -+ if (!ent_bits || !lrng_jent_initialized) { ++ if (!lrng_jent_initialized) { + spin_unlock_irqrestore(&lrng_jent_lock, flags); + return 0; + } @@ -173,3 +184,13 @@ Signed-off-by: Stephan Mueller + return lrng_fast_noise_entropylevel((lrng_jent_initialized) ? + jitterrng : 0, requested_bits); +} ++ ++void lrng_jent_es_state(unsigned char *buf, size_t buflen) ++{ ++ snprintf(buf, buflen, ++ "JitterRNG ES properties:\n" ++ " Enabled: %s\n", lrng_jent_initialized ? "true" : "false"); ++} +-- +2.31.1 + diff --git a/PATCH/LRNG/696-14-v42-0011-LRNG-add-SP800-90B-compliant-health-tests.patch b/PATCH/LRNG/696-16-v43-0013-LRNG-add-SP800-90B-compliant-health-tests.patch similarity index 93% rename from PATCH/LRNG/696-14-v42-0011-LRNG-add-SP800-90B-compliant-health-tests.patch rename to PATCH/LRNG/696-16-v43-0013-LRNG-add-SP800-90B-compliant-health-tests.patch index 9944c0afd..99e72c649 100644 --- a/PATCH/LRNG/696-14-v42-0011-LRNG-add-SP800-90B-compliant-health-tests.patch +++ b/PATCH/LRNG/696-16-v43-0013-LRNG-add-SP800-90B-compliant-health-tests.patch @@ -1,7 +1,7 @@ -From 0dc6dec5b9ab060d66af8e4abfe09099251b9fdf Mon Sep 17 00:00:00 2001 +From 4c05e0bf597db2ec72ab6df0d870cbee7061bb36 Mon Sep 17 00:00:00 2001 From: Stephan Mueller -Date: Mon, 2 Aug 2021 21:59:23 +0200 -Subject: [PATCH v42 11/13] LRNG - add SP800-90B compliant health tests +Date: Tue, 28 Sep 2021 18:10:36 +0200 +Subject: [PATCH v43 13/15] LRNG - add SP800-90B compliant health tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -129,30 +129,36 @@ Tested-by: Alexander Lobakin Reviewed-by: Roman Drahtmueller Tested-by: Marcelo Henrique Cerri Tested-by: Neil Horman +Tested-by: Jirka Hladky +Reviewed-by: Jirka Hladky Signed-off-by: Stephan Mueller --- - drivers/char/lrng/Kconfig | 56 +++++ + drivers/char/lrng/Kconfig | 58 +++++ drivers/char/lrng/Makefile | 1 + drivers/char/lrng/lrng_health.c | 410 ++++++++++++++++++++++++++++++++ - 3 files changed, 467 insertions(+) + 3 files changed, 469 insertions(+) create mode 100644 drivers/char/lrng/lrng_health.c +diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig +index 478b12839907..bc1b85929b94 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig -@@ -164,6 +164,62 @@ config LRNG_COLLECTION_SIZE +@@ -196,6 +196,64 @@ config LRNG_COLLECTION_SIZE default 4096 if LRNG_COLLECTION_SIZE_4096 default 8192 if LRNG_COLLECTION_SIZE_8192 +config LRNG_HEALTH_TESTS -+ bool "Enable noise source online health tests" ++ bool "Enable interrupt entropy source online health tests" ++ depends on LRNG_IRQ + help -+ The online health tests validate the noise source at -+ runtime for fatal errors. These tests include SP800-90B -+ compliant tests which are invoked if the system is booted -+ with fips=1. In case of fatal errors during active -+ SP800-90B tests, the issue is logged and the noise -+ data is discarded. These tests are required for full -+ compliance with SP800-90B. ++ The online health tests applied to the interrupt entropy ++ source validate the noise source at runtime for fatal ++ errors. These tests include SP800-90B compliant tests ++ which are invoked if the system is booted with fips=1. ++ In case of fatal errors during active SP800-90B tests, ++ the issue is logged and the noise data is discarded. ++ These tests are required for full compliance of the ++ interrupt entropy source with SP800-90B. + + If unsure, say Y. + @@ -201,14 +207,19 @@ Signed-off-by: Stephan Mueller + config LRNG_IRQ_ENTROPY_RATE int "Interrupt Entropy Source Entropy Rate" - range 256 4294967295 + depends on LRNG_IRQ +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +index c797fbd10a98..f868f9fe53a6 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile -@@ -15,3 +15,4 @@ obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kc +@@ -16,3 +16,4 @@ obj-$(CONFIG_LRNG_KCAPI_HASH) += lrng_kcapi_hash.o obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o obj-$(CONFIG_LRNG_JENT) += lrng_es_jent.o +obj-$(CONFIG_LRNG_HEALTH_TESTS) += lrng_health.o +diff --git a/drivers/char/lrng/lrng_health.c b/drivers/char/lrng/lrng_health.c +new file mode 100644 +index 000000000000..a56a0c4261ab --- /dev/null +++ b/drivers/char/lrng/lrng_health.c @@ -0,0 +1,410 @@ @@ -622,3 +633,6 @@ Signed-off-by: Stephan Mueller + + return lrng_health_pass; +} +-- +2.31.1 + diff --git a/PATCH/LRNG/696-15-v42-0012-LRNG-add-interface-for-gathering-of-raw-entropy.patch b/PATCH/LRNG/696-17-v43-0014-LRNG-add-interface-for-gathering-of-raw-entropy.patch similarity index 96% rename from PATCH/LRNG/696-15-v42-0012-LRNG-add-interface-for-gathering-of-raw-entropy.patch rename to PATCH/LRNG/696-17-v43-0014-LRNG-add-interface-for-gathering-of-raw-entropy.patch index bf5cecd71..c573b33c0 100644 --- a/PATCH/LRNG/696-15-v42-0012-LRNG-add-interface-for-gathering-of-raw-entropy.patch +++ b/PATCH/LRNG/696-17-v43-0014-LRNG-add-interface-for-gathering-of-raw-entropy.patch @@ -1,7 +1,7 @@ -From 4e03f13da1abe7b547fcc31e0d7bf1888663fb7d Mon Sep 17 00:00:00 2001 +From f8e35e321e7dcc52af7eac19b33c31e35c8b1f39 Mon Sep 17 00:00:00 2001 From: Stephan Mueller -Date: Mon, 2 Aug 2021 22:08:30 +0200 -Subject: [PATCH v42 12/13] LRNG - add interface for gathering of raw entropy +Date: Mon, 18 Oct 2021 20:55:51 +0200 +Subject: [PATCH v43 14/15] LRNG - add interface for gathering of raw entropy The test interface allows a privileged process to capture the raw unconditioned noise that is collected by the LRNG for statistical @@ -79,17 +79,21 @@ Tested-by: Alexander Lobakin Reviewed-by: Roman Drahtmueller Tested-by: Marcelo Henrique Cerri Tested-by: Neil Horman +Tested-by: Jirka Hladky +Reviewed-by: Jirka Hladky Signed-off-by: Stephan Mueller --- - drivers/char/lrng/Kconfig | 170 ++++++++ + drivers/char/lrng/Kconfig | 180 ++++++++ drivers/char/lrng/Makefile | 1 + drivers/char/lrng/lrng_testing.c | 689 +++++++++++++++++++++++++++++++ - 3 files changed, 860 insertions(+) + 3 files changed, 870 insertions(+) create mode 100644 drivers/char/lrng/lrng_testing.c +diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig +index bc1b85929b94..72b572cb7df5 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig -@@ -323,4 +323,174 @@ config LRNG_KCAPI +@@ -380,4 +380,184 @@ config LRNG_KCAPI provided by the selected kernel crypto API RNG. endif # LRNG_DRNG_SWITCH @@ -257,6 +261,16 @@ Signed-off-by: Stephan Mueller + operations without a reseed that has full entropy. The + interface is lrng_drng.max_wo_reseed. + ++config LRNG_TEST_CPU_ES_COMPRESSION ++ bool "Force CPU ES compression operation" ++ help ++ When enabling this option, the CPU ES compression operation ++ is forced by setting an arbitrary value > 1 for the data ++ multiplier even when the CPU ES would deliver full entropy. ++ This allows testing of the compression operation. It ++ therefore forces to pull more data from the CPU ES ++ than what may be required. ++ +config LRNG_TESTING + bool + default y if (LRNG_RAW_HIRES_ENTROPY || LRNG_RAW_JIFFIES_ENTROPY ||LRNG_RAW_IRQ_ENTROPY || LRNG_RAW_IRQFLAGS_ENTROPY || LRNG_RAW_RETIP_ENTROPY || LRNG_RAW_REGS_ENTROPY || LRNG_RAW_ARRAY || LRNG_IRQ_PERF || LRNG_ACVT_HASH) @@ -264,13 +278,18 @@ Signed-off-by: Stephan Mueller +endif #LRNG_TESTING_MENU + endif # LRNG +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +index f868f9fe53a6..6d5035aa611e 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile -@@ -16,3 +16,4 @@ obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o +@@ -17,3 +17,4 @@ obj-$(CONFIG_LRNG_DRBG) += lrng_drbg.o obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o obj-$(CONFIG_LRNG_JENT) += lrng_es_jent.o obj-$(CONFIG_LRNG_HEALTH_TESTS) += lrng_health.o +obj-$(CONFIG_LRNG_TESTING) += lrng_testing.o +diff --git a/drivers/char/lrng/lrng_testing.c b/drivers/char/lrng/lrng_testing.c +new file mode 100644 +index 000000000000..99cc35abf45c --- /dev/null +++ b/drivers/char/lrng/lrng_testing.c @@ -0,0 +1,689 @@ @@ -963,3 +982,6 @@ Signed-off-by: Stephan Mueller +} + +module_init(lrng_raw_init); +-- +2.31.1 + diff --git a/PATCH/LRNG/696-16-v42-0013-LRNG-add-power-on-and-runtime-self-tests.patch b/PATCH/LRNG/696-18-v43-0015-LRNG-add-power-on-and-runtime-self-tests.patch similarity index 91% rename from PATCH/LRNG/696-16-v42-0013-LRNG-add-power-on-and-runtime-self-tests.patch rename to PATCH/LRNG/696-18-v43-0015-LRNG-add-power-on-and-runtime-self-tests.patch index d8d60f0ab..4c299388f 100644 --- a/PATCH/LRNG/696-16-v42-0013-LRNG-add-power-on-and-runtime-self-tests.patch +++ b/PATCH/LRNG/696-18-v43-0015-LRNG-add-power-on-and-runtime-self-tests.patch @@ -1,7 +1,7 @@ -From 23983cc15570a566e4f095dadcbc9353f7d892eb Mon Sep 17 00:00:00 2001 +From 37fb62ae49cad72d2914336e7ed0e68372ffcf42 Mon Sep 17 00:00:00 2001 From: Stephan Mueller -Date: Mon, 2 Aug 2021 22:01:09 +0200 -Subject: [PATCH v42 13/13] LRNG - add power-on and runtime self-tests +Date: Tue, 28 Sep 2021 17:41:57 +0200 +Subject: [PATCH v43 15/15] LRNG - add power-on and runtime self-tests Parts of the LRNG are already covered by self-tests, including: @@ -66,42 +66,21 @@ CC: Marcelo Henrique Cerri CC: Neil Horman Reviewed-by: Alexander Lobakin Tested-by: Alexander Lobakin +Tested-by: Jirka Hladky +Reviewed-by: Jirka Hladky Signed-off-by: Stephan Mueller --- - drivers/char/lrng/Kconfig | 43 +++- + drivers/char/lrng/Kconfig | 26 ++ drivers/char/lrng/Makefile | 1 + - drivers/char/lrng/lrng_selftest.c | 369 ++++++++++++++++++++++++++++++ - 3 files changed, 405 insertions(+), 8 deletions(-) + drivers/char/lrng/lrng_selftest.c | 386 ++++++++++++++++++++++++++++++ + 3 files changed, 413 insertions(+) create mode 100644 drivers/char/lrng/lrng_selftest.c +diff --git a/drivers/char/lrng/Kconfig b/drivers/char/lrng/Kconfig +index 72b572cb7df5..6f969ac6e2fa 100644 --- a/drivers/char/lrng/Kconfig +++ b/drivers/char/lrng/Kconfig -@@ -165,15 +165,16 @@ config LRNG_COLLECTION_SIZE - default 8192 if LRNG_COLLECTION_SIZE_8192 - - config LRNG_HEALTH_TESTS -- bool "Enable noise source online health tests" -+ bool "Enable interrupt entropy source online health tests" - help -- The online health tests validate the noise source at -- runtime for fatal errors. These tests include SP800-90B -- compliant tests which are invoked if the system is booted -- with fips=1. In case of fatal errors during active -- SP800-90B tests, the issue is logged and the noise -- data is discarded. These tests are required for full -- compliance with SP800-90B. -+ The online health tests applied to the interrupt entropy -+ source validate the noise source at runtime for fatal -+ errors. These tests include SP800-90B compliant tests -+ which are invoked if the system is booted with fips=1. -+ In case of fatal errors during active SP800-90B tests, -+ the issue is logged and the noise data is discarded. -+ These tests are required for full compliance of the -+ interrupt entropy source with SP800-90B. - - If unsure, say Y. - -@@ -493,4 +494,30 @@ config LRNG_TESTING +@@ -560,4 +560,30 @@ config LRNG_TESTING endif #LRNG_TESTING_MENU @@ -132,16 +111,21 @@ Signed-off-by: Stephan Mueller +endif # LRNG_SELFTEST + endif # LRNG +diff --git a/drivers/char/lrng/Makefile b/drivers/char/lrng/Makefile +index 6d5035aa611e..e4f7f9702eb4 100644 --- a/drivers/char/lrng/Makefile +++ b/drivers/char/lrng/Makefile -@@ -17,3 +17,4 @@ obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o +@@ -18,3 +18,4 @@ obj-$(CONFIG_LRNG_KCAPI) += lrng_kcapi.o obj-$(CONFIG_LRNG_JENT) += lrng_es_jent.o obj-$(CONFIG_LRNG_HEALTH_TESTS) += lrng_health.o obj-$(CONFIG_LRNG_TESTING) += lrng_testing.o +obj-$(CONFIG_LRNG_SELFTEST) += lrng_selftest.o +diff --git a/drivers/char/lrng/lrng_selftest.c b/drivers/char/lrng/lrng_selftest.c +new file mode 100644 +index 000000000000..4412ebd2a5e6 --- /dev/null +++ b/drivers/char/lrng/lrng_selftest.c -@@ -0,0 +1,369 @@ +@@ -0,0 +1,386 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +/* + * LRNG power-on and on-demand self-test @@ -174,7 +158,6 @@ Signed-off-by: Stephan Mueller + +#include "lrng_chacha20.h" +#include "lrng_internal.h" -+#include "lrng_es_irq.h" + +#define LRNG_SELFTEST_PASSED 0 +#define LRNG_SEFLTEST_ERROR_TIME (1 << 0) @@ -183,23 +166,12 @@ Signed-off-by: Stephan Mueller +#define LRNG_SEFLTEST_ERROR_GCD (1 << 3) +#define LRNG_SELFTEST_NOT_EXECUTED 0xffffffff + -+static u32 lrng_data_selftest_ptr = 0; -+static u32 lrng_data_selftest[LRNG_DATA_ARRAY_SIZE]; -+ -+static unsigned int lrng_selftest_status = LRNG_SELFTEST_NOT_EXECUTED; -+ -+static inline void lrng_selftest_bswap32(u32 *ptr, u32 words) -+{ -+ u32 i; ++#ifdef CONFIG_LRNG_IRQ + -+ /* Byte-swap data which is an LE representation */ -+ for (i = 0; i < words; i++) { -+ __le32 *p = (__le32 *)ptr; ++#include "lrng_es_irq.h" + -+ *p = cpu_to_le32(*ptr); -+ ptr++; -+ } -+} ++static u32 lrng_data_selftest_ptr = 0; ++static u32 lrng_data_selftest[LRNG_DATA_ARRAY_SIZE]; + +static inline void lrng_data_process_selftest_insert(u32 time) +{ @@ -231,7 +203,7 @@ Signed-off-by: Stephan Mueller + /* MSB of data go into previous unit */ + pre_array = lrng_data_idx2array(pre_ptr); + /* zeroization of slot to ensure the following OR adds the data */ -+ lrng_data_selftest[pre_array] &= ~(0xffffffff &~ mask); ++ lrng_data_selftest[pre_array] &= ~(0xffffffff & ~mask); + lrng_data_selftest[pre_array] |= data & ~mask; + + /* LSB of data go into current unit */ @@ -291,6 +263,49 @@ Signed-off-by: Stephan Mueller + return LRNG_SEFLTEST_ERROR_TIME; +} + ++static unsigned int lrng_gcd_selftest(void) ++{ ++ u32 history[10]; ++ unsigned int i; ++ ++#define LRNG_GCD_SELFTEST 3 ++ for (i = 0; i < ARRAY_SIZE(history); i++) ++ history[i] = i * LRNG_GCD_SELFTEST; ++ ++ if (lrng_gcd_analyze(history, ARRAY_SIZE(history)) == LRNG_GCD_SELFTEST) ++ return LRNG_SELFTEST_PASSED; ++ ++ pr_err("LRNG GCD self-test FAILED\n"); ++ return LRNG_SEFLTEST_ERROR_GCD; ++} ++ ++#else /* CONFIG_LRNG_IRQ */ ++ ++static unsigned int lrng_data_process_selftest(void) ++{ ++ return LRNG_SELFTEST_PASSED; ++} ++ ++static unsigned int lrng_gcd_selftest(void) ++{ ++ return LRNG_SELFTEST_PASSED; ++} ++ ++#endif /* CONFIG_LRNG_IRQ */ ++ ++static inline void lrng_selftest_bswap32(u32 *ptr, u32 words) ++{ ++ u32 i; ++ ++ /* Byte-swap data which is an LE representation */ ++ for (i = 0; i < words; i++) { ++ __le32 *p = (__le32 *)ptr; ++ ++ *p = cpu_to_le32(*ptr); ++ ptr++; ++ } ++} ++ +/* The test vectors are taken from crypto/testmgr.h */ +static unsigned int lrng_hash_selftest(void) +{ @@ -451,21 +466,7 @@ Signed-off-by: Stephan Mueller + return LRNG_SEFLTEST_ERROR_CHACHA20; +} + -+static unsigned int lrng_gcd_selftest(void) -+{ -+ u32 history[10]; -+ unsigned int i; -+ -+#define LRNG_GCD_SELFTEST 3 -+ for (i = 0; i < ARRAY_SIZE(history); i++) -+ history[i] = i * LRNG_GCD_SELFTEST; -+ -+ if (lrng_gcd_analyze(history, ARRAY_SIZE(history)) == LRNG_GCD_SELFTEST) -+ return LRNG_SELFTEST_PASSED; -+ -+ pr_err("LRNG GCD self-test FAILED\n"); -+ return LRNG_SEFLTEST_ERROR_GCD; -+} ++static unsigned int lrng_selftest_status = LRNG_SELFTEST_NOT_EXECUTED; + +static int lrng_selftest(void) +{ @@ -511,3 +512,6 @@ Signed-off-by: Stephan Mueller +} + +module_init(lrng_selftest_init); +-- +2.31.1 + diff --git a/PATCH/LRNG/696-19-v42-04-net_rand_state.patch b/PATCH/LRNG/696-19-v42-04-net_rand_state.patch deleted file mode 100644 index eb5dd0b3b..000000000 --- a/PATCH/LRNG/696-19-v42-04-net_rand_state.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/drivers/char/lrng/lrng_es_irq.c -+++ b/drivers/char/lrng/lrng_es_irq.c -@@ -13,6 +13,7 @@ - #include - #include - #include -+#include - - #include "lrng_internal.h" - #include "lrng_es_irq.h" diff --git a/PATCH/LRNG/696-17-v42-01-remove_compat_ioctl.patch b/PATCH/LRNG/696-19-v43-01-remove_compat_ioctl.patch similarity index 54% rename from PATCH/LRNG/696-17-v42-01-remove_compat_ioctl.patch rename to PATCH/LRNG/696-19-v43-01-remove_compat_ioctl.patch index 96949bdcb..4a847365e 100644 --- a/PATCH/LRNG/696-17-v42-01-remove_compat_ioctl.patch +++ b/PATCH/LRNG/696-19-v43-01-remove_compat_ioctl.patch @@ -1,6 +1,6 @@ ---- a/drivers/char/lrng/lrng_interfaces.c -+++ b/drivers/char/lrng/lrng_interfaces.c -@@ -610,7 +610,6 @@ const struct file_operations random_fops +--- linux-5.4-2.orig/drivers/char/lrng/lrng_interfaces.c 2020-08-20 12:14:25.593091918 +0200 ++++ linux-5.4-2/drivers/char/lrng/lrng_interfaces.c 2020-08-20 12:14:55.877453575 +0200 +@@ -609,7 +609,6 @@ const struct file_operations random_fops .write = lrng_drng_write, .poll = lrng_random_poll, .unlocked_ioctl = lrng_ioctl, @@ -8,7 +8,7 @@ .fasync = lrng_fasync, .llseek = noop_llseek, }; -@@ -619,7 +618,6 @@ const struct file_operations urandom_fop +@@ -618,7 +617,6 @@ const struct file_operations urandom_fop .read = lrng_drng_read, .write = lrng_drng_write, .unlocked_ioctl = lrng_ioctl, diff --git a/PATCH/LRNG/696-20-v42-05-kzfree.patch b/PATCH/LRNG/696-20-v42-05-kzfree.patch deleted file mode 100644 index 774a6d119..000000000 --- a/PATCH/LRNG/696-20-v42-05-kzfree.patch +++ /dev/null @@ -1,44 +0,0 @@ ---- a/drivers/char/lrng/lrng_chacha20.c -+++ b/drivers/char/lrng/lrng_chacha20.c -@@ -182,7 +182,7 @@ static void lrng_cc20_drng_dealloc(void - } - - pr_debug("ChaCha20 core zeroized and freed\n"); -- kfree_sensitive(chacha20_state); -+ kzfree(chacha20_state); - } - - /******************************* Hash Operation *******************************/ ---- a/drivers/char/lrng/lrng_drbg.c -+++ b/drivers/char/lrng/lrng_drbg.c -@@ -140,7 +140,7 @@ static void lrng_drbg_drng_dealloc(void - if (drbg && drbg->d_ops) - drbg->d_ops->crypto_fini(drbg); - drbg_dealloc_state(drbg); -- kfree_sensitive(drbg); -+ kzfree(drbg); - pr_info("DRBG deallocated\n"); - } - ---- a/drivers/char/lrng/lrng_interfaces.c -+++ b/drivers/char/lrng/lrng_interfaces.c -@@ -431,7 +431,7 @@ static ssize_t lrng_read_common(char __u - - /* Wipe data just returned from memory */ - if (tmp_large) -- kfree_sensitive(tmp_large); -+ kzfree(tmp_large); - else - memzero_explicit(tmpbuf, sizeof(tmpbuf)); - ---- a/drivers/char/lrng/lrng_testing.c -+++ b/drivers/char/lrng/lrng_testing.c -@@ -236,7 +236,7 @@ static int lrng_testing_extract_user(str - ret += i; - } - -- kfree_sensitive(tmp); -+ kzfree(tmp); - - if (ret > 0) - *ppos += ret; diff --git a/PATCH/LRNG/696-18-v42-03-arch_random_early.patch b/PATCH/LRNG/696-20-v43-03-arch_random_early.patch similarity index 64% rename from PATCH/LRNG/696-18-v42-03-arch_random_early.patch rename to PATCH/LRNG/696-20-v43-03-arch_random_early.patch index d9e52ac77..a9bedca02 100644 --- a/PATCH/LRNG/696-18-v42-03-arch_random_early.patch +++ b/PATCH/LRNG/696-20-v43-03-arch_random_early.patch @@ -1,6 +1,6 @@ ---- a/drivers/char/lrng/lrng_es_mgr.c -+++ b/drivers/char/lrng/lrng_es_mgr.c -@@ -276,8 +276,8 @@ int __init rand_initialize(void) +--- linux-5.4/drivers/char/lrng/lrng_es_mgr.c.orig 2020-10-10 20:56:39.331954692 +0200 ++++ linux-5.4/drivers/char/lrng/lrng_es_mgr.c 2020-10-10 20:56:50.031999524 +0200 +@@ -318,8 +318,8 @@ int __init rand_initialize(void) seed.time = ktime_get_real(); for (i = 0; i < ARRAY_SIZE(seed.data); i++) { diff --git a/PATCH/LRNG/696-21-v43-04-net_rand_state.patch b/PATCH/LRNG/696-21-v43-04-net_rand_state.patch new file mode 100644 index 000000000..cf652103b --- /dev/null +++ b/PATCH/LRNG/696-21-v43-04-net_rand_state.patch @@ -0,0 +1,10 @@ +--- linux-5.4/drivers/char/lrng/lrng_es_irq.c.orig 2020-10-10 21:00:01.282688553 +0200 ++++ linux-5.4/drivers/char/lrng/lrng_es_irq.c 2020-10-10 21:12:07.975025774 +0200 +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + + #include "lrng_internal.h" + #include "lrng_es_irq.h" diff --git a/PATCH/LRNG/696-22-v43-05-kzfree.patch b/PATCH/LRNG/696-22-v43-05-kzfree.patch new file mode 100644 index 000000000..4e19d0fe7 --- /dev/null +++ b/PATCH/LRNG/696-22-v43-05-kzfree.patch @@ -0,0 +1,44 @@ +--- linux-5.4/drivers/char/lrng/lrng_chacha20.c.orig 2020-10-10 21:02:49.755374050 +0200 ++++ linux-5.4/drivers/char/lrng/lrng_chacha20.c 2020-10-10 21:03:21.878506872 +0200 +@@ -224,7 +224,7 @@ static void lrng_cc20_drng_dealloc(void + } + + pr_debug("ChaCha20 core zeroized and freed\n"); +- kfree_sensitive(chacha20_state); ++ kzfree(chacha20_state); + } + + /******************************* Hash Operation *******************************/ +--- linux-5.4/drivers/char/lrng/lrng_drbg.c.orig 2020-10-10 21:02:57.136404546 +0200 ++++ linux-5.4/drivers/char/lrng/lrng_drbg.c 2020-10-10 21:03:37.311570965 +0200 +@@ -140,7 +140,7 @@ static void lrng_drbg_drng_dealloc(void + if (drbg && drbg->d_ops) + drbg->d_ops->crypto_fini(drbg); + drbg_dealloc_state(drbg); +- kfree_sensitive(drbg); ++ kzfree(drbg); + pr_info("DRBG deallocated\n"); + } + +--- linux-5.4/drivers/char/lrng/lrng_interfaces.c.orig 2020-10-10 21:03:03.855432312 +0200 ++++ linux-5.4/drivers/char/lrng/lrng_interfaces.c 2020-10-10 21:03:53.879639777 +0200 +@@ -432,7 +432,7 @@ static ssize_t lrng_read_common(char __u + + /* Wipe data just returned from memory */ + if (tmp_large) +- kfree_sensitive(tmp_large); ++ kzfree(tmp_large); + else + memzero_explicit(tmpbuf, sizeof(tmpbuf)); + +--- linux-5.4/drivers/char/lrng/lrng_testing.c.orig 2020-10-10 21:03:08.427451210 +0200 ++++ linux-5.4/drivers/char/lrng/lrng_testing.c 2020-10-10 21:04:08.620700995 +0200 +@@ -234,7 +234,7 @@ static int lrng_testing_extract_user(str + ret += i; + } + +- kfree_sensitive(tmp); ++ kzfree(tmp); + + if (ret > 0) + *ppos += ret; diff --git a/PATCH/LRNG/696-21-v42-06-sha-includes.patch b/PATCH/LRNG/696-23-v43-06-sha-includes.patch similarity index 51% rename from PATCH/LRNG/696-21-v42-06-sha-includes.patch rename to PATCH/LRNG/696-23-v43-06-sha-includes.patch index 41852b792..4c9f8978e 100644 --- a/PATCH/LRNG/696-21-v42-06-sha-includes.patch +++ b/PATCH/LRNG/696-23-v43-06-sha-includes.patch @@ -1,5 +1,5 @@ ---- a/drivers/char/lrng/lrng_internal.h -+++ b/drivers/char/lrng/lrng_internal.h +--- linux-5.8/drivers/char/lrng/lrng_internal.h.orig 2021-05-24 20:14:23.197349733 +0200 ++++ linux-5.8/drivers/char/lrng/lrng_internal.h 2021-05-24 20:14:40.047461921 +0200 @@ -6,8 +6,7 @@ #ifndef _LRNG_INTERNAL_H #define _LRNG_INTERNAL_H @@ -10,9 +10,9 @@ #include #include #include ---- a/drivers/char/lrng/lrng_chacha20.c -+++ b/drivers/char/lrng/lrng_chacha20.c -@@ -189,7 +189,7 @@ static void lrng_cc20_drng_dealloc(void +--- linux-5.8/drivers/char/lrng/lrng_chacha20.c.orig 2021-05-24 20:12:14.143809900 +0200 ++++ linux-5.8/drivers/char/lrng/lrng_chacha20.c 2021-05-24 20:14:23.200349753 +0200 +@@ -188,7 +188,7 @@ static void lrng_cc20_drng_dealloc(void #ifdef CONFIG_CRYPTO_LIB_SHA256 @@ -21,7 +21,7 @@ static u32 lrng_cc20_hash_digestsize(void *hash) { -@@ -231,7 +231,7 @@ static void lrng_cc20_hash_desc_zero(str +@@ -230,7 +230,7 @@ static void lrng_cc20_hash_desc_zero(str #else /* CONFIG_CRYPTO_LIB_SHA256 */ diff --git a/PATCH/LRNG/696-22-v42-07-chacha_constants.patch b/PATCH/LRNG/696-24-v43-07-chacha_constants.patch similarity index 67% rename from PATCH/LRNG/696-22-v42-07-chacha_constants.patch rename to PATCH/LRNG/696-24-v43-07-chacha_constants.patch index 1649a9f55..572fbab8c 100644 --- a/PATCH/LRNG/696-22-v42-07-chacha_constants.patch +++ b/PATCH/LRNG/696-24-v43-07-chacha_constants.patch @@ -1,5 +1,5 @@ ---- a/drivers/char/lrng/lrng_chacha20.h -+++ b/drivers/char/lrng/lrng_chacha20.h +--- linux-5.10/drivers/char/lrng/lrng_chacha20.h.orig 2021-08-20 21:16:45.569017375 +0200 ++++ linux-5.10/drivers/char/lrng/lrng_chacha20.h 2021-08-20 21:18:21.255462479 +0200 @@ -21,5 +21,9 @@ struct chacha20_block { static inline void lrng_cc20_init_rfc7539(struct chacha20_block *chacha20) From b91010b22f099ed0626fc921376f8779068287d2 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 25 Nov 2021 10:52:41 +0800 Subject: [PATCH 207/244] Disable UKSM and Cacule UKSM -- KVM X Cacule -- Docker X Why not MuQSS? --- ...MultiQueue-Skiplist-Scheduler-v0.201.patch | 10742 ++++++++++++++++ ...MuQSS-Fix-build-error-on-config-leak.patch | 21 + ...on-of-finish_cpu-when-offlining-core.patch | 29 + README.md | 2 +- SCRIPTS/02_prepare_package.sh | 15 +- SCRIPTS/R2S/02_target_only.sh | 16 +- SCRIPTS/R4S/02_target_only.sh | 16 +- SCRIPTS/X86/02_target_only.sh | 8 +- 8 files changed, 10825 insertions(+), 24 deletions(-) create mode 100644 PATCH/MuQSS/0001-MultiQueue-Skiplist-Scheduler-v0.201.patch create mode 100644 PATCH/MuQSS/0002-MuQSS-Fix-build-error-on-config-leak.patch create mode 100644 PATCH/MuQSS/0003-MuQSS-Revert-invocation-of-finish_cpu-when-offlining-core.patch diff --git a/PATCH/MuQSS/0001-MultiQueue-Skiplist-Scheduler-v0.201.patch b/PATCH/MuQSS/0001-MultiQueue-Skiplist-Scheduler-v0.201.patch new file mode 100644 index 000000000..2ca432894 --- /dev/null +++ b/PATCH/MuQSS/0001-MultiQueue-Skiplist-Scheduler-v0.201.patch @@ -0,0 +1,10742 @@ +From 6e142c237f00ff6968410d85417d710a0ceb21dc Mon Sep 17 00:00:00 2001 +From: Con Kolivas +Date: Fri, 25 Oct 2019 14:00:52 +1100 +Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + +--- + .../admin-guide/kernel-parameters.txt | 8 + + Documentation/admin-guide/sysctl/kernel.rst | 37 + + Documentation/scheduler/sched-BFS.txt | 351 + + Documentation/scheduler/sched-MuQSS.txt | 373 + + arch/alpha/Kconfig | 2 + + arch/arm/Kconfig | 2 + + arch/arm64/Kconfig | 2 + + arch/powerpc/Kconfig | 2 + + arch/powerpc/platforms/cell/spufs/sched.c | 5 - + arch/x86/Kconfig | 18 + + fs/proc/base.c | 2 +- + include/linux/init_task.h | 4 + + include/linux/ioprio.h | 2 + + include/linux/sched.h | 60 +- + include/linux/sched/deadline.h | 9 + + include/linux/sched/nohz.h | 2 +- + include/linux/sched/prio.h | 12 + + include/linux/sched/rt.h | 2 + + include/linux/sched/task.h | 2 +- + include/linux/skip_list.h | 33 + + include/uapi/linux/sched.h | 9 +- + init/Kconfig | 23 +- + init/init_task.c | 10 + + init/main.c | 2 + + kernel/Kconfig.MuQSS | 105 + + kernel/Makefile | 2 +- + kernel/delayacct.c | 2 +- + kernel/exit.c | 4 +- + kernel/kthread.c | 30 +- + kernel/livepatch/transition.c | 6 +- + kernel/sched/Makefile | 10 +- + kernel/sched/MuQSS.c | 7606 +++++++++++++++++ + kernel/sched/MuQSS.h | 1022 +++ + kernel/sched/cpufreq_schedutil.c | 12 +- + kernel/sched/cpupri.h | 2 + + kernel/sched/cputime.c | 22 +- + kernel/sched/idle.c | 12 +- + kernel/sched/sched.h | 40 + + kernel/sched/topology.c | 9 + + kernel/skip_list.c | 148 + + kernel/sysctl.c | 54 +- + kernel/time/clockevents.c | 5 + + kernel/time/posix-cpu-timers.c | 4 +- + kernel/time/timer.c | 7 +- + kernel/trace/trace_selftest.c | 5 + + 45 files changed, 10025 insertions(+), 52 deletions(-) + create mode 100644 Documentation/scheduler/sched-BFS.txt + create mode 100644 Documentation/scheduler/sched-MuQSS.txt + create mode 100644 include/linux/skip_list.h + create mode 100644 kernel/Kconfig.MuQSS + create mode 100644 kernel/sched/MuQSS.c + create mode 100644 kernel/sched/MuQSS.h + create mode 100644 kernel/skip_list.c + +--- a/Documentation/admin-guide/kernel-parameters.txt ++++ b/Documentation/admin-guide/kernel-parameters.txt +@@ -4300,6 +4300,14 @@ + Memory area to be used by remote processor image, + managed by CMA. + ++ rqshare= [X86] Select the MuQSS scheduler runqueue sharing type. ++ Format: ++ smt -- Share SMT (hyperthread) sibling runqueues ++ mc -- Share MC (multicore) sibling runqueues ++ smp -- Share SMP runqueues ++ none -- So not share any runqueues ++ Default value is mc ++ + rw [KNL] Mount root device read-write on boot + + S [KNL] Run init in single mode +--- a/Documentation/admin-guide/sysctl/kernel.rst ++++ b/Documentation/admin-guide/sysctl/kernel.rst +@@ -46,6 +46,7 @@ show up in /proc/sys/kernel: + - hung_task_check_interval_secs + - hung_task_warnings + - hyperv_record_panic_msg ++- iso_cpu + - kexec_load_disabled + - kptr_restrict + - l2cr [ PPC only ] +@@ -82,6 +83,7 @@ show up in /proc/sys/kernel: + - randomize_va_space + - real-root-dev ==> Documentation/admin-guide/initrd.rst + - reboot-cmd [ SPARC only ] ++- rr_interval + - rtsig-max + - rtsig-nr + - sched_energy_aware +@@ -105,6 +107,7 @@ show up in /proc/sys/kernel: + - unknown_nmi_panic + - watchdog + - watchdog_thresh ++- yield_type + - version + + +@@ -438,6 +441,16 @@ When kptr_restrict is set to (2), kernel + %pK will be replaced with 0's regardless of privileges. + + ++iso_cpu: (MuQSS CPU scheduler only) ++=================================== ++ ++This sets the percentage cpu that the unprivileged SCHED_ISO tasks can ++run effectively at realtime priority, averaged over a rolling five ++seconds over the -whole- system, meaning all cpus. ++ ++Set to 70 (percent) by default. ++ ++ + l2cr: (PPC only) + ================ + +@@ -905,6 +918,20 @@ ROM/Flash boot loader. Maybe to tell it + rebooting. ??? + + ++rr_interval: (MuQSS CPU scheduler only) ++======================================= ++ ++This is the smallest duration that any cpu process scheduling unit ++will run for. Increasing this value can increase throughput of cpu ++bound tasks substantially but at the expense of increased latencies ++overall. Conversely decreasing it will decrease average and maximum ++latencies but at the expense of throughput. This value is in ++milliseconds and the default value chosen depends on the number of ++cpus available at scheduler initialisation with a minimum of 6. ++ ++Valid values are from 1-1000. ++ ++ + rtsig-max & rtsig-nr: + ===================== + +@@ -1175,3 +1202,13 @@ is 10 seconds. + + The softlockup threshold is (2 * watchdog_thresh). Setting this + tunable to zero will disable lockup detection altogether. ++ ++ ++yield_type: (MuQSS CPU scheduler only) ++====================================== ++ ++This determines what type of yield calls to sched_yield will perform. ++ ++ 0: No yield. ++ 1: Yield only to better priority/deadline tasks. (default) ++ 2: Expire timeslice and recalculate deadline. +--- /dev/null ++++ b/Documentation/scheduler/sched-BFS.txt +@@ -0,0 +1,351 @@ ++BFS - The Brain Fuck Scheduler by Con Kolivas. ++ ++Goals. ++ ++The goal of the Brain Fuck Scheduler, referred to as BFS from here on, is to ++completely do away with the complex designs of the past for the cpu process ++scheduler and instead implement one that is very simple in basic design. ++The main focus of BFS is to achieve excellent desktop interactivity and ++responsiveness without heuristics and tuning knobs that are difficult to ++understand, impossible to model and predict the effect of, and when tuned to ++one workload cause massive detriment to another. ++ ++ ++Design summary. ++ ++BFS is best described as a single runqueue, O(n) lookup, earliest effective ++virtual deadline first design, loosely based on EEVDF (earliest eligible virtual ++deadline first) and my previous Staircase Deadline scheduler. Each component ++shall be described in order to understand the significance of, and reasoning for ++it. The codebase when the first stable version was released was approximately ++9000 lines less code than the existing mainline linux kernel scheduler (in ++2.6.31). This does not even take into account the removal of documentation and ++the cgroups code that is not used. ++ ++Design reasoning. ++ ++The single runqueue refers to the queued but not running processes for the ++entire system, regardless of the number of CPUs. The reason for going back to ++a single runqueue design is that once multiple runqueues are introduced, ++per-CPU or otherwise, there will be complex interactions as each runqueue will ++be responsible for the scheduling latency and fairness of the tasks only on its ++own runqueue, and to achieve fairness and low latency across multiple CPUs, any ++advantage in throughput of having CPU local tasks causes other disadvantages. ++This is due to requiring a very complex balancing system to at best achieve some ++semblance of fairness across CPUs and can only maintain relatively low latency ++for tasks bound to the same CPUs, not across them. To increase said fairness ++and latency across CPUs, the advantage of local runqueue locking, which makes ++for better scalability, is lost due to having to grab multiple locks. ++ ++A significant feature of BFS is that all accounting is done purely based on CPU ++used and nowhere is sleep time used in any way to determine entitlement or ++interactivity. Interactivity "estimators" that use some kind of sleep/run ++algorithm are doomed to fail to detect all interactive tasks, and to falsely tag ++tasks that aren't interactive as being so. The reason for this is that it is ++close to impossible to determine that when a task is sleeping, whether it is ++doing it voluntarily, as in a userspace application waiting for input in the ++form of a mouse click or otherwise, or involuntarily, because it is waiting for ++another thread, process, I/O, kernel activity or whatever. Thus, such an ++estimator will introduce corner cases, and more heuristics will be required to ++cope with those corner cases, introducing more corner cases and failed ++interactivity detection and so on. Interactivity in BFS is built into the design ++by virtue of the fact that tasks that are waking up have not used up their quota ++of CPU time, and have earlier effective deadlines, thereby making it very likely ++they will preempt any CPU bound task of equivalent nice level. See below for ++more information on the virtual deadline mechanism. Even if they do not preempt ++a running task, because the rr interval is guaranteed to have a bound upper ++limit on how long a task will wait for, it will be scheduled within a timeframe ++that will not cause visible interface jitter. ++ ++ ++Design details. ++ ++Task insertion. ++ ++BFS inserts tasks into each relevant queue as an O(1) insertion into a double ++linked list. On insertion, *every* running queue is checked to see if the newly ++queued task can run on any idle queue, or preempt the lowest running task on the ++system. This is how the cross-CPU scheduling of BFS achieves significantly lower ++latency per extra CPU the system has. In this case the lookup is, in the worst ++case scenario, O(n) where n is the number of CPUs on the system. ++ ++Data protection. ++ ++BFS has one single lock protecting the process local data of every task in the ++global queue. Thus every insertion, removal and modification of task data in the ++global runqueue needs to grab the global lock. However, once a task is taken by ++a CPU, the CPU has its own local data copy of the running process' accounting ++information which only that CPU accesses and modifies (such as during a ++timer tick) thus allowing the accounting data to be updated lockless. Once a ++CPU has taken a task to run, it removes it from the global queue. Thus the ++global queue only ever has, at most, ++ ++ (number of tasks requesting cpu time) - (number of logical CPUs) + 1 ++ ++tasks in the global queue. This value is relevant for the time taken to look up ++tasks during scheduling. This will increase if many tasks with CPU affinity set ++in their policy to limit which CPUs they're allowed to run on if they outnumber ++the number of CPUs. The +1 is because when rescheduling a task, the CPU's ++currently running task is put back on the queue. Lookup will be described after ++the virtual deadline mechanism is explained. ++ ++Virtual deadline. ++ ++The key to achieving low latency, scheduling fairness, and "nice level" ++distribution in BFS is entirely in the virtual deadline mechanism. The one ++tunable in BFS is the rr_interval, or "round robin interval". This is the ++maximum time two SCHED_OTHER (or SCHED_NORMAL, the common scheduling policy) ++tasks of the same nice level will be running for, or looking at it the other ++way around, the longest duration two tasks of the same nice level will be ++delayed for. When a task requests cpu time, it is given a quota (time_slice) ++equal to the rr_interval and a virtual deadline. The virtual deadline is ++offset from the current time in jiffies by this equation: ++ ++ jiffies + (prio_ratio * rr_interval) ++ ++The prio_ratio is determined as a ratio compared to the baseline of nice -20 ++and increases by 10% per nice level. The deadline is a virtual one only in that ++no guarantee is placed that a task will actually be scheduled by this time, but ++it is used to compare which task should go next. There are three components to ++how a task is next chosen. First is time_slice expiration. If a task runs out ++of its time_slice, it is descheduled, the time_slice is refilled, and the ++deadline reset to that formula above. Second is sleep, where a task no longer ++is requesting CPU for whatever reason. The time_slice and deadline are _not_ ++adjusted in this case and are just carried over for when the task is next ++scheduled. Third is preemption, and that is when a newly waking task is deemed ++higher priority than a currently running task on any cpu by virtue of the fact ++that it has an earlier virtual deadline than the currently running task. The ++earlier deadline is the key to which task is next chosen for the first and ++second cases. Once a task is descheduled, it is put back on the queue, and an ++O(n) lookup of all queued-but-not-running tasks is done to determine which has ++the earliest deadline and that task is chosen to receive CPU next. ++ ++The CPU proportion of different nice tasks works out to be approximately the ++ ++ (prio_ratio difference)^2 ++ ++The reason it is squared is that a task's deadline does not change while it is ++running unless it runs out of time_slice. Thus, even if the time actually ++passes the deadline of another task that is queued, it will not get CPU time ++unless the current running task deschedules, and the time "base" (jiffies) is ++constantly moving. ++ ++Task lookup. ++ ++BFS has 103 priority queues. 100 of these are dedicated to the static priority ++of realtime tasks, and the remaining 3 are, in order of best to worst priority, ++SCHED_ISO (isochronous), SCHED_NORMAL, and SCHED_IDLEPRIO (idle priority ++scheduling). When a task of these priorities is queued, a bitmap of running ++priorities is set showing which of these priorities has tasks waiting for CPU ++time. When a CPU is made to reschedule, the lookup for the next task to get ++CPU time is performed in the following way: ++ ++First the bitmap is checked to see what static priority tasks are queued. If ++any realtime priorities are found, the corresponding queue is checked and the ++first task listed there is taken (provided CPU affinity is suitable) and lookup ++is complete. If the priority corresponds to a SCHED_ISO task, they are also ++taken in FIFO order (as they behave like SCHED_RR). If the priority corresponds ++to either SCHED_NORMAL or SCHED_IDLEPRIO, then the lookup becomes O(n). At this ++stage, every task in the runlist that corresponds to that priority is checked ++to see which has the earliest set deadline, and (provided it has suitable CPU ++affinity) it is taken off the runqueue and given the CPU. If a task has an ++expired deadline, it is taken and the rest of the lookup aborted (as they are ++chosen in FIFO order). ++ ++Thus, the lookup is O(n) in the worst case only, where n is as described ++earlier, as tasks may be chosen before the whole task list is looked over. ++ ++ ++Scalability. ++ ++The major limitations of BFS will be that of scalability, as the separate ++runqueue designs will have less lock contention as the number of CPUs rises. ++However they do not scale linearly even with separate runqueues as multiple ++runqueues will need to be locked concurrently on such designs to be able to ++achieve fair CPU balancing, to try and achieve some sort of nice-level fairness ++across CPUs, and to achieve low enough latency for tasks on a busy CPU when ++other CPUs would be more suited. BFS has the advantage that it requires no ++balancing algorithm whatsoever, as balancing occurs by proxy simply because ++all CPUs draw off the global runqueue, in priority and deadline order. Despite ++the fact that scalability is _not_ the prime concern of BFS, it both shows very ++good scalability to smaller numbers of CPUs and is likely a more scalable design ++at these numbers of CPUs. ++ ++It also has some very low overhead scalability features built into the design ++when it has been deemed their overhead is so marginal that they're worth adding. ++The first is the local copy of the running process' data to the CPU it's running ++on to allow that data to be updated lockless where possible. Then there is ++deference paid to the last CPU a task was running on, by trying that CPU first ++when looking for an idle CPU to use the next time it's scheduled. Finally there ++is the notion of cache locality beyond the last running CPU. The sched_domains ++information is used to determine the relative virtual "cache distance" that ++other CPUs have from the last CPU a task was running on. CPUs with shared ++caches, such as SMT siblings, or multicore CPUs with shared caches, are treated ++as cache local. CPUs without shared caches are treated as not cache local, and ++CPUs on different NUMA nodes are treated as very distant. This "relative cache ++distance" is used by modifying the virtual deadline value when doing lookups. ++Effectively, the deadline is unaltered between "cache local" CPUs, doubled for ++"cache distant" CPUs, and quadrupled for "very distant" CPUs. The reasoning ++behind the doubling of deadlines is as follows. The real cost of migrating a ++task from one CPU to another is entirely dependant on the cache footprint of ++the task, how cache intensive the task is, how long it's been running on that ++CPU to take up the bulk of its cache, how big the CPU cache is, how fast and ++how layered the CPU cache is, how fast a context switch is... and so on. In ++other words, it's close to random in the real world where we do more than just ++one sole workload. The only thing we can be sure of is that it's not free. So ++BFS uses the principle that an idle CPU is a wasted CPU and utilising idle CPUs ++is more important than cache locality, and cache locality only plays a part ++after that. Doubling the effective deadline is based on the premise that the ++"cache local" CPUs will tend to work on the same tasks up to double the number ++of cache local CPUs, and once the workload is beyond that amount, it is likely ++that none of the tasks are cache warm anywhere anyway. The quadrupling for NUMA ++is a value I pulled out of my arse. ++ ++When choosing an idle CPU for a waking task, the cache locality is determined ++according to where the task last ran and then idle CPUs are ranked from best ++to worst to choose the most suitable idle CPU based on cache locality, NUMA ++node locality and hyperthread sibling business. They are chosen in the ++following preference (if idle): ++ ++* Same core, idle or busy cache, idle threads ++* Other core, same cache, idle or busy cache, idle threads. ++* Same node, other CPU, idle cache, idle threads. ++* Same node, other CPU, busy cache, idle threads. ++* Same core, busy threads. ++* Other core, same cache, busy threads. ++* Same node, other CPU, busy threads. ++* Other node, other CPU, idle cache, idle threads. ++* Other node, other CPU, busy cache, idle threads. ++* Other node, other CPU, busy threads. ++ ++This shows the SMT or "hyperthread" awareness in the design as well which will ++choose a real idle core first before a logical SMT sibling which already has ++tasks on the physical CPU. ++ ++Early benchmarking of BFS suggested scalability dropped off at the 16 CPU mark. ++However this benchmarking was performed on an earlier design that was far less ++scalable than the current one so it's hard to know how scalable it is in terms ++of both CPUs (due to the global runqueue) and heavily loaded machines (due to ++O(n) lookup) at this stage. Note that in terms of scalability, the number of ++_logical_ CPUs matters, not the number of _physical_ CPUs. Thus, a dual (2x) ++quad core (4X) hyperthreaded (2X) machine is effectively a 16X. Newer benchmark ++results are very promising indeed, without needing to tweak any knobs, features ++or options. Benchmark contributions are most welcome. ++ ++ ++Features ++ ++As the initial prime target audience for BFS was the average desktop user, it ++was designed to not need tweaking, tuning or have features set to obtain benefit ++from it. Thus the number of knobs and features has been kept to an absolute ++minimum and should not require extra user input for the vast majority of cases. ++There are precisely 2 tunables, and 2 extra scheduling policies. The rr_interval ++and iso_cpu tunables, and the SCHED_ISO and SCHED_IDLEPRIO policies. In addition ++to this, BFS also uses sub-tick accounting. What BFS does _not_ now feature is ++support for CGROUPS. The average user should neither need to know what these ++are, nor should they need to be using them to have good desktop behaviour. ++ ++rr_interval ++ ++There is only one "scheduler" tunable, the round robin interval. This can be ++accessed in ++ ++ /proc/sys/kernel/rr_interval ++ ++The value is in milliseconds, and the default value is set to 6 on a ++uniprocessor machine, and automatically set to a progressively higher value on ++multiprocessor machines. The reasoning behind increasing the value on more CPUs ++is that the effective latency is decreased by virtue of there being more CPUs on ++BFS (for reasons explained above), and increasing the value allows for less ++cache contention and more throughput. Valid values are from 1 to 1000 ++Decreasing the value will decrease latencies at the cost of decreasing ++throughput, while increasing it will improve throughput, but at the cost of ++worsening latencies. The accuracy of the rr interval is limited by HZ resolution ++of the kernel configuration. Thus, the worst case latencies are usually slightly ++higher than this actual value. The default value of 6 is not an arbitrary one. ++It is based on the fact that humans can detect jitter at approximately 7ms, so ++aiming for much lower latencies is pointless under most circumstances. It is ++worth noting this fact when comparing the latency performance of BFS to other ++schedulers. Worst case latencies being higher than 7ms are far worse than ++average latencies not being in the microsecond range. ++ ++Isochronous scheduling. ++ ++Isochronous scheduling is a unique scheduling policy designed to provide ++near-real-time performance to unprivileged (ie non-root) users without the ++ability to starve the machine indefinitely. Isochronous tasks (which means ++"same time") are set using, for example, the schedtool application like so: ++ ++ schedtool -I -e amarok ++ ++This will start the audio application "amarok" as SCHED_ISO. How SCHED_ISO works ++is that it has a priority level between true realtime tasks and SCHED_NORMAL ++which would allow them to preempt all normal tasks, in a SCHED_RR fashion (ie, ++if multiple SCHED_ISO tasks are running, they purely round robin at rr_interval ++rate). However if ISO tasks run for more than a tunable finite amount of time, ++they are then demoted back to SCHED_NORMAL scheduling. This finite amount of ++time is the percentage of _total CPU_ available across the machine, configurable ++as a percentage in the following "resource handling" tunable (as opposed to a ++scheduler tunable): ++ ++ /proc/sys/kernel/iso_cpu ++ ++and is set to 70% by default. It is calculated over a rolling 5 second average ++Because it is the total CPU available, it means that on a multi CPU machine, it ++is possible to have an ISO task running as realtime scheduling indefinitely on ++just one CPU, as the other CPUs will be available. Setting this to 100 is the ++equivalent of giving all users SCHED_RR access and setting it to 0 removes the ++ability to run any pseudo-realtime tasks. ++ ++A feature of BFS is that it detects when an application tries to obtain a ++realtime policy (SCHED_RR or SCHED_FIFO) and the caller does not have the ++appropriate privileges to use those policies. When it detects this, it will ++give the task SCHED_ISO policy instead. Thus it is transparent to the user. ++Because some applications constantly set their policy as well as their nice ++level, there is potential for them to undo the override specified by the user ++on the command line of setting the policy to SCHED_ISO. To counter this, once ++a task has been set to SCHED_ISO policy, it needs superuser privileges to set ++it back to SCHED_NORMAL. This will ensure the task remains ISO and all child ++processes and threads will also inherit the ISO policy. ++ ++Idleprio scheduling. ++ ++Idleprio scheduling is a scheduling policy designed to give out CPU to a task ++_only_ when the CPU would be otherwise idle. The idea behind this is to allow ++ultra low priority tasks to be run in the background that have virtually no ++effect on the foreground tasks. This is ideally suited to distributed computing ++clients (like setiathome, folding, mprime etc) but can also be used to start ++a video encode or so on without any slowdown of other tasks. To avoid this ++policy from grabbing shared resources and holding them indefinitely, if it ++detects a state where the task is waiting on I/O, the machine is about to ++suspend to ram and so on, it will transiently schedule them as SCHED_NORMAL. As ++per the Isochronous task management, once a task has been scheduled as IDLEPRIO, ++it cannot be put back to SCHED_NORMAL without superuser privileges. Tasks can ++be set to start as SCHED_IDLEPRIO with the schedtool command like so: ++ ++ schedtool -D -e ./mprime ++ ++Subtick accounting. ++ ++It is surprisingly difficult to get accurate CPU accounting, and in many cases, ++the accounting is done by simply determining what is happening at the precise ++moment a timer tick fires off. This becomes increasingly inaccurate as the ++timer tick frequency (HZ) is lowered. It is possible to create an application ++which uses almost 100% CPU, yet by being descheduled at the right time, records ++zero CPU usage. While the main problem with this is that there are possible ++security implications, it is also difficult to determine how much CPU a task ++really does use. BFS tries to use the sub-tick accounting from the TSC clock, ++where possible, to determine real CPU usage. This is not entirely reliable, but ++is far more likely to produce accurate CPU usage data than the existing designs ++and will not show tasks as consuming no CPU usage when they actually are. Thus, ++the amount of CPU reported as being used by BFS will more accurately represent ++how much CPU the task itself is using (as is shown for example by the 'time' ++application), so the reported values may be quite different to other schedulers. ++Values reported as the 'load' are more prone to problems with this design, but ++per process values are closer to real usage. When comparing throughput of BFS ++to other designs, it is important to compare the actual completed work in terms ++of total wall clock time taken and total work done, rather than the reported ++"cpu usage". ++ ++ ++Con Kolivas Fri Aug 27 2010 +--- /dev/null ++++ b/Documentation/scheduler/sched-MuQSS.txt +@@ -0,0 +1,373 @@ ++MuQSS - The Multiple Queue Skiplist Scheduler by Con Kolivas. ++ ++MuQSS is a per-cpu runqueue variant of the original BFS scheduler with ++one 8 level skiplist per runqueue, and fine grained locking for much more ++scalability. ++ ++ ++Goals. ++ ++The goal of the Multiple Queue Skiplist Scheduler, referred to as MuQSS from ++here on (pronounced mux) is to completely do away with the complex designs of ++the past for the cpu process scheduler and instead implement one that is very ++simple in basic design. The main focus of MuQSS is to achieve excellent desktop ++interactivity and responsiveness without heuristics and tuning knobs that are ++difficult to understand, impossible to model and predict the effect of, and when ++tuned to one workload cause massive detriment to another, while still being ++scalable to many CPUs and processes. ++ ++ ++Design summary. ++ ++MuQSS is best described as per-cpu multiple runqueue, O(log n) insertion, O(1) ++lookup, earliest effective virtual deadline first tickless design, loosely based ++on EEVDF (earliest eligible virtual deadline first) and my previous Staircase ++Deadline scheduler, and evolved from the single runqueue O(n) BFS scheduler. ++Each component shall be described in order to understand the significance of, ++and reasoning for it. ++ ++ ++Design reasoning. ++ ++In BFS, the use of a single runqueue across all CPUs meant that each CPU would ++need to scan the entire runqueue looking for the process with the earliest ++deadline and schedule that next, regardless of which CPU it originally came ++from. This made BFS deterministic with respect to latency and provided ++guaranteed latencies dependent on number of processes and CPUs. The single ++runqueue, however, meant that all CPUs would compete for the single lock ++protecting it, which would lead to increasing lock contention as the number of ++CPUs rose and appeared to limit scalability of common workloads beyond 16 ++logical CPUs. Additionally, the O(n) lookup of the runqueue list obviously ++increased overhead proportionate to the number of queued proecesses and led to ++cache thrashing while iterating over the linked list. ++ ++MuQSS is an evolution of BFS, designed to maintain the same scheduling ++decision mechanism and be virtually deterministic without relying on the ++constrained design of the single runqueue by splitting out the single runqueue ++to be per-CPU and use skiplists instead of linked lists. ++ ++The original reason for going back to a single runqueue design for BFS was that ++once multiple runqueues are introduced, per-CPU or otherwise, there will be ++complex interactions as each runqueue will be responsible for the scheduling ++latency and fairness of the tasks only on its own runqueue, and to achieve ++fairness and low latency across multiple CPUs, any advantage in throughput of ++having CPU local tasks causes other disadvantages. This is due to requiring a ++very complex balancing system to at best achieve some semblance of fairness ++across CPUs and can only maintain relatively low latency for tasks bound to the ++same CPUs, not across them. To increase said fairness and latency across CPUs, ++the advantage of local runqueue locking, which makes for better scalability, is ++lost due to having to grab multiple locks. ++ ++MuQSS works around the problems inherent in multiple runqueue designs by ++making its skip lists priority ordered and through novel use of lockless ++examination of each other runqueue it can decide if it should take the earliest ++deadline task from another runqueue for latency reasons, or for CPU balancing ++reasons. It still does not have a balancing system, choosing to allow the ++next task scheduling decision and task wakeup CPU choice to allow balancing to ++happen by virtue of its choices. ++ ++As a further evolution of the design, MuQSS normally configures sharing of ++runqueues in a logical fashion for when CPU resources are shared for improved ++latency and throughput. By default it shares runqueues and locks between ++multicore siblings. Optionally it can be configured to run with sharing of ++SMT siblings only, all SMP packages or no sharing at all. Additionally it can ++be selected at boot time. ++ ++ ++Design details. ++ ++Custom skip list implementation: ++ ++To avoid the overhead of building up and tearing down skip list structures, ++the variant used by MuQSS has a number of optimisations making it specific for ++its use case in the scheduler. It uses static arrays of 8 'levels' instead of ++building up and tearing down structures dynamically. This makes each runqueue ++only scale O(log N) up to 64k tasks. However as there is one runqueue per CPU ++it means that it scales O(log N) up to 64k x number of logical CPUs which is ++far beyond the realistic task limits each CPU could handle. By being 8 levels ++it also makes the array exactly one cacheline in size. Additionally, each ++skip list node is bidirectional making insertion and removal amortised O(1), ++being O(k) where k is 1-8. Uniquely, we are only ever interested in the very ++first entry in each list at all times with MuQSS, so there is never a need to ++do a search and thus look up is always O(1). In interactive mode, the queues ++will be searched beyond their first entry if the first task is not suitable ++for affinity or SMT nice reasons. ++ ++Task insertion: ++ ++MuQSS inserts tasks into a per CPU runqueue as an O(log N) insertion into ++a custom skip list as described above (based on the original design by William ++Pugh). Insertion is ordered in such a way that there is never a need to do a ++search by ordering tasks according to static priority primarily, and then ++virtual deadline at the time of insertion. ++ ++Niffies: ++ ++Niffies are a monotonic forward moving timer not unlike the "jiffies" but are ++of nanosecond resolution. Niffies are calculated per-runqueue from the high ++resolution TSC timers, and in order to maintain fairness are synchronised ++between CPUs whenever both runqueues are locked concurrently. ++ ++Virtual deadline: ++ ++The key to achieving low latency, scheduling fairness, and "nice level" ++distribution in MuQSS is entirely in the virtual deadline mechanism. The one ++tunable in MuQSS is the rr_interval, or "round robin interval". This is the ++maximum time two SCHED_OTHER (or SCHED_NORMAL, the common scheduling policy) ++tasks of the same nice level will be running for, or looking at it the other ++way around, the longest duration two tasks of the same nice level will be ++delayed for. When a task requests cpu time, it is given a quota (time_slice) ++equal to the rr_interval and a virtual deadline. The virtual deadline is ++offset from the current time in niffies by this equation: ++ ++ niffies + (prio_ratio * rr_interval) ++ ++The prio_ratio is determined as a ratio compared to the baseline of nice -20 ++and increases by 10% per nice level. The deadline is a virtual one only in that ++no guarantee is placed that a task will actually be scheduled by this time, but ++it is used to compare which task should go next. There are three components to ++how a task is next chosen. First is time_slice expiration. If a task runs out ++of its time_slice, it is descheduled, the time_slice is refilled, and the ++deadline reset to that formula above. Second is sleep, where a task no longer ++is requesting CPU for whatever reason. The time_slice and deadline are _not_ ++adjusted in this case and are just carried over for when the task is next ++scheduled. Third is preemption, and that is when a newly waking task is deemed ++higher priority than a currently running task on any cpu by virtue of the fact ++that it has an earlier virtual deadline than the currently running task. The ++earlier deadline is the key to which task is next chosen for the first and ++second cases. ++ ++The CPU proportion of different nice tasks works out to be approximately the ++ ++ (prio_ratio difference)^2 ++ ++The reason it is squared is that a task's deadline does not change while it is ++running unless it runs out of time_slice. Thus, even if the time actually ++passes the deadline of another task that is queued, it will not get CPU time ++unless the current running task deschedules, and the time "base" (niffies) is ++constantly moving. ++ ++Task lookup: ++ ++As tasks are already pre-ordered according to anticipated scheduling order in ++the skip lists, lookup for the next suitable task per-runqueue is always a ++matter of simply selecting the first task in the 0th level skip list entry. ++In order to maintain optimal latency and fairness across CPUs, MuQSS does a ++novel examination of every other runqueue in cache locality order, choosing the ++best task across all runqueues. This provides near-determinism of how long any ++task across the entire system may wait before receiving CPU time. The other ++runqueues are first examine lockless and then trylocked to minimise the ++potential lock contention if they are likely to have a suitable better task. ++Each other runqueue lock is only held for as long as it takes to examine the ++entry for suitability. In "interactive" mode, the default setting, MuQSS will ++look for the best deadline task across all CPUs, while in !interactive mode, ++it will only select a better deadline task from another CPU if it is more ++heavily laden than the current one. ++ ++Lookup is therefore O(k) where k is number of CPUs. ++ ++ ++Latency. ++ ++Through the use of virtual deadlines to govern the scheduling order of normal ++tasks, queue-to-activation latency per runqueue is guaranteed to be bound by ++the rr_interval tunable which is set to 6ms by default. This means that the ++longest a CPU bound task will wait for more CPU is proportional to the number ++of running tasks and in the common case of 0-2 running tasks per CPU, will be ++under the 7ms threshold for human perception of jitter. Additionally, as newly ++woken tasks will have an early deadline from their previous runtime, the very ++tasks that are usually latency sensitive will have the shortest interval for ++activation, usually preempting any existing CPU bound tasks. ++ ++Tickless expiry: ++ ++A feature of MuQSS is that it is not tied to the resolution of the chosen tick ++rate in Hz, instead depending entirely on the high resolution timers where ++possible for sub-millisecond accuracy on timeouts regarless of the underlying ++tick rate. This allows MuQSS to be run with the low overhead of low Hz rates ++such as 100 by default, benefiting from the improved throughput and lower ++power usage it provides. Another advantage of this approach is that in ++combination with the Full No HZ option, which disables ticks on running task ++CPUs instead of just idle CPUs, the tick can be disabled at all times ++regardless of how many tasks are running instead of being limited to just one ++running task. Note that this option is NOT recommended for regular desktop ++users. ++ ++ ++Scalability and balancing. ++ ++Unlike traditional approaches where balancing is a combination of CPU selection ++at task wakeup and intermittent balancing based on a vast array of rules set ++according to architecture, busyness calculations and special case management, ++MuQSS indirectly balances on the fly at task wakeup and next task selection. ++During initialisation, MuQSS creates a cache coherency ordered list of CPUs for ++each logical CPU and uses this to aid task/CPU selection when CPUs are busy. ++Additionally it selects any idle CPUs, if they are available, at any time over ++busy CPUs according to the following preference: ++ ++ * Same thread, idle or busy cache, idle or busy threads ++ * Other core, same cache, idle or busy cache, idle threads. ++ * Same node, other CPU, idle cache, idle threads. ++ * Same node, other CPU, busy cache, idle threads. ++ * Other core, same cache, busy threads. ++ * Same node, other CPU, busy threads. ++ * Other node, other CPU, idle cache, idle threads. ++ * Other node, other CPU, busy cache, idle threads. ++ * Other node, other CPU, busy threads. ++ ++Mux is therefore SMT, MC and Numa aware without the need for extra ++intermittent balancing to maintain CPUs busy and make the most of cache ++coherency. ++ ++ ++Features ++ ++As the initial prime target audience for MuQSS was the average desktop user, it ++was designed to not need tweaking, tuning or have features set to obtain benefit ++from it. Thus the number of knobs and features has been kept to an absolute ++minimum and should not require extra user input for the vast majority of cases. ++There are 3 optional tunables, and 2 extra scheduling policies. The rr_interval, ++interactive, and iso_cpu tunables, and the SCHED_ISO and SCHED_IDLEPRIO ++policies. In addition to this, MuQSS also uses sub-tick accounting. What MuQSS ++does _not_ now feature is support for CGROUPS. The average user should neither ++need to know what these are, nor should they need to be using them to have good ++desktop behaviour. However since some applications refuse to work without ++cgroups, one can enable them with MuQSS as a stub and the filesystem will be ++created which will allow the applications to work. ++ ++rr_interval: ++ ++ /proc/sys/kernel/rr_interval ++ ++The value is in milliseconds, and the default value is set to 6. Valid values ++are from 1 to 1000 Decreasing the value will decrease latencies at the cost of ++decreasing throughput, while increasing it will improve throughput, but at the ++cost of worsening latencies. It is based on the fact that humans can detect ++jitter at approximately 7ms, so aiming for much lower latencies is pointless ++under most circumstances. It is worth noting this fact when comparing the ++latency performance of MuQSS to other schedulers. Worst case latencies being ++higher than 7ms are far worse than average latencies not being in the ++microsecond range. ++ ++interactive: ++ ++ /proc/sys/kernel/interactive ++ ++The value is a simple boolean of 1 for on and 0 for off and is set to on by ++default. Disabling this will disable the near-determinism of MuQSS when ++selecting the next task by not examining all CPUs for the earliest deadline ++task, or which CPU to wake to, instead prioritising CPU balancing for improved ++throughput. Latency will still be bound by rr_interval, but on a per-CPU basis ++instead of across the whole system. ++ ++Runqueue sharing. ++ ++By default MuQSS chooses to share runqueue resources (specifically the skip ++list and locking) between multicore siblings. It is configurable at build time ++to select between None, SMT, MC and SMP, corresponding to no sharing, sharing ++only between simultaneous mulithreading siblings, multicore siblings, or ++symmetric multiprocessing physical packages. Additionally it can be se at ++bootime with the use of the rqshare parameter. The reason for configurability ++is that some architectures have CPUs with many multicore siblings (>= 16) ++where it may be detrimental to throughput to share runqueues and another ++sharing option may be desirable. Additionally, more sharing than usual can ++improve latency on a system-wide level at the expense of throughput if desired. ++ ++The options are: ++none, smt, mc, smp ++ ++eg: ++ rqshare=mc ++ ++Isochronous scheduling: ++ ++Isochronous scheduling is a unique scheduling policy designed to provide ++near-real-time performance to unprivileged (ie non-root) users without the ++ability to starve the machine indefinitely. Isochronous tasks (which means ++"same time") are set using, for example, the schedtool application like so: ++ ++ schedtool -I -e amarok ++ ++This will start the audio application "amarok" as SCHED_ISO. How SCHED_ISO works ++is that it has a priority level between true realtime tasks and SCHED_NORMAL ++which would allow them to preempt all normal tasks, in a SCHED_RR fashion (ie, ++if multiple SCHED_ISO tasks are running, they purely round robin at rr_interval ++rate). However if ISO tasks run for more than a tunable finite amount of time, ++they are then demoted back to SCHED_NORMAL scheduling. This finite amount of ++time is the percentage of CPU available per CPU, configurable as a percentage in ++the following "resource handling" tunable (as opposed to a scheduler tunable): ++ ++iso_cpu: ++ ++ /proc/sys/kernel/iso_cpu ++ ++and is set to 70% by default. It is calculated over a rolling 5 second average ++Because it is the total CPU available, it means that on a multi CPU machine, it ++is possible to have an ISO task running as realtime scheduling indefinitely on ++just one CPU, as the other CPUs will be available. Setting this to 100 is the ++equivalent of giving all users SCHED_RR access and setting it to 0 removes the ++ability to run any pseudo-realtime tasks. ++ ++A feature of MuQSS is that it detects when an application tries to obtain a ++realtime policy (SCHED_RR or SCHED_FIFO) and the caller does not have the ++appropriate privileges to use those policies. When it detects this, it will ++give the task SCHED_ISO policy instead. Thus it is transparent to the user. ++ ++ ++Idleprio scheduling: ++ ++Idleprio scheduling is a scheduling policy designed to give out CPU to a task ++_only_ when the CPU would be otherwise idle. The idea behind this is to allow ++ultra low priority tasks to be run in the background that have virtually no ++effect on the foreground tasks. This is ideally suited to distributed computing ++clients (like setiathome, folding, mprime etc) but can also be used to start a ++video encode or so on without any slowdown of other tasks. To avoid this policy ++from grabbing shared resources and holding them indefinitely, if it detects a ++state where the task is waiting on I/O, the machine is about to suspend to ram ++and so on, it will transiently schedule them as SCHED_NORMAL. Once a task has ++been scheduled as IDLEPRIO, it cannot be put back to SCHED_NORMAL without ++superuser privileges since it is effectively a lower scheduling policy. Tasks ++can be set to start as SCHED_IDLEPRIO with the schedtool command like so: ++ ++schedtool -D -e ./mprime ++ ++Subtick accounting: ++ ++It is surprisingly difficult to get accurate CPU accounting, and in many cases, ++the accounting is done by simply determining what is happening at the precise ++moment a timer tick fires off. This becomes increasingly inaccurate as the timer ++tick frequency (HZ) is lowered. It is possible to create an application which ++uses almost 100% CPU, yet by being descheduled at the right time, records zero ++CPU usage. While the main problem with this is that there are possible security ++implications, it is also difficult to determine how much CPU a task really does ++use. Mux uses sub-tick accounting from the TSC clock to determine real CPU ++usage. Thus, the amount of CPU reported as being used by MuQSS will more ++accurately represent how much CPU the task itself is using (as is shown for ++example by the 'time' application), so the reported values may be quite ++different to other schedulers. When comparing throughput of MuQSS to other ++designs, it is important to compare the actual completed work in terms of total ++wall clock time taken and total work done, rather than the reported "cpu usage". ++ ++Symmetric MultiThreading (SMT) aware nice: ++ ++SMT, a.k.a. hyperthreading, is a very common feature on modern CPUs. While the ++logical CPU count rises by adding thread units to each CPU core, allowing more ++than one task to be run simultaneously on the same core, the disadvantage of it ++is that the CPU power is shared between the tasks, not summating to the power ++of two CPUs. The practical upshot of this is that two tasks running on ++separate threads of the same core run significantly slower than if they had one ++core each to run on. While smart CPU selection allows each task to have a core ++to itself whenever available (as is done on MuQSS), it cannot offset the ++slowdown that occurs when the cores are all loaded and only a thread is left. ++Most of the time this is harmless as the CPU is effectively overloaded at this ++point and the extra thread is of benefit. However when running a niced task in ++the presence of an un-niced task (say nice 19 v nice 0), the nice task gets ++precisely the same amount of CPU power as the unniced one. MuQSS has an ++optional configuration feature known as SMT-NICE which selectively idles the ++secondary niced thread for a period proportional to the nice difference, ++allowing CPU distribution according to nice level to be maintained, at the ++expense of a small amount of extra overhead. If this is configured in on a ++machine without SMT threads, the overhead is minimal. ++ ++ ++Con Kolivas Sat, 29th October 2016 +--- a/arch/alpha/Kconfig ++++ b/arch/alpha/Kconfig +@@ -665,6 +665,8 @@ config HZ + default 1200 if HZ_1200 + default 1024 + ++source "kernel/Kconfig.MuQSS" ++ + config SRM_ENV + tristate "SRM environment through procfs" + depends on PROC_FS +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -1242,6 +1242,8 @@ config SCHED_SMT + MultiThreading at a cost of slightly increased overhead in some + places. If unsure say N here. + ++source "kernel/Kconfig.MuQSS" ++ + config HAVE_ARM_SCU + bool + help +--- a/arch/arm64/Kconfig ++++ b/arch/arm64/Kconfig +@@ -881,6 +881,8 @@ config SCHED_SMT + MultiThreading at a cost of slightly increased overhead in some + places. If unsure say N here. + ++source "kernel/Kconfig.MuQSS" ++ + config NR_CPUS + int "Maximum number of CPUs (2-4096)" + range 2 4096 +--- a/arch/powerpc/Kconfig ++++ b/arch/powerpc/Kconfig +@@ -855,6 +855,8 @@ config SCHED_SMT + when dealing with POWER5 cpus at a cost of slightly increased + overhead in some places. If unsure say N here. + ++source "kernel/Kconfig.MuQSS" ++ + config PPC_DENORMALISATION + bool "PowerPC denormalisation exception handling" + depends on PPC_BOOK3S_64 +--- a/arch/powerpc/platforms/cell/spufs/sched.c ++++ b/arch/powerpc/platforms/cell/spufs/sched.c +@@ -52,11 +52,6 @@ static struct timer_list spusched_timer; + static struct timer_list spuloadavg_timer; + + /* +- * Priority of a normal, non-rt, non-niced'd process (aka nice level 0). +- */ +-#define NORMAL_PRIO 120 +- +-/* + * Frequency of the spu scheduler tick. By default we do one SPU scheduler + * tick for every 10 CPU scheduler ticks. + */ +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -1035,6 +1035,22 @@ config NR_CPUS + config SCHED_SMT + def_bool y if SMP + ++config SMT_NICE ++ bool "SMT (Hyperthreading) aware nice priority and policy support" ++ depends on SCHED_MUQSS && SCHED_SMT ++ default y ++ ---help--- ++ Enabling Hyperthreading on Intel CPUs decreases the effectiveness ++ of the use of 'nice' levels and different scheduling policies ++ (e.g. realtime) due to sharing of CPU power between hyperthreads. ++ SMT nice support makes each logical CPU aware of what is running on ++ its hyperthread siblings, maintaining appropriate distribution of ++ CPU according to nice levels and scheduling policies at the expense ++ of slightly increased overhead. ++ ++ If unsure say Y here. ++ ++ + config SCHED_MC + def_bool y + prompt "Multi-core scheduler support" +@@ -1065,6 +1081,8 @@ config SCHED_MC_PRIO + + If unsure say Y here. + ++source "kernel/Kconfig.MuQSS" ++ + config UP_LATE_INIT + def_bool y + depends on !SMP && X86_LOCAL_APIC +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -477,7 +477,7 @@ static int proc_pid_schedstat(struct seq + seq_puts(m, "0 0 0\n"); + else + seq_printf(m, "%llu %llu %lu\n", +- (unsigned long long)task->se.sum_exec_runtime, ++ (unsigned long long)tsk_seruntime(task), + (unsigned long long)task->sched_info.run_delay, + task->sched_info.pcount); + +--- a/include/linux/init_task.h ++++ b/include/linux/init_task.h +@@ -36,7 +36,11 @@ extern struct cred init_cred; + #define INIT_PREV_CPUTIME(x) + #endif + ++#ifdef CONFIG_SCHED_MUQSS ++#define INIT_TASK_COMM "MuQSS" ++#else + #define INIT_TASK_COMM "swapper" ++#endif + + /* Attach to the init_task data structure for proper alignment */ + #ifdef CONFIG_ARCH_TASK_STRUCT_ON_STACK +--- a/include/linux/ioprio.h ++++ b/include/linux/ioprio.h +@@ -53,6 +53,8 @@ enum { + */ + static inline int task_nice_ioprio(struct task_struct *task) + { ++ if (iso_task(task)) ++ return 0; + return (task_nice(task) + 20) / 5; + } + +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -31,6 +31,9 @@ + #include + #include + #include ++#ifdef CONFIG_SCHED_MUQSS ++#include ++#endif + + /* task_struct member predeclarations (sorted alphabetically): */ + struct audit_context; +@@ -644,9 +647,11 @@ struct task_struct { + unsigned int flags; + unsigned int ptrace; + ++#if defined(CONFIG_SMP) || defined(CONFIG_SCHED_MUQSS) ++ int on_cpu; ++#endif + #ifdef CONFIG_SMP + struct llist_node wake_entry; +- int on_cpu; + #ifdef CONFIG_THREAD_INFO_IN_TASK + /* Current CPU: */ + unsigned int cpu; +@@ -671,10 +676,25 @@ struct task_struct { + int static_prio; + int normal_prio; + unsigned int rt_priority; ++#ifdef CONFIG_SCHED_MUQSS ++ int time_slice; ++ u64 deadline; ++ skiplist_node node; /* Skip list node */ ++ u64 last_ran; ++ u64 sched_time; /* sched_clock time spent running */ ++#ifdef CONFIG_SMT_NICE ++ int smt_bias; /* Policy/nice level bias across smt siblings */ ++#endif ++#ifdef CONFIG_HOTPLUG_CPU ++ bool zerobound; /* Bound to CPU0 for hotplug */ ++#endif ++ unsigned long rt_timeout; ++#else /* CONFIG_SCHED_MUQSS */ + + const struct sched_class *sched_class; + struct sched_entity se; + struct sched_rt_entity rt; ++#endif + #ifdef CONFIG_CGROUP_SCHED + struct task_group *sched_task_group; + #endif +@@ -840,6 +860,10 @@ struct task_struct { + u64 utimescaled; + u64 stimescaled; + #endif ++#ifdef CONFIG_SCHED_MUQSS ++ /* Unbanked cpu time */ ++ unsigned long utime_ns, stime_ns; ++#endif + u64 gtime; + struct prev_cputime prev_cputime; + #ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN +@@ -1285,6 +1309,40 @@ struct task_struct { + */ + }; + ++#ifdef CONFIG_SCHED_MUQSS ++#define tsk_seruntime(t) ((t)->sched_time) ++#define tsk_rttimeout(t) ((t)->rt_timeout) ++ ++static inline void tsk_cpus_current(struct task_struct *p) ++{ ++} ++ ++void print_scheduler_version(void); ++ ++static inline bool iso_task(struct task_struct *p) ++{ ++ return (p->policy == SCHED_ISO); ++} ++#else /* CFS */ ++#define tsk_seruntime(t) ((t)->se.sum_exec_runtime) ++#define tsk_rttimeout(t) ((t)->rt.timeout) ++ ++static inline void tsk_cpus_current(struct task_struct *p) ++{ ++ p->nr_cpus_allowed = current->nr_cpus_allowed; ++} ++ ++static inline void print_scheduler_version(void) ++{ ++ printk(KERN_INFO "CFS CPU scheduler.\n"); ++} ++ ++static inline bool iso_task(struct task_struct *p) ++{ ++ return false; ++} ++#endif /* CONFIG_SCHED_MUQSS */ ++ + static inline struct pid *task_pid(struct task_struct *task) + { + return task->thread_pid; +--- a/include/linux/sched/deadline.h ++++ b/include/linux/sched/deadline.h +@@ -28,7 +28,16 @@ static inline bool dl_time_before(u64 a, + #ifdef CONFIG_SMP + + struct root_domain; ++#ifdef CONFIG_SCHED_MUQSS ++static inline void dl_clear_root_domain(struct root_domain *rd) ++{ ++} ++static inline void dl_add_task_root_domain(struct task_struct *p) ++{ ++} ++#else /* CONFIG_SCHED_MUQSS */ + extern void dl_add_task_root_domain(struct task_struct *p); + extern void dl_clear_root_domain(struct root_domain *rd); ++#endif /* CONFIG_SCHED_MUQSS */ + + #endif /* CONFIG_SMP */ +--- a/include/linux/sched/nohz.h ++++ b/include/linux/sched/nohz.h +@@ -13,7 +13,7 @@ extern int get_nohz_timer_target(void); + static inline void nohz_balance_enter_idle(int cpu) { } + #endif + +-#ifdef CONFIG_NO_HZ_COMMON ++#if defined(CONFIG_NO_HZ_COMMON) && !defined(CONFIG_SCHED_MUQSS) + void calc_load_nohz_start(void); + void calc_load_nohz_remote(struct rq *rq); + void calc_load_nohz_stop(void); +--- a/include/linux/sched/prio.h ++++ b/include/linux/sched/prio.h +@@ -20,8 +20,20 @@ + */ + + #define MAX_USER_RT_PRIO 100 ++ ++#ifdef CONFIG_SCHED_MUQSS ++/* Note different MAX_RT_PRIO */ ++#define MAX_RT_PRIO (MAX_USER_RT_PRIO + 1) ++ ++#define ISO_PRIO (MAX_RT_PRIO) ++#define NORMAL_PRIO (MAX_RT_PRIO + 1) ++#define IDLE_PRIO (MAX_RT_PRIO + 2) ++#define PRIO_LIMIT ((IDLE_PRIO) + 1) ++#else /* CONFIG_SCHED_MUQSS */ + #define MAX_RT_PRIO MAX_USER_RT_PRIO + ++#endif /* CONFIG_SCHED_MUQSS */ ++ + #define MAX_PRIO (MAX_RT_PRIO + NICE_WIDTH) + #define DEFAULT_PRIO (MAX_RT_PRIO + NICE_WIDTH / 2) + +--- a/include/linux/sched/rt.h ++++ b/include/linux/sched/rt.h +@@ -24,8 +24,10 @@ static inline bool task_is_realtime(stru + + if (policy == SCHED_FIFO || policy == SCHED_RR) + return true; ++#ifndef CONFIG_SCHED_MUQSS + if (policy == SCHED_DEADLINE) + return true; ++#endif + return false; + } + +--- a/include/linux/sched/task.h ++++ b/include/linux/sched/task.h +@@ -99,7 +99,7 @@ extern long kernel_wait4(pid_t, int __us + extern void free_task(struct task_struct *tsk); + + /* sched_exec is called by processes performing an exec */ +-#ifdef CONFIG_SMP ++#if defined(CONFIG_SMP) && !defined(CONFIG_SCHED_MUQSS) + extern void sched_exec(void); + #else + #define sched_exec() {} +--- /dev/null ++++ b/include/linux/skip_list.h +@@ -0,0 +1,33 @@ ++#ifndef _LINUX_SKIP_LISTS_H ++#define _LINUX_SKIP_LISTS_H ++typedef u64 keyType; ++typedef void *valueType; ++ ++typedef struct nodeStructure skiplist_node; ++ ++struct nodeStructure { ++ int level; /* Levels in this structure */ ++ keyType key; ++ valueType value; ++ skiplist_node *next[8]; ++ skiplist_node *prev[8]; ++}; ++ ++typedef struct listStructure { ++ int entries; ++ int level; /* Maximum level of the list ++ (1 more than the number of levels in the list) */ ++ skiplist_node *header; /* pointer to header */ ++} skiplist; ++ ++void skiplist_init(skiplist_node *slnode); ++skiplist *new_skiplist(skiplist_node *slnode); ++void free_skiplist(skiplist *l); ++void skiplist_node_init(skiplist_node *node); ++void skiplist_insert(skiplist *l, skiplist_node *node, keyType key, valueType value, unsigned int randseed); ++void skiplist_delete(skiplist *l, skiplist_node *node); ++ ++static inline bool skiplist_node_empty(skiplist_node *node) { ++ return (!node->next[0]); ++} ++#endif /* _LINUX_SKIP_LISTS_H */ +--- a/include/uapi/linux/sched.h ++++ b/include/uapi/linux/sched.h +@@ -84,9 +84,16 @@ struct clone_args { + #define SCHED_FIFO 1 + #define SCHED_RR 2 + #define SCHED_BATCH 3 +-/* SCHED_ISO: reserved but not implemented yet */ ++/* SCHED_ISO: Implemented on MuQSS only */ + #define SCHED_IDLE 5 ++#ifdef CONFIG_SCHED_MUQSS ++#define SCHED_ISO 4 ++#define SCHED_IDLEPRIO SCHED_IDLE ++#define SCHED_MAX (SCHED_IDLEPRIO) ++#define SCHED_RANGE(policy) ((policy) <= SCHED_MAX) ++#else /* CONFIG_SCHED_MUQSS */ + #define SCHED_DEADLINE 6 ++#endif /* CONFIG_SCHED_MUQSS */ + + /* Can be ORed in to make sure the process is reverted back to SCHED_NORMAL on fork */ + #define SCHED_RESET_ON_FORK 0x40000000 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -61,6 +61,18 @@ config THREAD_INFO_IN_TASK + + menu "General setup" + ++config SCHED_MUQSS ++ bool "MuQSS cpu scheduler" ++ select HIGH_RES_TIMERS ++ ---help--- ++ The Multiple Queue Skiplist Scheduler for excellent interactivity and ++ responsiveness on the desktop and highly scalable deterministic ++ low latency on any hardware. ++ ++ Say Y here. ++ default y ++ ++ + config BROKEN + bool + +@@ -770,6 +782,7 @@ config NUMA_BALANCING + depends on ARCH_SUPPORTS_NUMA_BALANCING + depends on !ARCH_WANT_NUMA_VARIABLE_LOCALITY + depends on SMP && NUMA && MIGRATION ++ depends on !SCHED_MUQSS + help + This option adds support for automatic NUMA aware memory/task placement. + The mechanism is quite primitive and is based on migrating memory when +@@ -869,9 +882,13 @@ menuconfig CGROUP_SCHED + help + This feature lets CPU scheduler recognize task groups and control CPU + bandwidth allocation to such task groups. It uses cgroups to group +- tasks. ++ tasks. In combination with MuQSS this is purely a STUB to create the ++ files associated with the CPU controller cgroup but most of the ++ controls do nothing. This is useful for working in environments and ++ with applications that will only work if this control group is ++ present. + +-if CGROUP_SCHED ++if CGROUP_SCHED && !SCHED_MUQSS + config FAIR_GROUP_SCHED + bool "Group scheduling for SCHED_OTHER" + depends on CGROUP_SCHED +@@ -1000,6 +1017,7 @@ config CGROUP_DEVICE + + config CGROUP_CPUACCT + bool "Simple CPU accounting controller" ++ depends on !SCHED_MUQSS + help + Provides a simple controller for monitoring the + total CPU consumed by the tasks in a cgroup. +@@ -1118,6 +1136,7 @@ config CHECKPOINT_RESTORE + + config SCHED_AUTOGROUP + bool "Automatic process group scheduling" ++ depends on !SCHED_MUQSS + select CGROUPS + select CGROUP_SCHED + select FAIR_GROUP_SCHED +--- a/init/init_task.c ++++ b/init/init_task.c +@@ -67,9 +67,17 @@ struct task_struct init_task + .stack = init_stack, + .usage = REFCOUNT_INIT(2), + .flags = PF_KTHREAD, ++#ifdef CONFIG_SCHED_MUQSS ++ .prio = NORMAL_PRIO, ++ .static_prio = MAX_PRIO - 20, ++ .normal_prio = NORMAL_PRIO, ++ .deadline = 0, ++ .time_slice = 1000000, ++#else + .prio = MAX_PRIO - 20, + .static_prio = MAX_PRIO - 20, + .normal_prio = MAX_PRIO - 20, ++#endif + .policy = SCHED_NORMAL, + .cpus_ptr = &init_task.cpus_mask, + .cpus_mask = CPU_MASK_ALL, +@@ -79,6 +87,7 @@ struct task_struct init_task + .restart_block = { + .fn = do_no_restart_syscall, + }, ++#ifndef CONFIG_SCHED_MUQSS + .se = { + .group_node = LIST_HEAD_INIT(init_task.se.group_node), + }, +@@ -86,6 +95,7 @@ struct task_struct init_task + .run_list = LIST_HEAD_INIT(init_task.rt.run_list), + .time_slice = RR_TIMESLICE, + }, ++#endif + .tasks = LIST_HEAD_INIT(init_task.tasks), + #ifdef CONFIG_SMP + .pushable_tasks = PLIST_NODE_INIT(init_task.pushable_tasks, MAX_PRIO), +--- a/init/main.c ++++ b/init/main.c +@@ -1152,6 +1152,8 @@ static int __ref kernel_init(void *unuse + + rcu_end_inkernel_boot(); + ++ print_scheduler_version(); ++ + if (ramdisk_execute_command) { + ret = run_init_process(ramdisk_execute_command); + if (!ret) +--- /dev/null ++++ b/kernel/Kconfig.MuQSS +@@ -0,0 +1,105 @@ ++choice ++ prompt "CPU scheduler runqueue sharing" ++ default RQ_MC if SCHED_MUQSS ++ default RQ_NONE ++ ++config RQ_NONE ++ bool "No sharing" ++ help ++ This is the default behaviour where the CPU scheduler has one runqueue ++ per CPU, whether it is a physical or logical CPU (hyperthread). ++ ++ This can still be enabled runtime with the boot parameter ++ rqshare=none ++ ++ If unsure, say N. ++ ++config RQ_SMT ++ bool "SMT (hyperthread) siblings" ++ depends on SCHED_SMT && SCHED_MUQSS ++ ++ help ++ With this option enabled, the CPU scheduler will have one runqueue ++ shared by SMT (hyperthread) siblings. As these logical cores share ++ one physical core, sharing the runqueue resource can lead to decreased ++ overhead, lower latency and higher throughput. ++ ++ This can still be enabled runtime with the boot parameter ++ rqshare=smt ++ ++ If unsure, say N. ++ ++config RQ_MC ++ bool "Multicore siblings" ++ depends on SCHED_MC && SCHED_MUQSS ++ help ++ With this option enabled, the CPU scheduler will have one runqueue ++ shared by multicore siblings in addition to any SMT siblings. ++ As these physical cores share caches, sharing the runqueue resource ++ will lead to lower latency, but its effects on overhead and throughput ++ are less predictable. As a general rule, 6 or fewer cores will likely ++ benefit from this, while larger CPUs will only derive a latency ++ benefit. If your workloads are primarily single threaded, this will ++ possibly worsen throughput. If you are only concerned about latency ++ then enable this regardless of how many cores you have. ++ ++ This can still be enabled runtime with the boot parameter ++ rqshare=mc ++ ++ If unsure, say Y. ++ ++config RQ_MC_LLC ++ bool "Multicore siblings (LLC)" ++ depends on SCHED_MC && SCHED_MUQSS ++ help ++ With this option enabled, the CPU scheduler will behave similarly as ++ with "Multicore siblings". ++ This option takes LLC cache into account when scheduling tasks. ++ Option may benefit CPUs with multiple LLC caches, such as Ryzen ++ and Xeon CPUs. ++ ++ This can still be enabled runtime with the boot parameter ++ rqshare=llc ++ ++ If unsure, say N. ++ ++config RQ_SMP ++ bool "Symmetric Multi-Processing" ++ depends on SMP && SCHED_MUQSS ++ help ++ With this option enabled, the CPU scheduler will have one runqueue ++ shared by all physical CPUs unless they are on separate NUMA nodes. ++ As physical CPUs usually do not share resources, sharing the runqueue ++ will normally worsen throughput but improve latency. If you only ++ care about latency enable this. ++ ++ This can still be enabled runtime with the boot parameter ++ rqshare=smp ++ ++ If unsure, say N. ++ ++config RQ_ALL ++ bool "NUMA" ++ depends on SMP && SCHED_MUQSS ++ help ++ With this option enabled, the CPU scheduler will have one runqueue ++ regardless of the architecture configuration, including across NUMA ++ nodes. This can substantially decrease throughput in NUMA ++ configurations, but light NUMA designs will not be dramatically ++ affected. This option should only be chosen if latency is the prime ++ concern. ++ ++ This can still be enabled runtime with the boot parameter ++ rqshare=all ++ ++ If unsure, say N. ++endchoice ++ ++config SHARERQ ++ int ++ default 0 if RQ_NONE ++ default 1 if RQ_SMT ++ default 2 if RQ_MC ++ default 3 if RQ_MC_LLC ++ default 4 if RQ_SMP ++ default 5 if RQ_ALL +--- a/kernel/Makefile ++++ b/kernel/Makefile +@@ -10,7 +10,7 @@ obj-y = fork.o exec_domain.o panic.o + extable.o params.o \ + kthread.o sys_ni.o nsproxy.o \ + notifier.o ksysfs.o cred.o reboot.o \ +- async.o range.o smpboot.o ucount.o ++ async.o range.o smpboot.o ucount.o skip_list.o + + obj-$(CONFIG_MODULES) += kmod.o + obj-$(CONFIG_MULTIUSER) += groups.o +--- a/kernel/delayacct.c ++++ b/kernel/delayacct.c +@@ -106,7 +106,7 @@ int __delayacct_add_tsk(struct taskstats + */ + t1 = tsk->sched_info.pcount; + t2 = tsk->sched_info.run_delay; +- t3 = tsk->se.sum_exec_runtime; ++ t3 = tsk_seruntime(tsk); + + d->cpu_count += t1; + +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -131,7 +131,7 @@ static void __exit_signal(struct task_st + sig->curr_target = next_thread(tsk); + } + +- add_device_randomness((const void*) &tsk->se.sum_exec_runtime, ++ add_device_randomness((const void*) &tsk_seruntime(tsk), + sizeof(unsigned long long)); + + /* +@@ -152,7 +152,7 @@ static void __exit_signal(struct task_st + sig->inblock += task_io_get_inblock(tsk); + sig->oublock += task_io_get_oublock(tsk); + task_io_accounting_add(&sig->ioac, &tsk->ioac); +- sig->sum_sched_runtime += tsk->se.sum_exec_runtime; ++ sig->sum_sched_runtime += tsk_seruntime(tsk); + sig->nr_threads--; + __unhash_process(tsk, group_dead); + write_sequnlock(&sig->stats_lock); +--- a/kernel/kthread.c ++++ b/kernel/kthread.c +@@ -466,6 +466,34 @@ void kthread_bind(struct task_struct *p, + } + EXPORT_SYMBOL(kthread_bind); + ++#if defined(CONFIG_SCHED_MUQSS) && defined(CONFIG_SMP) ++extern void __do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask); ++ ++/* ++ * new_kthread_bind is a special variant of __kthread_bind_mask. ++ * For new threads to work on muqss we want to call do_set_cpus_allowed ++ * without the task_cpu being set and the task rescheduled until they're ++ * rescheduled on their own so we call __do_set_cpus_allowed directly which ++ * only changes the cpumask. This is particularly important for smpboot threads ++ * to work. ++ */ ++static void new_kthread_bind(struct task_struct *p, unsigned int cpu) ++{ ++ unsigned long flags; ++ ++ if (WARN_ON(!wait_task_inactive(p, TASK_UNINTERRUPTIBLE))) ++ return; ++ ++ /* It's safe because the task is inactive. */ ++ raw_spin_lock_irqsave(&p->pi_lock, flags); ++ __do_set_cpus_allowed(p, cpumask_of(cpu)); ++ p->flags |= PF_NO_SETAFFINITY; ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++} ++#else ++#define new_kthread_bind(p, cpu) kthread_bind(p, cpu) ++#endif ++ + /** + * kthread_create_on_cpu - Create a cpu bound kthread + * @threadfn: the function to run until signal_pending(current). +@@ -487,7 +515,7 @@ struct task_struct *kthread_create_on_cp + cpu); + if (IS_ERR(p)) + return p; +- kthread_bind(p, cpu); ++ new_kthread_bind(p, cpu); + /* CPU hotplug need to bind once again when unparking the thread. */ + to_kthread(p)->cpu = cpu; + return p; +--- a/kernel/livepatch/transition.c ++++ b/kernel/livepatch/transition.c +@@ -282,7 +282,7 @@ static bool klp_try_switch_task(struct t + { + static char err_buf[STACK_ERR_BUF_SIZE]; + struct rq *rq; +- struct rq_flags flags; ++ struct rq_flags rf; + int ret; + bool success = false; + +@@ -304,7 +304,7 @@ static bool klp_try_switch_task(struct t + * functions. If all goes well, switch the task to the target patch + * state. + */ +- rq = task_rq_lock(task, &flags); ++ rq = task_rq_lock(task, &rf); + + if (task_running(rq, task) && task != current) { + snprintf(err_buf, STACK_ERR_BUF_SIZE, +@@ -323,7 +323,7 @@ static bool klp_try_switch_task(struct t + task->patch_state = klp_target_state; + + done: +- task_rq_unlock(rq, task, &flags); ++ task_rq_unlock(rq, task, &rf); + + /* + * Due to console deadlock issues, pr_debug() can't be used while +--- a/kernel/sched/Makefile ++++ b/kernel/sched/Makefile +@@ -16,15 +16,23 @@ ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER + CFLAGS_core.o := $(PROFILING) -fno-omit-frame-pointer + endif + ++ifdef CONFIG_SCHED_MUQSS ++obj-y += MuQSS.o clock.o cputime.o ++obj-y += idle.o ++obj-y += wait.o wait_bit.o swait.o completion.o ++ ++obj-$(CONFIG_SMP) += topology.o ++else + obj-y += core.o loadavg.o clock.o cputime.o + obj-y += idle.o fair.o rt.o deadline.o + obj-y += wait.o wait_bit.o swait.o completion.o + + obj-$(CONFIG_SMP) += cpupri.o cpudeadline.o topology.o stop_task.o pelt.o + obj-$(CONFIG_SCHED_AUTOGROUP) += autogroup.o +-obj-$(CONFIG_SCHEDSTATS) += stats.o + obj-$(CONFIG_SCHED_DEBUG) += debug.o + obj-$(CONFIG_CGROUP_CPUACCT) += cpuacct.o ++endif ++obj-$(CONFIG_SCHEDSTATS) += stats.o + obj-$(CONFIG_CPU_FREQ) += cpufreq.o + obj-$(CONFIG_CPU_FREQ_GOV_SCHEDUTIL) += cpufreq_schedutil.o + obj-$(CONFIG_MEMBARRIER) += membarrier.o +--- /dev/null ++++ b/kernel/sched/MuQSS.c +@@ -0,0 +1,7594 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * kernel/sched/MuQSS.c, was kernel/sched.c ++ * ++ * Kernel scheduler and related syscalls ++ * ++ * Copyright (C) 1991-2002 Linus Torvalds ++ * ++ * 1996-12-23 Modified by Dave Grothe to fix bugs in semaphores and ++ * make semaphores SMP safe ++ * 1998-11-19 Implemented schedule_timeout() and related stuff ++ * by Andrea Arcangeli ++ * 2002-01-04 New ultra-scalable O(1) scheduler by Ingo Molnar: ++ * hybrid priority-list and round-robin design with ++ * an array-switch method of distributing timeslices ++ * and per-CPU runqueues. Cleanups and useful suggestions ++ * by Davide Libenzi, preemptible kernel bits by Robert Love. ++ * 2003-09-03 Interactivity tuning by Con Kolivas. ++ * 2004-04-02 Scheduler domains code by Nick Piggin ++ * 2007-04-15 Work begun on replacing all interactivity tuning with a ++ * fair scheduling design by Con Kolivas. ++ * 2007-05-05 Load balancing (smp-nice) and other improvements ++ * by Peter Williams ++ * 2007-05-06 Interactivity improvements to CFS by Mike Galbraith ++ * 2007-07-01 Group scheduling enhancements by Srivatsa Vaddagiri ++ * 2007-11-29 RT balancing improvements by Steven Rostedt, Gregory Haskins, ++ * Thomas Gleixner, Mike Kravetz ++ * 2009-08-13 Brainfuck deadline scheduling policy by Con Kolivas deletes ++ * a whole lot of those previous things. ++ * 2016-10-01 Multiple Queue Skiplist Scheduler scalable evolution of BFS ++ * scheduler by Con Kolivas. ++ * 2019-08-31 LLC bits by Eduards Bezverhijs ++ */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include "../workqueue_internal.h" ++#include "../smpboot.h" ++ ++#define CREATE_TRACE_POINTS ++#include ++ ++#include "MuQSS.h" ++ ++#define rt_prio(prio) unlikely((prio) < MAX_RT_PRIO) ++#define rt_task(p) rt_prio((p)->prio) ++#define batch_task(p) (unlikely((p)->policy == SCHED_BATCH)) ++#define is_rt_policy(policy) ((policy) == SCHED_FIFO || \ ++ (policy) == SCHED_RR) ++#define has_rt_policy(p) unlikely(is_rt_policy((p)->policy)) ++ ++#define is_idle_policy(policy) ((policy) == SCHED_IDLEPRIO) ++#define idleprio_task(p) unlikely(is_idle_policy((p)->policy)) ++#define task_running_idle(p) unlikely((p)->prio == IDLE_PRIO) ++ ++#define is_iso_policy(policy) ((policy) == SCHED_ISO) ++#define iso_task(p) unlikely(is_iso_policy((p)->policy)) ++#define task_running_iso(p) unlikely((p)->prio == ISO_PRIO) ++ ++#define rq_idle(rq) ((rq)->rq_prio == PRIO_LIMIT) ++ ++#define ISO_PERIOD (5 * HZ) ++ ++#define STOP_PRIO (MAX_RT_PRIO - 1) ++ ++/* ++ * Some helpers for converting to/from various scales. Use shifts to get ++ * approximate multiples of ten for less overhead. ++ */ ++#define APPROX_NS_PS (1073741824) /* Approximate ns per second */ ++#define JIFFIES_TO_NS(TIME) ((TIME) * (APPROX_NS_PS / HZ)) ++#define JIFFY_NS (APPROX_NS_PS / HZ) ++#define JIFFY_US (1048576 / HZ) ++#define NS_TO_JIFFIES(TIME) ((TIME) / JIFFY_NS) ++#define HALF_JIFFY_NS (APPROX_NS_PS / HZ / 2) ++#define HALF_JIFFY_US (1048576 / HZ / 2) ++#define MS_TO_NS(TIME) ((TIME) << 20) ++#define MS_TO_US(TIME) ((TIME) << 10) ++#define NS_TO_MS(TIME) ((TIME) >> 20) ++#define NS_TO_US(TIME) ((TIME) >> 10) ++#define US_TO_NS(TIME) ((TIME) << 10) ++#define TICK_APPROX_NS ((APPROX_NS_PS+HZ/2)/HZ) ++ ++#define RESCHED_US (100) /* Reschedule if less than this many μs left */ ++ ++void print_scheduler_version(void) ++{ ++ printk(KERN_INFO "MuQSS CPU scheduler v0.200 by Con Kolivas.\n"); ++} ++ ++/* Define RQ share levels */ ++#define RQSHARE_NONE 0 ++#define RQSHARE_SMT 1 ++#define RQSHARE_MC 2 ++#define RQSHARE_MC_LLC 3 ++#define RQSHARE_SMP 4 ++#define RQSHARE_ALL 5 ++ ++/* Define locality levels */ ++#define LOCALITY_SAME 0 ++#define LOCALITY_SMT 1 ++#define LOCALITY_MC_LLC 2 ++#define LOCALITY_MC 3 ++#define LOCALITY_SMP 4 ++#define LOCALITY_DISTANT 5 ++ ++/* ++ * This determines what level of runqueue sharing will be done and is ++ * configurable at boot time with the bootparam rqshare = ++ */ ++static int rqshare __read_mostly = CONFIG_SHARERQ; /* Default RQSHARE_MC */ ++ ++static int __init set_rqshare(char *str) ++{ ++ if (!strncmp(str, "none", 4)) { ++ rqshare = RQSHARE_NONE; ++ return 0; ++ } ++ if (!strncmp(str, "smt", 3)) { ++ rqshare = RQSHARE_SMT; ++ return 0; ++ } ++ if (!strncmp(str, "mc", 2)) { ++ rqshare = RQSHARE_MC; ++ return 0; ++ } ++ if (!strncmp(str, "llc", 3)) { ++ rqshare = RQSHARE_MC_LLC; ++ return 0; ++ } ++ if (!strncmp(str, "smp", 3)) { ++ rqshare = RQSHARE_SMP; ++ return 0; ++ } ++ if (!strncmp(str, "all", 3)) { ++ rqshare = RQSHARE_ALL; ++ return 0; ++ } ++ return 1; ++} ++__setup("rqshare=", set_rqshare); ++ ++/* ++ * This is the time all tasks within the same priority round robin. ++ * Value is in ms and set to a minimum of 6ms. ++ * Tunable via /proc interface. ++ */ ++int rr_interval __read_mostly = 6; ++ ++/* ++ * Tunable to choose whether to prioritise latency or throughput, simple ++ * binary yes or no ++ */ ++int sched_interactive __read_mostly = 1; ++ ++/* ++ * sched_iso_cpu - sysctl which determines the cpu percentage SCHED_ISO tasks ++ * are allowed to run five seconds as real time tasks. This is the total over ++ * all online cpus. ++ */ ++int sched_iso_cpu __read_mostly = 70; ++ ++/* ++ * sched_yield_type - Choose what sort of yield sched_yield will perform. ++ * 0: No yield. ++ * 1: Yield only to better priority/deadline tasks. (default) ++ * 2: Expire timeslice and recalculate deadline. ++ */ ++int sched_yield_type __read_mostly = 1; ++ ++/* ++ * The relative length of deadline for each priority(nice) level. ++ */ ++static int prio_ratios[NICE_WIDTH] __read_mostly; ++ ++ ++/* ++ * The quota handed out to tasks of all priority levels when refilling their ++ * time_slice. ++ */ ++static inline int timeslice(void) ++{ ++ return MS_TO_US(rr_interval); ++} ++ ++DEFINE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues); ++ ++#ifdef CONFIG_SMP ++/* ++ * Total number of runqueues. Equals number of CPUs when there is no runqueue ++ * sharing but is usually less with SMT/MC sharing of runqueues. ++ */ ++static int total_runqueues __read_mostly = 1; ++ ++static cpumask_t cpu_idle_map ____cacheline_aligned_in_smp; ++ ++struct rq *cpu_rq(int cpu) ++{ ++ return &per_cpu(runqueues, (cpu)); ++} ++#define cpu_curr(cpu) (cpu_rq(cpu)->curr) ++ ++/* ++ * For asym packing, by default the lower numbered cpu has higher priority. ++ */ ++int __weak arch_asym_cpu_priority(int cpu) ++{ ++ return -cpu; ++} ++ ++int __weak arch_sd_sibling_asym_packing(void) ++{ ++ return 0*SD_ASYM_PACKING; ++} ++ ++#ifdef CONFIG_SCHED_SMT ++DEFINE_STATIC_KEY_FALSE(sched_smt_present); ++EXPORT_SYMBOL_GPL(sched_smt_present); ++#endif ++ ++#else ++struct rq *uprq; ++#endif /* CONFIG_SMP */ ++ ++#include "stats.h" ++ ++/* ++ * All common locking functions performed on rq->lock. rq->clock is local to ++ * the CPU accessing it so it can be modified just with interrupts disabled ++ * when we're not updating niffies. ++ * Looking up task_rq must be done under rq->lock to be safe. ++ */ ++ ++/* ++ * RQ-clock updating methods: ++ */ ++ ++#ifdef HAVE_SCHED_AVG_IRQ ++static void update_irq_load_avg(struct rq *rq, long delta); ++#else ++static inline void update_irq_load_avg(struct rq *rq, long delta) {} ++#endif ++ ++static void update_rq_clock_task(struct rq *rq, s64 delta) ++{ ++/* ++ * In theory, the compile should just see 0 here, and optimize out the call ++ * to sched_rt_avg_update. But I don't trust it... ++ */ ++ s64 __maybe_unused steal = 0, irq_delta = 0; ++#ifdef CONFIG_IRQ_TIME_ACCOUNTING ++ irq_delta = irq_time_read(cpu_of(rq)) - rq->prev_irq_time; ++ ++ /* ++ * Since irq_time is only updated on {soft,}irq_exit, we might run into ++ * this case when a previous update_rq_clock() happened inside a ++ * {soft,}irq region. ++ * ++ * When this happens, we stop ->clock_task and only update the ++ * prev_irq_time stamp to account for the part that fit, so that a next ++ * update will consume the rest. This ensures ->clock_task is ++ * monotonic. ++ * ++ * It does however cause some slight miss-attribution of {soft,}irq ++ * time, a more accurate solution would be to update the irq_time using ++ * the current rq->clock timestamp, except that would require using ++ * atomic ops. ++ */ ++ if (irq_delta > delta) ++ irq_delta = delta; ++ ++ rq->prev_irq_time += irq_delta; ++ delta -= irq_delta; ++#endif ++#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING ++ if (static_key_false((¶virt_steal_rq_enabled))) { ++ steal = paravirt_steal_clock(cpu_of(rq)); ++ steal -= rq->prev_steal_time_rq; ++ ++ if (unlikely(steal > delta)) ++ steal = delta; ++ ++ rq->prev_steal_time_rq += steal; ++ delta -= steal; ++ } ++#endif ++ rq->clock_task += delta; ++ ++#ifdef CONFIG_HAVE_SCHED_AVG_IRQ ++ if (irq_delta + steal) ++ update_irq_load_avg(rq, irq_delta + steal); ++#endif ++} ++ ++static inline void update_rq_clock(struct rq *rq) ++{ ++ s64 delta = sched_clock_cpu(cpu_of(rq)) - rq->clock; ++ ++ if (unlikely(delta < 0)) ++ return; ++ rq->clock += delta; ++ update_rq_clock_task(rq, delta); ++} ++ ++/* ++ * Niffies are a globally increasing nanosecond counter. They're only used by ++ * update_load_avg and time_slice_expired, however deadlines are based on them ++ * across CPUs. Update them whenever we will call one of those functions, and ++ * synchronise them across CPUs whenever we hold both runqueue locks. ++ */ ++static inline void update_clocks(struct rq *rq) ++{ ++ s64 ndiff, minndiff; ++ long jdiff; ++ ++ update_rq_clock(rq); ++ ndiff = rq->clock - rq->old_clock; ++ rq->old_clock = rq->clock; ++ jdiff = jiffies - rq->last_jiffy; ++ ++ /* Subtract any niffies added by balancing with other rqs */ ++ ndiff -= rq->niffies - rq->last_niffy; ++ minndiff = JIFFIES_TO_NS(jdiff) - rq->niffies + rq->last_jiffy_niffies; ++ if (minndiff < 0) ++ minndiff = 0; ++ ndiff = max(ndiff, minndiff); ++ rq->niffies += ndiff; ++ rq->last_niffy = rq->niffies; ++ if (jdiff) { ++ rq->last_jiffy += jdiff; ++ rq->last_jiffy_niffies = rq->niffies; ++ } ++} ++ ++/* ++ * Any time we have two runqueues locked we use that as an opportunity to ++ * synchronise niffies to the highest value as idle ticks may have artificially ++ * kept niffies low on one CPU and the truth can only be later. ++ */ ++static inline void synchronise_niffies(struct rq *rq1, struct rq *rq2) ++{ ++ if (rq1->niffies > rq2->niffies) ++ rq2->niffies = rq1->niffies; ++ else ++ rq1->niffies = rq2->niffies; ++} ++ ++/* ++ * double_rq_lock - safely lock two runqueues ++ * ++ * Note this does not disable interrupts like task_rq_lock, ++ * you need to do so manually before calling. ++ */ ++ ++/* For when we know rq1 != rq2 */ ++static inline void __double_rq_lock(struct rq *rq1, struct rq *rq2) ++ __acquires(rq1->lock) ++ __acquires(rq2->lock) ++{ ++ if (rq1 < rq2) { ++ raw_spin_lock(rq1->lock); ++ raw_spin_lock_nested(rq2->lock, SINGLE_DEPTH_NESTING); ++ } else { ++ raw_spin_lock(rq2->lock); ++ raw_spin_lock_nested(rq1->lock, SINGLE_DEPTH_NESTING); ++ } ++} ++ ++static inline void double_rq_lock(struct rq *rq1, struct rq *rq2) ++ __acquires(rq1->lock) ++ __acquires(rq2->lock) ++{ ++ BUG_ON(!irqs_disabled()); ++ if (rq1->lock == rq2->lock) { ++ raw_spin_lock(rq1->lock); ++ __acquire(rq2->lock); /* Fake it out ;) */ ++ } else ++ __double_rq_lock(rq1, rq2); ++ synchronise_niffies(rq1, rq2); ++} ++ ++/* ++ * double_rq_unlock - safely unlock two runqueues ++ * ++ * Note this does not restore interrupts like task_rq_unlock, ++ * you need to do so manually after calling. ++ */ ++static inline void double_rq_unlock(struct rq *rq1, struct rq *rq2) ++ __releases(rq1->lock) ++ __releases(rq2->lock) ++{ ++ raw_spin_unlock(rq1->lock); ++ if (rq1->lock != rq2->lock) ++ raw_spin_unlock(rq2->lock); ++ else ++ __release(rq2->lock); ++} ++ ++static inline void lock_all_rqs(void) ++{ ++ int cpu; ++ ++ preempt_disable(); ++ for_each_possible_cpu(cpu) { ++ struct rq *rq = cpu_rq(cpu); ++ ++ do_raw_spin_lock(rq->lock); ++ } ++} ++ ++static inline void unlock_all_rqs(void) ++{ ++ int cpu; ++ ++ for_each_possible_cpu(cpu) { ++ struct rq *rq = cpu_rq(cpu); ++ ++ do_raw_spin_unlock(rq->lock); ++ } ++ preempt_enable(); ++} ++ ++/* Specially nest trylock an rq */ ++static inline bool trylock_rq(struct rq *this_rq, struct rq *rq) ++{ ++ if (unlikely(!do_raw_spin_trylock(rq->lock))) ++ return false; ++ spin_acquire(&rq->lock->dep_map, SINGLE_DEPTH_NESTING, 1, _RET_IP_); ++ synchronise_niffies(this_rq, rq); ++ return true; ++} ++ ++/* Unlock a specially nested trylocked rq */ ++static inline void unlock_rq(struct rq *rq) ++{ ++ spin_release(&rq->lock->dep_map, 1, _RET_IP_); ++ do_raw_spin_unlock(rq->lock); ++} ++ ++/* ++ * cmpxchg based fetch_or, macro so it works for different integer types ++ */ ++#define fetch_or(ptr, mask) \ ++ ({ \ ++ typeof(ptr) _ptr = (ptr); \ ++ typeof(mask) _mask = (mask); \ ++ typeof(*_ptr) _old, _val = *_ptr; \ ++ \ ++ for (;;) { \ ++ _old = cmpxchg(_ptr, _val, _val | _mask); \ ++ if (_old == _val) \ ++ break; \ ++ _val = _old; \ ++ } \ ++ _old; \ ++}) ++ ++#if defined(CONFIG_SMP) && defined(TIF_POLLING_NRFLAG) ++/* ++ * Atomically set TIF_NEED_RESCHED and test for TIF_POLLING_NRFLAG, ++ * this avoids any races wrt polling state changes and thereby avoids ++ * spurious IPIs. ++ */ ++static bool set_nr_and_not_polling(struct task_struct *p) ++{ ++ struct thread_info *ti = task_thread_info(p); ++ return !(fetch_or(&ti->flags, _TIF_NEED_RESCHED) & _TIF_POLLING_NRFLAG); ++} ++ ++/* ++ * Atomically set TIF_NEED_RESCHED if TIF_POLLING_NRFLAG is set. ++ * ++ * If this returns true, then the idle task promises to call ++ * sched_ttwu_pending() and reschedule soon. ++ */ ++static bool set_nr_if_polling(struct task_struct *p) ++{ ++ struct thread_info *ti = task_thread_info(p); ++ typeof(ti->flags) old, val = READ_ONCE(ti->flags); ++ ++ for (;;) { ++ if (!(val & _TIF_POLLING_NRFLAG)) ++ return false; ++ if (val & _TIF_NEED_RESCHED) ++ return true; ++ old = cmpxchg(&ti->flags, val, val | _TIF_NEED_RESCHED); ++ if (old == val) ++ break; ++ val = old; ++ } ++ return true; ++} ++ ++#else ++static bool set_nr_and_not_polling(struct task_struct *p) ++{ ++ set_tsk_need_resched(p); ++ return true; ++} ++ ++#ifdef CONFIG_SMP ++static bool set_nr_if_polling(struct task_struct *p) ++{ ++ return false; ++} ++#endif ++#endif ++ ++static bool __wake_q_add(struct wake_q_head *head, struct task_struct *task) ++{ ++ struct wake_q_node *node = &task->wake_q; ++ ++ /* ++ * Atomically grab the task, if ->wake_q is !nil already it means ++ * its already queued (either by us or someone else) and will get the ++ * wakeup due to that. ++ * ++ * In order to ensure that a pending wakeup will observe our pending ++ * state, even in the failed case, an explicit smp_mb() must be used. ++ */ ++ smp_mb__before_atomic(); ++ if (unlikely(cmpxchg_relaxed(&node->next, NULL, WAKE_Q_TAIL))) ++ return false; ++ ++ /* ++ * The head is context local, there can be no concurrency. ++ */ ++ *head->lastp = node; ++ head->lastp = &node->next; ++ return true; ++} ++ ++/** ++ * wake_q_add() - queue a wakeup for 'later' waking. ++ * @head: the wake_q_head to add @task to ++ * @task: the task to queue for 'later' wakeup ++ * ++ * Queue a task for later wakeup, most likely by the wake_up_q() call in the ++ * same context, _HOWEVER_ this is not guaranteed, the wakeup can come ++ * instantly. ++ * ++ * This function must be used as-if it were wake_up_process(); IOW the task ++ * must be ready to be woken at this location. ++ */ ++void wake_q_add(struct wake_q_head *head, struct task_struct *task) ++{ ++ if (__wake_q_add(head, task)) ++ get_task_struct(task); ++} ++ ++/** ++ * wake_q_add_safe() - safely queue a wakeup for 'later' waking. ++ * @head: the wake_q_head to add @task to ++ * @task: the task to queue for 'later' wakeup ++ * ++ * Queue a task for later wakeup, most likely by the wake_up_q() call in the ++ * same context, _HOWEVER_ this is not guaranteed, the wakeup can come ++ * instantly. ++ * ++ * This function must be used as-if it were wake_up_process(); IOW the task ++ * must be ready to be woken at this location. ++ * ++ * This function is essentially a task-safe equivalent to wake_q_add(). Callers ++ * that already hold reference to @task can call the 'safe' version and trust ++ * wake_q to do the right thing depending whether or not the @task is already ++ * queued for wakeup. ++ */ ++void wake_q_add_safe(struct wake_q_head *head, struct task_struct *task) ++{ ++ if (!__wake_q_add(head, task)) ++ put_task_struct(task); ++} ++ ++void wake_up_q(struct wake_q_head *head) ++{ ++ struct wake_q_node *node = head->first; ++ ++ while (node != WAKE_Q_TAIL) { ++ struct task_struct *task; ++ ++ task = container_of(node, struct task_struct, wake_q); ++ BUG_ON(!task); ++ /* Task can safely be re-inserted now */ ++ node = node->next; ++ task->wake_q.next = NULL; ++ ++ /* ++ * wake_up_process() executes a full barrier, which pairs with ++ * the queueing in wake_q_add() so as not to miss wakeups. ++ */ ++ wake_up_process(task); ++ put_task_struct(task); ++ } ++} ++ ++static inline void smp_sched_reschedule(int cpu) ++{ ++ if (likely(cpu_online(cpu))) ++ smp_send_reschedule(cpu); ++} ++ ++/* ++ * resched_task - mark a task 'to be rescheduled now'. ++ * ++ * On UP this means the setting of the need_resched flag, on SMP it ++ * might also involve a cross-CPU call to trigger the scheduler on ++ * the target CPU. ++ */ ++void resched_task(struct task_struct *p) ++{ ++ int cpu; ++#ifdef CONFIG_LOCKDEP ++ /* Kernel threads call this when creating workqueues while still ++ * inactive from __kthread_bind_mask, holding only the pi_lock */ ++ if (!(p->flags & PF_KTHREAD)) { ++ struct rq *rq = task_rq(p); ++ ++ lockdep_assert_held(rq->lock); ++ } ++#endif ++ if (test_tsk_need_resched(p)) ++ return; ++ ++ cpu = task_cpu(p); ++ if (cpu == smp_processor_id()) { ++ set_tsk_need_resched(p); ++ set_preempt_need_resched(); ++ return; ++ } ++ ++ if (set_nr_and_not_polling(p)) ++ smp_sched_reschedule(cpu); ++ else ++ trace_sched_wake_idle_without_ipi(cpu); ++} ++ ++/* ++ * A task that is not running or queued will not have a node set. ++ * A task that is queued but not running will have a node set. ++ * A task that is currently running will have ->on_cpu set but no node set. ++ */ ++static inline bool task_queued(struct task_struct *p) ++{ ++ return !skiplist_node_empty(&p->node); ++} ++ ++static void enqueue_task(struct rq *rq, struct task_struct *p, int flags); ++static inline void resched_if_idle(struct rq *rq); ++ ++static inline bool deadline_before(u64 deadline, u64 time) ++{ ++ return (deadline < time); ++} ++ ++/* ++ * Deadline is "now" in niffies + (offset by priority). Setting the deadline ++ * is the key to everything. It distributes cpu fairly amongst tasks of the ++ * same nice value, it proportions cpu according to nice level, it means the ++ * task that last woke up the longest ago has the earliest deadline, thus ++ * ensuring that interactive tasks get low latency on wake up. The CPU ++ * proportion works out to the square of the virtual deadline difference, so ++ * this equation will give nice 19 3% CPU compared to nice 0. ++ */ ++static inline u64 prio_deadline_diff(int user_prio) ++{ ++ return (prio_ratios[user_prio] * rr_interval * (MS_TO_NS(1) / 128)); ++} ++ ++static inline u64 task_deadline_diff(struct task_struct *p) ++{ ++ return prio_deadline_diff(TASK_USER_PRIO(p)); ++} ++ ++static inline u64 static_deadline_diff(int static_prio) ++{ ++ return prio_deadline_diff(USER_PRIO(static_prio)); ++} ++ ++static inline int longest_deadline_diff(void) ++{ ++ return prio_deadline_diff(39); ++} ++ ++static inline int ms_longest_deadline_diff(void) ++{ ++ return NS_TO_MS(longest_deadline_diff()); ++} ++ ++static inline bool rq_local(struct rq *rq); ++ ++#ifndef SCHED_CAPACITY_SCALE ++#define SCHED_CAPACITY_SCALE 1024 ++#endif ++ ++static inline int rq_load(struct rq *rq) ++{ ++ return rq->nr_running; ++} ++ ++/* ++ * Update the load average for feeding into cpu frequency governors. Use a ++ * rough estimate of a rolling average with ~ time constant of 32ms. ++ * 80/128 ~ 0.63. * 80 / 32768 / 128 == * 5 / 262144 ++ * Make sure a call to update_clocks has been made before calling this to get ++ * an updated rq->niffies. ++ */ ++static void update_load_avg(struct rq *rq, unsigned int flags) ++{ ++ long us_interval, load; ++ ++ us_interval = NS_TO_US(rq->niffies - rq->load_update); ++ if (unlikely(us_interval <= 0)) ++ return; ++ ++ load = rq->load_avg - (rq->load_avg * us_interval * 5 / 262144); ++ if (unlikely(load < 0)) ++ load = 0; ++ load += rq_load(rq) * SCHED_CAPACITY_SCALE * us_interval * 5 / 262144; ++ rq->load_avg = load; ++ ++ rq->load_update = rq->niffies; ++ update_irq_load_avg(rq, 0); ++ if (likely(rq_local(rq))) ++ cpufreq_trigger(rq, flags); ++} ++ ++#ifdef HAVE_SCHED_AVG_IRQ ++/* ++ * IRQ variant of update_load_avg below. delta is actually time in nanoseconds ++ * here so we scale curload to how long it's been since the last update. ++ */ ++static void update_irq_load_avg(struct rq *rq, long delta) ++{ ++ long us_interval, load; ++ ++ us_interval = NS_TO_US(rq->niffies - rq->irq_load_update); ++ if (unlikely(us_interval <= 0)) ++ return; ++ ++ load = rq->irq_load_avg - (rq->irq_load_avg * us_interval * 5 / 262144); ++ if (unlikely(load < 0)) ++ load = 0; ++ load += NS_TO_US(delta) * SCHED_CAPACITY_SCALE * 5 / 262144; ++ rq->irq_load_avg = load; ++ ++ rq->irq_load_update = rq->niffies; ++} ++#endif ++ ++/* ++ * Removing from the runqueue. Enter with rq locked. Deleting a task ++ * from the skip list is done via the stored node reference in the task struct ++ * and does not require a full look up. Thus it occurs in O(k) time where k ++ * is the "level" of the list the task was stored at - usually < 4, max 8. ++ */ ++static void dequeue_task(struct rq *rq, struct task_struct *p, int flags) ++{ ++ skiplist_delete(rq->sl, &p->node); ++ rq->best_key = rq->node->next[0]->key; ++ update_clocks(rq); ++ ++ if (!(flags & DEQUEUE_SAVE)) { ++ sched_info_dequeued(rq, p); ++ psi_dequeue(p, flags & DEQUEUE_SLEEP); ++ } ++ rq->nr_running--; ++ if (rt_task(p)) ++ rq->rt_nr_running--; ++ update_load_avg(rq, flags); ++} ++ ++#ifdef CONFIG_PREEMPT_RCU ++static bool rcu_read_critical(struct task_struct *p) ++{ ++ return p->rcu_read_unlock_special.b.blocked; ++} ++#else /* CONFIG_PREEMPT_RCU */ ++#define rcu_read_critical(p) (false) ++#endif /* CONFIG_PREEMPT_RCU */ ++ ++/* ++ * To determine if it's safe for a task of SCHED_IDLEPRIO to actually run as ++ * an idle task, we ensure none of the following conditions are met. ++ */ ++static bool idleprio_suitable(struct task_struct *p) ++{ ++ return (!(task_contributes_to_load(p)) && !(p->flags & (PF_EXITING)) && ++ !signal_pending(p) && !rcu_read_critical(p) && !freezing(p)); ++} ++ ++/* ++ * To determine if a task of SCHED_ISO can run in pseudo-realtime, we check ++ * that the iso_refractory flag is not set. ++ */ ++static inline bool isoprio_suitable(struct rq *rq) ++{ ++ return !rq->iso_refractory; ++} ++ ++/* ++ * Adding to the runqueue. Enter with rq locked. ++ */ ++static void enqueue_task(struct rq *rq, struct task_struct *p, int flags) ++{ ++ unsigned int randseed, cflags = 0; ++ u64 sl_id; ++ ++ if (!rt_task(p)) { ++ /* Check it hasn't gotten rt from PI */ ++ if ((idleprio_task(p) && idleprio_suitable(p)) || ++ (iso_task(p) && isoprio_suitable(rq))) ++ p->prio = p->normal_prio; ++ else ++ p->prio = NORMAL_PRIO; ++ } else ++ rq->rt_nr_running++; ++ /* ++ * The sl_id key passed to the skiplist generates a sorted list. ++ * Realtime and sched iso tasks run FIFO so they only need be sorted ++ * according to priority. The skiplist will put tasks of the same ++ * key inserted later in FIFO order. Tasks of sched normal, batch ++ * and idleprio are sorted according to their deadlines. Idleprio ++ * tasks are offset by an impossibly large deadline value ensuring ++ * they get sorted into last positions, but still according to their ++ * own deadlines. This creates a "landscape" of skiplists running ++ * from priority 0 realtime in first place to the lowest priority ++ * idleprio tasks last. Skiplist insertion is an O(log n) process. ++ */ ++ if (p->prio <= ISO_PRIO) { ++ sl_id = p->prio; ++ } else { ++ sl_id = p->deadline; ++ if (idleprio_task(p)) { ++ if (p->prio == IDLE_PRIO) ++ sl_id |= 0xF000000000000000; ++ else ++ sl_id += longest_deadline_diff(); ++ } ++ } ++ /* ++ * Some architectures don't have better than microsecond resolution ++ * so mask out ~microseconds as the random seed for skiplist insertion. ++ */ ++ update_clocks(rq); ++ if (!(flags & ENQUEUE_RESTORE)) { ++ sched_info_queued(rq, p); ++ psi_enqueue(p, flags & ENQUEUE_WAKEUP); ++ } ++ ++ randseed = (rq->niffies >> 10) & 0xFFFFFFFF; ++ skiplist_insert(rq->sl, &p->node, sl_id, p, randseed); ++ rq->best_key = rq->node->next[0]->key; ++ if (p->in_iowait) ++ cflags |= SCHED_CPUFREQ_IOWAIT; ++ rq->nr_running++; ++ update_load_avg(rq, cflags); ++} ++ ++/* ++ * Returns the relative length of deadline all compared to the shortest ++ * deadline which is that of nice -20. ++ */ ++static inline int task_prio_ratio(struct task_struct *p) ++{ ++ return prio_ratios[TASK_USER_PRIO(p)]; ++} ++ ++/* ++ * task_timeslice - all tasks of all priorities get the exact same timeslice ++ * length. CPU distribution is handled by giving different deadlines to ++ * tasks of different priorities. Use 128 as the base value for fast shifts. ++ */ ++static inline int task_timeslice(struct task_struct *p) ++{ ++ return (rr_interval * task_prio_ratio(p) / 128); ++} ++ ++#ifdef CONFIG_SMP ++/* Entered with rq locked */ ++static inline void resched_if_idle(struct rq *rq) ++{ ++ if (rq_idle(rq)) ++ resched_task(rq->curr); ++} ++ ++static inline bool rq_local(struct rq *rq) ++{ ++ return (rq->cpu == smp_processor_id()); ++} ++#ifdef CONFIG_SMT_NICE ++static const cpumask_t *thread_cpumask(int cpu); ++ ++/* Find the best real time priority running on any SMT siblings of cpu and if ++ * none are running, the static priority of the best deadline task running. ++ * The lookups to the other runqueues is done lockless as the occasional wrong ++ * value would be harmless. */ ++static int best_smt_bias(struct rq *this_rq) ++{ ++ int other_cpu, best_bias = 0; ++ ++ for_each_cpu(other_cpu, &this_rq->thread_mask) { ++ struct rq *rq = cpu_rq(other_cpu); ++ ++ if (rq_idle(rq)) ++ continue; ++ if (unlikely(!rq->online)) ++ continue; ++ if (!rq->rq_mm) ++ continue; ++ if (likely(rq->rq_smt_bias > best_bias)) ++ best_bias = rq->rq_smt_bias; ++ } ++ return best_bias; ++} ++ ++static int task_prio_bias(struct task_struct *p) ++{ ++ if (rt_task(p)) ++ return 1 << 30; ++ else if (task_running_iso(p)) ++ return 1 << 29; ++ else if (task_running_idle(p)) ++ return 0; ++ return MAX_PRIO - p->static_prio; ++} ++ ++static bool smt_always_schedule(struct task_struct __maybe_unused *p, struct rq __maybe_unused *this_rq) ++{ ++ return true; ++} ++ ++static bool (*smt_schedule)(struct task_struct *p, struct rq *this_rq) = &smt_always_schedule; ++ ++/* We've already decided p can run on CPU, now test if it shouldn't for SMT ++ * nice reasons. */ ++static bool smt_should_schedule(struct task_struct *p, struct rq *this_rq) ++{ ++ int best_bias, task_bias; ++ ++ /* Kernel threads always run */ ++ if (unlikely(!p->mm)) ++ return true; ++ if (rt_task(p)) ++ return true; ++ if (!idleprio_suitable(p)) ++ return true; ++ best_bias = best_smt_bias(this_rq); ++ /* The smt siblings are all idle or running IDLEPRIO */ ++ if (best_bias < 1) ++ return true; ++ task_bias = task_prio_bias(p); ++ if (task_bias < 1) ++ return false; ++ if (task_bias >= best_bias) ++ return true; ++ /* Dither 25% cpu of normal tasks regardless of nice difference */ ++ if (best_bias % 4 == 1) ++ return true; ++ /* Sorry, you lose */ ++ return false; ++} ++#else /* CONFIG_SMT_NICE */ ++#define smt_schedule(p, this_rq) (true) ++#endif /* CONFIG_SMT_NICE */ ++ ++static inline void atomic_set_cpu(int cpu, cpumask_t *cpumask) ++{ ++ set_bit(cpu, (volatile unsigned long *)cpumask); ++} ++ ++/* ++ * The cpu_idle_map stores a bitmap of all the CPUs currently idle to ++ * allow easy lookup of whether any suitable idle CPUs are available. ++ * It's cheaper to maintain a binary yes/no if there are any idle CPUs on the ++ * idle_cpus variable than to do a full bitmask check when we are busy. The ++ * bits are set atomically but read locklessly as occasional false positive / ++ * negative is harmless. ++ */ ++static inline void set_cpuidle_map(int cpu) ++{ ++ if (likely(cpu_online(cpu))) ++ atomic_set_cpu(cpu, &cpu_idle_map); ++} ++ ++static inline void atomic_clear_cpu(int cpu, cpumask_t *cpumask) ++{ ++ clear_bit(cpu, (volatile unsigned long *)cpumask); ++} ++ ++static inline void clear_cpuidle_map(int cpu) ++{ ++ atomic_clear_cpu(cpu, &cpu_idle_map); ++} ++ ++static bool suitable_idle_cpus(struct task_struct *p) ++{ ++ return (cpumask_intersects(p->cpus_ptr, &cpu_idle_map)); ++} ++ ++/* ++ * Resched current on rq. We don't know if rq is local to this CPU nor if it ++ * is locked so we do not use an intermediate variable for the task to avoid ++ * having it dereferenced. ++ */ ++static void resched_curr(struct rq *rq) ++{ ++ int cpu; ++ ++ if (test_tsk_need_resched(rq->curr)) ++ return; ++ ++ rq->preempt = rq->curr; ++ cpu = rq->cpu; ++ ++ /* We're doing this without holding the rq lock if it's not task_rq */ ++ ++ if (cpu == smp_processor_id()) { ++ set_tsk_need_resched(rq->curr); ++ set_preempt_need_resched(); ++ return; ++ } ++ ++ if (set_nr_and_not_polling(rq->curr)) ++ smp_sched_reschedule(cpu); ++ else ++ trace_sched_wake_idle_without_ipi(cpu); ++} ++ ++#define CPUIDLE_DIFF_THREAD (1) ++#define CPUIDLE_DIFF_CORE_LLC (2) ++#define CPUIDLE_DIFF_CORE (4) ++#define CPUIDLE_CACHE_BUSY (8) ++#define CPUIDLE_DIFF_CPU (16) ++#define CPUIDLE_THREAD_BUSY (32) ++#define CPUIDLE_DIFF_NODE (64) ++ ++/* ++ * The best idle CPU is chosen according to the CPUIDLE ranking above where the ++ * lowest value would give the most suitable CPU to schedule p onto next. The ++ * order works out to be the following: ++ * ++ * Same thread, idle or busy cache, idle or busy threads ++ * Other core, same cache, idle or busy cache, idle threads. ++ * Same node, other CPU, idle cache, idle threads. ++ * Same node, other CPU, busy cache, idle threads. ++ * Other core, same cache, busy threads. ++ * Same node, other CPU, busy threads. ++ * Other node, other CPU, idle cache, idle threads. ++ * Other node, other CPU, busy cache, idle threads. ++ * Other node, other CPU, busy threads. ++ */ ++static int best_mask_cpu(int best_cpu, struct rq *rq, cpumask_t *tmpmask) ++{ ++ int best_ranking = CPUIDLE_DIFF_NODE | CPUIDLE_THREAD_BUSY | ++ CPUIDLE_DIFF_CPU | CPUIDLE_CACHE_BUSY | CPUIDLE_DIFF_CORE | ++ CPUIDLE_DIFF_CORE_LLC | CPUIDLE_DIFF_THREAD; ++ int cpu_tmp; ++ ++ if (cpumask_test_cpu(best_cpu, tmpmask)) ++ goto out; ++ ++ for_each_cpu(cpu_tmp, tmpmask) { ++ int ranking, locality; ++ struct rq *tmp_rq; ++ ++ ranking = 0; ++ tmp_rq = cpu_rq(cpu_tmp); ++ ++ locality = rq->cpu_locality[cpu_tmp]; ++#ifdef CONFIG_NUMA ++ if (locality > LOCALITY_SMP) ++ ranking |= CPUIDLE_DIFF_NODE; ++ else ++#endif ++ if (locality > LOCALITY_MC) ++ ranking |= CPUIDLE_DIFF_CPU; ++#ifdef CONFIG_SCHED_MC ++ else if (locality == LOCALITY_MC_LLC) ++ ranking |= CPUIDLE_DIFF_CORE_LLC; ++ else if (locality == LOCALITY_MC) ++ ranking |= CPUIDLE_DIFF_CORE; ++ if (!(tmp_rq->cache_idle(tmp_rq))) ++ ranking |= CPUIDLE_CACHE_BUSY; ++#endif ++#ifdef CONFIG_SCHED_SMT ++ if (locality == LOCALITY_SMT) ++ ranking |= CPUIDLE_DIFF_THREAD; ++#endif ++ if (ranking < best_ranking ++#ifdef CONFIG_SCHED_SMT ++ || (ranking == best_ranking && (tmp_rq->siblings_idle(tmp_rq))) ++#endif ++ ) { ++ best_cpu = cpu_tmp; ++ best_ranking = ranking; ++ } ++ } ++out: ++ return best_cpu; ++} ++ ++bool cpus_share_cache(int this_cpu, int that_cpu) ++{ ++ struct rq *this_rq = cpu_rq(this_cpu); ++ ++ return (this_rq->cpu_locality[that_cpu] < LOCALITY_SMP); ++} ++ ++/* As per resched_curr but only will resched idle task */ ++static inline void resched_idle(struct rq *rq) ++{ ++ if (test_tsk_need_resched(rq->idle)) ++ return; ++ ++ rq->preempt = rq->idle; ++ ++ set_tsk_need_resched(rq->idle); ++ ++ if (rq_local(rq)) { ++ set_preempt_need_resched(); ++ return; ++ } ++ ++ smp_sched_reschedule(rq->cpu); ++} ++ ++static struct rq *resched_best_idle(struct task_struct *p, int cpu) ++{ ++ cpumask_t tmpmask; ++ struct rq *rq; ++ int best_cpu; ++ ++ cpumask_and(&tmpmask, p->cpus_ptr, &cpu_idle_map); ++ best_cpu = best_mask_cpu(cpu, task_rq(p), &tmpmask); ++ rq = cpu_rq(best_cpu); ++ if (!smt_schedule(p, rq)) ++ return NULL; ++ rq->preempt = p; ++ resched_idle(rq); ++ return rq; ++} ++ ++static inline void resched_suitable_idle(struct task_struct *p) ++{ ++ if (suitable_idle_cpus(p)) ++ resched_best_idle(p, task_cpu(p)); ++} ++ ++static inline struct rq *rq_order(struct rq *rq, int cpu) ++{ ++ return rq->rq_order[cpu]; ++} ++#else /* CONFIG_SMP */ ++static inline void set_cpuidle_map(int cpu) ++{ ++} ++ ++static inline void clear_cpuidle_map(int cpu) ++{ ++} ++ ++static inline bool suitable_idle_cpus(struct task_struct *p) ++{ ++ return uprq->curr == uprq->idle; ++} ++ ++static inline void resched_suitable_idle(struct task_struct *p) ++{ ++} ++ ++static inline void resched_curr(struct rq *rq) ++{ ++ resched_task(rq->curr); ++} ++ ++static inline void resched_if_idle(struct rq *rq) ++{ ++} ++ ++static inline bool rq_local(struct rq *rq) ++{ ++ return true; ++} ++ ++static inline struct rq *rq_order(struct rq *rq, int cpu) ++{ ++ return rq; ++} ++ ++static inline bool smt_schedule(struct task_struct *p, struct rq *rq) ++{ ++ return true; ++} ++#endif /* CONFIG_SMP */ ++ ++static inline int normal_prio(struct task_struct *p) ++{ ++ if (has_rt_policy(p)) ++ return MAX_RT_PRIO - 1 - p->rt_priority; ++ if (idleprio_task(p)) ++ return IDLE_PRIO; ++ if (iso_task(p)) ++ return ISO_PRIO; ++ return NORMAL_PRIO; ++} ++ ++/* ++ * Calculate the current priority, i.e. the priority ++ * taken into account by the scheduler. This value might ++ * be boosted by RT tasks as it will be RT if the task got ++ * RT-boosted. If not then it returns p->normal_prio. ++ */ ++static int effective_prio(struct task_struct *p) ++{ ++ p->normal_prio = normal_prio(p); ++ /* ++ * If we are RT tasks or we were boosted to RT priority, ++ * keep the priority unchanged. Otherwise, update priority ++ * to the normal priority: ++ */ ++ if (!rt_prio(p->prio)) ++ return p->normal_prio; ++ return p->prio; ++} ++ ++/* ++ * activate_task - move a task to the runqueue. Enter with rq locked. ++ */ ++static void activate_task(struct rq *rq, struct task_struct *p, int flags) ++{ ++ resched_if_idle(rq); ++ ++ /* ++ * Sleep time is in units of nanosecs, so shift by 20 to get a ++ * milliseconds-range estimation of the amount of time that the task ++ * spent sleeping: ++ */ ++ if (unlikely(prof_on == SLEEP_PROFILING)) { ++ if (p->state == TASK_UNINTERRUPTIBLE) ++ profile_hits(SLEEP_PROFILING, (void *)get_wchan(p), ++ (rq->niffies - p->last_ran) >> 20); ++ } ++ ++ p->prio = effective_prio(p); ++ if (task_contributes_to_load(p)) ++ rq->nr_uninterruptible--; ++ ++ enqueue_task(rq, p, flags); ++ p->on_rq = TASK_ON_RQ_QUEUED; ++} ++ ++/* ++ * deactivate_task - If it's running, it's not on the runqueue and we can just ++ * decrement the nr_running. Enter with rq locked. ++ */ ++static inline void deactivate_task(struct task_struct *p, struct rq *rq) ++{ ++ if (task_contributes_to_load(p)) ++ rq->nr_uninterruptible++; ++ ++ p->on_rq = 0; ++ sched_info_dequeued(rq, p); ++ /* deactivate_task is always DEQUEUE_SLEEP in muqss */ ++ psi_dequeue(p, DEQUEUE_SLEEP); ++} ++ ++#ifdef CONFIG_SMP ++void set_task_cpu(struct task_struct *p, unsigned int new_cpu) ++{ ++ struct rq *rq; ++ ++ if (task_cpu(p) == new_cpu) ++ return; ++ ++ /* Do NOT call set_task_cpu on a currently queued task as we will not ++ * be reliably holding the rq lock after changing CPU. */ ++ BUG_ON(task_queued(p)); ++ rq = task_rq(p); ++ ++#ifdef CONFIG_LOCKDEP ++ /* ++ * The caller should hold either p->pi_lock or rq->lock, when changing ++ * a task's CPU. ->pi_lock for waking tasks, rq->lock for runnable tasks. ++ * ++ * Furthermore, all task_rq users should acquire both locks, see ++ * task_rq_lock(). ++ */ ++ WARN_ON_ONCE(debug_locks && !(lockdep_is_held(&p->pi_lock) || ++ lockdep_is_held(rq->lock))); ++#endif ++ ++ trace_sched_migrate_task(p, new_cpu); ++ rseq_migrate(p); ++ perf_event_task_migrate(p); ++ ++ /* ++ * After ->cpu is set up to a new value, task_rq_lock(p, ...) can be ++ * successfully executed on another CPU. We must ensure that updates of ++ * per-task data have been completed by this moment. ++ */ ++ smp_wmb(); ++ ++ p->wake_cpu = new_cpu; ++ ++ if (task_running(rq, p)) { ++ /* ++ * We should only be calling this on a running task if we're ++ * holding rq lock. ++ */ ++ lockdep_assert_held(rq->lock); ++ ++ /* ++ * We can't change the task_thread_info CPU on a running task ++ * as p will still be protected by the rq lock of the CPU it ++ * is still running on so we only set the wake_cpu for it to be ++ * lazily updated once off the CPU. ++ */ ++ return; ++ } ++ ++#ifdef CONFIG_THREAD_INFO_IN_TASK ++ WRITE_ONCE(p->cpu, new_cpu); ++#else ++ WRITE_ONCE(task_thread_info(p)->cpu, new_cpu); ++#endif ++ /* We're no longer protecting p after this point since we're holding ++ * the wrong runqueue lock. */ ++} ++#endif /* CONFIG_SMP */ ++ ++/* ++ * Move a task off the runqueue and take it to a cpu for it will ++ * become the running task. ++ */ ++static inline void take_task(struct rq *rq, int cpu, struct task_struct *p) ++{ ++ struct rq *p_rq = task_rq(p); ++ ++ dequeue_task(p_rq, p, DEQUEUE_SAVE); ++ if (p_rq != rq) { ++ sched_info_dequeued(p_rq, p); ++ sched_info_queued(rq, p); ++ } ++ set_task_cpu(p, cpu); ++} ++ ++/* ++ * Returns a descheduling task to the runqueue unless it is being ++ * deactivated. ++ */ ++static inline void return_task(struct task_struct *p, struct rq *rq, ++ int cpu, bool deactivate) ++{ ++ if (deactivate) ++ deactivate_task(p, rq); ++ else { ++#ifdef CONFIG_SMP ++ /* ++ * set_task_cpu was called on the running task that doesn't ++ * want to deactivate so it has to be enqueued to a different ++ * CPU and we need its lock. Tag it to be moved with as the ++ * lock is dropped in finish_lock_switch. ++ */ ++ if (unlikely(p->wake_cpu != cpu)) ++ WRITE_ONCE(p->on_rq, TASK_ON_RQ_MIGRATING); ++ else ++#endif ++ enqueue_task(rq, p, ENQUEUE_RESTORE); ++ } ++} ++ ++/* Enter with rq lock held. We know p is on the local cpu */ ++static inline void __set_tsk_resched(struct task_struct *p) ++{ ++ set_tsk_need_resched(p); ++ set_preempt_need_resched(); ++} ++ ++/** ++ * task_curr - is this task currently executing on a CPU? ++ * @p: the task in question. ++ * ++ * Return: 1 if the task is currently executing. 0 otherwise. ++ */ ++inline int task_curr(const struct task_struct *p) ++{ ++ return cpu_curr(task_cpu(p)) == p; ++} ++ ++#ifdef CONFIG_SMP ++/* ++ * wait_task_inactive - wait for a thread to unschedule. ++ * ++ * If @match_state is nonzero, it's the @p->state value just checked and ++ * not expected to change. If it changes, i.e. @p might have woken up, ++ * then return zero. When we succeed in waiting for @p to be off its CPU, ++ * we return a positive number (its total switch count). If a second call ++ * a short while later returns the same number, the caller can be sure that ++ * @p has remained unscheduled the whole time. ++ * ++ * The caller must ensure that the task *will* unschedule sometime soon, ++ * else this function might spin for a *long* time. This function can't ++ * be called with interrupts off, or it may introduce deadlock with ++ * smp_call_function() if an IPI is sent by the same process we are ++ * waiting to become inactive. ++ */ ++unsigned long wait_task_inactive(struct task_struct *p, long match_state) ++{ ++ int running, queued; ++ struct rq_flags rf; ++ unsigned long ncsw; ++ struct rq *rq; ++ ++ for (;;) { ++ rq = task_rq(p); ++ ++ /* ++ * If the task is actively running on another CPU ++ * still, just relax and busy-wait without holding ++ * any locks. ++ * ++ * NOTE! Since we don't hold any locks, it's not ++ * even sure that "rq" stays as the right runqueue! ++ * But we don't care, since this will return false ++ * if the runqueue has changed and p is actually now ++ * running somewhere else! ++ */ ++ while (task_running(rq, p)) { ++ if (match_state && unlikely(p->state != match_state)) ++ return 0; ++ cpu_relax(); ++ } ++ ++ /* ++ * Ok, time to look more closely! We need the rq ++ * lock now, to be *sure*. If we're wrong, we'll ++ * just go back and repeat. ++ */ ++ rq = task_rq_lock(p, &rf); ++ trace_sched_wait_task(p); ++ running = task_running(rq, p); ++ queued = task_on_rq_queued(p); ++ ncsw = 0; ++ if (!match_state || p->state == match_state) ++ ncsw = p->nvcsw | LONG_MIN; /* sets MSB */ ++ task_rq_unlock(rq, p, &rf); ++ ++ /* ++ * If it changed from the expected state, bail out now. ++ */ ++ if (unlikely(!ncsw)) ++ break; ++ ++ /* ++ * Was it really running after all now that we ++ * checked with the proper locks actually held? ++ * ++ * Oops. Go back and try again.. ++ */ ++ if (unlikely(running)) { ++ cpu_relax(); ++ continue; ++ } ++ ++ /* ++ * It's not enough that it's not actively running, ++ * it must be off the runqueue _entirely_, and not ++ * preempted! ++ * ++ * So if it was still runnable (but just not actively ++ * running right now), it's preempted, and we should ++ * yield - it could be a while. ++ */ ++ if (unlikely(queued)) { ++ ktime_t to = NSEC_PER_SEC / HZ; ++ ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ schedule_hrtimeout(&to, HRTIMER_MODE_REL); ++ continue; ++ } ++ ++ /* ++ * Ahh, all good. It wasn't running, and it wasn't ++ * runnable, which means that it will never become ++ * running in the future either. We're all done! ++ */ ++ break; ++ } ++ ++ return ncsw; ++} ++ ++/*** ++ * kick_process - kick a running thread to enter/exit the kernel ++ * @p: the to-be-kicked thread ++ * ++ * Cause a process which is running on another CPU to enter ++ * kernel-mode, without any delay. (to get signals handled.) ++ * ++ * NOTE: this function doesn't have to take the runqueue lock, ++ * because all it wants to ensure is that the remote task enters ++ * the kernel. If the IPI races and the task has been migrated ++ * to another CPU then no harm is done and the purpose has been ++ * achieved as well. ++ */ ++void kick_process(struct task_struct *p) ++{ ++ int cpu; ++ ++ preempt_disable(); ++ cpu = task_cpu(p); ++ if ((cpu != smp_processor_id()) && task_curr(p)) ++ smp_sched_reschedule(cpu); ++ preempt_enable(); ++} ++EXPORT_SYMBOL_GPL(kick_process); ++#endif ++ ++/* ++ * RT tasks preempt purely on priority. SCHED_NORMAL tasks preempt on the ++ * basis of earlier deadlines. SCHED_IDLEPRIO don't preempt anything else or ++ * between themselves, they cooperatively multitask. An idle rq scores as ++ * prio PRIO_LIMIT so it is always preempted. ++ */ ++static inline bool ++can_preempt(struct task_struct *p, int prio, u64 deadline) ++{ ++ /* Better static priority RT task or better policy preemption */ ++ if (p->prio < prio) ++ return true; ++ if (p->prio > prio) ++ return false; ++ if (p->policy == SCHED_BATCH) ++ return false; ++ /* SCHED_NORMAL and ISO will preempt based on deadline */ ++ if (!deadline_before(p->deadline, deadline)) ++ return false; ++ return true; ++} ++ ++#ifdef CONFIG_SMP ++ ++/* ++ * Per-CPU kthreads are allowed to run on !active && online CPUs, see ++ * __set_cpus_allowed_ptr(). ++ */ ++static inline bool is_cpu_allowed(struct task_struct *p, int cpu) ++{ ++ if (!cpumask_test_cpu(cpu, p->cpus_ptr)) ++ return false; ++ ++ if (is_per_cpu_kthread(p)) ++ return cpu_online(cpu); ++ ++ return cpu_active(cpu); ++} ++ ++/* ++ * Check to see if p can run on cpu, and if not, whether there are any online ++ * CPUs it can run on instead. This only happens with the hotplug threads that ++ * bring up the CPUs. ++ */ ++static inline bool sched_other_cpu(struct task_struct *p, int cpu) ++{ ++ if (likely(cpumask_test_cpu(cpu, p->cpus_ptr))) ++ return false; ++ if (p->nr_cpus_allowed == 1) { ++ cpumask_t valid_mask; ++ ++ cpumask_and(&valid_mask, p->cpus_ptr, cpu_online_mask); ++ if (unlikely(cpumask_empty(&valid_mask))) ++ return false; ++ } ++ return true; ++} ++ ++static inline bool needs_other_cpu(struct task_struct *p, int cpu) ++{ ++ if (cpumask_test_cpu(cpu, p->cpus_ptr)) ++ return false; ++ return true; ++} ++ ++#define cpu_online_map (*(cpumask_t *)cpu_online_mask) ++ ++static void try_preempt(struct task_struct *p, struct rq *this_rq) ++{ ++ int i, this_entries = rq_load(this_rq); ++ cpumask_t tmp; ++ ++ if (suitable_idle_cpus(p) && resched_best_idle(p, task_cpu(p))) ++ return; ++ ++ /* IDLEPRIO tasks never preempt anything but idle */ ++ if (p->policy == SCHED_IDLEPRIO) ++ return; ++ ++ cpumask_and(&tmp, &cpu_online_map, p->cpus_ptr); ++ ++ for (i = 0; i < num_online_cpus(); i++) { ++ struct rq *rq = this_rq->cpu_order[i]; ++ ++ if (!cpumask_test_cpu(rq->cpu, &tmp)) ++ continue; ++ ++ if (!sched_interactive && rq != this_rq && rq_load(rq) <= this_entries) ++ continue; ++ if (smt_schedule(p, rq) && can_preempt(p, rq->rq_prio, rq->rq_deadline)) { ++ /* We set rq->preempting lockless, it's a hint only */ ++ rq->preempting = p; ++ resched_curr(rq); ++ return; ++ } ++ } ++} ++ ++static int __set_cpus_allowed_ptr(struct task_struct *p, ++ const struct cpumask *new_mask, bool check); ++#else /* CONFIG_SMP */ ++static inline bool needs_other_cpu(struct task_struct *p, int cpu) ++{ ++ return false; ++} ++ ++static void try_preempt(struct task_struct *p, struct rq *this_rq) ++{ ++ if (p->policy == SCHED_IDLEPRIO) ++ return; ++ if (can_preempt(p, uprq->rq_prio, uprq->rq_deadline)) ++ resched_curr(uprq); ++} ++ ++static inline int __set_cpus_allowed_ptr(struct task_struct *p, ++ const struct cpumask *new_mask, bool check) ++{ ++ return set_cpus_allowed_ptr(p, new_mask); ++} ++#endif /* CONFIG_SMP */ ++ ++static void ++ttwu_stat(struct task_struct *p, int cpu, int wake_flags) ++{ ++ struct rq *rq; ++ ++ if (!schedstat_enabled()) ++ return; ++ ++ rq = this_rq(); ++ ++#ifdef CONFIG_SMP ++ if (cpu == rq->cpu) { ++ __schedstat_inc(rq->ttwu_local); ++ } else { ++ struct sched_domain *sd; ++ ++ rcu_read_lock(); ++ for_each_domain(rq->cpu, sd) { ++ if (cpumask_test_cpu(cpu, sched_domain_span(sd))) { ++ __schedstat_inc(sd->ttwu_wake_remote); ++ break; ++ } ++ } ++ rcu_read_unlock(); ++ } ++ ++#endif /* CONFIG_SMP */ ++ ++ __schedstat_inc(rq->ttwu_count); ++} ++ ++/* ++ * Mark the task runnable and perform wakeup-preemption. ++ */ ++static void ttwu_do_wakeup(struct rq *rq, struct task_struct *p, int wake_flags) ++{ ++ /* ++ * Sync wakeups (i.e. those types of wakeups where the waker ++ * has indicated that it will leave the CPU in short order) ++ * don't trigger a preemption if there are no idle cpus, ++ * instead waiting for current to deschedule. ++ */ ++ if (wake_flags & WF_SYNC) ++ resched_suitable_idle(p); ++ else ++ try_preempt(p, rq); ++ p->state = TASK_RUNNING; ++ trace_sched_wakeup(p); ++} ++ ++static void ++ttwu_do_activate(struct rq *rq, struct task_struct *p, int wake_flags) ++{ ++ int en_flags = ENQUEUE_WAKEUP; ++ ++ lockdep_assert_held(rq->lock); ++ ++#ifdef CONFIG_SMP ++ if (p->sched_contributes_to_load) ++ rq->nr_uninterruptible--; ++ ++ if (wake_flags & WF_MIGRATED) ++ en_flags |= ENQUEUE_MIGRATED; ++#endif ++ ++ activate_task(rq, p, en_flags); ++ ttwu_do_wakeup(rq, p, wake_flags); ++} ++ ++/* ++ * Called in case the task @p isn't fully descheduled from its runqueue, ++ * in this case we must do a remote wakeup. Its a 'light' wakeup though, ++ * since all we need to do is flip p->state to TASK_RUNNING, since ++ * the task is still ->on_rq. ++ */ ++static int ttwu_remote(struct task_struct *p, int wake_flags) ++{ ++ struct rq *rq; ++ int ret = 0; ++ ++ rq = __task_rq_lock(p, NULL); ++ if (likely(task_on_rq_queued(p))) { ++ ttwu_do_wakeup(rq, p, wake_flags); ++ ret = 1; ++ } ++ __task_rq_unlock(rq, NULL); ++ ++ return ret; ++} ++ ++#ifdef CONFIG_SMP ++void sched_ttwu_pending(void) ++{ ++ struct rq *rq = this_rq(); ++ struct llist_node *llist = llist_del_all(&rq->wake_list); ++ struct task_struct *p, *t; ++ struct rq_flags rf; ++ ++ if (!llist) ++ return; ++ ++ rq_lock_irqsave(rq, &rf); ++ ++ llist_for_each_entry_safe(p, t, llist, wake_entry) ++ ttwu_do_activate(rq, p, 0); ++ ++ rq_unlock_irqrestore(rq, &rf); ++} ++ ++void scheduler_ipi(void) ++{ ++ /* ++ * Fold TIF_NEED_RESCHED into the preempt_count; anybody setting ++ * TIF_NEED_RESCHED remotely (for the first time) will also send ++ * this IPI. ++ */ ++ preempt_fold_need_resched(); ++ ++ if (llist_empty(&this_rq()->wake_list) && (!idle_cpu(smp_processor_id()) || need_resched())) ++ return; ++ ++ /* ++ * Not all reschedule IPI handlers call irq_enter/irq_exit, since ++ * traditionally all their work was done from the interrupt return ++ * path. Now that we actually do some work, we need to make sure ++ * we do call them. ++ * ++ * Some archs already do call them, luckily irq_enter/exit nest ++ * properly. ++ * ++ * Arguably we should visit all archs and update all handlers, ++ * however a fair share of IPIs are still resched only so this would ++ * somewhat pessimize the simple resched case. ++ */ ++ irq_enter(); ++ sched_ttwu_pending(); ++ irq_exit(); ++} ++ ++static void ttwu_queue_remote(struct task_struct *p, int cpu, int wake_flags) ++{ ++ struct rq *rq = cpu_rq(cpu); ++ ++ if (llist_add(&p->wake_entry, &cpu_rq(cpu)->wake_list)) { ++ if (!set_nr_if_polling(rq->idle)) ++ smp_sched_reschedule(cpu); ++ else ++ trace_sched_wake_idle_without_ipi(cpu); ++ } ++} ++ ++void wake_up_if_idle(int cpu) ++{ ++ struct rq *rq = cpu_rq(cpu); ++ struct rq_flags rf; ++ ++ rcu_read_lock(); ++ ++ if (!is_idle_task(rcu_dereference(rq->curr))) ++ goto out; ++ ++ if (set_nr_if_polling(rq->idle)) { ++ trace_sched_wake_idle_without_ipi(cpu); ++ } else { ++ rq_lock_irqsave(rq, &rf); ++ if (likely(is_idle_task(rq->curr))) ++ smp_sched_reschedule(cpu); ++ /* Else cpu is not in idle, do nothing here */ ++ rq_unlock_irqrestore(rq, &rf); ++ } ++ ++out: ++ rcu_read_unlock(); ++} ++ ++static int valid_task_cpu(struct task_struct *p) ++{ ++ cpumask_t valid_mask; ++ ++ if (p->flags & PF_KTHREAD) ++ cpumask_and(&valid_mask, p->cpus_ptr, cpu_all_mask); ++ else ++ cpumask_and(&valid_mask, p->cpus_ptr, cpu_active_mask); ++ ++ if (unlikely(!cpumask_weight(&valid_mask))) { ++ /* We shouldn't be hitting this any more */ ++ printk(KERN_WARNING "SCHED: No cpumask for %s/%d weight %d\n", p->comm, ++ p->pid, cpumask_weight(p->cpus_ptr)); ++ return cpumask_any(p->cpus_ptr); ++ } ++ return cpumask_any(&valid_mask); ++} ++ ++/* ++ * For a task that's just being woken up we have a valuable balancing ++ * opportunity so choose the nearest cache most lightly loaded runqueue. ++ * Entered with rq locked and returns with the chosen runqueue locked. ++ */ ++static inline int select_best_cpu(struct task_struct *p) ++{ ++ unsigned int idlest = ~0U; ++ struct rq *rq = NULL; ++ int i; ++ ++ if (suitable_idle_cpus(p)) { ++ int cpu = task_cpu(p); ++ ++ if (unlikely(needs_other_cpu(p, cpu))) ++ cpu = valid_task_cpu(p); ++ rq = resched_best_idle(p, cpu); ++ if (likely(rq)) ++ return rq->cpu; ++ } ++ ++ for (i = 0; i < num_online_cpus(); i++) { ++ struct rq *other_rq = task_rq(p)->cpu_order[i]; ++ int entries; ++ ++ if (!other_rq->online) ++ continue; ++ if (needs_other_cpu(p, other_rq->cpu)) ++ continue; ++ entries = rq_load(other_rq); ++ if (entries >= idlest) ++ continue; ++ idlest = entries; ++ rq = other_rq; ++ } ++ if (unlikely(!rq)) ++ return task_cpu(p); ++ return rq->cpu; ++} ++#else /* CONFIG_SMP */ ++static int valid_task_cpu(struct task_struct *p) ++{ ++ return 0; ++} ++ ++static inline int select_best_cpu(struct task_struct *p) ++{ ++ return 0; ++} ++ ++static struct rq *resched_best_idle(struct task_struct *p, int cpu) ++{ ++ return NULL; ++} ++#endif /* CONFIG_SMP */ ++ ++static void ttwu_queue(struct task_struct *p, int cpu, int wake_flags) ++{ ++ struct rq *rq = cpu_rq(cpu); ++ ++#if defined(CONFIG_SMP) ++ if (!cpus_share_cache(smp_processor_id(), cpu)) { ++ sched_clock_cpu(cpu); /* Sync clocks across CPUs */ ++ ttwu_queue_remote(p, cpu, wake_flags); ++ return; ++ } ++#endif ++ rq_lock(rq); ++ ttwu_do_activate(rq, p, wake_flags); ++ rq_unlock(rq); ++} ++ ++/*** ++ * try_to_wake_up - wake up a thread ++ * @p: the thread to be awakened ++ * @state: the mask of task states that can be woken ++ * @wake_flags: wake modifier flags (WF_*) ++ * ++ * Put it on the run-queue if it's not already there. The "current" ++ * thread is always on the run-queue (except when the actual ++ * re-schedule is in progress), and as such you're allowed to do ++ * the simpler "current->state = TASK_RUNNING" to mark yourself ++ * runnable without the overhead of this. ++ * ++ * Return: %true if @p was woken up, %false if it was already running. ++ * or @state didn't match @p's state. ++ */ ++static int ++try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) ++{ ++ unsigned long flags; ++ int cpu, success = 0; ++ ++ preempt_disable(); ++ if (p == current) { ++ /* ++ * We're waking current, this means 'p->on_rq' and 'task_cpu(p) ++ * == smp_processor_id()'. Together this means we can special ++ * case the whole 'p->on_rq && ttwu_remote()' case below ++ * without taking any locks. ++ * ++ * In particular: ++ * - we rely on Program-Order guarantees for all the ordering, ++ * - we're serialized against set_special_state() by virtue of ++ * it disabling IRQs (this allows not taking ->pi_lock). ++ */ ++ if (!(p->state & state)) ++ goto out; ++ ++ success = 1; ++ cpu = task_cpu(p); ++ trace_sched_waking(p); ++ p->state = TASK_RUNNING; ++ trace_sched_wakeup(p); ++ goto out; ++ } ++ ++ /* ++ * If we are going to wake up a thread waiting for CONDITION we ++ * need to ensure that CONDITION=1 done by the caller can not be ++ * reordered with p->state check below. This pairs with mb() in ++ * set_current_state() the waiting thread does. ++ */ ++ raw_spin_lock_irqsave(&p->pi_lock, flags); ++ smp_mb__after_spinlock(); ++ if (!(p->state & state)) ++ goto unlock; ++ ++ trace_sched_waking(p); ++ ++ /* We're going to change ->state: */ ++ success = 1; ++ cpu = task_cpu(p); ++ ++ /* ++ * Ensure we load p->on_rq _after_ p->state, otherwise it would ++ * be possible to, falsely, observe p->on_rq == 0 and get stuck ++ * in smp_cond_load_acquire() below. ++ * ++ * sched_ttwu_pending() try_to_wake_up() ++ * STORE p->on_rq = 1 LOAD p->state ++ * UNLOCK rq->lock ++ * ++ * __schedule() (switch to task 'p') ++ * LOCK rq->lock smp_rmb(); ++ * smp_mb__after_spinlock(); ++ * UNLOCK rq->lock ++ * ++ * [task p] ++ * STORE p->state = UNINTERRUPTIBLE LOAD p->on_rq ++ * ++ * Pairs with the LOCK+smp_mb__after_spinlock() on rq->lock in ++ * __schedule(). See the comment for smp_mb__after_spinlock(). ++ */ ++ smp_rmb(); ++ if (p->on_rq && ttwu_remote(p, wake_flags)) ++ goto unlock; ++ ++#ifdef CONFIG_SMP ++ /* ++ * Ensure we load p->on_cpu _after_ p->on_rq, otherwise it would be ++ * possible to, falsely, observe p->on_cpu == 0. ++ * ++ * One must be running (->on_cpu == 1) in order to remove oneself ++ * from the runqueue. ++ * ++ * __schedule() (switch to task 'p') try_to_wake_up() ++ * STORE p->on_cpu = 1 LOAD p->on_rq ++ * UNLOCK rq->lock ++ * ++ * __schedule() (put 'p' to sleep) ++ * LOCK rq->lock smp_rmb(); ++ * smp_mb__after_spinlock(); ++ * STORE p->on_rq = 0 LOAD p->on_cpu ++ * ++ * Pairs with the LOCK+smp_mb__after_spinlock() on rq->lock in ++ * __schedule(). See the comment for smp_mb__after_spinlock(). ++ */ ++ smp_rmb(); ++ ++ /* ++ * If the owning (remote) CPU is still in the middle of schedule() with ++ * this task as prev, wait until its done referencing the task. ++ * ++ * Pairs with the smp_store_release() in finish_task(). ++ * ++ * This ensures that tasks getting woken will be fully ordered against ++ * their previous state and preserve Program Order. ++ */ ++ smp_cond_load_acquire(&p->on_cpu, !VAL); ++ ++ p->sched_contributes_to_load = !!task_contributes_to_load(p); ++ p->state = TASK_WAKING; ++ ++ if (p->in_iowait) { ++ delayacct_blkio_end(p); ++ atomic_dec(&task_rq(p)->nr_iowait); ++ } ++ ++ cpu = select_best_cpu(p); ++ if (task_cpu(p) != cpu) { ++ wake_flags |= WF_MIGRATED; ++ psi_ttwu_dequeue(p); ++ set_task_cpu(p, cpu); ++ } ++ ++#else /* CONFIG_SMP */ ++ ++ if (p->in_iowait) { ++ delayacct_blkio_end(p); ++ atomic_dec(&task_rq(p)->nr_iowait); ++ } ++ ++#endif /* CONFIG_SMP */ ++ ++ ttwu_queue(p, cpu, wake_flags); ++unlock: ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++out: ++ if (success) ++ ttwu_stat(p, cpu, wake_flags); ++ preempt_enable(); ++ ++ return success; ++} ++ ++/** ++ * wake_up_process - Wake up a specific process ++ * @p: The process to be woken up. ++ * ++ * Attempt to wake up the nominated process and move it to the set of runnable ++ * processes. ++ * ++ * Return: 1 if the process was woken up, 0 if it was already running. ++ * ++ * This function executes a full memory barrier before accessing the task state. ++ */ ++int wake_up_process(struct task_struct *p) ++{ ++ return try_to_wake_up(p, TASK_NORMAL, 0); ++} ++EXPORT_SYMBOL(wake_up_process); ++ ++int wake_up_state(struct task_struct *p, unsigned int state) ++{ ++ return try_to_wake_up(p, state, 0); ++} ++ ++static void time_slice_expired(struct task_struct *p, struct rq *rq); ++ ++/* ++ * Perform scheduler related setup for a newly forked process p. ++ * p is forked by current. ++ */ ++int sched_fork(unsigned long __maybe_unused clone_flags, struct task_struct *p) ++{ ++ unsigned long flags; ++ ++#ifdef CONFIG_PREEMPT_NOTIFIERS ++ INIT_HLIST_HEAD(&p->preempt_notifiers); ++#endif ++ ++#ifdef CONFIG_COMPACTION ++ p->capture_control = NULL; ++#endif ++ ++ /* ++ * We mark the process as NEW here. This guarantees that ++ * nobody will actually run it, and a signal or other external ++ * event cannot wake it up and insert it on the runqueue either. ++ */ ++ p->state = TASK_NEW; ++ ++ /* ++ * The process state is set to the same value of the process executing ++ * do_fork() code. That is running. This guarantees that nobody will ++ * actually run it, and a signal or other external event cannot wake ++ * it up and insert it on the runqueue either. ++ */ ++ ++ /* Should be reset in fork.c but done here for ease of MuQSS patching */ ++ p->on_cpu = ++ p->on_rq = ++ p->utime = ++ p->stime = ++ p->sched_time = ++ p->stime_ns = ++ p->utime_ns = 0; ++ skiplist_node_init(&p->node); ++ ++ /* ++ * Revert to default priority/policy on fork if requested. ++ */ ++ if (unlikely(p->sched_reset_on_fork)) { ++ if (p->policy == SCHED_FIFO || p->policy == SCHED_RR || p-> policy == SCHED_ISO) { ++ p->policy = SCHED_NORMAL; ++ p->normal_prio = normal_prio(p); ++ } ++ ++ if (PRIO_TO_NICE(p->static_prio) < 0) { ++ p->static_prio = NICE_TO_PRIO(0); ++ p->normal_prio = p->static_prio; ++ } ++ ++ /* ++ * We don't need the reset flag anymore after the fork. It has ++ * fulfilled its duty: ++ */ ++ p->sched_reset_on_fork = 0; ++ } ++ ++ /* ++ * Silence PROVE_RCU. ++ */ ++ raw_spin_lock_irqsave(&p->pi_lock, flags); ++ set_task_cpu(p, smp_processor_id()); ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++ ++#ifdef CONFIG_SCHED_INFO ++ if (unlikely(sched_info_on())) ++ memset(&p->sched_info, 0, sizeof(p->sched_info)); ++#endif ++ init_task_preempt_count(p); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_SCHEDSTATS ++ ++DEFINE_STATIC_KEY_FALSE(sched_schedstats); ++static bool __initdata __sched_schedstats = false; ++ ++static void set_schedstats(bool enabled) ++{ ++ if (enabled) ++ static_branch_enable(&sched_schedstats); ++ else ++ static_branch_disable(&sched_schedstats); ++} ++ ++void force_schedstat_enabled(void) ++{ ++ if (!schedstat_enabled()) { ++ pr_info("kernel profiling enabled schedstats, disable via kernel.sched_schedstats.\n"); ++ static_branch_enable(&sched_schedstats); ++ } ++} ++ ++static int __init setup_schedstats(char *str) ++{ ++ int ret = 0; ++ if (!str) ++ goto out; ++ ++ /* ++ * This code is called before jump labels have been set up, so we can't ++ * change the static branch directly just yet. Instead set a temporary ++ * variable so init_schedstats() can do it later. ++ */ ++ if (!strcmp(str, "enable")) { ++ __sched_schedstats = true; ++ ret = 1; ++ } else if (!strcmp(str, "disable")) { ++ __sched_schedstats = false; ++ ret = 1; ++ } ++out: ++ if (!ret) ++ pr_warn("Unable to parse schedstats=\n"); ++ ++ return ret; ++} ++__setup("schedstats=", setup_schedstats); ++ ++static void __init init_schedstats(void) ++{ ++ set_schedstats(__sched_schedstats); ++} ++ ++#ifdef CONFIG_PROC_SYSCTL ++int sysctl_schedstats(struct ctl_table *table, int write, ++ void __user *buffer, size_t *lenp, loff_t *ppos) ++{ ++ struct ctl_table t; ++ int err; ++ int state = static_branch_likely(&sched_schedstats); ++ ++ if (write && !capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ ++ t = *table; ++ t.data = &state; ++ err = proc_dointvec_minmax(&t, write, buffer, lenp, ppos); ++ if (err < 0) ++ return err; ++ if (write) ++ set_schedstats(state); ++ return err; ++} ++#endif /* CONFIG_PROC_SYSCTL */ ++#else /* !CONFIG_SCHEDSTATS */ ++static inline void init_schedstats(void) {} ++#endif /* CONFIG_SCHEDSTATS */ ++ ++static void update_cpu_clock_switch(struct rq *rq, struct task_struct *p); ++ ++static void account_task_cpu(struct rq *rq, struct task_struct *p) ++{ ++ update_clocks(rq); ++ /* This isn't really a context switch but accounting is the same */ ++ update_cpu_clock_switch(rq, p); ++ p->last_ran = rq->niffies; ++} ++ ++bool sched_smp_initialized __read_mostly; ++ ++static inline int hrexpiry_enabled(struct rq *rq) ++{ ++ if (unlikely(!cpu_active(cpu_of(rq)) || !sched_smp_initialized)) ++ return 0; ++ return hrtimer_is_hres_active(&rq->hrexpiry_timer); ++} ++ ++/* ++ * Use HR-timers to deliver accurate preemption points. ++ */ ++static inline void hrexpiry_clear(struct rq *rq) ++{ ++ if (!hrexpiry_enabled(rq)) ++ return; ++ if (hrtimer_active(&rq->hrexpiry_timer)) ++ hrtimer_cancel(&rq->hrexpiry_timer); ++} ++ ++/* ++ * High-resolution time_slice expiry. ++ * Runs from hardirq context with interrupts disabled. ++ */ ++static enum hrtimer_restart hrexpiry(struct hrtimer *timer) ++{ ++ struct rq *rq = container_of(timer, struct rq, hrexpiry_timer); ++ struct task_struct *p; ++ ++ /* This can happen during CPU hotplug / resume */ ++ if (unlikely(cpu_of(rq) != smp_processor_id())) ++ goto out; ++ ++ /* ++ * We're doing this without the runqueue lock but this should always ++ * be run on the local CPU. Time slice should run out in __schedule ++ * but we set it to zero here in case niffies is slightly less. ++ */ ++ p = rq->curr; ++ p->time_slice = 0; ++ __set_tsk_resched(p); ++out: ++ return HRTIMER_NORESTART; ++} ++ ++/* ++ * Called to set the hrexpiry timer state. ++ * ++ * called with irqs disabled from the local CPU only ++ */ ++static void hrexpiry_start(struct rq *rq, u64 delay) ++{ ++ if (!hrexpiry_enabled(rq)) ++ return; ++ ++ hrtimer_start(&rq->hrexpiry_timer, ns_to_ktime(delay), ++ HRTIMER_MODE_REL_PINNED); ++} ++ ++static void init_rq_hrexpiry(struct rq *rq) ++{ ++ hrtimer_init(&rq->hrexpiry_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); ++ rq->hrexpiry_timer.function = hrexpiry; ++} ++ ++static inline int rq_dither(struct rq *rq) ++{ ++ if (!hrexpiry_enabled(rq)) ++ return HALF_JIFFY_US; ++ return 0; ++} ++ ++/* ++ * wake_up_new_task - wake up a newly created task for the first time. ++ * ++ * This function will do some initial scheduler statistics housekeeping ++ * that must be done for every newly created context, then puts the task ++ * on the runqueue and wakes it. ++ */ ++void wake_up_new_task(struct task_struct *p) ++{ ++ struct task_struct *parent, *rq_curr; ++ struct rq *rq, *new_rq; ++ unsigned long flags; ++ ++ parent = p->parent; ++ ++ raw_spin_lock_irqsave(&p->pi_lock, flags); ++ p->state = TASK_RUNNING; ++ /* Task_rq can't change yet on a new task */ ++ new_rq = rq = task_rq(p); ++ if (unlikely(needs_other_cpu(p, task_cpu(p)))) { ++ set_task_cpu(p, valid_task_cpu(p)); ++ new_rq = task_rq(p); ++ } ++ ++ double_rq_lock(rq, new_rq); ++ rq_curr = rq->curr; ++ ++ /* ++ * Make sure we do not leak PI boosting priority to the child. ++ */ ++ p->prio = rq_curr->normal_prio; ++ ++ trace_sched_wakeup_new(p); ++ ++ /* ++ * Share the timeslice between parent and child, thus the ++ * total amount of pending timeslices in the system doesn't change, ++ * resulting in more scheduling fairness. If it's negative, it won't ++ * matter since that's the same as being 0. rq->rq_deadline is only ++ * modified within schedule() so it is always equal to ++ * current->deadline. ++ */ ++ account_task_cpu(rq, rq_curr); ++ p->last_ran = rq_curr->last_ran; ++ if (likely(rq_curr->policy != SCHED_FIFO)) { ++ rq_curr->time_slice /= 2; ++ if (rq_curr->time_slice < RESCHED_US) { ++ /* ++ * Forking task has run out of timeslice. Reschedule it and ++ * start its child with a new time slice and deadline. The ++ * child will end up running first because its deadline will ++ * be slightly earlier. ++ */ ++ __set_tsk_resched(rq_curr); ++ time_slice_expired(p, new_rq); ++ if (suitable_idle_cpus(p)) ++ resched_best_idle(p, task_cpu(p)); ++ else if (unlikely(rq != new_rq)) ++ try_preempt(p, new_rq); ++ } else { ++ p->time_slice = rq_curr->time_slice; ++ if (rq_curr == parent && rq == new_rq && !suitable_idle_cpus(p)) { ++ /* ++ * The VM isn't cloned, so we're in a good position to ++ * do child-runs-first in anticipation of an exec. This ++ * usually avoids a lot of COW overhead. ++ */ ++ __set_tsk_resched(rq_curr); ++ } else { ++ /* ++ * Adjust the hrexpiry since rq_curr will keep ++ * running and its timeslice has been shortened. ++ */ ++ hrexpiry_start(rq, US_TO_NS(rq_curr->time_slice)); ++ try_preempt(p, new_rq); ++ } ++ } ++ } else { ++ time_slice_expired(p, new_rq); ++ try_preempt(p, new_rq); ++ } ++ activate_task(new_rq, p, 0); ++ double_rq_unlock(rq, new_rq); ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++} ++ ++#ifdef CONFIG_PREEMPT_NOTIFIERS ++ ++static DEFINE_STATIC_KEY_FALSE(preempt_notifier_key); ++ ++void preempt_notifier_inc(void) ++{ ++ static_branch_inc(&preempt_notifier_key); ++} ++EXPORT_SYMBOL_GPL(preempt_notifier_inc); ++ ++void preempt_notifier_dec(void) ++{ ++ static_branch_dec(&preempt_notifier_key); ++} ++EXPORT_SYMBOL_GPL(preempt_notifier_dec); ++ ++/** ++ * preempt_notifier_register - tell me when current is being preempted & rescheduled ++ * @notifier: notifier struct to register ++ */ ++void preempt_notifier_register(struct preempt_notifier *notifier) ++{ ++ if (!static_branch_unlikely(&preempt_notifier_key)) ++ WARN(1, "registering preempt_notifier while notifiers disabled\n"); ++ ++ hlist_add_head(¬ifier->link, ¤t->preempt_notifiers); ++} ++EXPORT_SYMBOL_GPL(preempt_notifier_register); ++ ++/** ++ * preempt_notifier_unregister - no longer interested in preemption notifications ++ * @notifier: notifier struct to unregister ++ * ++ * This is *not* safe to call from within a preemption notifier. ++ */ ++void preempt_notifier_unregister(struct preempt_notifier *notifier) ++{ ++ hlist_del(¬ifier->link); ++} ++EXPORT_SYMBOL_GPL(preempt_notifier_unregister); ++ ++static void __fire_sched_in_preempt_notifiers(struct task_struct *curr) ++{ ++ struct preempt_notifier *notifier; ++ ++ hlist_for_each_entry(notifier, &curr->preempt_notifiers, link) ++ notifier->ops->sched_in(notifier, raw_smp_processor_id()); ++} ++ ++static __always_inline void fire_sched_in_preempt_notifiers(struct task_struct *curr) ++{ ++ if (static_branch_unlikely(&preempt_notifier_key)) ++ __fire_sched_in_preempt_notifiers(curr); ++} ++ ++static void ++__fire_sched_out_preempt_notifiers(struct task_struct *curr, ++ struct task_struct *next) ++{ ++ struct preempt_notifier *notifier; ++ ++ hlist_for_each_entry(notifier, &curr->preempt_notifiers, link) ++ notifier->ops->sched_out(notifier, next); ++} ++ ++static __always_inline void ++fire_sched_out_preempt_notifiers(struct task_struct *curr, ++ struct task_struct *next) ++{ ++ if (static_branch_unlikely(&preempt_notifier_key)) ++ __fire_sched_out_preempt_notifiers(curr, next); ++} ++ ++#else /* !CONFIG_PREEMPT_NOTIFIERS */ ++ ++static inline void fire_sched_in_preempt_notifiers(struct task_struct *curr) ++{ ++} ++ ++static inline void ++fire_sched_out_preempt_notifiers(struct task_struct *curr, ++ struct task_struct *next) ++{ ++} ++ ++#endif /* CONFIG_PREEMPT_NOTIFIERS */ ++ ++static inline void prepare_task(struct task_struct *next) ++{ ++ /* ++ * Claim the task as running, we do this before switching to it ++ * such that any running task will have this set. ++ */ ++ next->on_cpu = 1; ++} ++ ++static inline void finish_task(struct task_struct *prev) ++{ ++#ifdef CONFIG_SMP ++ /* ++ * After ->on_cpu is cleared, the task can be moved to a different CPU. ++ * We must ensure this doesn't happen until the switch is completely ++ * finished. ++ * ++ * In particular, the load of prev->state in finish_task_switch() must ++ * happen before this. ++ * ++ * Pairs with the smp_cond_load_acquire() in try_to_wake_up(). ++ */ ++ smp_store_release(&prev->on_cpu, 0); ++#endif ++} ++ ++static inline void ++prepare_lock_switch(struct rq *rq, struct task_struct *next) ++{ ++ /* ++ * Since the runqueue lock will be released by the next ++ * task (which is an invalid locking op but in the case ++ * of the scheduler it's an obvious special-case), so we ++ * do an early lockdep release here: ++ */ ++ spin_release(&rq->lock->dep_map, 1, _THIS_IP_); ++#ifdef CONFIG_DEBUG_SPINLOCK ++ /* this is a valid case when another task releases the spinlock */ ++ rq->lock->owner = next; ++#endif ++} ++ ++static inline void finish_lock_switch(struct rq *rq, struct task_struct *prev) ++{ ++ /* ++ * If we are tracking spinlock dependencies then we have to ++ * fix up the runqueue lock - which gets 'carried over' from ++ * prev into current: ++ */ ++ spin_acquire(&rq->lock->dep_map, 0, 0, _THIS_IP_); ++ ++#ifdef CONFIG_SMP ++ /* ++ * If prev was marked as migrating to another CPU in return_task, drop ++ * the local runqueue lock but leave interrupts disabled and grab the ++ * remote lock we're migrating it to before enabling them. ++ */ ++ if (unlikely(task_on_rq_migrating(prev))) { ++ sched_info_dequeued(rq, prev); ++ /* ++ * We move the ownership of prev to the new cpu now. ttwu can't ++ * activate prev to the wrong cpu since it has to grab this ++ * runqueue in ttwu_remote. ++ */ ++#ifdef CONFIG_THREAD_INFO_IN_TASK ++ prev->cpu = prev->wake_cpu; ++#else ++ task_thread_info(prev)->cpu = prev->wake_cpu; ++#endif ++ raw_spin_unlock(rq->lock); ++ ++ raw_spin_lock(&prev->pi_lock); ++ rq = __task_rq_lock(prev, NULL); ++ /* Check that someone else hasn't already queued prev */ ++ if (likely(!task_queued(prev))) { ++ enqueue_task(rq, prev, 0); ++ prev->on_rq = TASK_ON_RQ_QUEUED; ++ /* Wake up the CPU if it's not already running */ ++ resched_if_idle(rq); ++ } ++ raw_spin_unlock(&prev->pi_lock); ++ } ++#endif ++ rq_unlock(rq); ++ local_irq_enable(); ++} ++ ++#ifndef prepare_arch_switch ++# define prepare_arch_switch(next) do { } while (0) ++#endif ++#ifndef finish_arch_switch ++# define finish_arch_switch(prev) do { } while (0) ++#endif ++#ifndef finish_arch_post_lock_switch ++# define finish_arch_post_lock_switch() do { } while (0) ++#endif ++ ++/** ++ * prepare_task_switch - prepare to switch tasks ++ * @rq: the runqueue preparing to switch ++ * @next: the task we are going to switch to. ++ * ++ * This is called with the rq lock held and interrupts off. It must ++ * be paired with a subsequent finish_task_switch after the context ++ * switch. ++ * ++ * prepare_task_switch sets up locking and calls architecture specific ++ * hooks. ++ */ ++static inline void ++prepare_task_switch(struct rq *rq, struct task_struct *prev, ++ struct task_struct *next) ++{ ++ kcov_prepare_switch(prev); ++ sched_info_switch(rq, prev, next); ++ perf_event_task_sched_out(prev, next); ++ rseq_preempt(prev); ++ fire_sched_out_preempt_notifiers(prev, next); ++ prepare_task(next); ++ prepare_arch_switch(next); ++} ++ ++/** ++ * finish_task_switch - clean up after a task-switch ++ * @rq: runqueue associated with task-switch ++ * @prev: the thread we just switched away from. ++ * ++ * finish_task_switch must be called after the context switch, paired ++ * with a prepare_task_switch call before the context switch. ++ * finish_task_switch will reconcile locking set up by prepare_task_switch, ++ * and do any other architecture-specific cleanup actions. ++ * ++ * Note that we may have delayed dropping an mm in context_switch(). If ++ * so, we finish that here outside of the runqueue lock. (Doing it ++ * with the lock held can cause deadlocks; see schedule() for ++ * details.) ++ * ++ * The context switch have flipped the stack from under us and restored the ++ * local variables which were saved when this task called schedule() in the ++ * past. prev == current is still correct but we need to recalculate this_rq ++ * because prev may have moved to another CPU. ++ */ ++static void finish_task_switch(struct task_struct *prev) ++ __releases(rq->lock) ++{ ++ struct rq *rq = this_rq(); ++ struct mm_struct *mm = rq->prev_mm; ++ long prev_state; ++ ++ /* ++ * The previous task will have left us with a preempt_count of 2 ++ * because it left us after: ++ * ++ * schedule() ++ * preempt_disable(); // 1 ++ * __schedule() ++ * raw_spin_lock_irq(rq->lock) // 2 ++ * ++ * Also, see FORK_PREEMPT_COUNT. ++ */ ++ if (WARN_ONCE(preempt_count() != 2*PREEMPT_DISABLE_OFFSET, ++ "corrupted preempt_count: %s/%d/0x%x\n", ++ current->comm, current->pid, preempt_count())) ++ preempt_count_set(FORK_PREEMPT_COUNT); ++ ++ rq->prev_mm = NULL; ++ ++ /* ++ * A task struct has one reference for the use as "current". ++ * If a task dies, then it sets TASK_DEAD in tsk->state and calls ++ * schedule one last time. The schedule call will never return, and ++ * the scheduled task must drop that reference. ++ * ++ * We must observe prev->state before clearing prev->on_cpu (in ++ * finish_task), otherwise a concurrent wakeup can get prev ++ * running on another CPU and we could rave with its RUNNING -> DEAD ++ * transition, resulting in a double drop. ++ */ ++ prev_state = prev->state; ++ vtime_task_switch(prev); ++ perf_event_task_sched_in(prev, current); ++ finish_task(prev); ++ finish_lock_switch(rq, prev); ++ finish_arch_post_lock_switch(); ++ kcov_finish_switch(current); ++ ++ fire_sched_in_preempt_notifiers(current); ++ /* ++ * When switching through a kernel thread, the loop in ++ * membarrier_{private,global}_expedited() may have observed that ++ * kernel thread and not issued an IPI. It is therefore possible to ++ * schedule between user->kernel->user threads without passing though ++ * switch_mm(). Membarrier requires a barrier after storing to ++ * rq->curr, before returning to userspace, so provide them here: ++ * ++ * - a full memory barrier for {PRIVATE,GLOBAL}_EXPEDITED, implicitly ++ * provided by mmdrop(), ++ * - a sync_core for SYNC_CORE. ++ */ ++ if (mm) { ++ membarrier_mm_sync_core_before_usermode(mm); ++ mmdrop(mm); ++ } ++ if (unlikely(prev_state == TASK_DEAD)) { ++ /* ++ * Remove function-return probe instances associated with this ++ * task and put them back on the free list. ++ */ ++ kprobe_flush_task(prev); ++ ++ /* Task is done with its stack. */ ++ put_task_stack(prev); ++ ++ put_task_struct_rcu_user(prev); ++ } ++} ++ ++/** ++ * schedule_tail - first thing a freshly forked thread must call. ++ * @prev: the thread we just switched away from. ++ */ ++asmlinkage __visible void schedule_tail(struct task_struct *prev) ++{ ++ /* ++ * New tasks start with FORK_PREEMPT_COUNT, see there and ++ * finish_task_switch() for details. ++ * ++ * finish_task_switch() will drop rq->lock() and lower preempt_count ++ * and the preempt_enable() will end up enabling preemption (on ++ * PREEMPT_COUNT kernels). ++ */ ++ ++ finish_task_switch(prev); ++ preempt_enable(); ++ ++ if (current->set_child_tid) ++ put_user(task_pid_vnr(current), current->set_child_tid); ++ ++ calculate_sigpending(); ++} ++ ++/* ++ * context_switch - switch to the new MM and the new thread's register state. ++ */ ++static __always_inline void ++context_switch(struct rq *rq, struct task_struct *prev, ++ struct task_struct *next) ++{ ++ prepare_task_switch(rq, prev, next); ++ ++ /* ++ * For paravirt, this is coupled with an exit in switch_to to ++ * combine the page table reload and the switch backend into ++ * one hypercall. ++ */ ++ arch_start_context_switch(prev); ++ ++ /* ++ * kernel -> kernel lazy + transfer active ++ * user -> kernel lazy + mmgrab() active ++ * ++ * kernel -> user switch + mmdrop() active ++ * user -> user switch ++ */ ++ if (!next->mm) { // to kernel ++ enter_lazy_tlb(prev->active_mm, next); ++ ++ next->active_mm = prev->active_mm; ++ if (prev->mm) // from user ++ mmgrab(prev->active_mm); ++ else ++ prev->active_mm = NULL; ++ } else { // to user ++ membarrier_switch_mm(rq, prev->active_mm, next->mm); ++ /* ++ * sys_membarrier() requires an smp_mb() between setting ++ * rq->curr / membarrier_switch_mm() and returning to userspace. ++ * ++ * The below provides this either through switch_mm(), or in ++ * case 'prev->active_mm == next->mm' through ++ * finish_task_switch()'s mmdrop(). ++ */ ++ switch_mm_irqs_off(prev->active_mm, next->mm, next); ++ ++ if (!prev->mm) { // from kernel ++ /* will mmdrop() in finish_task_switch(). */ ++ rq->prev_mm = prev->active_mm; ++ prev->active_mm = NULL; ++ } ++ } ++ prepare_lock_switch(rq, next); ++ ++ /* Here we just switch the register state and the stack. */ ++ switch_to(prev, next, prev); ++ barrier(); ++ ++ finish_task_switch(prev); ++} ++ ++/* ++ * nr_running, nr_uninterruptible and nr_context_switches: ++ * ++ * externally visible scheduler statistics: current number of runnable ++ * threads, total number of context switches performed since bootup. ++ */ ++unsigned long nr_running(void) ++{ ++ unsigned long i, sum = 0; ++ ++ for_each_online_cpu(i) ++ sum += cpu_rq(i)->nr_running; ++ ++ return sum; ++} ++ ++static unsigned long nr_uninterruptible(void) ++{ ++ unsigned long i, sum = 0; ++ ++ for_each_online_cpu(i) ++ sum += cpu_rq(i)->nr_uninterruptible; ++ ++ return sum; ++} ++ ++/* ++ * Check if only the current task is running on the CPU. ++ * ++ * Caution: this function does not check that the caller has disabled ++ * preemption, thus the result might have a time-of-check-to-time-of-use ++ * race. The caller is responsible to use it correctly, for example: ++ * ++ * - from a non-preemptible section (of course) ++ * ++ * - from a thread that is bound to a single CPU ++ * ++ * - in a loop with very short iterations (e.g. a polling loop) ++ */ ++bool single_task_running(void) ++{ ++ if (rq_load(raw_rq()) == 1) ++ return true; ++ else ++ return false; ++} ++EXPORT_SYMBOL(single_task_running); ++ ++unsigned long long nr_context_switches(void) ++{ ++ int cpu; ++ unsigned long long sum = 0; ++ ++ for_each_possible_cpu(cpu) ++ sum += cpu_rq(cpu)->nr_switches; ++ ++ return sum; ++} ++ ++/* ++ * Consumers of these two interfaces, like for example the cpufreq menu ++ * governor are using nonsensical data. Boosting frequency for a CPU that has ++ * IO-wait which might not even end up running the task when it does become ++ * runnable. ++ */ ++ ++unsigned long nr_iowait_cpu(int cpu) ++{ ++ return atomic_read(&cpu_rq(cpu)->nr_iowait); ++} ++ ++/* ++ * IO-wait accounting, and how its mostly bollocks (on SMP). ++ * ++ * The idea behind IO-wait account is to account the idle time that we could ++ * have spend running if it were not for IO. That is, if we were to improve the ++ * storage performance, we'd have a proportional reduction in IO-wait time. ++ * ++ * This all works nicely on UP, where, when a task blocks on IO, we account ++ * idle time as IO-wait, because if the storage were faster, it could've been ++ * running and we'd not be idle. ++ * ++ * This has been extended to SMP, by doing the same for each CPU. This however ++ * is broken. ++ * ++ * Imagine for instance the case where two tasks block on one CPU, only the one ++ * CPU will have IO-wait accounted, while the other has regular idle. Even ++ * though, if the storage were faster, both could've ran at the same time, ++ * utilising both CPUs. ++ * ++ * This means, that when looking globally, the current IO-wait accounting on ++ * SMP is a lower bound, by reason of under accounting. ++ * ++ * Worse, since the numbers are provided per CPU, they are sometimes ++ * interpreted per CPU, and that is nonsensical. A blocked task isn't strictly ++ * associated with any one particular CPU, it can wake to another CPU than it ++ * blocked on. This means the per CPU IO-wait number is meaningless. ++ * ++ * Task CPU affinities can make all that even more 'interesting'. ++ */ ++ ++unsigned long nr_iowait(void) ++{ ++ unsigned long cpu, sum = 0; ++ ++ for_each_possible_cpu(cpu) ++ sum += nr_iowait_cpu(cpu); ++ ++ return sum; ++} ++ ++unsigned long nr_active(void) ++{ ++ return nr_running() + nr_uninterruptible(); ++} ++ ++/* Variables and functions for calc_load */ ++static unsigned long calc_load_update; ++unsigned long avenrun[3]; ++EXPORT_SYMBOL(avenrun); ++ ++/** ++ * get_avenrun - get the load average array ++ * @loads: pointer to dest load array ++ * @offset: offset to add ++ * @shift: shift count to shift the result left ++ * ++ * These values are estimates at best, so no need for locking. ++ */ ++void get_avenrun(unsigned long *loads, unsigned long offset, int shift) ++{ ++ loads[0] = (avenrun[0] + offset) << shift; ++ loads[1] = (avenrun[1] + offset) << shift; ++ loads[2] = (avenrun[2] + offset) << shift; ++} ++ ++/* ++ * calc_load - update the avenrun load estimates every LOAD_FREQ seconds. ++ */ ++void calc_global_load(unsigned long ticks) ++{ ++ long active; ++ ++ if (time_before(jiffies, READ_ONCE(calc_load_update))) ++ return; ++ active = nr_active() * FIXED_1; ++ ++ avenrun[0] = calc_load(avenrun[0], EXP_1, active); ++ avenrun[1] = calc_load(avenrun[1], EXP_5, active); ++ avenrun[2] = calc_load(avenrun[2], EXP_15, active); ++ ++ calc_load_update = jiffies + LOAD_FREQ; ++} ++ ++/** ++ * fixed_power_int - compute: x^n, in O(log n) time ++ * ++ * @x: base of the power ++ * @frac_bits: fractional bits of @x ++ * @n: power to raise @x to. ++ * ++ * By exploiting the relation between the definition of the natural power ++ * function: x^n := x*x*...*x (x multiplied by itself for n times), and ++ * the binary encoding of numbers used by computers: n := \Sum n_i * 2^i, ++ * (where: n_i \elem {0, 1}, the binary vector representing n), ++ * we find: x^n := x^(\Sum n_i * 2^i) := \Prod x^(n_i * 2^i), which is ++ * of course trivially computable in O(log_2 n), the length of our binary ++ * vector. ++ */ ++static unsigned long ++fixed_power_int(unsigned long x, unsigned int frac_bits, unsigned int n) ++{ ++ unsigned long result = 1UL << frac_bits; ++ ++ if (n) { ++ for (;;) { ++ if (n & 1) { ++ result *= x; ++ result += 1UL << (frac_bits - 1); ++ result >>= frac_bits; ++ } ++ n >>= 1; ++ if (!n) ++ break; ++ x *= x; ++ x += 1UL << (frac_bits - 1); ++ x >>= frac_bits; ++ } ++ } ++ ++ return result; ++} ++ ++/* ++ * a1 = a0 * e + a * (1 - e) ++ * ++ * a2 = a1 * e + a * (1 - e) ++ * = (a0 * e + a * (1 - e)) * e + a * (1 - e) ++ * = a0 * e^2 + a * (1 - e) * (1 + e) ++ * ++ * a3 = a2 * e + a * (1 - e) ++ * = (a0 * e^2 + a * (1 - e) * (1 + e)) * e + a * (1 - e) ++ * = a0 * e^3 + a * (1 - e) * (1 + e + e^2) ++ * ++ * ... ++ * ++ * an = a0 * e^n + a * (1 - e) * (1 + e + ... + e^n-1) [1] ++ * = a0 * e^n + a * (1 - e) * (1 - e^n)/(1 - e) ++ * = a0 * e^n + a * (1 - e^n) ++ * ++ * [1] application of the geometric series: ++ * ++ * n 1 - x^(n+1) ++ * S_n := \Sum x^i = ------------- ++ * i=0 1 - x ++ */ ++unsigned long ++calc_load_n(unsigned long load, unsigned long exp, ++ unsigned long active, unsigned int n) ++{ ++ return calc_load(load, fixed_power_int(exp, FSHIFT, n), active); ++} ++ ++DEFINE_PER_CPU(struct kernel_stat, kstat); ++DEFINE_PER_CPU(struct kernel_cpustat, kernel_cpustat); ++ ++EXPORT_PER_CPU_SYMBOL(kstat); ++EXPORT_PER_CPU_SYMBOL(kernel_cpustat); ++ ++#ifdef CONFIG_PARAVIRT ++static inline u64 steal_ticks(u64 steal) ++{ ++ if (unlikely(steal > NSEC_PER_SEC)) ++ return div_u64(steal, TICK_NSEC); ++ ++ return __iter_div_u64_rem(steal, TICK_NSEC, &steal); ++} ++#endif ++ ++#ifndef nsecs_to_cputime ++# define nsecs_to_cputime(__nsecs) nsecs_to_jiffies(__nsecs) ++#endif ++ ++/* ++ * On each tick, add the number of nanoseconds to the unbanked variables and ++ * once one tick's worth has accumulated, account it allowing for accurate ++ * sub-tick accounting and totals. Use the TICK_APPROX_NS to match the way we ++ * deduct nanoseconds. ++ */ ++static void pc_idle_time(struct rq *rq, struct task_struct *idle, unsigned long ns) ++{ ++ u64 *cpustat = kcpustat_this_cpu->cpustat; ++ unsigned long ticks; ++ ++ if (atomic_read(&rq->nr_iowait) > 0) { ++ rq->iowait_ns += ns; ++ if (rq->iowait_ns >= JIFFY_NS) { ++ ticks = NS_TO_JIFFIES(rq->iowait_ns); ++ cpustat[CPUTIME_IOWAIT] += (__force u64)TICK_APPROX_NS * ticks; ++ rq->iowait_ns %= JIFFY_NS; ++ } ++ } else { ++ rq->idle_ns += ns; ++ if (rq->idle_ns >= JIFFY_NS) { ++ ticks = NS_TO_JIFFIES(rq->idle_ns); ++ cpustat[CPUTIME_IDLE] += (__force u64)TICK_APPROX_NS * ticks; ++ rq->idle_ns %= JIFFY_NS; ++ } ++ } ++ acct_update_integrals(idle); ++} ++ ++static void pc_system_time(struct rq *rq, struct task_struct *p, ++ int hardirq_offset, unsigned long ns) ++{ ++ u64 *cpustat = kcpustat_this_cpu->cpustat; ++ unsigned long ticks; ++ ++ p->stime_ns += ns; ++ if (p->stime_ns >= JIFFY_NS) { ++ ticks = NS_TO_JIFFIES(p->stime_ns); ++ p->stime_ns %= JIFFY_NS; ++ p->stime += (__force u64)TICK_APPROX_NS * ticks; ++ account_group_system_time(p, TICK_APPROX_NS * ticks); ++ } ++ p->sched_time += ns; ++ account_group_exec_runtime(p, ns); ++ ++ if (hardirq_count() - hardirq_offset) { ++ rq->irq_ns += ns; ++ if (rq->irq_ns >= JIFFY_NS) { ++ ticks = NS_TO_JIFFIES(rq->irq_ns); ++ cpustat[CPUTIME_IRQ] += (__force u64)TICK_APPROX_NS * ticks; ++ rq->irq_ns %= JIFFY_NS; ++ } ++ } else if (in_serving_softirq()) { ++ rq->softirq_ns += ns; ++ if (rq->softirq_ns >= JIFFY_NS) { ++ ticks = NS_TO_JIFFIES(rq->softirq_ns); ++ cpustat[CPUTIME_SOFTIRQ] += (__force u64)TICK_APPROX_NS * ticks; ++ rq->softirq_ns %= JIFFY_NS; ++ } ++ } else { ++ rq->system_ns += ns; ++ if (rq->system_ns >= JIFFY_NS) { ++ ticks = NS_TO_JIFFIES(rq->system_ns); ++ cpustat[CPUTIME_SYSTEM] += (__force u64)TICK_APPROX_NS * ticks; ++ rq->system_ns %= JIFFY_NS; ++ } ++ } ++ acct_update_integrals(p); ++} ++ ++static void pc_user_time(struct rq *rq, struct task_struct *p, unsigned long ns) ++{ ++ u64 *cpustat = kcpustat_this_cpu->cpustat; ++ unsigned long ticks; ++ ++ p->utime_ns += ns; ++ if (p->utime_ns >= JIFFY_NS) { ++ ticks = NS_TO_JIFFIES(p->utime_ns); ++ p->utime_ns %= JIFFY_NS; ++ p->utime += (__force u64)TICK_APPROX_NS * ticks; ++ account_group_user_time(p, TICK_APPROX_NS * ticks); ++ } ++ p->sched_time += ns; ++ account_group_exec_runtime(p, ns); ++ ++ if (this_cpu_ksoftirqd() == p) { ++ /* ++ * ksoftirqd time do not get accounted in cpu_softirq_time. ++ * So, we have to handle it separately here. ++ */ ++ rq->softirq_ns += ns; ++ if (rq->softirq_ns >= JIFFY_NS) { ++ ticks = NS_TO_JIFFIES(rq->softirq_ns); ++ cpustat[CPUTIME_SOFTIRQ] += (__force u64)TICK_APPROX_NS * ticks; ++ rq->softirq_ns %= JIFFY_NS; ++ } ++ } ++ ++ if (task_nice(p) > 0 || idleprio_task(p)) { ++ rq->nice_ns += ns; ++ if (rq->nice_ns >= JIFFY_NS) { ++ ticks = NS_TO_JIFFIES(rq->nice_ns); ++ cpustat[CPUTIME_NICE] += (__force u64)TICK_APPROX_NS * ticks; ++ rq->nice_ns %= JIFFY_NS; ++ } ++ } else { ++ rq->user_ns += ns; ++ if (rq->user_ns >= JIFFY_NS) { ++ ticks = NS_TO_JIFFIES(rq->user_ns); ++ cpustat[CPUTIME_USER] += (__force u64)TICK_APPROX_NS * ticks; ++ rq->user_ns %= JIFFY_NS; ++ } ++ } ++ acct_update_integrals(p); ++} ++ ++/* ++ * This is called on clock ticks. ++ * Bank in p->sched_time the ns elapsed since the last tick or switch. ++ * CPU scheduler quota accounting is also performed here in microseconds. ++ */ ++static void update_cpu_clock_tick(struct rq *rq, struct task_struct *p) ++{ ++ s64 account_ns = rq->niffies - p->last_ran; ++ struct task_struct *idle = rq->idle; ++ ++ /* Accurate tick timekeeping */ ++ if (user_mode(get_irq_regs())) ++ pc_user_time(rq, p, account_ns); ++ else if (p != idle || (irq_count() != HARDIRQ_OFFSET)) { ++ pc_system_time(rq, p, HARDIRQ_OFFSET, account_ns); ++ } else ++ pc_idle_time(rq, idle, account_ns); ++ ++ /* time_slice accounting is done in usecs to avoid overflow on 32bit */ ++ if (p->policy != SCHED_FIFO && p != idle) ++ p->time_slice -= NS_TO_US(account_ns); ++ ++ p->last_ran = rq->niffies; ++} ++ ++/* ++ * This is called on context switches. ++ * Bank in p->sched_time the ns elapsed since the last tick or switch. ++ * CPU scheduler quota accounting is also performed here in microseconds. ++ */ ++static void update_cpu_clock_switch(struct rq *rq, struct task_struct *p) ++{ ++ s64 account_ns = rq->niffies - p->last_ran; ++ struct task_struct *idle = rq->idle; ++ ++ /* Accurate subtick timekeeping */ ++ if (p != idle) ++ pc_user_time(rq, p, account_ns); ++ else ++ pc_idle_time(rq, idle, account_ns); ++ ++ /* time_slice accounting is done in usecs to avoid overflow on 32bit */ ++ if (p->policy != SCHED_FIFO && p != idle) ++ p->time_slice -= NS_TO_US(account_ns); ++} ++ ++/* ++ * Return any ns on the sched_clock that have not yet been accounted in ++ * @p in case that task is currently running. ++ * ++ * Called with task_rq_lock(p) held. ++ */ ++static inline u64 do_task_delta_exec(struct task_struct *p, struct rq *rq) ++{ ++ u64 ns = 0; ++ ++ /* ++ * Must be ->curr _and_ ->on_rq. If dequeued, we would ++ * project cycles that may never be accounted to this ++ * thread, breaking clock_gettime(). ++ */ ++ if (p == rq->curr && task_on_rq_queued(p)) { ++ update_clocks(rq); ++ ns = rq->niffies - p->last_ran; ++ } ++ ++ return ns; ++} ++ ++/* ++ * Return accounted runtime for the task. ++ * Return separately the current's pending runtime that have not been ++ * accounted yet. ++ * ++ */ ++unsigned long long task_sched_runtime(struct task_struct *p) ++{ ++ struct rq_flags rf; ++ struct rq *rq; ++ u64 ns; ++ ++#if defined(CONFIG_64BIT) && defined(CONFIG_SMP) ++ /* ++ * 64-bit doesn't need locks to atomically read a 64-bit value. ++ * So we have a optimisation chance when the task's delta_exec is 0. ++ * Reading ->on_cpu is racy, but this is ok. ++ * ++ * If we race with it leaving CPU, we'll take a lock. So we're correct. ++ * If we race with it entering CPU, unaccounted time is 0. This is ++ * indistinguishable from the read occurring a few cycles earlier. ++ * If we see ->on_cpu without ->on_rq, the task is leaving, and has ++ * been accounted, so we're correct here as well. ++ */ ++ if (!p->on_cpu || !task_on_rq_queued(p)) ++ return tsk_seruntime(p); ++#endif ++ ++ rq = task_rq_lock(p, &rf); ++ ns = p->sched_time + do_task_delta_exec(p, rq); ++ task_rq_unlock(rq, p, &rf); ++ ++ return ns; ++} ++ ++/* ++ * Functions to test for when SCHED_ISO tasks have used their allocated ++ * quota as real time scheduling and convert them back to SCHED_NORMAL. All ++ * data is modified only by the local runqueue during scheduler_tick with ++ * interrupts disabled. ++ */ ++ ++/* ++ * Test if SCHED_ISO tasks have run longer than their alloted period as RT ++ * tasks and set the refractory flag if necessary. There is 10% hysteresis ++ * for unsetting the flag. 115/128 is ~90/100 as a fast shift instead of a ++ * slow division. ++ */ ++static inline void iso_tick(struct rq *rq) ++{ ++ rq->iso_ticks = rq->iso_ticks * (ISO_PERIOD - 1) / ISO_PERIOD; ++ rq->iso_ticks += 100; ++ if (rq->iso_ticks > ISO_PERIOD * sched_iso_cpu) { ++ rq->iso_refractory = true; ++ if (unlikely(rq->iso_ticks > ISO_PERIOD * 100)) ++ rq->iso_ticks = ISO_PERIOD * 100; ++ } ++} ++ ++/* No SCHED_ISO task was running so decrease rq->iso_ticks */ ++static inline void no_iso_tick(struct rq *rq, int ticks) ++{ ++ if (rq->iso_ticks > 0 || rq->iso_refractory) { ++ rq->iso_ticks = rq->iso_ticks * (ISO_PERIOD - ticks) / ISO_PERIOD; ++ if (rq->iso_ticks < ISO_PERIOD * (sched_iso_cpu * 115 / 128)) { ++ rq->iso_refractory = false; ++ if (unlikely(rq->iso_ticks < 0)) ++ rq->iso_ticks = 0; ++ } ++ } ++} ++ ++/* This manages tasks that have run out of timeslice during a scheduler_tick */ ++static void task_running_tick(struct rq *rq) ++{ ++ struct task_struct *p = rq->curr; ++ ++ /* ++ * If a SCHED_ISO task is running we increment the iso_ticks. In ++ * order to prevent SCHED_ISO tasks from causing starvation in the ++ * presence of true RT tasks we account those as iso_ticks as well. ++ */ ++ if (rt_task(p) || task_running_iso(p)) ++ iso_tick(rq); ++ else ++ no_iso_tick(rq, 1); ++ ++ /* SCHED_FIFO tasks never run out of timeslice. */ ++ if (p->policy == SCHED_FIFO) ++ return; ++ ++ if (iso_task(p)) { ++ if (task_running_iso(p)) { ++ if (rq->iso_refractory) { ++ /* ++ * SCHED_ISO task is running as RT and limit ++ * has been hit. Force it to reschedule as ++ * SCHED_NORMAL by zeroing its time_slice ++ */ ++ p->time_slice = 0; ++ } ++ } else if (!rq->iso_refractory) { ++ /* Can now run again ISO. Reschedule to pick up prio */ ++ goto out_resched; ++ } ++ } ++ ++ /* ++ * Tasks that were scheduled in the first half of a tick are not ++ * allowed to run into the 2nd half of the next tick if they will ++ * run out of time slice in the interim. Otherwise, if they have ++ * less than RESCHED_US μs of time slice left they will be rescheduled. ++ * Dither is used as a backup for when hrexpiry is disabled or high res ++ * timers not configured in. ++ */ ++ if (p->time_slice - rq->dither >= RESCHED_US) ++ return; ++out_resched: ++ rq_lock(rq); ++ __set_tsk_resched(p); ++ rq_unlock(rq); ++} ++ ++static inline void task_tick(struct rq *rq) ++{ ++ if (!rq_idle(rq)) ++ task_running_tick(rq); ++ else if (rq->last_jiffy > rq->last_scheduler_tick) ++ no_iso_tick(rq, rq->last_jiffy - rq->last_scheduler_tick); ++} ++ ++#ifdef CONFIG_NO_HZ_FULL ++/* ++ * We can stop the timer tick any time highres timers are active since ++ * we rely entirely on highres timeouts for task expiry rescheduling. ++ */ ++static void sched_stop_tick(struct rq *rq, int cpu) ++{ ++ if (!hrexpiry_enabled(rq)) ++ return; ++ if (!tick_nohz_full_enabled()) ++ return; ++ if (!tick_nohz_full_cpu(cpu)) ++ return; ++ tick_nohz_dep_clear_cpu(cpu, TICK_DEP_BIT_SCHED); ++} ++ ++static inline void sched_start_tick(struct rq *rq, int cpu) ++{ ++ tick_nohz_dep_set_cpu(cpu, TICK_DEP_BIT_SCHED); ++} ++ ++struct tick_work { ++ int cpu; ++ atomic_t state; ++ struct delayed_work work; ++}; ++/* Values for ->state, see diagram below. */ ++#define TICK_SCHED_REMOTE_OFFLINE 0 ++#define TICK_SCHED_REMOTE_OFFLINING 1 ++#define TICK_SCHED_REMOTE_RUNNING 2 ++ ++/* ++ * State diagram for ->state: ++ * ++ * ++ * TICK_SCHED_REMOTE_OFFLINE ++ * | ^ ++ * | | ++ * | | sched_tick_remote() ++ * | | ++ * | | ++ * +--TICK_SCHED_REMOTE_OFFLINING ++ * | ^ ++ * | | ++ * sched_tick_start() | | sched_tick_stop() ++ * | | ++ * V | ++ * TICK_SCHED_REMOTE_RUNNING ++ * ++ * ++ * Other transitions get WARN_ON_ONCE(), except that sched_tick_remote() ++ * and sched_tick_start() are happy to leave the state in RUNNING. ++ */ ++ ++static struct tick_work __percpu *tick_work_cpu; ++ ++static void sched_tick_remote(struct work_struct *work) ++{ ++ struct delayed_work *dwork = to_delayed_work(work); ++ struct tick_work *twork = container_of(dwork, struct tick_work, work); ++ int cpu = twork->cpu; ++ struct rq *rq = cpu_rq(cpu); ++ struct task_struct *curr; ++ u64 delta; ++ int os; ++ ++ /* ++ * Handle the tick only if it appears the remote CPU is running in full ++ * dynticks mode. The check is racy by nature, but missing a tick or ++ * having one too much is no big deal because the scheduler tick updates ++ * statistics and checks timeslices in a time-independent way, regardless ++ * of when exactly it is running. ++ */ ++ if (!tick_nohz_tick_stopped_cpu(cpu)) ++ goto out_requeue; ++ ++ rq_lock_irq(rq); ++ curr = rq->curr; ++ if (cpu_is_offline(cpu)) ++ goto out_unlock; ++ ++ curr = rq->curr; ++ update_rq_clock(rq); ++ ++ if (!is_idle_task(curr)) { ++ /* ++ * Make sure the next tick runs within a reasonable ++ * amount of time. ++ */ ++ delta = rq_clock_task(rq) - curr->last_ran; ++ WARN_ON_ONCE(delta > (u64)NSEC_PER_SEC * 3); ++ } ++ task_tick(rq); ++ ++out_unlock: ++ rq_unlock_irq(rq, NULL); ++ ++out_requeue: ++ ++ /* ++ * Run the remote tick once per second (1Hz). This arbitrary ++ * frequency is large enough to avoid overload but short enough ++ * to keep scheduler internal stats reasonably up to date. But ++ * first update state to reflect hotplug activity if required. ++ */ ++ os = atomic_fetch_add_unless(&twork->state, -1, TICK_SCHED_REMOTE_RUNNING); ++ WARN_ON_ONCE(os == TICK_SCHED_REMOTE_OFFLINE); ++ if (os == TICK_SCHED_REMOTE_RUNNING) ++ queue_delayed_work(system_unbound_wq, dwork, HZ); ++} ++ ++static void sched_tick_start(int cpu) ++{ ++ struct tick_work *twork; ++ int os; ++ ++ if (housekeeping_cpu(cpu, HK_FLAG_TICK)) ++ return; ++ ++ WARN_ON_ONCE(!tick_work_cpu); ++ ++ twork = per_cpu_ptr(tick_work_cpu, cpu); ++ os = atomic_xchg(&twork->state, TICK_SCHED_REMOTE_RUNNING); ++ WARN_ON_ONCE(os == TICK_SCHED_REMOTE_RUNNING); ++ if (os == TICK_SCHED_REMOTE_OFFLINE) { ++ twork->cpu = cpu; ++ INIT_DELAYED_WORK(&twork->work, sched_tick_remote); ++ queue_delayed_work(system_unbound_wq, &twork->work, HZ); ++ } ++} ++ ++#ifdef CONFIG_HOTPLUG_CPU ++static void sched_tick_stop(int cpu) ++{ ++ struct tick_work *twork; ++ int os; ++ ++ if (housekeeping_cpu(cpu, HK_FLAG_TICK)) ++ return; ++ ++ WARN_ON_ONCE(!tick_work_cpu); ++ ++ twork = per_cpu_ptr(tick_work_cpu, cpu); ++ /* There cannot be competing actions, but don't rely on stop-machine. */ ++ os = atomic_xchg(&twork->state, TICK_SCHED_REMOTE_OFFLINING); ++ WARN_ON_ONCE(os != TICK_SCHED_REMOTE_RUNNING); ++ /* Don't cancel, as this would mess up the state machine. */ ++} ++#endif /* CONFIG_HOTPLUG_CPU */ ++ ++int __init sched_tick_offload_init(void) ++{ ++ tick_work_cpu = alloc_percpu(struct tick_work); ++ BUG_ON(!tick_work_cpu); ++ return 0; ++} ++ ++#else /* !CONFIG_NO_HZ_FULL */ ++static inline void sched_stop_tick(struct rq *rq, int cpu) {} ++static inline void sched_start_tick(struct rq *rq, int cpu) {} ++static inline void sched_tick_start(int cpu) { } ++static inline void sched_tick_stop(int cpu) { } ++#endif ++ ++/* ++ * This function gets called by the timer code, with HZ frequency. ++ * We call it with interrupts disabled. ++ */ ++void scheduler_tick(void) ++{ ++ int cpu __maybe_unused = smp_processor_id(); ++ struct rq *rq = cpu_rq(cpu); ++ ++ sched_clock_tick(); ++ update_clocks(rq); ++ update_load_avg(rq, 0); ++ update_cpu_clock_tick(rq, rq->curr); ++ task_tick(rq); ++ rq->last_scheduler_tick = rq->last_jiffy; ++ rq->last_tick = rq->clock; ++ psi_task_tick(rq); ++ perf_event_task_tick(); ++ sched_stop_tick(rq, cpu); ++} ++ ++#if defined(CONFIG_PREEMPTION) && (defined(CONFIG_DEBUG_PREEMPT) || \ ++ defined(CONFIG_TRACE_PREEMPT_TOGGLE)) ++/* ++ * If the value passed in is equal to the current preempt count ++ * then we just disabled preemption. Start timing the latency. ++ */ ++static inline void preempt_latency_start(int val) ++{ ++ if (preempt_count() == val) { ++ unsigned long ip = get_lock_parent_ip(); ++#ifdef CONFIG_DEBUG_PREEMPT ++ current->preempt_disable_ip = ip; ++#endif ++ trace_preempt_off(CALLER_ADDR0, ip); ++ } ++} ++ ++void preempt_count_add(int val) ++{ ++#ifdef CONFIG_DEBUG_PREEMPT ++ /* ++ * Underflow? ++ */ ++ if (DEBUG_LOCKS_WARN_ON((preempt_count() < 0))) ++ return; ++#endif ++ __preempt_count_add(val); ++#ifdef CONFIG_DEBUG_PREEMPT ++ /* ++ * Spinlock count overflowing soon? ++ */ ++ DEBUG_LOCKS_WARN_ON((preempt_count() & PREEMPT_MASK) >= ++ PREEMPT_MASK - 10); ++#endif ++ preempt_latency_start(val); ++} ++EXPORT_SYMBOL(preempt_count_add); ++NOKPROBE_SYMBOL(preempt_count_add); ++ ++/* ++ * If the value passed in equals to the current preempt count ++ * then we just enabled preemption. Stop timing the latency. ++ */ ++static inline void preempt_latency_stop(int val) ++{ ++ if (preempt_count() == val) ++ trace_preempt_on(CALLER_ADDR0, get_lock_parent_ip()); ++} ++ ++void preempt_count_sub(int val) ++{ ++#ifdef CONFIG_DEBUG_PREEMPT ++ /* ++ * Underflow? ++ */ ++ if (DEBUG_LOCKS_WARN_ON(val > preempt_count())) ++ return; ++ /* ++ * Is the spinlock portion underflowing? ++ */ ++ if (DEBUG_LOCKS_WARN_ON((val < PREEMPT_MASK) && ++ !(preempt_count() & PREEMPT_MASK))) ++ return; ++#endif ++ ++ preempt_latency_stop(val); ++ __preempt_count_sub(val); ++} ++EXPORT_SYMBOL(preempt_count_sub); ++NOKPROBE_SYMBOL(preempt_count_sub); ++ ++#else ++static inline void preempt_latency_start(int val) { } ++static inline void preempt_latency_stop(int val) { } ++#endif ++ ++static inline unsigned long get_preempt_disable_ip(struct task_struct *p) ++{ ++#ifdef CONFIG_DEBUG_PREEMPT ++ return p->preempt_disable_ip; ++#else ++ return 0; ++#endif ++} ++ ++/* ++ * The time_slice is only refilled when it is empty and that is when we set a ++ * new deadline. Make sure update_clocks has been called recently to update ++ * rq->niffies. ++ */ ++static void time_slice_expired(struct task_struct *p, struct rq *rq) ++{ ++ p->time_slice = timeslice(); ++ p->deadline = rq->niffies + task_deadline_diff(p); ++#ifdef CONFIG_SMT_NICE ++ if (!p->mm) ++ p->smt_bias = 0; ++ else if (rt_task(p)) ++ p->smt_bias = 1 << 30; ++ else if (task_running_iso(p)) ++ p->smt_bias = 1 << 29; ++ else if (idleprio_task(p)) { ++ if (task_running_idle(p)) ++ p->smt_bias = 0; ++ else ++ p->smt_bias = 1; ++ } else if (--p->smt_bias < 1) ++ p->smt_bias = MAX_PRIO - p->static_prio; ++#endif ++} ++ ++/* ++ * Timeslices below RESCHED_US are considered as good as expired as there's no ++ * point rescheduling when there's so little time left. SCHED_BATCH tasks ++ * have been flagged be not latency sensitive and likely to be fully CPU ++ * bound so every time they're rescheduled they have their time_slice ++ * refilled, but get a new later deadline to have little effect on ++ * SCHED_NORMAL tasks. ++ ++ */ ++static inline void check_deadline(struct task_struct *p, struct rq *rq) ++{ ++ if (p->time_slice < RESCHED_US || batch_task(p)) ++ time_slice_expired(p, rq); ++} ++ ++/* ++ * Task selection with skiplists is a simple matter of picking off the first ++ * task in the sorted list, an O(1) operation. The lookup is amortised O(1) ++ * being bound to the number of processors. ++ * ++ * Runqueues are selectively locked based on their unlocked data and then ++ * unlocked if not needed. At most 3 locks will be held at any time and are ++ * released as soon as they're no longer needed. All balancing between CPUs ++ * is thus done here in an extremely simple first come best fit manner. ++ * ++ * This iterates over runqueues in cache locality order. In interactive mode ++ * it iterates over all CPUs and finds the task with the best key/deadline. ++ * In non-interactive mode it will only take a task if it's from the current ++ * runqueue or a runqueue with more tasks than the current one with a better ++ * key/deadline. ++ */ ++#ifdef CONFIG_SMP ++static inline struct task_struct ++*earliest_deadline_task(struct rq *rq, int cpu, struct task_struct *idle) ++{ ++ struct rq *locked = NULL, *chosen = NULL; ++ struct task_struct *edt = idle; ++ int i, best_entries = 0; ++ u64 best_key = ~0ULL; ++ ++ for (i = 0; i < total_runqueues; i++) { ++ struct rq *other_rq = rq_order(rq, i); ++ skiplist_node *next; ++ int entries; ++ ++ entries = other_rq->sl->entries; ++ /* ++ * Check for queued entres lockless first. The local runqueue ++ * is locked so entries will always be accurate. ++ */ ++ if (!sched_interactive) { ++ /* ++ * Don't reschedule balance across nodes unless the CPU ++ * is idle. ++ */ ++ if (edt != idle && rq->cpu_locality[other_rq->cpu] > LOCALITY_SMP) ++ break; ++ if (entries <= best_entries) ++ continue; ++ } else if (!entries) ++ continue; ++ ++ /* if (i) implies other_rq != rq */ ++ if (i) { ++ /* Check for best id queued lockless first */ ++ if (other_rq->best_key >= best_key) ++ continue; ++ ++ if (unlikely(!trylock_rq(rq, other_rq))) ++ continue; ++ ++ /* Need to reevaluate entries after locking */ ++ entries = other_rq->sl->entries; ++ if (unlikely(!entries)) { ++ unlock_rq(other_rq); ++ continue; ++ } ++ } ++ ++ next = other_rq->node; ++ /* ++ * In interactive mode we check beyond the best entry on other ++ * runqueues if we can't get the best for smt or affinity ++ * reasons. ++ */ ++ while ((next = next->next[0]) != other_rq->node) { ++ struct task_struct *p; ++ u64 key = next->key; ++ ++ /* Reevaluate key after locking */ ++ if (key >= best_key) ++ break; ++ ++ p = next->value; ++ if (!smt_schedule(p, rq)) { ++ if (i && !sched_interactive) ++ break; ++ continue; ++ } ++ ++ if (sched_other_cpu(p, cpu)) { ++ if (sched_interactive || !i) ++ continue; ++ break; ++ } ++ /* Make sure affinity is ok */ ++ if (i) { ++ /* From this point on p is the best so far */ ++ if (locked) ++ unlock_rq(locked); ++ chosen = locked = other_rq; ++ } ++ best_entries = entries; ++ best_key = key; ++ edt = p; ++ break; ++ } ++ /* rq->preempting is a hint only as the state may have changed ++ * since it was set with the resched call but if we have met ++ * the condition we can break out here. */ ++ if (edt == rq->preempting) ++ break; ++ if (i && other_rq != chosen) ++ unlock_rq(other_rq); ++ } ++ ++ if (likely(edt != idle)) ++ take_task(rq, cpu, edt); ++ ++ if (locked) ++ unlock_rq(locked); ++ ++ rq->preempting = NULL; ++ ++ return edt; ++} ++#else /* CONFIG_SMP */ ++static inline struct task_struct ++*earliest_deadline_task(struct rq *rq, int cpu, struct task_struct *idle) ++{ ++ struct task_struct *edt; ++ ++ if (unlikely(!rq->sl->entries)) ++ return idle; ++ edt = rq->node->next[0]->value; ++ take_task(rq, cpu, edt); ++ return edt; ++} ++#endif /* CONFIG_SMP */ ++ ++/* ++ * Print scheduling while atomic bug: ++ */ ++static noinline void __schedule_bug(struct task_struct *prev) ++{ ++ /* Save this before calling printk(), since that will clobber it */ ++ unsigned long preempt_disable_ip = get_preempt_disable_ip(current); ++ ++ if (oops_in_progress) ++ return; ++ ++ printk(KERN_ERR "BUG: scheduling while atomic: %s/%d/0x%08x\n", ++ prev->comm, prev->pid, preempt_count()); ++ ++ debug_show_held_locks(prev); ++ print_modules(); ++ if (irqs_disabled()) ++ print_irqtrace_events(prev); ++ if (IS_ENABLED(CONFIG_DEBUG_PREEMPT) ++ && in_atomic_preempt_off()) { ++ pr_err("Preemption disabled at:"); ++ print_ip_sym(preempt_disable_ip); ++ pr_cont("\n"); ++ } ++ dump_stack(); ++ add_taint(TAINT_WARN, LOCKDEP_STILL_OK); ++} ++ ++/* ++ * Various schedule()-time debugging checks and statistics: ++ */ ++static inline void schedule_debug(struct task_struct *prev, bool preempt) ++{ ++#ifdef CONFIG_SCHED_STACK_END_CHECK ++ if (task_stack_end_corrupted(prev)) ++ panic("corrupted stack end detected inside scheduler\n"); ++#endif ++ ++#ifdef CONFIG_DEBUG_ATOMIC_SLEEP ++ if (!preempt && prev->state && prev->non_block_count) { ++ printk(KERN_ERR "BUG: scheduling in a non-blocking section: %s/%d/%i\n", ++ prev->comm, prev->pid, prev->non_block_count); ++ dump_stack(); ++ add_taint(TAINT_WARN, LOCKDEP_STILL_OK); ++ } ++#endif ++ ++ if (unlikely(in_atomic_preempt_off())) { ++ __schedule_bug(prev); ++ preempt_count_set(PREEMPT_DISABLED); ++ } ++ rcu_sleep_check(); ++ ++ profile_hit(SCHED_PROFILING, __builtin_return_address(0)); ++ ++ schedstat_inc(this_rq()->sched_count); ++} ++ ++/* ++ * The currently running task's information is all stored in rq local data ++ * which is only modified by the local CPU. ++ */ ++static inline void set_rq_task(struct rq *rq, struct task_struct *p) ++{ ++ if (p == rq->idle || p->policy == SCHED_FIFO) ++ hrexpiry_clear(rq); ++ else ++ hrexpiry_start(rq, US_TO_NS(p->time_slice)); ++ if (rq->clock - rq->last_tick > HALF_JIFFY_NS) ++ rq->dither = 0; ++ else ++ rq->dither = rq_dither(rq); ++ ++ rq->rq_deadline = p->deadline; ++ rq->rq_prio = p->prio; ++#ifdef CONFIG_SMT_NICE ++ rq->rq_mm = p->mm; ++ rq->rq_smt_bias = p->smt_bias; ++#endif ++} ++ ++#ifdef CONFIG_SMT_NICE ++static void check_no_siblings(struct rq __maybe_unused *this_rq) {} ++static void wake_no_siblings(struct rq __maybe_unused *this_rq) {} ++static void (*check_siblings)(struct rq *this_rq) = &check_no_siblings; ++static void (*wake_siblings)(struct rq *this_rq) = &wake_no_siblings; ++ ++/* Iterate over smt siblings when we've scheduled a process on cpu and decide ++ * whether they should continue running or be descheduled. */ ++static void check_smt_siblings(struct rq *this_rq) ++{ ++ int other_cpu; ++ ++ for_each_cpu(other_cpu, &this_rq->thread_mask) { ++ struct task_struct *p; ++ struct rq *rq; ++ ++ rq = cpu_rq(other_cpu); ++ if (rq_idle(rq)) ++ continue; ++ p = rq->curr; ++ if (!smt_schedule(p, this_rq)) ++ resched_curr(rq); ++ } ++} ++ ++static void wake_smt_siblings(struct rq *this_rq) ++{ ++ int other_cpu; ++ ++ for_each_cpu(other_cpu, &this_rq->thread_mask) { ++ struct rq *rq; ++ ++ rq = cpu_rq(other_cpu); ++ if (rq_idle(rq)) ++ resched_idle(rq); ++ } ++} ++#else ++static void check_siblings(struct rq __maybe_unused *this_rq) {} ++static void wake_siblings(struct rq __maybe_unused *this_rq) {} ++#endif ++ ++/* ++ * schedule() is the main scheduler function. ++ * ++ * The main means of driving the scheduler and thus entering this function are: ++ * ++ * 1. Explicit blocking: mutex, semaphore, waitqueue, etc. ++ * ++ * 2. TIF_NEED_RESCHED flag is checked on interrupt and userspace return ++ * paths. For example, see arch/x86/entry_64.S. ++ * ++ * To drive preemption between tasks, the scheduler sets the flag in timer ++ * interrupt handler scheduler_tick(). ++ * ++ * 3. Wakeups don't really cause entry into schedule(). They add a ++ * task to the run-queue and that's it. ++ * ++ * Now, if the new task added to the run-queue preempts the current ++ * task, then the wakeup sets TIF_NEED_RESCHED and schedule() gets ++ * called on the nearest possible occasion: ++ * ++ * - If the kernel is preemptible (CONFIG_PREEMPTION=y): ++ * ++ * - in syscall or exception context, at the next outmost ++ * preempt_enable(). (this might be as soon as the wake_up()'s ++ * spin_unlock()!) ++ * ++ * - in IRQ context, return from interrupt-handler to ++ * preemptible context ++ * ++ * - If the kernel is not preemptible (CONFIG_PREEMPTION is not set) ++ * then at the next: ++ * ++ * - cond_resched() call ++ * - explicit schedule() call ++ * - return from syscall or exception to user-space ++ * - return from interrupt-handler to user-space ++ * ++ * WARNING: must be called with preemption disabled! ++ */ ++static void __sched notrace __schedule(bool preempt) ++{ ++ struct task_struct *prev, *next, *idle; ++ unsigned long *switch_count; ++ bool deactivate = false; ++ struct rq *rq; ++ u64 niffies; ++ int cpu; ++ ++ cpu = smp_processor_id(); ++ rq = cpu_rq(cpu); ++ prev = rq->curr; ++ idle = rq->idle; ++ ++ schedule_debug(prev, preempt); ++ ++ local_irq_disable(); ++ rcu_note_context_switch(preempt); ++ ++ /* ++ * Make sure that signal_pending_state()->signal_pending() below ++ * can't be reordered with __set_current_state(TASK_INTERRUPTIBLE) ++ * done by the caller to avoid the race with signal_wake_up(). ++ * ++ * The membarrier system call requires a full memory barrier ++ * after coming from user-space, before storing to rq->curr. ++ */ ++ rq_lock(rq); ++ smp_mb__after_spinlock(); ++#ifdef CONFIG_SMP ++ if (rq->preempt) { ++ /* ++ * Make sure resched_curr hasn't triggered a preemption ++ * locklessly on a task that has since scheduled away. Spurious ++ * wakeup of idle is okay though. ++ */ ++ if (unlikely(preempt && prev != idle && !test_tsk_need_resched(prev))) { ++ rq->preempt = NULL; ++ clear_preempt_need_resched(); ++ rq_unlock_irq(rq, NULL); ++ return; ++ } ++ rq->preempt = NULL; ++ } ++#endif ++ ++ switch_count = &prev->nivcsw; ++ if (!preempt && prev->state) { ++ if (signal_pending_state(prev->state, prev)) { ++ prev->state = TASK_RUNNING; ++ } else { ++ deactivate = true; ++ ++ if (prev->in_iowait) { ++ atomic_inc(&rq->nr_iowait); ++ delayacct_blkio_start(); ++ } ++ } ++ switch_count = &prev->nvcsw; ++ } ++ ++ /* ++ * Store the niffy value here for use by the next task's last_ran ++ * below to avoid losing niffies due to update_clocks being called ++ * again after this point. ++ */ ++ update_clocks(rq); ++ niffies = rq->niffies; ++ update_cpu_clock_switch(rq, prev); ++ ++ clear_tsk_need_resched(prev); ++ clear_preempt_need_resched(); ++ ++ if (idle != prev) { ++ check_deadline(prev, rq); ++ return_task(prev, rq, cpu, deactivate); ++ } ++ ++ next = earliest_deadline_task(rq, cpu, idle); ++ if (likely(next->prio != PRIO_LIMIT)) ++ clear_cpuidle_map(cpu); ++ else { ++ set_cpuidle_map(cpu); ++ update_load_avg(rq, 0); ++ } ++ ++ set_rq_task(rq, next); ++ next->last_ran = niffies; ++ ++ if (likely(prev != next)) { ++ /* ++ * Don't reschedule an idle task or deactivated tasks ++ */ ++ if (prev == idle) { ++ rq->nr_running++; ++ if (rt_task(next)) ++ rq->rt_nr_running++; ++ } else if (!deactivate) ++ resched_suitable_idle(prev); ++ if (unlikely(next == idle)) { ++ rq->nr_running--; ++ if (rt_task(prev)) ++ rq->rt_nr_running--; ++ wake_siblings(rq); ++ } else ++ check_siblings(rq); ++ rq->nr_switches++; ++ /* ++ * RCU users of rcu_dereference(rq->curr) may not see ++ * changes to task_struct made by pick_next_task(). ++ */ ++ RCU_INIT_POINTER(rq->curr, next); ++ /* ++ * The membarrier system call requires each architecture ++ * to have a full memory barrier after updating ++ * rq->curr, before returning to user-space. ++ * ++ * Here are the schemes providing that barrier on the ++ * various architectures: ++ * - mm ? switch_mm() : mmdrop() for x86, s390, sparc, PowerPC. ++ * switch_mm() rely on membarrier_arch_switch_mm() on PowerPC. ++ * - finish_lock_switch() for weakly-ordered ++ * architectures where spin_unlock is a full barrier, ++ * - switch_to() for arm64 (weakly-ordered, spin_unlock ++ * is a RELEASE barrier), ++ */ ++ ++*switch_count; ++ ++ trace_sched_switch(preempt, prev, next); ++ context_switch(rq, prev, next); /* unlocks the rq */ ++ } else { ++ check_siblings(rq); ++ rq_unlock(rq); ++ local_irq_enable(); ++ } ++} ++ ++void __noreturn do_task_dead(void) ++{ ++ /* Causes final put_task_struct in finish_task_switch(). */ ++ set_special_state(TASK_DEAD); ++ ++ /* Tell freezer to ignore us: */ ++ current->flags |= PF_NOFREEZE; ++ __schedule(false); ++ BUG(); ++ ++ /* Avoid "noreturn function does return" - but don't continue if BUG() is a NOP: */ ++ for (;;) ++ cpu_relax(); ++} ++ ++static inline void sched_submit_work(struct task_struct *tsk) ++{ ++ if (!tsk->state) ++ return; ++ ++ /* ++ * If a worker went to sleep, notify and ask workqueue whether ++ * it wants to wake up a task to maintain concurrency. ++ * As this function is called inside the schedule() context, ++ * we disable preemption to avoid it calling schedule() again ++ * in the possible wakeup of a kworker. ++ */ ++ if (tsk->flags & PF_WQ_WORKER) { ++ preempt_disable(); ++ wq_worker_sleeping(tsk); ++ preempt_enable_no_resched(); ++ } ++ ++ if (tsk_is_pi_blocked(tsk)) ++ return; ++ ++ /* ++ * If we are going to sleep and we have plugged IO queued, ++ * make sure to submit it to avoid deadlocks. ++ */ ++ if (blk_needs_flush_plug(tsk)) ++ blk_schedule_flush_plug(tsk); ++} ++ ++static inline void sched_update_worker(struct task_struct *tsk) ++{ ++ if (tsk->flags & PF_WQ_WORKER) ++ wq_worker_running(tsk); ++} ++ ++asmlinkage __visible void __sched schedule(void) ++{ ++ struct task_struct *tsk = current; ++ ++ sched_submit_work(tsk); ++ do { ++ preempt_disable(); ++ __schedule(false); ++ sched_preempt_enable_no_resched(); ++ } while (need_resched()); ++ sched_update_worker(tsk); ++} ++ ++EXPORT_SYMBOL(schedule); ++ ++/* ++ * synchronize_rcu_tasks() makes sure that no task is stuck in preempted ++ * state (have scheduled out non-voluntarily) by making sure that all ++ * tasks have either left the run queue or have gone into user space. ++ * As idle tasks do not do either, they must not ever be preempted ++ * (schedule out non-voluntarily). ++ * ++ * schedule_idle() is similar to schedule_preempt_disable() except that it ++ * never enables preemption because it does not call sched_submit_work(). ++ */ ++void __sched schedule_idle(void) ++{ ++ /* ++ * As this skips calling sched_submit_work(), which the idle task does ++ * regardless because that function is a nop when the task is in a ++ * TASK_RUNNING state, make sure this isn't used someplace that the ++ * current task can be in any other state. Note, idle is always in the ++ * TASK_RUNNING state. ++ */ ++ WARN_ON_ONCE(current->state); ++ do { ++ __schedule(false); ++ } while (need_resched()); ++} ++ ++#ifdef CONFIG_CONTEXT_TRACKING ++asmlinkage __visible void __sched schedule_user(void) ++{ ++ /* ++ * If we come here after a random call to set_need_resched(), ++ * or we have been woken up remotely but the IPI has not yet arrived, ++ * we haven't yet exited the RCU idle mode. Do it here manually until ++ * we find a better solution. ++ * ++ * NB: There are buggy callers of this function. Ideally we ++ * should warn if prev_state != IN_USER, but that will trigger ++ * too frequently to make sense yet. ++ */ ++ enum ctx_state prev_state = exception_enter(); ++ schedule(); ++ exception_exit(prev_state); ++} ++#endif ++ ++/** ++ * schedule_preempt_disabled - called with preemption disabled ++ * ++ * Returns with preemption disabled. Note: preempt_count must be 1 ++ */ ++void __sched schedule_preempt_disabled(void) ++{ ++ sched_preempt_enable_no_resched(); ++ schedule(); ++ preempt_disable(); ++} ++ ++static void __sched notrace preempt_schedule_common(void) ++{ ++ do { ++ /* ++ * Because the function tracer can trace preempt_count_sub() ++ * and it also uses preempt_enable/disable_notrace(), if ++ * NEED_RESCHED is set, the preempt_enable_notrace() called ++ * by the function tracer will call this function again and ++ * cause infinite recursion. ++ * ++ * Preemption must be disabled here before the function ++ * tracer can trace. Break up preempt_disable() into two ++ * calls. One to disable preemption without fear of being ++ * traced. The other to still record the preemption latency, ++ * which can also be traced by the function tracer. ++ */ ++ preempt_disable_notrace(); ++ preempt_latency_start(1); ++ __schedule(true); ++ preempt_latency_stop(1); ++ preempt_enable_no_resched_notrace(); ++ ++ /* ++ * Check again in case we missed a preemption opportunity ++ * between schedule and now. ++ */ ++ } while (need_resched()); ++} ++ ++#ifdef CONFIG_PREEMPTION ++/* ++ * This is the entry point to schedule() from in-kernel preemption ++ * off of preempt_enable. ++ */ ++asmlinkage __visible void __sched notrace preempt_schedule(void) ++{ ++ /* ++ * If there is a non-zero preempt_count or interrupts are disabled, ++ * we do not want to preempt the current task. Just return.. ++ */ ++ if (likely(!preemptible())) ++ return; ++ ++ preempt_schedule_common(); ++} ++NOKPROBE_SYMBOL(preempt_schedule); ++EXPORT_SYMBOL(preempt_schedule); ++ ++/** ++ * preempt_schedule_notrace - preempt_schedule called by tracing ++ * ++ * The tracing infrastructure uses preempt_enable_notrace to prevent ++ * recursion and tracing preempt enabling caused by the tracing ++ * infrastructure itself. But as tracing can happen in areas coming ++ * from userspace or just about to enter userspace, a preempt enable ++ * can occur before user_exit() is called. This will cause the scheduler ++ * to be called when the system is still in usermode. ++ * ++ * To prevent this, the preempt_enable_notrace will use this function ++ * instead of preempt_schedule() to exit user context if needed before ++ * calling the scheduler. ++ */ ++asmlinkage __visible void __sched notrace preempt_schedule_notrace(void) ++{ ++ enum ctx_state prev_ctx; ++ ++ if (likely(!preemptible())) ++ return; ++ ++ do { ++ /* ++ * Because the function tracer can trace preempt_count_sub() ++ * and it also uses preempt_enable/disable_notrace(), if ++ * NEED_RESCHED is set, the preempt_enable_notrace() called ++ * by the function tracer will call this function again and ++ * cause infinite recursion. ++ * ++ * Preemption must be disabled here before the function ++ * tracer can trace. Break up preempt_disable() into two ++ * calls. One to disable preemption without fear of being ++ * traced. The other to still record the preemption latency, ++ * which can also be traced by the function tracer. ++ */ ++ preempt_disable_notrace(); ++ preempt_latency_start(1); ++ /* ++ * Needs preempt disabled in case user_exit() is traced ++ * and the tracer calls preempt_enable_notrace() causing ++ * an infinite recursion. ++ */ ++ prev_ctx = exception_enter(); ++ __schedule(true); ++ exception_exit(prev_ctx); ++ ++ preempt_latency_stop(1); ++ preempt_enable_no_resched_notrace(); ++ } while (need_resched()); ++} ++EXPORT_SYMBOL_GPL(preempt_schedule_notrace); ++ ++#endif /* CONFIG_PREEMPTION */ ++ ++/* ++ * This is the entry point to schedule() from kernel preemption ++ * off of irq context. ++ * Note, that this is called and return with irqs disabled. This will ++ * protect us against recursive calling from irq. ++ */ ++asmlinkage __visible void __sched preempt_schedule_irq(void) ++{ ++ enum ctx_state prev_state; ++ ++ /* Catch callers which need to be fixed */ ++ BUG_ON(preempt_count() || !irqs_disabled()); ++ ++ prev_state = exception_enter(); ++ ++ do { ++ preempt_disable(); ++ local_irq_enable(); ++ __schedule(true); ++ local_irq_disable(); ++ sched_preempt_enable_no_resched(); ++ } while (need_resched()); ++ ++ exception_exit(prev_state); ++} ++ ++int default_wake_function(wait_queue_entry_t *curr, unsigned mode, int wake_flags, ++ void *key) ++{ ++ return try_to_wake_up(curr->private, mode, wake_flags); ++} ++EXPORT_SYMBOL(default_wake_function); ++ ++#ifdef CONFIG_RT_MUTEXES ++ ++static inline int __rt_effective_prio(struct task_struct *pi_task, int prio) ++{ ++ if (pi_task) ++ prio = min(prio, pi_task->prio); ++ ++ return prio; ++} ++ ++static inline int rt_effective_prio(struct task_struct *p, int prio) ++{ ++ struct task_struct *pi_task = rt_mutex_get_top_task(p); ++ ++ return __rt_effective_prio(pi_task, prio); ++} ++ ++/* ++ * rt_mutex_setprio - set the current priority of a task ++ * @p: task to boost ++ * @pi_task: donor task ++ * ++ * This function changes the 'effective' priority of a task. It does ++ * not touch ->normal_prio like __setscheduler(). ++ * ++ * Used by the rt_mutex code to implement priority inheritance ++ * logic. Call site only calls if the priority of the task changed. ++ */ ++void rt_mutex_setprio(struct task_struct *p, struct task_struct *pi_task) ++{ ++ int prio, oldprio; ++ struct rq *rq; ++ ++ /* XXX used to be waiter->prio, not waiter->task->prio */ ++ prio = __rt_effective_prio(pi_task, p->normal_prio); ++ ++ /* ++ * If nothing changed; bail early. ++ */ ++ if (p->pi_top_task == pi_task && prio == p->prio) ++ return; ++ ++ rq = __task_rq_lock(p, NULL); ++ update_rq_clock(rq); ++ /* ++ * Set under pi_lock && rq->lock, such that the value can be used under ++ * either lock. ++ * ++ * Note that there is loads of tricky to make this pointer cache work ++ * right. rt_mutex_slowunlock()+rt_mutex_postunlock() work together to ++ * ensure a task is de-boosted (pi_task is set to NULL) before the ++ * task is allowed to run again (and can exit). This ensures the pointer ++ * points to a blocked task -- which guaratees the task is present. ++ */ ++ p->pi_top_task = pi_task; ++ ++ /* ++ * For FIFO/RR we only need to set prio, if that matches we're done. ++ */ ++ if (prio == p->prio) ++ goto out_unlock; ++ ++ /* ++ * Idle task boosting is a nono in general. There is one ++ * exception, when PREEMPT_RT and NOHZ is active: ++ * ++ * The idle task calls get_next_timer_interrupt() and holds ++ * the timer wheel base->lock on the CPU and another CPU wants ++ * to access the timer (probably to cancel it). We can safely ++ * ignore the boosting request, as the idle CPU runs this code ++ * with interrupts disabled and will complete the lock ++ * protected section without being interrupted. So there is no ++ * real need to boost. ++ */ ++ if (unlikely(p == rq->idle)) { ++ WARN_ON(p != rq->curr); ++ WARN_ON(p->pi_blocked_on); ++ goto out_unlock; ++ } ++ ++ trace_sched_pi_setprio(p, pi_task); ++ oldprio = p->prio; ++ p->prio = prio; ++ if (task_running(rq, p)){ ++ if (prio > oldprio) ++ resched_task(p); ++ } else if (task_queued(p)) { ++ dequeue_task(rq, p, DEQUEUE_SAVE); ++ enqueue_task(rq, p, ENQUEUE_RESTORE); ++ if (prio < oldprio) ++ try_preempt(p, rq); ++ } ++out_unlock: ++ __task_rq_unlock(rq, NULL); ++} ++#else ++static inline int rt_effective_prio(struct task_struct *p, int prio) ++{ ++ return prio; ++} ++#endif ++ ++/* ++ * Adjust the deadline for when the priority is to change, before it's ++ * changed. ++ */ ++static inline void adjust_deadline(struct task_struct *p, int new_prio) ++{ ++ p->deadline += static_deadline_diff(new_prio) - task_deadline_diff(p); ++} ++ ++void set_user_nice(struct task_struct *p, long nice) ++{ ++ int new_static, old_static; ++ struct rq_flags rf; ++ struct rq *rq; ++ ++ if (task_nice(p) == nice || nice < MIN_NICE || nice > MAX_NICE) ++ return; ++ new_static = NICE_TO_PRIO(nice); ++ /* ++ * We have to be careful, if called from sys_setpriority(), ++ * the task might be in the middle of scheduling on another CPU. ++ */ ++ rq = task_rq_lock(p, &rf); ++ update_rq_clock(rq); ++ ++ /* ++ * The RT priorities are set via sched_setscheduler(), but we still ++ * allow the 'normal' nice value to be set - but as expected ++ * it wont have any effect on scheduling until the task is ++ * not SCHED_NORMAL/SCHED_BATCH: ++ */ ++ if (has_rt_policy(p)) { ++ p->static_prio = new_static; ++ goto out_unlock; ++ } ++ ++ adjust_deadline(p, new_static); ++ old_static = p->static_prio; ++ p->static_prio = new_static; ++ p->prio = effective_prio(p); ++ ++ if (task_queued(p)) { ++ dequeue_task(rq, p, DEQUEUE_SAVE); ++ enqueue_task(rq, p, ENQUEUE_RESTORE); ++ if (new_static < old_static) ++ try_preempt(p, rq); ++ } else if (task_running(rq, p)) { ++ set_rq_task(rq, p); ++ if (old_static < new_static) ++ resched_task(p); ++ } ++out_unlock: ++ task_rq_unlock(rq, p, &rf); ++} ++EXPORT_SYMBOL(set_user_nice); ++ ++/* ++ * can_nice - check if a task can reduce its nice value ++ * @p: task ++ * @nice: nice value ++ */ ++int can_nice(const struct task_struct *p, const int nice) ++{ ++ /* Convert nice value [19,-20] to rlimit style value [1,40] */ ++ int nice_rlim = nice_to_rlimit(nice); ++ ++ return (nice_rlim <= task_rlimit(p, RLIMIT_NICE) || ++ capable(CAP_SYS_NICE)); ++} ++ ++#ifdef __ARCH_WANT_SYS_NICE ++ ++/* ++ * sys_nice - change the priority of the current process. ++ * @increment: priority increment ++ * ++ * sys_setpriority is a more generic, but much slower function that ++ * does similar things. ++ */ ++SYSCALL_DEFINE1(nice, int, increment) ++{ ++ long nice, retval; ++ ++ /* ++ * Setpriority might change our priority at the same moment. ++ * We don't have to worry. Conceptually one call occurs first ++ * and we have a single winner. ++ */ ++ ++ increment = clamp(increment, -NICE_WIDTH, NICE_WIDTH); ++ nice = task_nice(current) + increment; ++ ++ nice = clamp_val(nice, MIN_NICE, MAX_NICE); ++ if (increment < 0 && !can_nice(current, nice)) ++ return -EPERM; ++ ++ retval = security_task_setnice(current, nice); ++ if (retval) ++ return retval; ++ ++ set_user_nice(current, nice); ++ return 0; ++} ++ ++#endif ++ ++/** ++ * task_prio - return the priority value of a given task. ++ * @p: the task in question. ++ * ++ * Return: The priority value as seen by users in /proc. ++ * RT tasks are offset by -100. Normal tasks are centered around 1, value goes ++ * from 0 (SCHED_ISO) up to 82 (nice +19 SCHED_IDLEPRIO). ++ */ ++int task_prio(const struct task_struct *p) ++{ ++ int delta, prio = p->prio - MAX_RT_PRIO; ++ ++ /* rt tasks and iso tasks */ ++ if (prio <= 0) ++ goto out; ++ ++ /* Convert to ms to avoid overflows */ ++ delta = NS_TO_MS(p->deadline - task_rq(p)->niffies); ++ if (unlikely(delta < 0)) ++ delta = 0; ++ delta = delta * 40 / ms_longest_deadline_diff(); ++ if (delta <= 80) ++ prio += delta; ++ if (idleprio_task(p)) ++ prio += 40; ++out: ++ return prio; ++} ++ ++/** ++ * idle_cpu - is a given CPU idle currently? ++ * @cpu: the processor in question. ++ * ++ * Return: 1 if the CPU is currently idle. 0 otherwise. ++ */ ++int idle_cpu(int cpu) ++{ ++ return cpu_curr(cpu) == cpu_rq(cpu)->idle; ++} ++ ++/** ++ * available_idle_cpu - is a given CPU idle for enqueuing work. ++ * @cpu: the CPU in question. ++ * ++ * Return: 1 if the CPU is currently idle. 0 otherwise. ++ */ ++int available_idle_cpu(int cpu) ++{ ++ if (!idle_cpu(cpu)) ++ return 0; ++ ++ if (vcpu_is_preempted(cpu)) ++ return 0; ++ ++ return 1; ++} ++ ++/** ++ * idle_task - return the idle task for a given CPU. ++ * @cpu: the processor in question. ++ * ++ * Return: The idle task for the CPU @cpu. ++ */ ++struct task_struct *idle_task(int cpu) ++{ ++ return cpu_rq(cpu)->idle; ++} ++ ++/** ++ * find_process_by_pid - find a process with a matching PID value. ++ * @pid: the pid in question. ++ * ++ * The task of @pid, if found. %NULL otherwise. ++ */ ++static inline struct task_struct *find_process_by_pid(pid_t pid) ++{ ++ return pid ? find_task_by_vpid(pid) : current; ++} ++ ++/* Actually do priority change: must hold rq lock. */ ++static void __setscheduler(struct task_struct *p, struct rq *rq, int policy, ++ int prio, const struct sched_attr *attr, ++ bool keep_boost) ++{ ++ int oldrtprio, oldprio; ++ ++ /* ++ * If params can't change scheduling class changes aren't allowed ++ * either. ++ */ ++ if (attr->sched_flags & SCHED_FLAG_KEEP_PARAMS) ++ return; ++ ++ p->policy = policy; ++ oldrtprio = p->rt_priority; ++ p->rt_priority = prio; ++ p->normal_prio = normal_prio(p); ++ oldprio = p->prio; ++ /* ++ * Keep a potential priority boosting if called from ++ * sched_setscheduler(). ++ */ ++ p->prio = normal_prio(p); ++ if (keep_boost) ++ p->prio = rt_effective_prio(p, p->prio); ++ ++ if (task_running(rq, p)) { ++ set_rq_task(rq, p); ++ resched_task(p); ++ } else if (task_queued(p)) { ++ dequeue_task(rq, p, DEQUEUE_SAVE); ++ enqueue_task(rq, p, ENQUEUE_RESTORE); ++ if (p->prio < oldprio || p->rt_priority > oldrtprio) ++ try_preempt(p, rq); ++ } ++} ++ ++/* ++ * Check the target process has a UID that matches the current process's ++ */ ++static bool check_same_owner(struct task_struct *p) ++{ ++ const struct cred *cred = current_cred(), *pcred; ++ bool match; ++ ++ rcu_read_lock(); ++ pcred = __task_cred(p); ++ match = (uid_eq(cred->euid, pcred->euid) || ++ uid_eq(cred->euid, pcred->uid)); ++ rcu_read_unlock(); ++ return match; ++} ++ ++static int __sched_setscheduler(struct task_struct *p, ++ const struct sched_attr *attr, ++ bool user, bool pi) ++{ ++ int retval, policy = attr->sched_policy, oldpolicy = -1, priority = attr->sched_priority; ++ unsigned long rlim_rtprio = 0; ++ struct rq_flags rf; ++ int reset_on_fork; ++ struct rq *rq; ++ ++ /* The pi code expects interrupts enabled */ ++ BUG_ON(pi && in_interrupt()); ++ ++ if (is_rt_policy(policy) && !capable(CAP_SYS_NICE)) { ++ unsigned long lflags; ++ ++ if (!lock_task_sighand(p, &lflags)) ++ return -ESRCH; ++ rlim_rtprio = task_rlimit(p, RLIMIT_RTPRIO); ++ unlock_task_sighand(p, &lflags); ++ if (rlim_rtprio) ++ goto recheck; ++ /* ++ * If the caller requested an RT policy without having the ++ * necessary rights, we downgrade the policy to SCHED_ISO. ++ * We also set the parameter to zero to pass the checks. ++ */ ++ policy = SCHED_ISO; ++ priority = 0; ++ } ++recheck: ++ /* Double check policy once rq lock held */ ++ if (policy < 0) { ++ reset_on_fork = p->sched_reset_on_fork; ++ policy = oldpolicy = p->policy; ++ } else { ++ reset_on_fork = !!(policy & SCHED_RESET_ON_FORK); ++ policy &= ~SCHED_RESET_ON_FORK; ++ ++ if (!SCHED_RANGE(policy)) ++ return -EINVAL; ++ } ++ ++ if (attr->sched_flags & ~(SCHED_FLAG_ALL | SCHED_FLAG_SUGOV)) ++ return -EINVAL; ++ ++ /* ++ * Valid priorities for SCHED_FIFO and SCHED_RR are ++ * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL and ++ * SCHED_BATCH is 0. ++ */ ++ if (priority < 0 || ++ (p->mm && priority > MAX_USER_RT_PRIO - 1) || ++ (!p->mm && priority > MAX_RT_PRIO - 1)) ++ return -EINVAL; ++ if (is_rt_policy(policy) != (priority != 0)) ++ return -EINVAL; ++ ++ /* ++ * Allow unprivileged RT tasks to decrease priority: ++ */ ++ if (user && !capable(CAP_SYS_NICE)) { ++ if (is_rt_policy(policy)) { ++ unsigned long rlim_rtprio = ++ task_rlimit(p, RLIMIT_RTPRIO); ++ ++ /* Can't set/change the rt policy */ ++ if (policy != p->policy && !rlim_rtprio) ++ return -EPERM; ++ ++ /* Can't increase priority */ ++ if (priority > p->rt_priority && ++ priority > rlim_rtprio) ++ return -EPERM; ++ } else { ++ switch (p->policy) { ++ /* ++ * Can only downgrade policies but not back to ++ * SCHED_NORMAL ++ */ ++ case SCHED_ISO: ++ if (policy == SCHED_ISO) ++ goto out; ++ if (policy != SCHED_NORMAL) ++ return -EPERM; ++ break; ++ case SCHED_BATCH: ++ if (policy == SCHED_BATCH) ++ goto out; ++ if (policy != SCHED_IDLEPRIO) ++ return -EPERM; ++ break; ++ case SCHED_IDLEPRIO: ++ if (policy == SCHED_IDLEPRIO) ++ goto out; ++ return -EPERM; ++ default: ++ break; ++ } ++ } ++ ++ /* Can't change other user's priorities */ ++ if (!check_same_owner(p)) ++ return -EPERM; ++ ++ /* Normal users shall not reset the sched_reset_on_fork flag: */ ++ if (p->sched_reset_on_fork && !reset_on_fork) ++ return -EPERM; ++ } ++ ++ if (user) { ++ retval = security_task_setscheduler(p); ++ if (retval) ++ return retval; ++ } ++ ++ if (pi) ++ cpuset_read_lock(); ++ ++ /* ++ * Make sure no PI-waiters arrive (or leave) while we are ++ * changing the priority of the task: ++ * ++ * To be able to change p->policy safely, the runqueue lock must be ++ * held. ++ */ ++ rq = task_rq_lock(p, &rf); ++ update_rq_clock(rq); ++ ++ /* ++ * Changing the policy of the stop threads its a very bad idea: ++ */ ++ if (p == rq->stop) { ++ retval = -EINVAL; ++ goto unlock; ++ } ++ ++ /* ++ * If not changing anything there's no need to proceed further, ++ * but store a possible modification of reset_on_fork. ++ */ ++ if (unlikely(policy == p->policy && (!is_rt_policy(policy) || ++ priority == p->rt_priority))) { ++ p->sched_reset_on_fork = reset_on_fork; ++ retval = 0; ++ goto unlock; ++ } ++ ++ /* Re-check policy now with rq lock held */ ++ if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) { ++ policy = oldpolicy = -1; ++ task_rq_unlock(rq, p, &rf); ++ if (pi) ++ cpuset_read_unlock(); ++ goto recheck; ++ } ++ p->sched_reset_on_fork = reset_on_fork; ++ ++ __setscheduler(p, rq, policy, priority, attr, pi); ++ ++ /* Avoid rq from going away on us: */ ++ preempt_disable(); ++ task_rq_unlock(rq, p, &rf); ++ ++ if (pi) { ++ cpuset_read_unlock(); ++ rt_mutex_adjust_pi(p); ++ } ++ preempt_enable(); ++out: ++ return 0; ++ ++unlock: ++ task_rq_unlock(rq, p, &rf); ++ if (pi) ++ cpuset_read_unlock(); ++ return retval; ++} ++ ++static int _sched_setscheduler(struct task_struct *p, int policy, ++ const struct sched_param *param, bool check) ++{ ++ struct sched_attr attr = { ++ .sched_policy = policy, ++ .sched_priority = param->sched_priority, ++ .sched_nice = PRIO_TO_NICE(p->static_prio), ++ }; ++ ++ return __sched_setscheduler(p, &attr, check, true); ++} ++/** ++ * sched_setscheduler - change the scheduling policy and/or RT priority of a thread. ++ * @p: the task in question. ++ * @policy: new policy. ++ * @param: structure containing the new RT priority. ++ * ++ * Return: 0 on success. An error code otherwise. ++ * ++ * NOTE that the task may be already dead. ++ */ ++int sched_setscheduler(struct task_struct *p, int policy, ++ const struct sched_param *param) ++{ ++ return _sched_setscheduler(p, policy, param, true); ++} ++ ++EXPORT_SYMBOL_GPL(sched_setscheduler); ++ ++int sched_setattr(struct task_struct *p, const struct sched_attr *attr) ++{ ++ return __sched_setscheduler(p, attr, true, true); ++} ++EXPORT_SYMBOL_GPL(sched_setattr); ++ ++int sched_setattr_nocheck(struct task_struct *p, const struct sched_attr *attr) ++{ ++ return __sched_setscheduler(p, attr, false, true); ++} ++ ++/** ++ * sched_setscheduler_nocheck - change the scheduling policy and/or RT priority of a thread from kernelspace. ++ * @p: the task in question. ++ * @policy: new policy. ++ * @param: structure containing the new RT priority. ++ * ++ * Just like sched_setscheduler, only don't bother checking if the ++ * current context has permission. For example, this is needed in ++ * stop_machine(): we create temporary high priority worker threads, ++ * but our caller might not have that capability. ++ * ++ * Return: 0 on success. An error code otherwise. ++ */ ++int sched_setscheduler_nocheck(struct task_struct *p, int policy, ++ const struct sched_param *param) ++{ ++ return _sched_setscheduler(p, policy, param, false); ++} ++EXPORT_SYMBOL_GPL(sched_setscheduler_nocheck); ++ ++static int ++do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param) ++{ ++ struct sched_param lparam; ++ struct task_struct *p; ++ int retval; ++ ++ if (!param || pid < 0) ++ return -EINVAL; ++ if (copy_from_user(&lparam, param, sizeof(struct sched_param))) ++ return -EFAULT; ++ ++ rcu_read_lock(); ++ retval = -ESRCH; ++ p = find_process_by_pid(pid); ++ if (likely(p)) ++ get_task_struct(p); ++ rcu_read_unlock(); ++ ++ if (likely(p)) { ++ retval = sched_setscheduler(p, policy, &lparam); ++ put_task_struct(p); ++ } ++ ++ return retval; ++} ++ ++/* ++ * Mimics kernel/events/core.c perf_copy_attr(). ++ */ ++static int sched_copy_attr(struct sched_attr __user *uattr, ++ struct sched_attr *attr) ++{ ++ u32 size; ++ int ret; ++ ++ /* Zero the full structure, so that a short copy will be nice: */ ++ memset(attr, 0, sizeof(*attr)); ++ ++ ret = get_user(size, &uattr->size); ++ if (ret) ++ return ret; ++ ++ /* ABI compatibility quirk: */ ++ if (!size) ++ size = SCHED_ATTR_SIZE_VER0; ++ ++ if (size < SCHED_ATTR_SIZE_VER0 || size > PAGE_SIZE) ++ goto err_size; ++ ++ ret = copy_struct_from_user(attr, sizeof(*attr), uattr, size); ++ if (ret) { ++ if (ret == -E2BIG) ++ goto err_size; ++ return ret; ++ } ++ ++ /* ++ * XXX: Do we want to be lenient like existing syscalls; or do we want ++ * to be strict and return an error on out-of-bounds values? ++ */ ++ attr->sched_nice = clamp(attr->sched_nice, -20, 19); ++ ++ /* sched/core.c uses zero here but we already know ret is zero */ ++ return 0; ++ ++err_size: ++ put_user(sizeof(*attr), &uattr->size); ++ return -E2BIG; ++} ++ ++/* ++ * sched_setparam() passes in -1 for its policy, to let the functions ++ * it calls know not to change it. ++ */ ++#define SETPARAM_POLICY -1 ++ ++/** ++ * sys_sched_setscheduler - set/change the scheduler policy and RT priority ++ * @pid: the pid in question. ++ * @policy: new policy. ++ * @param: structure containing the new RT priority. ++ * ++ * Return: 0 on success. An error code otherwise. ++ */ ++SYSCALL_DEFINE3(sched_setscheduler, pid_t, pid, int, policy, struct sched_param __user *, param) ++{ ++ if (policy < 0) ++ return -EINVAL; ++ ++ return do_sched_setscheduler(pid, policy, param); ++} ++ ++/** ++ * sys_sched_setparam - set/change the RT priority of a thread ++ * @pid: the pid in question. ++ * @param: structure containing the new RT priority. ++ * ++ * Return: 0 on success. An error code otherwise. ++ */ ++SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param) ++{ ++ return do_sched_setscheduler(pid, SETPARAM_POLICY, param); ++} ++ ++/** ++ * sys_sched_setattr - same as above, but with extended sched_attr ++ * @pid: the pid in question. ++ * @uattr: structure containing the extended parameters. ++ */ ++SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr, ++ unsigned int, flags) ++{ ++ struct sched_attr attr; ++ struct task_struct *p; ++ int retval; ++ ++ if (!uattr || pid < 0 || flags) ++ return -EINVAL; ++ ++ retval = sched_copy_attr(uattr, &attr); ++ if (retval) ++ return retval; ++ ++ if ((int)attr.sched_policy < 0) ++ return -EINVAL; ++ if (attr.sched_flags & SCHED_FLAG_KEEP_POLICY) ++ attr.sched_policy = SETPARAM_POLICY; ++ ++ rcu_read_lock(); ++ retval = -ESRCH; ++ p = find_process_by_pid(pid); ++ if (likely(p)) ++ get_task_struct(p); ++ rcu_read_unlock(); ++ ++ if (likely(p)) { ++ retval = sched_setattr(p, &attr); ++ put_task_struct(p); ++ } ++ ++ return retval; ++} ++ ++/** ++ * sys_sched_getscheduler - get the policy (scheduling class) of a thread ++ * @pid: the pid in question. ++ * ++ * Return: On success, the policy of the thread. Otherwise, a negative error ++ * code. ++ */ ++SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid) ++{ ++ struct task_struct *p; ++ int retval = -EINVAL; ++ ++ if (pid < 0) ++ goto out_nounlock; ++ ++ retval = -ESRCH; ++ rcu_read_lock(); ++ p = find_process_by_pid(pid); ++ if (p) { ++ retval = security_task_getscheduler(p); ++ if (!retval) ++ retval = p->policy; ++ } ++ rcu_read_unlock(); ++ ++out_nounlock: ++ return retval; ++} ++ ++/** ++ * sys_sched_getscheduler - get the RT priority of a thread ++ * @pid: the pid in question. ++ * @param: structure containing the RT priority. ++ * ++ * Return: On success, 0 and the RT priority is in @param. Otherwise, an error ++ * code. ++ */ ++SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param) ++{ ++ struct sched_param lp = { .sched_priority = 0 }; ++ struct task_struct *p; ++ int retval = -EINVAL; ++ ++ if (!param || pid < 0) ++ goto out_nounlock; ++ ++ rcu_read_lock(); ++ p = find_process_by_pid(pid); ++ retval = -ESRCH; ++ if (!p) ++ goto out_unlock; ++ ++ retval = security_task_getscheduler(p); ++ if (retval) ++ goto out_unlock; ++ ++ if (has_rt_policy(p)) ++ lp.sched_priority = p->rt_priority; ++ rcu_read_unlock(); ++ ++ /* ++ * This one might sleep, we cannot do it with a spinlock held ... ++ */ ++ retval = copy_to_user(param, &lp, sizeof(*param)) ? -EFAULT : 0; ++ ++out_nounlock: ++ return retval; ++ ++out_unlock: ++ rcu_read_unlock(); ++ return retval; ++} ++ ++/* ++ * Copy the kernel size attribute structure (which might be larger ++ * than what user-space knows about) to user-space. ++ * ++ * Note that all cases are valid: user-space buffer can be larger or ++ * smaller than the kernel-space buffer. The usual case is that both ++ * have the same size. ++ */ ++static int ++sched_attr_copy_to_user(struct sched_attr __user *uattr, ++ struct sched_attr *kattr, ++ unsigned int usize) ++{ ++ unsigned int ksize = sizeof(*kattr); ++ ++ if (!access_ok(uattr, usize)) ++ return -EFAULT; ++ ++ /* ++ * sched_getattr() ABI forwards and backwards compatibility: ++ * ++ * If usize == ksize then we just copy everything to user-space and all is good. ++ * ++ * If usize < ksize then we only copy as much as user-space has space for, ++ * this keeps ABI compatibility as well. We skip the rest. ++ * ++ * If usize > ksize then user-space is using a newer version of the ABI, ++ * which part the kernel doesn't know about. Just ignore it - tooling can ++ * detect the kernel's knowledge of attributes from the attr->size value ++ * which is set to ksize in this case. ++ */ ++ kattr->size = min(usize, ksize); ++ ++ if (copy_to_user(uattr, kattr, kattr->size)) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++/** ++ * sys_sched_getattr - similar to sched_getparam, but with sched_attr ++ * @pid: the pid in question. ++ * @uattr: structure containing the extended parameters. ++ * @usize: sizeof(attr) for fwd/bwd comp. ++ * @flags: for future extension. ++ */ ++SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr, ++ unsigned int, usize, unsigned int, flags) ++{ ++ struct sched_attr kattr = { }; ++ struct task_struct *p; ++ int retval; ++ ++ if (!uattr || pid < 0 || usize > PAGE_SIZE || ++ usize < SCHED_ATTR_SIZE_VER0 || flags) ++ return -EINVAL; ++ ++ rcu_read_lock(); ++ p = find_process_by_pid(pid); ++ retval = -ESRCH; ++ if (!p) ++ goto out_unlock; ++ ++ retval = security_task_getscheduler(p); ++ if (retval) ++ goto out_unlock; ++ ++ kattr.sched_policy = p->policy; ++ if (rt_task(p)) ++ kattr.sched_priority = p->rt_priority; ++ else ++ kattr.sched_nice = task_nice(p); ++ ++ rcu_read_unlock(); ++ ++ return sched_attr_copy_to_user(uattr, &kattr, usize); ++ ++out_unlock: ++ rcu_read_unlock(); ++ return retval; ++} ++ ++long sched_setaffinity(pid_t pid, const struct cpumask *in_mask) ++{ ++ cpumask_var_t cpus_allowed, new_mask; ++ struct task_struct *p; ++ int retval; ++ ++ rcu_read_lock(); ++ ++ p = find_process_by_pid(pid); ++ if (!p) { ++ rcu_read_unlock(); ++ return -ESRCH; ++ } ++ ++ /* Prevent p going away */ ++ get_task_struct(p); ++ rcu_read_unlock(); ++ ++ if (p->flags & PF_NO_SETAFFINITY) { ++ retval = -EINVAL; ++ goto out_put_task; ++ } ++ if (!alloc_cpumask_var(&cpus_allowed, GFP_KERNEL)) { ++ retval = -ENOMEM; ++ goto out_put_task; ++ } ++ if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) { ++ retval = -ENOMEM; ++ goto out_free_cpus_allowed; ++ } ++ retval = -EPERM; ++ if (!check_same_owner(p)) { ++ rcu_read_lock(); ++ if (!ns_capable(__task_cred(p)->user_ns, CAP_SYS_NICE)) { ++ rcu_read_unlock(); ++ goto out_unlock; ++ } ++ rcu_read_unlock(); ++ } ++ ++ retval = security_task_setscheduler(p); ++ if (retval) ++ goto out_unlock; ++ ++ cpuset_cpus_allowed(p, cpus_allowed); ++ cpumask_and(new_mask, in_mask, cpus_allowed); ++again: ++ retval = __set_cpus_allowed_ptr(p, new_mask, true); ++ ++ if (!retval) { ++ cpuset_cpus_allowed(p, cpus_allowed); ++ if (!cpumask_subset(new_mask, cpus_allowed)) { ++ /* ++ * We must have raced with a concurrent cpuset ++ * update. Just reset the cpus_allowed to the ++ * cpuset's cpus_allowed ++ */ ++ cpumask_copy(new_mask, cpus_allowed); ++ goto again; ++ } ++ } ++out_unlock: ++ free_cpumask_var(new_mask); ++out_free_cpus_allowed: ++ free_cpumask_var(cpus_allowed); ++out_put_task: ++ put_task_struct(p); ++ return retval; ++} ++ ++static int get_user_cpu_mask(unsigned long __user *user_mask_ptr, unsigned len, ++ cpumask_t *new_mask) ++{ ++ if (len < cpumask_size()) ++ cpumask_clear(new_mask); ++ else if (len > cpumask_size()) ++ len = cpumask_size(); ++ ++ return copy_from_user(new_mask, user_mask_ptr, len) ? -EFAULT : 0; ++} ++ ++ ++/** ++ * sys_sched_setaffinity - set the CPU affinity of a process ++ * @pid: pid of the process ++ * @len: length in bytes of the bitmask pointed to by user_mask_ptr ++ * @user_mask_ptr: user-space pointer to the new CPU mask ++ * ++ * Return: 0 on success. An error code otherwise. ++ */ ++SYSCALL_DEFINE3(sched_setaffinity, pid_t, pid, unsigned int, len, ++ unsigned long __user *, user_mask_ptr) ++{ ++ cpumask_var_t new_mask; ++ int retval; ++ ++ if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) ++ return -ENOMEM; ++ ++ retval = get_user_cpu_mask(user_mask_ptr, len, new_mask); ++ if (retval == 0) ++ retval = sched_setaffinity(pid, new_mask); ++ free_cpumask_var(new_mask); ++ return retval; ++} ++ ++long sched_getaffinity(pid_t pid, cpumask_t *mask) ++{ ++ struct task_struct *p; ++ unsigned long flags; ++ int retval; ++ ++ get_online_cpus(); ++ rcu_read_lock(); ++ ++ retval = -ESRCH; ++ p = find_process_by_pid(pid); ++ if (!p) ++ goto out_unlock; ++ ++ retval = security_task_getscheduler(p); ++ if (retval) ++ goto out_unlock; ++ ++ raw_spin_lock_irqsave(&p->pi_lock, flags); ++ cpumask_and(mask, &p->cpus_mask, cpu_active_mask); ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++ ++out_unlock: ++ rcu_read_unlock(); ++ put_online_cpus(); ++ ++ return retval; ++} ++ ++/** ++ * sys_sched_getaffinity - get the CPU affinity of a process ++ * @pid: pid of the process ++ * @len: length in bytes of the bitmask pointed to by user_mask_ptr ++ * @user_mask_ptr: user-space pointer to hold the current CPU mask ++ * ++ * Return: 0 on success. An error code otherwise. ++ */ ++SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len, ++ unsigned long __user *, user_mask_ptr) ++{ ++ int ret; ++ cpumask_var_t mask; ++ ++ if ((len * BITS_PER_BYTE) < nr_cpu_ids) ++ return -EINVAL; ++ if (len & (sizeof(unsigned long)-1)) ++ return -EINVAL; ++ ++ if (!alloc_cpumask_var(&mask, GFP_KERNEL)) ++ return -ENOMEM; ++ ++ ret = sched_getaffinity(pid, mask); ++ if (ret == 0) { ++ unsigned int retlen = min(len, cpumask_size()); ++ ++ if (copy_to_user(user_mask_ptr, mask, retlen)) ++ ret = -EFAULT; ++ else ++ ret = retlen; ++ } ++ free_cpumask_var(mask); ++ ++ return ret; ++} ++ ++/** ++ * sys_sched_yield - yield the current processor to other threads. ++ * ++ * This function yields the current CPU to other tasks. It does this by ++ * scheduling away the current task. If it still has the earliest deadline ++ * it will be scheduled again as the next task. ++ * ++ * Return: 0. ++ */ ++static void do_sched_yield(void) ++{ ++ struct rq *rq; ++ ++ if (!sched_yield_type) ++ return; ++ ++ local_irq_disable(); ++ rq = this_rq(); ++ rq_lock(rq); ++ ++ if (sched_yield_type > 1) ++ time_slice_expired(current, rq); ++ schedstat_inc(rq->yld_count); ++ ++ /* ++ * Since we are going to call schedule() anyway, there's ++ * no need to preempt or enable interrupts: ++ */ ++ preempt_disable(); ++ rq_unlock(rq); ++ sched_preempt_enable_no_resched(); ++ ++ schedule(); ++} ++ ++SYSCALL_DEFINE0(sched_yield) ++{ ++ do_sched_yield(); ++ return 0; ++} ++ ++#ifndef CONFIG_PREEMPTION ++int __sched _cond_resched(void) ++{ ++ if (should_resched(0)) { ++ preempt_schedule_common(); ++ return 1; ++ } ++ rcu_all_qs(); ++ return 0; ++} ++EXPORT_SYMBOL(_cond_resched); ++#endif ++ ++/* ++ * __cond_resched_lock() - if a reschedule is pending, drop the given lock, ++ * call schedule, and on return reacquire the lock. ++ * ++ * This works OK both with and without CONFIG_PREEMPTION. We do strange low-level ++ * operations here to prevent schedule() from being called twice (once via ++ * spin_unlock(), once by hand). ++ */ ++int __cond_resched_lock(spinlock_t *lock) ++{ ++ int resched = should_resched(PREEMPT_LOCK_OFFSET); ++ int ret = 0; ++ ++ lockdep_assert_held(lock); ++ ++ if (spin_needbreak(lock) || resched) { ++ spin_unlock(lock); ++ if (resched) ++ preempt_schedule_common(); ++ else ++ cpu_relax(); ++ ret = 1; ++ spin_lock(lock); ++ } ++ return ret; ++} ++EXPORT_SYMBOL(__cond_resched_lock); ++ ++/** ++ * yield - yield the current processor to other threads. ++ * ++ * Do not ever use this function, there's a 99% chance you're doing it wrong. ++ * ++ * The scheduler is at all times free to pick the calling task as the most ++ * eligible task to run, if removing the yield() call from your code breaks ++ * it, its already broken. ++ * ++ * Typical broken usage is: ++ * ++ * while (!event) ++ * yield(); ++ * ++ * where one assumes that yield() will let 'the other' process run that will ++ * make event true. If the current task is a SCHED_FIFO task that will never ++ * happen. Never use yield() as a progress guarantee!! ++ * ++ * If you want to use yield() to wait for something, use wait_event(). ++ * If you want to use yield() to be 'nice' for others, use cond_resched(). ++ * If you still want to use yield(), do not! ++ */ ++void __sched yield(void) ++{ ++ set_current_state(TASK_RUNNING); ++ do_sched_yield(); ++} ++EXPORT_SYMBOL(yield); ++ ++/** ++ * yield_to - yield the current processor to another thread in ++ * your thread group, or accelerate that thread toward the ++ * processor it's on. ++ * @p: target task ++ * @preempt: whether task preemption is allowed or not ++ * ++ * It's the caller's job to ensure that the target task struct ++ * can't go away on us before we can do any checks. ++ * ++ * Return: ++ * true (>0) if we indeed boosted the target task. ++ * false (0) if we failed to boost the target. ++ * -ESRCH if there's no task to yield to. ++ */ ++int __sched yield_to(struct task_struct *p, bool preempt) ++{ ++ struct task_struct *rq_p; ++ struct rq *rq, *p_rq; ++ unsigned long flags; ++ int yielded = 0; ++ ++ local_irq_save(flags); ++ rq = this_rq(); ++ ++again: ++ p_rq = task_rq(p); ++ /* ++ * If we're the only runnable task on the rq and target rq also ++ * has only one task, there's absolutely no point in yielding. ++ */ ++ if (task_running(p_rq, p) || p->state) { ++ yielded = -ESRCH; ++ goto out_irq; ++ } ++ ++ double_rq_lock(rq, p_rq); ++ if (unlikely(task_rq(p) != p_rq)) { ++ double_rq_unlock(rq, p_rq); ++ goto again; ++ } ++ ++ yielded = 1; ++ schedstat_inc(rq->yld_count); ++ rq_p = rq->curr; ++ if (p->deadline > rq_p->deadline) ++ p->deadline = rq_p->deadline; ++ p->time_slice += rq_p->time_slice; ++ if (p->time_slice > timeslice()) ++ p->time_slice = timeslice(); ++ time_slice_expired(rq_p, rq); ++ if (preempt && rq != p_rq) ++ resched_task(p_rq->curr); ++ double_rq_unlock(rq, p_rq); ++out_irq: ++ local_irq_restore(flags); ++ ++ if (yielded > 0) ++ schedule(); ++ return yielded; ++} ++EXPORT_SYMBOL_GPL(yield_to); ++ ++int io_schedule_prepare(void) ++{ ++ int old_iowait = current->in_iowait; ++ ++ current->in_iowait = 1; ++ blk_schedule_flush_plug(current); ++ ++ return old_iowait; ++} ++ ++void io_schedule_finish(int token) ++{ ++ current->in_iowait = token; ++} ++ ++/* ++ * This task is about to go to sleep on IO. Increment rq->nr_iowait so ++ * that process accounting knows that this is a task in IO wait state. ++ * ++ * But don't do that if it is a deliberate, throttling IO wait (this task ++ * has set its backing_dev_info: the queue against which it should throttle) ++ */ ++ ++long __sched io_schedule_timeout(long timeout) ++{ ++ int token; ++ long ret; ++ ++ token = io_schedule_prepare(); ++ ret = schedule_timeout(timeout); ++ io_schedule_finish(token); ++ ++ return ret; ++} ++EXPORT_SYMBOL(io_schedule_timeout); ++ ++void __sched io_schedule(void) ++{ ++ int token; ++ ++ token = io_schedule_prepare(); ++ schedule(); ++ io_schedule_finish(token); ++} ++EXPORT_SYMBOL(io_schedule); ++ ++/** ++ * sys_sched_get_priority_max - return maximum RT priority. ++ * @policy: scheduling class. ++ * ++ * Return: On success, this syscall returns the maximum ++ * rt_priority that can be used by a given scheduling class. ++ * On failure, a negative error code is returned. ++ */ ++SYSCALL_DEFINE1(sched_get_priority_max, int, policy) ++{ ++ int ret = -EINVAL; ++ ++ switch (policy) { ++ case SCHED_FIFO: ++ case SCHED_RR: ++ ret = MAX_USER_RT_PRIO-1; ++ break; ++ case SCHED_NORMAL: ++ case SCHED_BATCH: ++ case SCHED_ISO: ++ case SCHED_IDLEPRIO: ++ ret = 0; ++ break; ++ } ++ return ret; ++} ++ ++/** ++ * sys_sched_get_priority_min - return minimum RT priority. ++ * @policy: scheduling class. ++ * ++ * Return: On success, this syscall returns the minimum ++ * rt_priority that can be used by a given scheduling class. ++ * On failure, a negative error code is returned. ++ */ ++SYSCALL_DEFINE1(sched_get_priority_min, int, policy) ++{ ++ int ret = -EINVAL; ++ ++ switch (policy) { ++ case SCHED_FIFO: ++ case SCHED_RR: ++ ret = 1; ++ break; ++ case SCHED_NORMAL: ++ case SCHED_BATCH: ++ case SCHED_ISO: ++ case SCHED_IDLEPRIO: ++ ret = 0; ++ break; ++ } ++ return ret; ++} ++ ++static int sched_rr_get_interval(pid_t pid, struct timespec64 *t) ++{ ++ struct task_struct *p; ++ unsigned int time_slice; ++ struct rq_flags rf; ++ struct rq *rq; ++ int retval; ++ ++ if (pid < 0) ++ return -EINVAL; ++ ++ retval = -ESRCH; ++ rcu_read_lock(); ++ p = find_process_by_pid(pid); ++ if (!p) ++ goto out_unlock; ++ ++ retval = security_task_getscheduler(p); ++ if (retval) ++ goto out_unlock; ++ ++ rq = task_rq_lock(p, &rf); ++ time_slice = p->policy == SCHED_FIFO ? 0 : MS_TO_NS(task_timeslice(p)); ++ task_rq_unlock(rq, p, &rf); ++ ++ rcu_read_unlock(); ++ *t = ns_to_timespec64(time_slice); ++ return 0; ++ ++out_unlock: ++ rcu_read_unlock(); ++ return retval; ++} ++ ++/** ++ * sys_sched_rr_get_interval - return the default timeslice of a process. ++ * @pid: pid of the process. ++ * @interval: userspace pointer to the timeslice value. ++ * ++ * this syscall writes the default timeslice value of a given process ++ * into the user-space timespec buffer. A value of '0' means infinity. ++ * ++ * Return: On success, 0 and the timeslice is in @interval. Otherwise, ++ * an error code. ++ */ ++SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid, ++ struct __kernel_timespec __user *, interval) ++{ ++ struct timespec64 t; ++ int retval = sched_rr_get_interval(pid, &t); ++ ++ if (retval == 0) ++ retval = put_timespec64(&t, interval); ++ ++ return retval; ++} ++ ++#ifdef CONFIG_COMPAT_32BIT_TIME ++SYSCALL_DEFINE2(sched_rr_get_interval_time32, pid_t, pid, ++ struct old_timespec32 __user *, interval) ++{ ++ struct timespec64 t; ++ int retval = sched_rr_get_interval(pid, &t); ++ ++ if (retval == 0) ++ retval = put_old_timespec32(&t, interval); ++ return retval; ++} ++#endif ++ ++void sched_show_task(struct task_struct *p) ++{ ++ unsigned long free = 0; ++ int ppid; ++ ++ if (!try_get_task_stack(p)) ++ return; ++ ++ printk(KERN_INFO "%-15.15s %c", p->comm, task_state_to_char(p)); ++ ++ if (p->state == TASK_RUNNING) ++ printk(KERN_CONT " running task "); ++#ifdef CONFIG_DEBUG_STACK_USAGE ++ free = stack_not_used(p); ++#endif ++ ppid = 0; ++ rcu_read_lock(); ++ if (pid_alive(p)) ++ ppid = task_pid_nr(rcu_dereference(p->real_parent)); ++ rcu_read_unlock(); ++ printk(KERN_CONT "%5lu %5d %6d 0x%08lx\n", free, ++ task_pid_nr(p), ppid, ++ (unsigned long)task_thread_info(p)->flags); ++ ++ print_worker_info(KERN_INFO, p); ++ show_stack(p, NULL); ++ put_task_stack(p); ++} ++EXPORT_SYMBOL_GPL(sched_show_task); ++ ++static inline bool ++state_filter_match(unsigned long state_filter, struct task_struct *p) ++{ ++ /* no filter, everything matches */ ++ if (!state_filter) ++ return true; ++ ++ /* filter, but doesn't match */ ++ if (!(p->state & state_filter)) ++ return false; ++ ++ /* ++ * When looking for TASK_UNINTERRUPTIBLE skip TASK_IDLE (allows ++ * TASK_KILLABLE). ++ */ ++ if (state_filter == TASK_UNINTERRUPTIBLE && p->state == TASK_IDLE) ++ return false; ++ ++ return true; ++} ++ ++void show_state_filter(unsigned long state_filter) ++{ ++ struct task_struct *g, *p; ++ ++#if BITS_PER_LONG == 32 ++ printk(KERN_INFO ++ " task PC stack pid father\n"); ++#else ++ printk(KERN_INFO ++ " task PC stack pid father\n"); ++#endif ++ rcu_read_lock(); ++ for_each_process_thread(g, p) { ++ /* ++ * reset the NMI-timeout, listing all files on a slow ++ * console might take a lot of time: ++ * Also, reset softlockup watchdogs on all CPUs, because ++ * another CPU might be blocked waiting for us to process ++ * an IPI. ++ */ ++ touch_nmi_watchdog(); ++ touch_all_softlockup_watchdogs(); ++ if (state_filter_match(state_filter, p)) ++ sched_show_task(p); ++ } ++ ++ rcu_read_unlock(); ++ /* ++ * Only show locks if all tasks are dumped: ++ */ ++ if (!state_filter) ++ debug_show_all_locks(); ++} ++ ++void dump_cpu_task(int cpu) ++{ ++ pr_info("Task dump for CPU %d:\n", cpu); ++ sched_show_task(cpu_curr(cpu)); ++} ++ ++#ifdef CONFIG_SMP ++void set_cpus_allowed_common(struct task_struct *p, const struct cpumask *new_mask) ++{ ++ cpumask_copy(&p->cpus_mask, new_mask); ++ p->nr_cpus_allowed = cpumask_weight(new_mask); ++} ++ ++void __do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask) ++{ ++ struct rq *rq = task_rq(p); ++ ++ lockdep_assert_held(&p->pi_lock); ++ ++ cpumask_copy(&p->cpus_mask, new_mask); ++ ++ if (task_queued(p)) { ++ /* ++ * Because __kthread_bind() calls this on blocked tasks without ++ * holding rq->lock. ++ */ ++ lockdep_assert_held(rq->lock); ++ } ++} ++ ++/* ++ * Calling do_set_cpus_allowed from outside the scheduler code should not be ++ * called on a running or queued task. We should be holding pi_lock. ++ */ ++void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask) ++{ ++ __do_set_cpus_allowed(p, new_mask); ++ if (needs_other_cpu(p, task_cpu(p))) { ++ struct rq *rq; ++ ++ rq = __task_rq_lock(p, NULL); ++ set_task_cpu(p, valid_task_cpu(p)); ++ resched_task(p); ++ __task_rq_unlock(rq, NULL); ++ } ++} ++#endif ++ ++/** ++ * init_idle - set up an idle thread for a given CPU ++ * @idle: task in question ++ * @cpu: cpu the idle task belongs to ++ * ++ * NOTE: this function does not set the idle thread's NEED_RESCHED ++ * flag, to make booting more robust. ++ */ ++void init_idle(struct task_struct *idle, int cpu) ++{ ++ struct rq *rq = cpu_rq(cpu); ++ unsigned long flags; ++ ++ raw_spin_lock_irqsave(&idle->pi_lock, flags); ++ raw_spin_lock(rq->lock); ++ idle->last_ran = rq->niffies; ++ time_slice_expired(idle, rq); ++ idle->state = TASK_RUNNING; ++ /* Setting prio to illegal value shouldn't matter when never queued */ ++ idle->prio = PRIO_LIMIT; ++ idle->flags |= PF_IDLE; ++ ++ kasan_unpoison_task_stack(idle); ++ ++#ifdef CONFIG_SMP ++ /* ++ * It's possible that init_idle() gets called multiple times on a task, ++ * in that case do_set_cpus_allowed() will not do the right thing. ++ * ++ * And since this is boot we can forgo the serialisation. ++ */ ++ set_cpus_allowed_common(idle, cpumask_of(cpu)); ++#ifdef CONFIG_SMT_NICE ++ idle->smt_bias = 0; ++#endif ++#endif ++ set_rq_task(rq, idle); ++ ++ /* Silence PROVE_RCU */ ++ rcu_read_lock(); ++ set_task_cpu(idle, cpu); ++ rcu_read_unlock(); ++ ++ rq->idle = idle; ++ rcu_assign_pointer(rq->curr, idle); ++ idle->on_rq = TASK_ON_RQ_QUEUED; ++ raw_spin_unlock(rq->lock); ++ raw_spin_unlock_irqrestore(&idle->pi_lock, flags); ++ ++ /* Set the preempt count _outside_ the spinlocks! */ ++ init_idle_preempt_count(idle, cpu); ++ ++ ftrace_graph_init_idle_task(idle, cpu); ++ vtime_init_idle(idle, cpu); ++#ifdef CONFIG_SMP ++ sprintf(idle->comm, "%s/%d", INIT_TASK_COMM, cpu); ++#endif ++} ++ ++int cpuset_cpumask_can_shrink(const struct cpumask __maybe_unused *cur, ++ const struct cpumask __maybe_unused *trial) ++{ ++ return 1; ++} ++ ++int task_can_attach(struct task_struct *p, ++ const struct cpumask *cs_cpus_allowed) ++{ ++ int ret = 0; ++ ++ /* ++ * Kthreads which disallow setaffinity shouldn't be moved ++ * to a new cpuset; we don't want to change their CPU ++ * affinity and isolating such threads by their set of ++ * allowed nodes is unnecessary. Thus, cpusets are not ++ * applicable for such threads. This prevents checking for ++ * success of set_cpus_allowed_ptr() on all attached tasks ++ * before cpus_mask may be changed. ++ */ ++ if (p->flags & PF_NO_SETAFFINITY) ++ ret = -EINVAL; ++ ++ return ret; ++} ++ ++void resched_cpu(int cpu) ++{ ++ struct rq *rq = cpu_rq(cpu); ++ struct rq_flags rf; ++ ++ rq_lock_irqsave(rq, &rf); ++ if (cpu_online(cpu) || cpu == smp_processor_id()) ++ resched_curr(rq); ++ rq_unlock_irqrestore(rq, &rf); ++} ++ ++#ifdef CONFIG_SMP ++#ifdef CONFIG_NO_HZ_COMMON ++void select_nohz_load_balancer(int stop_tick) ++{ ++} ++ ++void set_cpu_sd_state_idle(void) {} ++void nohz_balance_enter_idle(int cpu) {} ++ ++/* ++ * In the semi idle case, use the nearest busy CPU for migrating timers ++ * from an idle CPU. This is good for power-savings. ++ * ++ * We don't do similar optimization for completely idle system, as ++ * selecting an idle CPU will add more delays to the timers than intended ++ * (as that CPU's timer base may not be uptodate wrt jiffies etc). ++ */ ++int get_nohz_timer_target(void) ++{ ++ int i, cpu = smp_processor_id(), default_cpu = -1; ++ struct sched_domain *sd; ++ ++ if (housekeeping_cpu(cpu, HK_FLAG_TIMER)) { ++ if (!idle_cpu(cpu)) ++ return cpu; ++ default_cpu = cpu; ++ } ++ ++ rcu_read_lock(); ++ for_each_domain(cpu, sd) { ++ for_each_cpu_and(i, sched_domain_span(sd), ++ housekeeping_cpumask(HK_FLAG_TIMER)) { ++ if (cpu == i) ++ continue; ++ ++ if (!idle_cpu(i)) { ++ cpu = i; ++ goto unlock; ++ } ++ } ++ } ++ ++ if (default_cpu == -1) ++ default_cpu = housekeeping_any_cpu(HK_FLAG_TIMER); ++ cpu = default_cpu; ++unlock: ++ rcu_read_unlock(); ++ return cpu; ++} ++ ++/* ++ * When add_timer_on() enqueues a timer into the timer wheel of an ++ * idle CPU then this timer might expire before the next timer event ++ * which is scheduled to wake up that CPU. In case of a completely ++ * idle system the next event might even be infinite time into the ++ * future. wake_up_idle_cpu() ensures that the CPU is woken up and ++ * leaves the inner idle loop so the newly added timer is taken into ++ * account when the CPU goes back to idle and evaluates the timer ++ * wheel for the next timer event. ++ */ ++void wake_up_idle_cpu(int cpu) ++{ ++ if (cpu == smp_processor_id()) ++ return; ++ ++ if (set_nr_and_not_polling(cpu_rq(cpu)->idle)) ++ smp_sched_reschedule(cpu); ++ else ++ trace_sched_wake_idle_without_ipi(cpu); ++} ++ ++static bool wake_up_full_nohz_cpu(int cpu) ++{ ++ /* ++ * We just need the target to call irq_exit() and re-evaluate ++ * the next tick. The nohz full kick at least implies that. ++ * If needed we can still optimize that later with an ++ * empty IRQ. ++ */ ++ if (cpu_is_offline(cpu)) ++ return true; /* Don't try to wake offline CPUs. */ ++ if (tick_nohz_full_cpu(cpu)) { ++ if (cpu != smp_processor_id() || ++ tick_nohz_tick_stopped()) ++ tick_nohz_full_kick_cpu(cpu); ++ return true; ++ } ++ ++ return false; ++} ++ ++/* ++ * Wake up the specified CPU. If the CPU is going offline, it is the ++ * caller's responsibility to deal with the lost wakeup, for example, ++ * by hooking into the CPU_DEAD notifier like timers and hrtimers do. ++ */ ++void wake_up_nohz_cpu(int cpu) ++{ ++ if (!wake_up_full_nohz_cpu(cpu)) ++ wake_up_idle_cpu(cpu); ++} ++#endif /* CONFIG_NO_HZ_COMMON */ ++ ++/* ++ * Change a given task's CPU affinity. Migrate the thread to a ++ * proper CPU and schedule it away if the CPU it's executing on ++ * is removed from the allowed bitmask. ++ * ++ * NOTE: the caller must have a valid reference to the task, the ++ * task must not exit() & deallocate itself prematurely. The ++ * call is not atomic; no spinlocks may be held. ++ */ ++static int __set_cpus_allowed_ptr(struct task_struct *p, ++ const struct cpumask *new_mask, bool check) ++{ ++ const struct cpumask *cpu_valid_mask = cpu_active_mask; ++ bool queued = false, running_wrong = false, kthread; ++ struct cpumask old_mask; ++ unsigned int dest_cpu; ++ struct rq_flags rf; ++ struct rq *rq; ++ int ret = 0; ++ ++ rq = task_rq_lock(p, &rf); ++ update_rq_clock(rq); ++ ++ kthread = !!(p->flags & PF_KTHREAD); ++ if (kthread) { ++ /* ++ * Kernel threads are allowed on online && !active CPUs ++ */ ++ cpu_valid_mask = cpu_online_mask; ++ } ++ ++ /* ++ * Must re-check here, to close a race against __kthread_bind(), ++ * sched_setaffinity() is not guaranteed to observe the flag. ++ */ ++ if (check && (p->flags & PF_NO_SETAFFINITY)) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ cpumask_copy(&old_mask, p->cpus_ptr); ++ if (cpumask_equal(&old_mask, new_mask)) ++ goto out; ++ ++ dest_cpu = cpumask_any_and(cpu_valid_mask, new_mask); ++ if (dest_cpu >= nr_cpu_ids) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ queued = task_queued(p); ++ __do_set_cpus_allowed(p, new_mask); ++ ++ if (kthread) { ++ /* ++ * For kernel threads that do indeed end up on online && ++ * !active we want to ensure they are strict per-CPU threads. ++ */ ++ WARN_ON(cpumask_intersects(new_mask, cpu_online_mask) && ++ !cpumask_intersects(new_mask, cpu_active_mask) && ++ p->nr_cpus_allowed != 1); ++ } ++ ++ /* Can the task run on the task's current CPU? If so, we're done */ ++ if (cpumask_test_cpu(task_cpu(p), new_mask)) ++ goto out; ++ ++ if (task_running(rq, p)) { ++ /* Task is running on the wrong cpu now, reschedule it. */ ++ if (rq == this_rq()) { ++ set_task_cpu(p, dest_cpu); ++ set_tsk_need_resched(p); ++ running_wrong = true; ++ } else ++ resched_task(p); ++ } else { ++ if (queued) { ++ /* ++ * Switch runqueue locks after dequeueing the task ++ * here while still holding the pi_lock to be holding ++ * the correct lock for enqueueing. ++ */ ++ dequeue_task(rq, p, 0); ++ rq_unlock(rq); ++ ++ rq = cpu_rq(dest_cpu); ++ rq_lock(rq); ++ } ++ set_task_cpu(p, dest_cpu); ++ if (queued) ++ enqueue_task(rq, p, 0); ++ } ++ if (queued) ++ try_preempt(p, rq); ++ if (running_wrong) ++ preempt_disable(); ++out: ++ task_rq_unlock(rq, p, &rf); ++ ++ if (running_wrong) { ++ __schedule(true); ++ preempt_enable(); ++ } ++ ++ return ret; ++} ++ ++int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask) ++{ ++ return __set_cpus_allowed_ptr(p, new_mask, false); ++} ++EXPORT_SYMBOL_GPL(set_cpus_allowed_ptr); ++ ++#ifdef CONFIG_HOTPLUG_CPU ++/* ++ * Run through task list and find tasks affined to the dead cpu, then remove ++ * that cpu from the list, enable cpu0 and set the zerobound flag. Must hold ++ * cpu 0 and src_cpu's runqueue locks. We should be holding both rq lock and ++ * pi_lock to change cpus_mask but it's not going to matter here. ++ */ ++static void bind_zero(int src_cpu) ++{ ++ struct task_struct *p, *t; ++ struct rq *rq0; ++ int bound = 0; ++ ++ if (src_cpu == 0) ++ return; ++ ++ rq0 = cpu_rq(0); ++ ++ do_each_thread(t, p) { ++ if (cpumask_test_cpu(src_cpu, p->cpus_ptr)) { ++ bool local = (task_cpu(p) == src_cpu); ++ struct rq *rq = task_rq(p); ++ ++ /* task_running is the cpu stopper thread */ ++ if (local && task_running(rq, p)) ++ continue; ++ atomic_clear_cpu(src_cpu, &p->cpus_mask); ++ atomic_set_cpu(0, &p->cpus_mask); ++ p->zerobound = true; ++ bound++; ++ if (local) { ++ bool queued = task_queued(p); ++ ++ if (queued) ++ dequeue_task(rq, p, 0); ++ set_task_cpu(p, 0); ++ if (queued) ++ enqueue_task(rq0, p, 0); ++ } ++ } ++ } while_each_thread(t, p); ++ ++ if (bound) { ++ printk(KERN_INFO "MuQSS removed affinity for %d processes to cpu %d\n", ++ bound, src_cpu); ++ } ++} ++ ++/* Find processes with the zerobound flag and reenable their affinity for the ++ * CPU coming alive. */ ++static void unbind_zero(int src_cpu) ++{ ++ int unbound = 0, zerobound = 0; ++ struct task_struct *p, *t; ++ ++ if (src_cpu == 0) ++ return; ++ ++ do_each_thread(t, p) { ++ if (!p->mm) ++ p->zerobound = false; ++ if (p->zerobound) { ++ unbound++; ++ cpumask_set_cpu(src_cpu, &p->cpus_mask); ++ /* Once every CPU affinity has been re-enabled, remove ++ * the zerobound flag */ ++ if (cpumask_subset(cpu_possible_mask, p->cpus_ptr)) { ++ p->zerobound = false; ++ zerobound++; ++ } ++ } ++ } while_each_thread(t, p); ++ ++ if (unbound) { ++ printk(KERN_INFO "MuQSS added affinity for %d processes to cpu %d\n", ++ unbound, src_cpu); ++ } ++ if (zerobound) { ++ printk(KERN_INFO "MuQSS released forced binding to cpu0 for %d processes\n", ++ zerobound); ++ } ++} ++ ++/* ++ * Ensure that the idle task is using init_mm right before its cpu goes ++ * offline. ++ */ ++void idle_task_exit(void) ++{ ++ struct mm_struct *mm = current->active_mm; ++ ++ BUG_ON(cpu_online(smp_processor_id())); ++ ++ if (mm != &init_mm) { ++ switch_mm(mm, &init_mm, current); ++ current->active_mm = &init_mm; ++ finish_arch_post_lock_switch(); ++ } ++ mmdrop(mm); ++} ++#else /* CONFIG_HOTPLUG_CPU */ ++static void unbind_zero(int src_cpu) {} ++#endif /* CONFIG_HOTPLUG_CPU */ ++ ++void sched_set_stop_task(int cpu, struct task_struct *stop) ++{ ++ struct sched_param stop_param = { .sched_priority = STOP_PRIO }; ++ struct sched_param start_param = { .sched_priority = 0 }; ++ struct task_struct *old_stop = cpu_rq(cpu)->stop; ++ ++ if (stop) { ++ /* ++ * Make it appear like a SCHED_FIFO task, its something ++ * userspace knows about and won't get confused about. ++ * ++ * Also, it will make PI more or less work without too ++ * much confusion -- but then, stop work should not ++ * rely on PI working anyway. ++ */ ++ sched_setscheduler_nocheck(stop, SCHED_FIFO, &stop_param); ++ } ++ ++ cpu_rq(cpu)->stop = stop; ++ ++ if (old_stop) { ++ /* ++ * Reset it back to a normal scheduling policy so that ++ * it can die in pieces. ++ */ ++ sched_setscheduler_nocheck(old_stop, SCHED_NORMAL, &start_param); ++ } ++} ++ ++#if defined(CONFIG_SCHED_DEBUG) && defined(CONFIG_SYSCTL) ++ ++static struct ctl_table sd_ctl_dir[] = { ++ { ++ .procname = "sched_domain", ++ .mode = 0555, ++ }, ++ {} ++}; ++ ++static struct ctl_table sd_ctl_root[] = { ++ { ++ .procname = "kernel", ++ .mode = 0555, ++ .child = sd_ctl_dir, ++ }, ++ {} ++}; ++ ++static struct ctl_table *sd_alloc_ctl_entry(int n) ++{ ++ struct ctl_table *entry = ++ kcalloc(n, sizeof(struct ctl_table), GFP_KERNEL); ++ ++ return entry; ++} ++ ++static void sd_free_ctl_entry(struct ctl_table **tablep) ++{ ++ struct ctl_table *entry; ++ ++ /* ++ * In the intermediate directories, both the child directory and ++ * procname are dynamically allocated and could fail but the mode ++ * will always be set. In the lowest directory the names are ++ * static strings and all have proc handlers. ++ */ ++ for (entry = *tablep; entry->mode; entry++) { ++ if (entry->child) ++ sd_free_ctl_entry(&entry->child); ++ if (entry->proc_handler == NULL) ++ kfree(entry->procname); ++ } ++ ++ kfree(*tablep); ++ *tablep = NULL; ++} ++ ++static void ++set_table_entry(struct ctl_table *entry, ++ const char *procname, void *data, int maxlen, ++ umode_t mode, proc_handler *proc_handler) ++{ ++ entry->procname = procname; ++ entry->data = data; ++ entry->maxlen = maxlen; ++ entry->mode = mode; ++ entry->proc_handler = proc_handler; ++} ++ ++static struct ctl_table * ++sd_alloc_ctl_domain_table(struct sched_domain *sd) ++{ ++ struct ctl_table *table = sd_alloc_ctl_entry(9); ++ ++ if (table == NULL) ++ return NULL; ++ ++ set_table_entry(&table[0], "min_interval", &sd->min_interval, sizeof(long), 0644, proc_doulongvec_minmax); ++ set_table_entry(&table[1], "max_interval", &sd->max_interval, sizeof(long), 0644, proc_doulongvec_minmax); ++ set_table_entry(&table[2], "busy_factor", &sd->busy_factor, sizeof(int), 0644, proc_dointvec_minmax); ++ set_table_entry(&table[3], "imbalance_pct", &sd->imbalance_pct, sizeof(int), 0644, proc_dointvec_minmax); ++ set_table_entry(&table[4], "cache_nice_tries", &sd->cache_nice_tries, sizeof(int), 0644, proc_dointvec_minmax); ++ set_table_entry(&table[5], "flags", &sd->flags, sizeof(int), 0644, proc_dointvec_minmax); ++ set_table_entry(&table[6], "max_newidle_lb_cost", &sd->max_newidle_lb_cost, sizeof(long), 0644, proc_doulongvec_minmax); ++ set_table_entry(&table[7], "name", sd->name, CORENAME_MAX_SIZE, 0444, proc_dostring); ++ /* &table[8] is terminator */ ++ ++ return table; ++} ++ ++static struct ctl_table *sd_alloc_ctl_cpu_table(int cpu) ++{ ++ struct ctl_table *entry, *table; ++ struct sched_domain *sd; ++ int domain_num = 0, i; ++ char buf[32]; ++ ++ for_each_domain(cpu, sd) ++ domain_num++; ++ entry = table = sd_alloc_ctl_entry(domain_num + 1); ++ if (table == NULL) ++ return NULL; ++ ++ i = 0; ++ for_each_domain(cpu, sd) { ++ snprintf(buf, 32, "domain%d", i); ++ entry->procname = kstrdup(buf, GFP_KERNEL); ++ entry->mode = 0555; ++ entry->child = sd_alloc_ctl_domain_table(sd); ++ entry++; ++ i++; ++ } ++ return table; ++} ++ ++static cpumask_var_t sd_sysctl_cpus; ++static struct ctl_table_header *sd_sysctl_header; ++ ++void register_sched_domain_sysctl(void) ++{ ++ static struct ctl_table *cpu_entries; ++ static struct ctl_table **cpu_idx; ++ char buf[32]; ++ int i; ++ ++ if (!cpu_entries) { ++ cpu_entries = sd_alloc_ctl_entry(num_possible_cpus() + 1); ++ if (!cpu_entries) ++ return; ++ ++ WARN_ON(sd_ctl_dir[0].child); ++ sd_ctl_dir[0].child = cpu_entries; ++ } ++ ++ if (!cpu_idx) { ++ struct ctl_table *e = cpu_entries; ++ ++ cpu_idx = kcalloc(nr_cpu_ids, sizeof(struct ctl_table*), GFP_KERNEL); ++ if (!cpu_idx) ++ return; ++ ++ /* deal with sparse possible map */ ++ for_each_possible_cpu(i) { ++ cpu_idx[i] = e; ++ e++; ++ } ++ } ++ ++ if (!cpumask_available(sd_sysctl_cpus)) { ++ if (!alloc_cpumask_var(&sd_sysctl_cpus, GFP_KERNEL)) ++ return; ++ ++ /* init to possible to not have holes in @cpu_entries */ ++ cpumask_copy(sd_sysctl_cpus, cpu_possible_mask); ++ } ++ ++ for_each_cpu(i, sd_sysctl_cpus) { ++ struct ctl_table *e = cpu_idx[i]; ++ ++ if (e->child) ++ sd_free_ctl_entry(&e->child); ++ ++ if (!e->procname) { ++ snprintf(buf, 32, "cpu%d", i); ++ e->procname = kstrdup(buf, GFP_KERNEL); ++ } ++ e->mode = 0555; ++ e->child = sd_alloc_ctl_cpu_table(i); ++ ++ __cpumask_clear_cpu(i, sd_sysctl_cpus); ++ } ++ ++ WARN_ON(sd_sysctl_header); ++ sd_sysctl_header = register_sysctl_table(sd_ctl_root); ++} ++ ++void dirty_sched_domain_sysctl(int cpu) ++{ ++ if (cpumask_available(sd_sysctl_cpus)) ++ __cpumask_set_cpu(cpu, sd_sysctl_cpus); ++} ++ ++/* may be called multiple times per register */ ++void unregister_sched_domain_sysctl(void) ++{ ++ unregister_sysctl_table(sd_sysctl_header); ++ sd_sysctl_header = NULL; ++} ++#endif /* CONFIG_SYSCTL */ ++ ++void set_rq_online(struct rq *rq) ++{ ++ if (!rq->online) { ++ cpumask_set_cpu(cpu_of(rq), rq->rd->online); ++ rq->online = true; ++ } ++} ++ ++void set_rq_offline(struct rq *rq) ++{ ++ if (rq->online) { ++ int cpu = cpu_of(rq); ++ ++ cpumask_clear_cpu(cpu, rq->rd->online); ++ rq->online = false; ++ clear_cpuidle_map(cpu); ++ } ++} ++ ++/* ++ * used to mark begin/end of suspend/resume: ++ */ ++static int num_cpus_frozen; ++ ++/* ++ * Update cpusets according to cpu_active mask. If cpusets are ++ * disabled, cpuset_update_active_cpus() becomes a simple wrapper ++ * around partition_sched_domains(). ++ * ++ * If we come here as part of a suspend/resume, don't touch cpusets because we ++ * want to restore it back to its original state upon resume anyway. ++ */ ++static void cpuset_cpu_active(void) ++{ ++ if (cpuhp_tasks_frozen) { ++ /* ++ * num_cpus_frozen tracks how many CPUs are involved in suspend ++ * resume sequence. As long as this is not the last online ++ * operation in the resume sequence, just build a single sched ++ * domain, ignoring cpusets. ++ */ ++ partition_sched_domains(1, NULL, NULL); ++ if (--num_cpus_frozen) ++ return; ++ /* ++ * This is the last CPU online operation. So fall through and ++ * restore the original sched domains by considering the ++ * cpuset configurations. ++ */ ++ cpuset_force_rebuild(); ++ } ++ ++ cpuset_update_active_cpus(); ++} ++ ++static int cpuset_cpu_inactive(unsigned int cpu) ++{ ++ if (!cpuhp_tasks_frozen) { ++ cpuset_update_active_cpus(); ++ } else { ++ num_cpus_frozen++; ++ partition_sched_domains(1, NULL, NULL); ++ } ++ return 0; ++} ++ ++int sched_cpu_activate(unsigned int cpu) ++{ ++ struct rq *rq = cpu_rq(cpu); ++ struct rq_flags rf; ++ ++#ifdef CONFIG_SCHED_SMT ++ /* ++ * When going up, increment the number of cores with SMT present. ++ */ ++ if (cpumask_weight(cpu_smt_mask(cpu)) == 2) ++ static_branch_inc_cpuslocked(&sched_smt_present); ++#endif ++ set_cpu_active(cpu, true); ++ ++ if (sched_smp_initialized) { ++ sched_domains_numa_masks_set(cpu); ++ cpuset_cpu_active(); ++ } ++ ++ /* ++ * Put the rq online, if not already. This happens: ++ * ++ * 1) In the early boot process, because we build the real domains ++ * after all CPUs have been brought up. ++ * ++ * 2) At runtime, if cpuset_cpu_active() fails to rebuild the ++ * domains. ++ */ ++ rq_lock_irqsave(rq, &rf); ++ if (rq->rd) { ++ BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span)); ++ set_rq_online(rq); ++ } ++ unbind_zero(cpu); ++ rq_unlock_irqrestore(rq, &rf); ++ ++ return 0; ++} ++ ++int sched_cpu_deactivate(unsigned int cpu) ++{ ++ int ret; ++ ++ set_cpu_active(cpu, false); ++ /* ++ * We've cleared cpu_active_mask, wait for all preempt-disabled and RCU ++ * users of this state to go away such that all new such users will ++ * observe it. ++ * ++ * Do sync before park smpboot threads to take care the rcu boost case. ++ */ ++ synchronize_rcu(); ++ ++#ifdef CONFIG_SCHED_SMT ++ /* ++ * When going down, decrement the number of cores with SMT present. ++ */ ++ if (cpumask_weight(cpu_smt_mask(cpu)) == 2) ++ static_branch_dec_cpuslocked(&sched_smt_present); ++#endif ++ ++ if (!sched_smp_initialized) ++ return 0; ++ ++ ret = cpuset_cpu_inactive(cpu); ++ if (ret) { ++ set_cpu_active(cpu, true); ++ return ret; ++ } ++ sched_domains_numa_masks_clear(cpu); ++ return 0; ++} ++ ++int sched_cpu_starting(unsigned int cpu) ++{ ++ sched_tick_start(cpu); ++ return 0; ++} ++ ++#ifdef CONFIG_HOTPLUG_CPU ++int sched_cpu_dying(unsigned int cpu) ++{ ++ struct rq *rq = cpu_rq(cpu); ++ unsigned long flags; ++ ++ /* Handle pending wakeups and then migrate everything off */ ++ sched_ttwu_pending(); ++ sched_tick_stop(cpu); ++ ++ local_irq_save(flags); ++ double_rq_lock(rq, cpu_rq(0)); ++ if (rq->rd) { ++ BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span)); ++ set_rq_offline(rq); ++ } ++ bind_zero(cpu); ++ double_rq_unlock(rq, cpu_rq(0)); ++ sched_start_tick(rq, cpu); ++ hrexpiry_clear(rq); ++ local_irq_restore(flags); ++ ++ return 0; ++} ++#endif ++ ++#if defined(CONFIG_SCHED_SMT) || defined(CONFIG_SCHED_MC) ++/* ++ * Cheaper version of the below functions in case support for SMT and MC is ++ * compiled in but CPUs have no siblings. ++ */ ++static bool sole_cpu_idle(struct rq *rq) ++{ ++ return rq_idle(rq); ++} ++#endif ++#ifdef CONFIG_SCHED_SMT ++static const cpumask_t *thread_cpumask(int cpu) ++{ ++ return topology_sibling_cpumask(cpu); ++} ++/* All this CPU's SMT siblings are idle */ ++static bool siblings_cpu_idle(struct rq *rq) ++{ ++ return cpumask_subset(&rq->thread_mask, &cpu_idle_map); ++} ++#endif ++#ifdef CONFIG_SCHED_MC ++static const cpumask_t *core_cpumask(int cpu) ++{ ++ return topology_core_cpumask(cpu); ++} ++/* All this CPU's shared cache siblings are idle */ ++static bool cache_cpu_idle(struct rq *rq) ++{ ++ return cpumask_subset(&rq->core_mask, &cpu_idle_map); ++} ++/* MC siblings CPU mask which share the same LLC */ ++static const cpumask_t *llc_core_cpumask(int cpu) ++{ ++#ifdef CONFIG_X86 ++ return per_cpu(cpu_llc_shared_map, cpu); ++#else ++ return topology_core_cpumask(cpu); ++#endif ++} ++#endif ++ ++enum sched_domain_level { ++ SD_LV_NONE = 0, ++ SD_LV_SIBLING, ++ SD_LV_MC, ++ SD_LV_BOOK, ++ SD_LV_CPU, ++ SD_LV_NODE, ++ SD_LV_ALLNODES, ++ SD_LV_MAX ++}; ++ ++/* ++ * Set up the relative cache distance of each online cpu from each ++ * other in a simple array for quick lookup. Locality is determined ++ * by the closest sched_domain that CPUs are separated by. CPUs with ++ * shared cache in SMT and MC are treated as local. Separate CPUs ++ * (within the same package or physically) within the same node are ++ * treated as not local. CPUs not even in the same domain (different ++ * nodes) are treated as very distant. ++ */ ++static void __init select_leaders(void) ++{ ++ struct rq *rq, *other_rq, *leader; ++ struct sched_domain *sd; ++ int cpu, other_cpu; ++#ifdef CONFIG_SCHED_SMT ++ bool smt_threads = false; ++#endif ++ ++ for (cpu = 0; cpu < num_online_cpus(); cpu++) { ++ rq = cpu_rq(cpu); ++ leader = NULL; ++ /* First check if this cpu is in the same node */ ++ for_each_domain(cpu, sd) { ++ if (sd->level > SD_LV_MC) ++ continue; ++ if (rqshare != RQSHARE_ALL) ++ leader = NULL; ++ /* Set locality to local node if not already found lower */ ++ for_each_cpu(other_cpu, sched_domain_span(sd)) { ++ if (rqshare >= RQSHARE_SMP) { ++ other_rq = cpu_rq(other_cpu); ++ ++ /* Set the smp_leader to the first CPU */ ++ if (!leader) ++ leader = rq; ++ if (!other_rq->smp_leader) ++ other_rq->smp_leader = leader; ++ } ++ if (rq->cpu_locality[other_cpu] > LOCALITY_SMP) ++ rq->cpu_locality[other_cpu] = LOCALITY_SMP; ++ } ++ } ++ ++ /* ++ * Each runqueue has its own function in case it doesn't have ++ * siblings of its own allowing mixed topologies. ++ */ ++#ifdef CONFIG_SCHED_MC ++ leader = NULL; ++ if (cpumask_weight(core_cpumask(cpu)) > 1) { ++ cpumask_copy(&rq->core_mask, llc_core_cpumask(cpu)); ++ cpumask_clear_cpu(cpu, &rq->core_mask); ++ for_each_cpu(other_cpu, core_cpumask(cpu)) { ++ if (rqshare == RQSHARE_MC || ++ (rqshare == RQSHARE_MC_LLC && cpumask_test_cpu(other_cpu, llc_core_cpumask(cpu)))) { ++ other_rq = cpu_rq(other_cpu); ++ ++ /* Set the mc_leader to the first CPU */ ++ if (!leader) ++ leader = rq; ++ if (!other_rq->mc_leader) ++ other_rq->mc_leader = leader; ++ } ++ if (rq->cpu_locality[other_cpu] > LOCALITY_MC) { ++ /* this is to get LLC into play even in case LLC sharing is not used */ ++ if (cpumask_test_cpu(other_cpu, llc_core_cpumask(cpu))) ++ rq->cpu_locality[other_cpu] = LOCALITY_MC_LLC; ++ else ++ rq->cpu_locality[other_cpu] = LOCALITY_MC; ++ } ++ } ++ rq->cache_idle = cache_cpu_idle; ++ } ++#endif ++#ifdef CONFIG_SCHED_SMT ++ leader = NULL; ++ if (cpumask_weight(thread_cpumask(cpu)) > 1) { ++ cpumask_copy(&rq->thread_mask, thread_cpumask(cpu)); ++ cpumask_clear_cpu(cpu, &rq->thread_mask); ++ for_each_cpu(other_cpu, thread_cpumask(cpu)) { ++ if (rqshare == RQSHARE_SMT) { ++ other_rq = cpu_rq(other_cpu); ++ ++ /* Set the smt_leader to the first CPU */ ++ if (!leader) ++ leader = rq; ++ if (!other_rq->smt_leader) ++ other_rq->smt_leader = leader; ++ } ++ if (rq->cpu_locality[other_cpu] > LOCALITY_SMT) ++ rq->cpu_locality[other_cpu] = LOCALITY_SMT; ++ } ++ rq->siblings_idle = siblings_cpu_idle; ++ smt_threads = true; ++ } ++#endif ++ } ++ ++#ifdef CONFIG_SMT_NICE ++ if (smt_threads) { ++ check_siblings = &check_smt_siblings; ++ wake_siblings = &wake_smt_siblings; ++ smt_schedule = &smt_should_schedule; ++ } ++#endif ++ ++ for_each_online_cpu(cpu) { ++ rq = cpu_rq(cpu); ++ for_each_online_cpu(other_cpu) { ++ printk(KERN_DEBUG "MuQSS locality CPU %d to %d: %d\n", cpu, other_cpu, rq->cpu_locality[other_cpu]); ++ } ++ } ++} ++ ++/* FIXME freeing locked spinlock */ ++static void __init share_and_free_rq(struct rq *leader, struct rq *rq) ++{ ++ WARN_ON(rq->nr_running > 0); ++ ++ kfree(rq->node); ++ kfree(rq->sl); ++ kfree(rq->lock); ++ rq->node = leader->node; ++ rq->sl = leader->sl; ++ rq->lock = leader->lock; ++ rq->is_leader = false; ++ barrier(); ++ /* To make up for not unlocking the freed runlock */ ++ preempt_enable(); ++} ++ ++static void __init share_rqs(void) ++{ ++ struct rq *rq, *leader; ++ int cpu; ++ ++ for_each_online_cpu(cpu) { ++ rq = cpu_rq(cpu); ++ leader = rq->smp_leader; ++ ++ rq_lock(rq); ++ if (leader && rq != leader) { ++ printk(KERN_INFO "MuQSS sharing SMP runqueue from CPU %d to CPU %d\n", ++ leader->cpu, rq->cpu); ++ share_and_free_rq(leader, rq); ++ } else ++ rq_unlock(rq); ++ } ++ ++#ifdef CONFIG_SCHED_MC ++ for_each_online_cpu(cpu) { ++ rq = cpu_rq(cpu); ++ leader = rq->mc_leader; ++ ++ rq_lock(rq); ++ if (leader && rq != leader) { ++ printk(KERN_INFO "MuQSS sharing MC runqueue from CPU %d to CPU %d\n", ++ leader->cpu, rq->cpu); ++ share_and_free_rq(leader, rq); ++ } else ++ rq_unlock(rq); ++ } ++#endif /* CONFIG_SCHED_MC */ ++ ++#ifdef CONFIG_SCHED_SMT ++ for_each_online_cpu(cpu) { ++ rq = cpu_rq(cpu); ++ leader = rq->smt_leader; ++ ++ rq_lock(rq); ++ if (leader && rq != leader) { ++ printk(KERN_INFO "MuQSS sharing SMT runqueue from CPU %d to CPU %d\n", ++ leader->cpu, rq->cpu); ++ share_and_free_rq(leader, rq); ++ } else ++ rq_unlock(rq); ++ } ++#endif /* CONFIG_SCHED_SMT */ ++} ++ ++static void __init setup_rq_orders(void) ++{ ++ struct rq *rq, *other_rq; ++ int cpu, other_cpu, i; ++ ++ total_runqueues = 0; ++ for_each_online_cpu(cpu) { ++ int locality, total_rqs = 0, total_cpus = 0; ++ ++ rq = cpu_rq(cpu); ++ if (rq->is_leader) ++ total_runqueues++; ++ ++ for (locality = LOCALITY_SAME; locality <= LOCALITY_DISTANT; locality++) { ++ int selected_cpus[NR_CPUS], selected_cpu_cnt, selected_cpu_idx, test_cpu_idx, cpu_idx, best_locality, test_cpu; ++ int ordered_cpus[NR_CPUS], ordered_cpus_idx; ++ ++ ordered_cpus_idx = -1; ++ selected_cpu_cnt = 0; ++ ++ for_each_online_cpu(test_cpu) { ++ if (cpu < num_online_cpus() / 2) ++ other_cpu = cpu + test_cpu; ++ else ++ other_cpu = cpu - test_cpu; ++ if (other_cpu < 0) ++ other_cpu += num_online_cpus(); ++ else ++ other_cpu %= num_online_cpus(); ++ /* gather CPUs of the same locality */ ++ if (rq->cpu_locality[other_cpu] == locality) { ++ selected_cpus[selected_cpu_cnt] = other_cpu; ++ selected_cpu_cnt++; ++ } ++ } ++ ++ /* reserve first CPU as starting point */ ++ if (selected_cpu_cnt > 0) { ++ ordered_cpus_idx++; ++ ordered_cpus[ordered_cpus_idx] = selected_cpus[ordered_cpus_idx]; ++ selected_cpus[ordered_cpus_idx] = -1; ++ } ++ ++ /* take each CPU and sort it within the same locality based on each inter-CPU localities */ ++ for(test_cpu_idx = 1; test_cpu_idx < selected_cpu_cnt; test_cpu_idx++) { ++ /* starting point with worst locality and current CPU */ ++ best_locality = LOCALITY_DISTANT; ++ selected_cpu_idx = test_cpu_idx; ++ ++ /* try to find the best locality within group */ ++ for(cpu_idx = 1; cpu_idx < selected_cpu_cnt; cpu_idx++) { ++ /* if CPU has not been used and locality is better */ ++ if (selected_cpus[cpu_idx] > -1) { ++ other_rq = cpu_rq(ordered_cpus[ordered_cpus_idx]); ++ if (best_locality > other_rq->cpu_locality[selected_cpus[cpu_idx]]) { ++ /* assign best locality and best CPU idx in array */ ++ best_locality = other_rq->cpu_locality[selected_cpus[cpu_idx]]; ++ selected_cpu_idx = cpu_idx; ++ } ++ } ++ } ++ ++ /* add our next best CPU to ordered list */ ++ ordered_cpus_idx++; ++ ordered_cpus[ordered_cpus_idx] = selected_cpus[selected_cpu_idx]; ++ /* mark this CPU as used */ ++ selected_cpus[selected_cpu_idx] = -1; ++ } ++ ++ /* set up RQ and CPU orders */ ++ for (test_cpu = 0; test_cpu <= ordered_cpus_idx; test_cpu++) { ++ other_rq = cpu_rq(ordered_cpus[test_cpu]); ++ /* set up cpu orders */ ++ rq->cpu_order[total_cpus++] = other_rq; ++ if (other_rq->is_leader) { ++ /* set up RQ orders */ ++ rq->rq_order[total_rqs++] = other_rq; ++ } ++ } ++ } ++ } ++ ++#ifdef CONFIG_X86 ++ for_each_online_cpu(cpu) { ++ rq = cpu_rq(cpu); ++ for (i = 0; i < total_runqueues; i++) { ++ printk(KERN_DEBUG "MuQSS CPU %d llc %d RQ order %d RQ %d llc %d\n", cpu, per_cpu(cpu_llc_id, cpu), i, ++ rq->rq_order[i]->cpu, per_cpu(cpu_llc_id, rq->rq_order[i]->cpu)); ++ } ++ } ++ ++ for_each_online_cpu(cpu) { ++ rq = cpu_rq(cpu); ++ for (i = 0; i < num_online_cpus(); i++) { ++ printk(KERN_DEBUG "MuQSS CPU %d llc %d CPU order %d RQ %d llc %d\n", cpu, per_cpu(cpu_llc_id, cpu), i, ++ rq->cpu_order[i]->cpu, per_cpu(cpu_llc_id, rq->cpu_order[i]->cpu)); ++ } ++ } ++#endif ++} ++ ++void __init sched_init_smp(void) ++{ ++ sched_init_numa(); ++ ++ /* ++ * There's no userspace yet to cause hotplug operations; hence all the ++ * cpu masks are stable and all blatant races in the below code cannot ++ * happen. ++ */ ++ mutex_lock(&sched_domains_mutex); ++ sched_init_domains(cpu_active_mask); ++ mutex_unlock(&sched_domains_mutex); ++ ++ /* Move init over to a non-isolated CPU */ ++ if (set_cpus_allowed_ptr(current, housekeeping_cpumask(HK_FLAG_DOMAIN)) < 0) ++ BUG(); ++ ++ local_irq_disable(); ++ mutex_lock(&sched_domains_mutex); ++ lock_all_rqs(); ++ ++ printk(KERN_INFO "MuQSS possible/present/online CPUs: %d/%d/%d\n", ++ num_possible_cpus(), num_present_cpus(), num_online_cpus()); ++ ++ select_leaders(); ++ ++ unlock_all_rqs(); ++ mutex_unlock(&sched_domains_mutex); ++ ++ share_rqs(); ++ ++ local_irq_enable(); ++ ++ setup_rq_orders(); ++ ++ switch (rqshare) { ++ case RQSHARE_ALL: ++ /* This should only ever read 1 */ ++ printk(KERN_INFO "MuQSS runqueue share type ALL total runqueues: %d\n", ++ total_runqueues); ++ break; ++ case RQSHARE_SMP: ++ printk(KERN_INFO "MuQSS runqueue share type SMP total runqueues: %d\n", ++ total_runqueues); ++ break; ++ case RQSHARE_MC: ++ printk(KERN_INFO "MuQSS runqueue share type MC total runqueues: %d\n", ++ total_runqueues); ++ break; ++ case RQSHARE_MC_LLC: ++ printk(KERN_INFO "MuQSS runqueue share type LLC total runqueues: %d\n", ++ total_runqueues); ++ break; ++ case RQSHARE_SMT: ++ printk(KERN_INFO "MuQSS runqueue share type SMT total runqueues: %d\n", ++ total_runqueues); ++ break; ++ case RQSHARE_NONE: ++ printk(KERN_INFO "MuQSS runqueue share type NONE total runqueues: %d\n", ++ total_runqueues); ++ break; ++ } ++ ++ sched_smp_initialized = true; ++} ++#else ++void __init sched_init_smp(void) ++{ ++ sched_smp_initialized = true; ++} ++#endif /* CONFIG_SMP */ ++ ++int in_sched_functions(unsigned long addr) ++{ ++ return in_lock_functions(addr) || ++ (addr >= (unsigned long)__sched_text_start ++ && addr < (unsigned long)__sched_text_end); ++} ++ ++#ifdef CONFIG_CGROUP_SCHED ++/* task group related information */ ++struct task_group { ++ struct cgroup_subsys_state css; ++ ++ struct rcu_head rcu; ++ struct list_head list; ++ ++ struct task_group *parent; ++ struct list_head siblings; ++ struct list_head children; ++}; ++ ++/* ++ * Default task group. ++ * Every task in system belongs to this group at bootup. ++ */ ++struct task_group root_task_group; ++LIST_HEAD(task_groups); ++ ++/* Cacheline aligned slab cache for task_group */ ++static struct kmem_cache *task_group_cache __read_mostly; ++#endif /* CONFIG_CGROUP_SCHED */ ++ ++void __init sched_init(void) ++{ ++#ifdef CONFIG_SMP ++ int cpu_ids; ++#endif ++ int i; ++ struct rq *rq; ++ ++ wait_bit_init(); ++ ++ prio_ratios[0] = 128; ++ for (i = 1 ; i < NICE_WIDTH ; i++) ++ prio_ratios[i] = prio_ratios[i - 1] * 11 / 10; ++ ++ skiplist_node_init(&init_task.node); ++ ++#ifdef CONFIG_SMP ++ init_defrootdomain(); ++ cpumask_clear(&cpu_idle_map); ++#else ++ uprq = &per_cpu(runqueues, 0); ++#endif ++ ++#ifdef CONFIG_CGROUP_SCHED ++ task_group_cache = KMEM_CACHE(task_group, 0); ++ ++ list_add(&root_task_group.list, &task_groups); ++ INIT_LIST_HEAD(&root_task_group.children); ++ INIT_LIST_HEAD(&root_task_group.siblings); ++#endif /* CONFIG_CGROUP_SCHED */ ++ for_each_possible_cpu(i) { ++ rq = cpu_rq(i); ++ rq->node = kmalloc(sizeof(skiplist_node), GFP_ATOMIC); ++ skiplist_init(rq->node); ++ rq->sl = new_skiplist(rq->node); ++ rq->lock = kmalloc(sizeof(raw_spinlock_t), GFP_ATOMIC); ++ raw_spin_lock_init(rq->lock); ++ rq->nr_running = 0; ++ rq->nr_uninterruptible = 0; ++ rq->nr_switches = 0; ++ rq->clock = rq->old_clock = rq->last_niffy = rq->niffies = 0; ++ rq->last_jiffy = jiffies; ++ rq->user_ns = rq->nice_ns = rq->softirq_ns = rq->system_ns = ++ rq->iowait_ns = rq->idle_ns = 0; ++ rq->dither = 0; ++ set_rq_task(rq, &init_task); ++ rq->iso_ticks = 0; ++ rq->iso_refractory = false; ++#ifdef CONFIG_SMP ++ rq->is_leader = true; ++ rq->smp_leader = NULL; ++#ifdef CONFIG_SCHED_MC ++ rq->mc_leader = NULL; ++#endif ++#ifdef CONFIG_SCHED_SMT ++ rq->smt_leader = NULL; ++#endif ++ rq->sd = NULL; ++ rq->rd = NULL; ++ rq->online = false; ++ rq->cpu = i; ++ rq_attach_root(rq, &def_root_domain); ++#endif ++ init_rq_hrexpiry(rq); ++ atomic_set(&rq->nr_iowait, 0); ++ } ++ ++#ifdef CONFIG_SMP ++ cpu_ids = i; ++ /* ++ * Set the base locality for cpu cache distance calculation to ++ * "distant" (3). Make sure the distance from a CPU to itself is 0. ++ */ ++ for_each_possible_cpu(i) { ++ int j; ++ ++ rq = cpu_rq(i); ++#ifdef CONFIG_SCHED_SMT ++ rq->siblings_idle = sole_cpu_idle; ++#endif ++#ifdef CONFIG_SCHED_MC ++ rq->cache_idle = sole_cpu_idle; ++#endif ++ rq->cpu_locality = kmalloc(cpu_ids * sizeof(int *), GFP_ATOMIC); ++ for_each_possible_cpu(j) { ++ if (i == j) ++ rq->cpu_locality[j] = LOCALITY_SAME; ++ else ++ rq->cpu_locality[j] = LOCALITY_DISTANT; ++ } ++ rq->rq_order = kmalloc(cpu_ids * sizeof(struct rq *), GFP_ATOMIC); ++ rq->cpu_order = kmalloc(cpu_ids * sizeof(struct rq *), GFP_ATOMIC); ++ rq->rq_order[0] = rq->cpu_order[0] = rq; ++ for (j = 1; j < cpu_ids; j++) ++ rq->rq_order[j] = rq->cpu_order[j] = cpu_rq(j); ++ } ++#endif ++ ++ /* ++ * The boot idle thread does lazy MMU switching as well: ++ */ ++ mmgrab(&init_mm); ++ enter_lazy_tlb(&init_mm, current); ++ ++ /* ++ * Make us the idle thread. Technically, schedule() should not be ++ * called from this thread, however somewhere below it might be, ++ * but because we are the idle thread, we just pick up running again ++ * when this runqueue becomes "idle". ++ */ ++ init_idle(current, smp_processor_id()); ++ ++#ifdef CONFIG_SMP ++ idle_thread_set_boot_cpu(); ++#endif /* SMP */ ++ ++ init_schedstats(); ++ ++ psi_init(); ++} ++ ++#ifdef CONFIG_DEBUG_ATOMIC_SLEEP ++static inline int preempt_count_equals(int preempt_offset) ++{ ++ int nested = preempt_count() + rcu_preempt_depth(); ++ ++ return (nested == preempt_offset); ++} ++ ++void __might_sleep(const char *file, int line, int preempt_offset) ++{ ++ /* ++ * Blocking primitives will set (and therefore destroy) current->state, ++ * since we will exit with TASK_RUNNING make sure we enter with it, ++ * otherwise we will destroy state. ++ */ ++ WARN_ONCE(current->state != TASK_RUNNING && current->task_state_change, ++ "do not call blocking ops when !TASK_RUNNING; " ++ "state=%lx set at [<%p>] %pS\n", ++ current->state, ++ (void *)current->task_state_change, ++ (void *)current->task_state_change); ++ ++ ___might_sleep(file, line, preempt_offset); ++} ++EXPORT_SYMBOL(__might_sleep); ++ ++void __cant_sleep(const char *file, int line, int preempt_offset) ++{ ++ static unsigned long prev_jiffy; ++ ++ if (irqs_disabled()) ++ return; ++ ++ if (!IS_ENABLED(CONFIG_PREEMPT_COUNT)) ++ return; ++ ++ if (preempt_count() > preempt_offset) ++ return; ++ ++ if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy) ++ return; ++ prev_jiffy = jiffies; ++ ++ printk(KERN_ERR "BUG: assuming atomic context at %s:%d\n", file, line); ++ printk(KERN_ERR "in_atomic(): %d, irqs_disabled(): %d, pid: %d, name: %s\n", ++ in_atomic(), irqs_disabled(), ++ current->pid, current->comm); ++ ++ debug_show_held_locks(current); ++ dump_stack(); ++ add_taint(TAINT_WARN, LOCKDEP_STILL_OK); ++} ++EXPORT_SYMBOL_GPL(__cant_sleep); ++ ++void ___might_sleep(const char *file, int line, int preempt_offset) ++{ ++ /* Ratelimiting timestamp: */ ++ static unsigned long prev_jiffy; ++ ++ unsigned long preempt_disable_ip; ++ ++ /* WARN_ON_ONCE() by default, no rate limit required: */ ++ rcu_sleep_check(); ++ ++ if ((preempt_count_equals(preempt_offset) && !irqs_disabled() && ++ !is_idle_task(current) && !current->non_block_count) || ++ system_state == SYSTEM_BOOTING || system_state > SYSTEM_RUNNING || ++ oops_in_progress) ++ return; ++ ++ if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy) ++ return; ++ prev_jiffy = jiffies; ++ ++ /* Save this before calling printk(), since that will clobber it: */ ++ preempt_disable_ip = get_preempt_disable_ip(current); ++ ++ printk(KERN_ERR ++ "BUG: sleeping function called from invalid context at %s:%d\n", ++ file, line); ++ printk(KERN_ERR ++ "in_atomic(): %d, irqs_disabled(): %d, non_block: %d, pid: %d, name: %s\n", ++ in_atomic(), irqs_disabled(), current->non_block_count, ++ current->pid, current->comm); ++ ++ if (task_stack_end_corrupted(current)) ++ printk(KERN_EMERG "Thread overran stack, or stack corrupted\n"); ++ ++ debug_show_held_locks(current); ++ if (irqs_disabled()) ++ print_irqtrace_events(current); ++ if (IS_ENABLED(CONFIG_DEBUG_PREEMPT) ++ && !preempt_count_equals(preempt_offset)) { ++ pr_err("Preemption disabled at:"); ++ print_ip_sym(preempt_disable_ip); ++ pr_cont("\n"); ++ } ++ dump_stack(); ++ add_taint(TAINT_WARN, LOCKDEP_STILL_OK); ++} ++EXPORT_SYMBOL(___might_sleep); ++#endif ++ ++#ifdef CONFIG_MAGIC_SYSRQ ++static inline void normalise_rt_tasks(void) ++{ ++ struct sched_attr attr = {}; ++ struct task_struct *g, *p; ++ struct rq_flags rf; ++ struct rq *rq; ++ ++ read_lock(&tasklist_lock); ++ for_each_process_thread(g, p) { ++ /* ++ * Only normalize user tasks: ++ */ ++ if (p->flags & PF_KTHREAD) ++ continue; ++ ++ if (!rt_task(p) && !iso_task(p)) ++ continue; ++ ++ rq = task_rq_lock(p, &rf); ++ __setscheduler(p, rq, SCHED_NORMAL, 0, &attr, false); ++ task_rq_unlock(rq, p, &rf); ++ } ++ read_unlock(&tasklist_lock); ++} ++ ++void normalize_rt_tasks(void) ++{ ++ normalise_rt_tasks(); ++} ++#endif /* CONFIG_MAGIC_SYSRQ */ ++ ++#if defined(CONFIG_IA64) || defined(CONFIG_KGDB_KDB) ++/* ++ * These functions are only useful for the IA64 MCA handling, or kdb. ++ * ++ * They can only be called when the whole system has been ++ * stopped - every CPU needs to be quiescent, and no scheduling ++ * activity can take place. Using them for anything else would ++ * be a serious bug, and as a result, they aren't even visible ++ * under any other configuration. ++ */ ++ ++/** ++ * curr_task - return the current task for a given CPU. ++ * @cpu: the processor in question. ++ * ++ * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED! ++ * ++ * Return: The current task for @cpu. ++ */ ++struct task_struct *curr_task(int cpu) ++{ ++ return cpu_curr(cpu); ++} ++ ++#endif /* defined(CONFIG_IA64) || defined(CONFIG_KGDB_KDB) */ ++ ++#ifdef CONFIG_IA64 ++/** ++ * ia64_set_curr_task - set the current task for a given CPU. ++ * @cpu: the processor in question. ++ * @p: the task pointer to set. ++ * ++ * Description: This function must only be used when non-maskable interrupts ++ * are serviced on a separate stack. It allows the architecture to switch the ++ * notion of the current task on a CPU in a non-blocking manner. This function ++ * must be called with all CPU's synchronised, and interrupts disabled, the ++ * and caller must save the original value of the current task (see ++ * curr_task() above) and restore that value before reenabling interrupts and ++ * re-starting the system. ++ * ++ * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED! ++ */ ++void ia64_set_curr_task(int cpu, struct task_struct *p) ++{ ++ cpu_curr(cpu) = p; ++} ++ ++#endif ++ ++void init_idle_bootup_task(struct task_struct *idle) ++{} ++ ++#ifdef CONFIG_SCHED_DEBUG ++__read_mostly bool sched_debug_enabled; ++ ++void proc_sched_show_task(struct task_struct *p, struct pid_namespace *ns, ++ struct seq_file *m) ++{ ++ seq_printf(m, "%s (%d, #threads: %d)\n", p->comm, task_pid_nr_ns(p, ns), ++ get_nr_threads(p)); ++} ++ ++void proc_sched_set_task(struct task_struct *p) ++{} ++#endif ++ ++#ifdef CONFIG_CGROUP_SCHED ++static void sched_free_group(struct task_group *tg) ++{ ++ kmem_cache_free(task_group_cache, tg); ++} ++ ++/* allocate runqueue etc for a new task group */ ++struct task_group *sched_create_group(struct task_group *parent) ++{ ++ struct task_group *tg; ++ ++ tg = kmem_cache_alloc(task_group_cache, GFP_KERNEL | __GFP_ZERO); ++ if (!tg) ++ return ERR_PTR(-ENOMEM); ++ ++ return tg; ++} ++ ++void sched_online_group(struct task_group *tg, struct task_group *parent) ++{ ++} ++ ++/* rcu callback to free various structures associated with a task group */ ++static void sched_free_group_rcu(struct rcu_head *rhp) ++{ ++ /* Now it should be safe to free those cfs_rqs */ ++ sched_free_group(container_of(rhp, struct task_group, rcu)); ++} ++ ++void sched_destroy_group(struct task_group *tg) ++{ ++ /* Wait for possible concurrent references to cfs_rqs complete */ ++ call_rcu(&tg->rcu, sched_free_group_rcu); ++} ++ ++void sched_offline_group(struct task_group *tg) ++{ ++} ++ ++static inline struct task_group *css_tg(struct cgroup_subsys_state *css) ++{ ++ return css ? container_of(css, struct task_group, css) : NULL; ++} ++ ++static struct cgroup_subsys_state * ++cpu_cgroup_css_alloc(struct cgroup_subsys_state *parent_css) ++{ ++ struct task_group *parent = css_tg(parent_css); ++ struct task_group *tg; ++ ++ if (!parent) { ++ /* This is early initialization for the top cgroup */ ++ return &root_task_group.css; ++ } ++ ++ tg = sched_create_group(parent); ++ if (IS_ERR(tg)) ++ return ERR_PTR(-ENOMEM); ++ return &tg->css; ++} ++ ++/* Expose task group only after completing cgroup initialization */ ++static int cpu_cgroup_css_online(struct cgroup_subsys_state *css) ++{ ++ struct task_group *tg = css_tg(css); ++ struct task_group *parent = css_tg(css->parent); ++ ++ if (parent) ++ sched_online_group(tg, parent); ++ return 0; ++} ++ ++static void cpu_cgroup_css_released(struct cgroup_subsys_state *css) ++{ ++ struct task_group *tg = css_tg(css); ++ ++ sched_offline_group(tg); ++} ++ ++static void cpu_cgroup_css_free(struct cgroup_subsys_state *css) ++{ ++ struct task_group *tg = css_tg(css); ++ ++ /* ++ * Relies on the RCU grace period between css_released() and this. ++ */ ++ sched_free_group(tg); ++} ++ ++static void cpu_cgroup_fork(struct task_struct *task) ++{ ++} ++ ++static int cpu_cgroup_can_attach(struct cgroup_taskset *tset) ++{ ++ return 0; ++} ++ ++static void cpu_cgroup_attach(struct cgroup_taskset *tset) ++{ ++} ++ ++static struct cftype cpu_legacy_files[] = { ++ { } /* Terminate */ ++}; ++ ++static struct cftype cpu_files[] = { ++ { } /* terminate */ ++}; ++ ++static int cpu_extra_stat_show(struct seq_file *sf, ++ struct cgroup_subsys_state *css) ++{ ++ return 0; ++} ++ ++struct cgroup_subsys cpu_cgrp_subsys = { ++ .css_alloc = cpu_cgroup_css_alloc, ++ .css_online = cpu_cgroup_css_online, ++ .css_released = cpu_cgroup_css_released, ++ .css_free = cpu_cgroup_css_free, ++ .css_extra_stat_show = cpu_extra_stat_show, ++ .fork = cpu_cgroup_fork, ++ .can_attach = cpu_cgroup_can_attach, ++ .attach = cpu_cgroup_attach, ++ .legacy_cftypes = cpu_files, ++ .legacy_cftypes = cpu_legacy_files, ++ .dfl_cftypes = cpu_files, ++ .early_init = true, ++ .threaded = true, ++}; ++#endif /* CONFIG_CGROUP_SCHED */ ++ ++#undef CREATE_TRACE_POINTS +--- /dev/null ++++ b/kernel/sched/MuQSS.h +@@ -0,0 +1,1019 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef MUQSS_SCHED_H ++#define MUQSS_SCHED_H ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef CONFIG_PARAVIRT ++#include ++#endif ++ ++#include "cpupri.h" ++ ++#ifdef CONFIG_SCHED_DEBUG ++# define SCHED_WARN_ON(x) WARN_ONCE(x, #x) ++#else ++# define SCHED_WARN_ON(x) ((void)(x)) ++#endif ++ ++/* ++ * wake flags ++ */ ++#define WF_SYNC 0x01 /* waker goes to sleep after wakeup */ ++#define WF_FORK 0x02 /* child wakeup after fork */ ++#define WF_MIGRATED 0x04 /* internal use, task got migrated */ ++ ++/* task_struct::on_rq states: */ ++#define TASK_ON_RQ_QUEUED 1 ++#define TASK_ON_RQ_MIGRATING 2 ++ ++struct rq; ++ ++#ifdef CONFIG_SMP ++ ++static inline bool sched_asym_prefer(int a, int b) ++{ ++ return arch_asym_cpu_priority(a) > arch_asym_cpu_priority(b); ++} ++ ++struct perf_domain { ++ struct em_perf_domain *em_pd; ++ struct perf_domain *next; ++ struct rcu_head rcu; ++}; ++ ++/* Scheduling group status flags */ ++#define SG_OVERLOAD 0x1 /* More than one runnable task on a CPU. */ ++#define SG_OVERUTILIZED 0x2 /* One or more CPUs are over-utilized. */ ++ ++/* ++ * We add the notion of a root-domain which will be used to define per-domain ++ * variables. Each exclusive cpuset essentially defines an island domain by ++ * fully partitioning the member cpus from any other cpuset. Whenever a new ++ * exclusive cpuset is created, we also create and attach a new root-domain ++ * object. ++ * ++ */ ++struct root_domain { ++ atomic_t refcount; ++ atomic_t rto_count; ++ struct rcu_head rcu; ++ cpumask_var_t span; ++ cpumask_var_t online; ++ ++ /* ++ * Indicate pullable load on at least one CPU, e.g: ++ * - More than one runnable task ++ * - Running task is misfit ++ */ ++ int overload; ++ ++ /* Indicate one or more cpus over-utilized (tipping point) */ ++ int overutilized; ++ ++ /* ++ * The bit corresponding to a CPU gets set here if such CPU has more ++ * than one runnable -deadline task (as it is below for RT tasks). ++ */ ++ cpumask_var_t dlo_mask; ++ atomic_t dlo_count; ++ /* Replace unused CFS structures with void */ ++ //struct dl_bw dl_bw; ++ //struct cpudl cpudl; ++ void *dl_bw; ++ void *cpudl; ++ ++ /* ++ * The "RT overload" flag: it gets set if a CPU has more than ++ * one runnable RT task. ++ */ ++ cpumask_var_t rto_mask; ++ //struct cpupri cpupri; ++ void *cpupri; ++ ++ unsigned long max_cpu_capacity; ++ ++ /* ++ * NULL-terminated list of performance domains intersecting with the ++ * CPUs of the rd. Protected by RCU. ++ */ ++ struct perf_domain *pd; ++}; ++ ++extern void init_defrootdomain(void); ++extern int sched_init_domains(const struct cpumask *cpu_map); ++extern void rq_attach_root(struct rq *rq, struct root_domain *rd); ++ ++static inline void cpupri_cleanup(void __maybe_unused *cpupri) ++{ ++} ++ ++static inline void cpudl_cleanup(void __maybe_unused *cpudl) ++{ ++} ++ ++static inline void init_dl_bw(void __maybe_unused *dl_bw) ++{ ++} ++ ++static inline int cpudl_init(void __maybe_unused *dl_bw) ++{ ++ return 0; ++} ++ ++static inline int cpupri_init(void __maybe_unused *cpupri) ++{ ++ return 0; ++} ++#endif /* CONFIG_SMP */ ++ ++/* ++ * This is the main, per-CPU runqueue data structure. ++ * This data should only be modified by the local cpu. ++ */ ++struct rq { ++ raw_spinlock_t *lock; ++ raw_spinlock_t *orig_lock; ++ ++ struct task_struct __rcu *curr; ++ struct task_struct *idle; ++ struct task_struct *stop; ++ struct mm_struct *prev_mm; ++ ++ unsigned int nr_running; ++ /* ++ * This is part of a global counter where only the total sum ++ * over all CPUs matters. A task can increase this counter on ++ * one CPU and if it got migrated afterwards it may decrease ++ * it on another CPU. Always updated under the runqueue lock: ++ */ ++ unsigned long nr_uninterruptible; ++ u64 nr_switches; ++ ++ /* Stored data about rq->curr to work outside rq lock */ ++ u64 rq_deadline; ++ int rq_prio; ++ ++ /* Best queued id for use outside lock */ ++ u64 best_key; ++ ++ unsigned long last_scheduler_tick; /* Last jiffy this RQ ticked */ ++ unsigned long last_jiffy; /* Last jiffy this RQ updated rq clock */ ++ u64 niffies; /* Last time this RQ updated rq clock */ ++ u64 last_niffy; /* Last niffies as updated by local clock */ ++ u64 last_jiffy_niffies; /* Niffies @ last_jiffy */ ++ ++ u64 load_update; /* When we last updated load */ ++ unsigned long load_avg; /* Rolling load average */ ++#ifdef CONFIG_HAVE_SCHED_AVG_IRQ ++ u64 irq_load_update; /* When we last updated IRQ load */ ++ unsigned long irq_load_avg; /* Rolling IRQ load average */ ++#endif ++#ifdef CONFIG_SMT_NICE ++ struct mm_struct *rq_mm; ++ int rq_smt_bias; /* Policy/nice level bias across smt siblings */ ++#endif ++ /* Accurate timekeeping data */ ++ unsigned long user_ns, nice_ns, irq_ns, softirq_ns, system_ns, ++ iowait_ns, idle_ns; ++ atomic_t nr_iowait; ++ ++#ifdef CONFIG_MEMBARRIER ++ int membarrier_state; ++#endif ++ ++ skiplist_node *node; ++ skiplist *sl; ++#ifdef CONFIG_SMP ++ struct task_struct *preempt; /* Preempt triggered on this task */ ++ struct task_struct *preempting; /* Hint only, what task is preempting */ ++ ++ int cpu; /* cpu of this runqueue */ ++ bool online; ++ ++ struct root_domain *rd; ++ struct sched_domain *sd; ++ ++ unsigned long cpu_capacity_orig; ++ ++ int *cpu_locality; /* CPU relative cache distance */ ++ struct rq **rq_order; /* Shared RQs ordered by relative cache distance */ ++ struct rq **cpu_order; /* RQs of discrete CPUs ordered by distance */ ++ ++ bool is_leader; ++ struct rq *smp_leader; /* First physical CPU per node */ ++#ifdef CONFIG_SCHED_SMT ++ struct rq *smt_leader; /* First logical CPU in SMT siblings */ ++ cpumask_t thread_mask; ++ bool (*siblings_idle)(struct rq *rq); ++ /* See if all smt siblings are idle */ ++#endif /* CONFIG_SCHED_SMT */ ++#ifdef CONFIG_SCHED_MC ++ struct rq *mc_leader; /* First logical CPU in MC siblings */ ++ cpumask_t core_mask; ++ bool (*cache_idle)(struct rq *rq); ++ /* See if all cache siblings are idle */ ++#endif /* CONFIG_SCHED_MC */ ++#endif /* CONFIG_SMP */ ++#ifdef CONFIG_IRQ_TIME_ACCOUNTING ++ u64 prev_irq_time; ++#endif /* CONFIG_IRQ_TIME_ACCOUNTING */ ++#ifdef CONFIG_PARAVIRT ++ u64 prev_steal_time; ++#endif /* CONFIG_PARAVIRT */ ++#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING ++ u64 prev_steal_time_rq; ++#endif /* CONFIG_PARAVIRT_TIME_ACCOUNTING */ ++ ++ u64 clock, old_clock, last_tick; ++ /* Ensure that all clocks are in the same cache line */ ++ u64 clock_task ____cacheline_aligned; ++ int dither; ++ ++ int iso_ticks; ++ bool iso_refractory; ++ ++#ifdef CONFIG_HIGH_RES_TIMERS ++ struct hrtimer hrexpiry_timer; ++#endif ++ ++ int rt_nr_running; /* Number real time tasks running */ ++#ifdef CONFIG_SCHEDSTATS ++ ++ /* latency stats */ ++ struct sched_info rq_sched_info; ++ unsigned long long rq_cpu_time; ++ /* could above be rq->cfs_rq.exec_clock + rq->rt_rq.rt_runtime ? */ ++ ++ /* sys_sched_yield() stats */ ++ unsigned int yld_count; ++ ++ /* schedule() stats */ ++ unsigned int sched_switch; ++ unsigned int sched_count; ++ unsigned int sched_goidle; ++ ++ /* try_to_wake_up() stats */ ++ unsigned int ttwu_count; ++ unsigned int ttwu_local; ++#endif /* CONFIG_SCHEDSTATS */ ++ ++#ifdef CONFIG_SMP ++ struct llist_head wake_list; ++#endif ++ ++#ifdef CONFIG_CPU_IDLE ++ /* Must be inspected within a rcu lock section */ ++ struct cpuidle_state *idle_state; ++#endif ++}; ++ ++struct rq_flags { ++ unsigned long flags; ++}; ++ ++#ifdef CONFIG_SMP ++struct rq *cpu_rq(int cpu); ++#endif ++ ++#ifndef CONFIG_SMP ++extern struct rq *uprq; ++#define cpu_rq(cpu) (uprq) ++#define this_rq() (uprq) ++#define raw_rq() (uprq) ++#define task_rq(p) (uprq) ++#define cpu_curr(cpu) ((uprq)->curr) ++#else /* CONFIG_SMP */ ++DECLARE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues); ++#define this_rq() this_cpu_ptr(&runqueues) ++#define raw_rq() raw_cpu_ptr(&runqueues) ++#define task_rq(p) cpu_rq(task_cpu(p)) ++#endif /* CONFIG_SMP */ ++ ++static inline int task_current(struct rq *rq, struct task_struct *p) ++{ ++ return rq->curr == p; ++} ++ ++static inline int task_running(struct rq *rq, struct task_struct *p) ++{ ++#ifdef CONFIG_SMP ++ return p->on_cpu; ++#else ++ return task_current(rq, p); ++#endif ++} ++ ++static inline int task_on_rq_queued(struct task_struct *p) ++{ ++ return p->on_rq == TASK_ON_RQ_QUEUED; ++} ++ ++static inline int task_on_rq_migrating(struct task_struct *p) ++{ ++ return READ_ONCE(p->on_rq) == TASK_ON_RQ_MIGRATING; ++} ++ ++static inline void rq_lock(struct rq *rq) ++ __acquires(rq->lock) ++{ ++ raw_spin_lock(rq->lock); ++} ++ ++static inline void rq_unlock(struct rq *rq) ++ __releases(rq->lock) ++{ ++ raw_spin_unlock(rq->lock); ++} ++ ++static inline void rq_lock_irq(struct rq *rq) ++ __acquires(rq->lock) ++{ ++ raw_spin_lock_irq(rq->lock); ++} ++ ++static inline void rq_unlock_irq(struct rq *rq, struct rq_flags __always_unused *rf) ++ __releases(rq->lock) ++{ ++ raw_spin_unlock_irq(rq->lock); ++} ++ ++static inline void rq_lock_irqsave(struct rq *rq, struct rq_flags *rf) ++ __acquires(rq->lock) ++{ ++ raw_spin_lock_irqsave(rq->lock, rf->flags); ++} ++ ++static inline void rq_unlock_irqrestore(struct rq *rq, struct rq_flags *rf) ++ __releases(rq->lock) ++{ ++ raw_spin_unlock_irqrestore(rq->lock, rf->flags); ++} ++ ++static inline struct rq *task_rq_lock(struct task_struct *p, struct rq_flags *rf) ++ __acquires(p->pi_lock) ++ __acquires(rq->lock) ++{ ++ struct rq *rq; ++ ++ while (42) { ++ raw_spin_lock_irqsave(&p->pi_lock, rf->flags); ++ rq = task_rq(p); ++ raw_spin_lock(rq->lock); ++ if (likely(rq == task_rq(p))) ++ break; ++ raw_spin_unlock(rq->lock); ++ raw_spin_unlock_irqrestore(&p->pi_lock, rf->flags); ++ } ++ return rq; ++} ++ ++static inline void task_rq_unlock(struct rq *rq, struct task_struct *p, struct rq_flags *rf) ++ __releases(rq->lock) ++ __releases(p->pi_lock) ++{ ++ rq_unlock(rq); ++ raw_spin_unlock_irqrestore(&p->pi_lock, rf->flags); ++} ++ ++static inline struct rq *__task_rq_lock(struct task_struct *p, struct rq_flags __always_unused *rf) ++ __acquires(rq->lock) ++{ ++ struct rq *rq; ++ ++ lockdep_assert_held(&p->pi_lock); ++ ++ while (42) { ++ rq = task_rq(p); ++ raw_spin_lock(rq->lock); ++ if (likely(rq == task_rq(p))) ++ break; ++ raw_spin_unlock(rq->lock); ++ } ++ return rq; ++} ++ ++static inline void __task_rq_unlock(struct rq *rq, struct rq_flags __always_unused *rf) ++{ ++ rq_unlock(rq); ++} ++ ++static inline struct rq * ++this_rq_lock_irq(struct rq_flags *rf) ++ __acquires(rq->lock) ++{ ++ struct rq *rq; ++ ++ local_irq_disable(); ++ rq = this_rq(); ++ rq_lock(rq); ++ return rq; ++} ++ ++/* ++ * {de,en}queue flags: Most not used on MuQSS. ++ * ++ * DEQUEUE_SLEEP - task is no longer runnable ++ * ENQUEUE_WAKEUP - task just became runnable ++ * ++ * SAVE/RESTORE - an otherwise spurious dequeue/enqueue, done to ensure tasks ++ * are in a known state which allows modification. Such pairs ++ * should preserve as much state as possible. ++ * ++ * MOVE - paired with SAVE/RESTORE, explicitly does not preserve the location ++ * in the runqueue. ++ * ++ * ENQUEUE_HEAD - place at front of runqueue (tail if not specified) ++ * ENQUEUE_REPLENISH - CBS (replenish runtime and postpone deadline) ++ * ENQUEUE_MIGRATED - the task was migrated during wakeup ++ * ++ */ ++ ++#define DEQUEUE_SLEEP 0x01 ++#define DEQUEUE_SAVE 0x02 /* matches ENQUEUE_RESTORE */ ++ ++#define ENQUEUE_WAKEUP 0x01 ++#define ENQUEUE_RESTORE 0x02 ++ ++#ifdef CONFIG_SMP ++#define ENQUEUE_MIGRATED 0x40 ++#else ++#define ENQUEUE_MIGRATED 0x00 ++#endif ++ ++static inline u64 __rq_clock_broken(struct rq *rq) ++{ ++ return READ_ONCE(rq->clock); ++} ++ ++static inline u64 rq_clock(struct rq *rq) ++{ ++ lockdep_assert_held(rq->lock); ++ ++ return rq->clock; ++} ++ ++static inline u64 rq_clock_task(struct rq *rq) ++{ ++ lockdep_assert_held(rq->lock); ++ ++ return rq->clock_task; ++} ++ ++#ifdef CONFIG_NUMA ++enum numa_topology_type { ++ NUMA_DIRECT, ++ NUMA_GLUELESS_MESH, ++ NUMA_BACKPLANE, ++}; ++extern enum numa_topology_type sched_numa_topology_type; ++extern int sched_max_numa_distance; ++extern bool find_numa_distance(int distance); ++extern void sched_init_numa(void); ++extern void sched_domains_numa_masks_set(unsigned int cpu); ++extern void sched_domains_numa_masks_clear(unsigned int cpu); ++extern int sched_numa_find_closest(const struct cpumask *cpus, int cpu); ++#else ++static inline void sched_init_numa(void) { } ++static inline void sched_domains_numa_masks_set(unsigned int cpu) { } ++static inline void sched_domains_numa_masks_clear(unsigned int cpu) { } ++static inline int sched_numa_find_closest(const struct cpumask *cpus, int cpu) ++{ ++ return nr_cpu_ids; ++} ++#endif ++ ++extern struct mutex sched_domains_mutex; ++extern struct static_key_false sched_schedstats; ++ ++#define rcu_dereference_check_sched_domain(p) \ ++ rcu_dereference_check((p), \ ++ lockdep_is_held(&sched_domains_mutex)) ++ ++#ifdef CONFIG_SMP ++ ++/* ++ * The domain tree (rq->sd) is protected by RCU's quiescent state transition. ++ * See destroy_sched_domains: call_rcu for details. ++ * ++ * The domain tree of any CPU may only be accessed from within ++ * preempt-disabled sections. ++ */ ++#define for_each_domain(cpu, __sd) \ ++ for (__sd = rcu_dereference_check_sched_domain(cpu_rq(cpu)->sd); \ ++ __sd; __sd = __sd->parent) ++ ++#define for_each_lower_domain(sd) for (; sd; sd = sd->child) ++ ++/** ++ * highest_flag_domain - Return highest sched_domain containing flag. ++ * @cpu: The cpu whose highest level of sched domain is to ++ * be returned. ++ * @flag: The flag to check for the highest sched_domain ++ * for the given cpu. ++ * ++ * Returns the highest sched_domain of a cpu which contains the given flag. ++ */ ++static inline struct sched_domain *highest_flag_domain(int cpu, int flag) ++{ ++ struct sched_domain *sd, *hsd = NULL; ++ ++ for_each_domain(cpu, sd) { ++ if (!(sd->flags & flag)) ++ break; ++ hsd = sd; ++ } ++ ++ return hsd; ++} ++ ++static inline struct sched_domain *lowest_flag_domain(int cpu, int flag) ++{ ++ struct sched_domain *sd; ++ ++ for_each_domain(cpu, sd) { ++ if (sd->flags & flag) ++ break; ++ } ++ ++ return sd; ++} ++ ++DECLARE_PER_CPU(struct sched_domain *, sd_llc); ++DECLARE_PER_CPU(int, sd_llc_size); ++DECLARE_PER_CPU(int, sd_llc_id); ++DECLARE_PER_CPU(struct sched_domain_shared *, sd_llc_shared); ++DECLARE_PER_CPU(struct sched_domain *, sd_numa); ++DECLARE_PER_CPU(struct sched_domain *, sd_asym_packing); ++DECLARE_PER_CPU(struct sched_domain *, sd_asym_cpucapacity); ++ ++struct sched_group_capacity { ++ atomic_t ref; ++ /* ++ * CPU capacity of this group, SCHED_CAPACITY_SCALE being max capacity ++ * for a single CPU. ++ */ ++ unsigned long capacity; ++ unsigned long min_capacity; /* Min per-CPU capacity in group */ ++ unsigned long max_capacity; /* Max per-CPU capacity in group */ ++ unsigned long next_update; ++ int imbalance; /* XXX unrelated to capacity but shared group state */ ++ ++#ifdef CONFIG_SCHED_DEBUG ++ int id; ++#endif ++ ++ unsigned long cpumask[0]; /* balance mask */ ++}; ++ ++struct sched_group { ++ struct sched_group *next; /* Must be a circular list */ ++ atomic_t ref; ++ ++ unsigned int group_weight; ++ struct sched_group_capacity *sgc; ++ int asym_prefer_cpu; /* cpu of highest priority in group */ ++ ++ /* ++ * The CPUs this group covers. ++ * ++ * NOTE: this field is variable length. (Allocated dynamically ++ * by attaching extra space to the end of the structure, ++ * depending on how many CPUs the kernel has booted up with) ++ */ ++ unsigned long cpumask[0]; ++}; ++ ++static inline struct cpumask *sched_group_span(struct sched_group *sg) ++{ ++ return to_cpumask(sg->cpumask); ++} ++ ++/* ++ * See build_balance_mask(). ++ */ ++static inline struct cpumask *group_balance_mask(struct sched_group *sg) ++{ ++ return to_cpumask(sg->sgc->cpumask); ++} ++ ++/** ++ * group_first_cpu - Returns the first cpu in the cpumask of a sched_group. ++ * @group: The group whose first cpu is to be returned. ++ */ ++static inline unsigned int group_first_cpu(struct sched_group *group) ++{ ++ return cpumask_first(sched_group_span(group)); ++} ++ ++ ++#if defined(CONFIG_SCHED_DEBUG) && defined(CONFIG_SYSCTL) ++void register_sched_domain_sysctl(void); ++void dirty_sched_domain_sysctl(int cpu); ++void unregister_sched_domain_sysctl(void); ++#else ++static inline void register_sched_domain_sysctl(void) ++{ ++} ++static inline void dirty_sched_domain_sysctl(int cpu) ++{ ++} ++static inline void unregister_sched_domain_sysctl(void) ++{ ++} ++#endif ++ ++extern void sched_ttwu_pending(void); ++extern void set_cpus_allowed_common(struct task_struct *p, const struct cpumask *new_mask); ++extern void set_rq_online (struct rq *rq); ++extern void set_rq_offline(struct rq *rq); ++extern bool sched_smp_initialized; ++ ++static inline void update_group_capacity(struct sched_domain *sd, int cpu) ++{ ++} ++ ++static inline void trigger_load_balance(struct rq *rq) ++{ ++} ++ ++#define sched_feat(x) 0 ++ ++#else /* CONFIG_SMP */ ++ ++static inline void sched_ttwu_pending(void) { } ++ ++#endif /* CONFIG_SMP */ ++ ++#ifdef CONFIG_CPU_IDLE ++static inline void idle_set_state(struct rq *rq, ++ struct cpuidle_state *idle_state) ++{ ++ rq->idle_state = idle_state; ++} ++ ++static inline struct cpuidle_state *idle_get_state(struct rq *rq) ++{ ++ SCHED_WARN_ON(!rcu_read_lock_held()); ++ return rq->idle_state; ++} ++#else ++static inline void idle_set_state(struct rq *rq, ++ struct cpuidle_state *idle_state) ++{ ++} ++ ++static inline struct cpuidle_state *idle_get_state(struct rq *rq) ++{ ++ return NULL; ++} ++#endif ++ ++#ifdef CONFIG_SCHED_DEBUG ++extern bool sched_debug_enabled; ++#endif ++ ++extern void schedule_idle(void); ++ ++#ifdef CONFIG_IRQ_TIME_ACCOUNTING ++struct irqtime { ++ u64 total; ++ u64 tick_delta; ++ u64 irq_start_time; ++ struct u64_stats_sync sync; ++}; ++ ++DECLARE_PER_CPU(struct irqtime, cpu_irqtime); ++ ++/* ++ * Returns the irqtime minus the softirq time computed by ksoftirqd. ++ * Otherwise ksoftirqd's sum_exec_runtime is substracted its own runtime ++ * and never move forward. ++ */ ++static inline u64 irq_time_read(int cpu) ++{ ++ struct irqtime *irqtime = &per_cpu(cpu_irqtime, cpu); ++ unsigned int seq; ++ u64 total; ++ ++ do { ++ seq = __u64_stats_fetch_begin(&irqtime->sync); ++ total = irqtime->total; ++ } while (__u64_stats_fetch_retry(&irqtime->sync, seq)); ++ ++ return total; ++} ++#endif /* CONFIG_IRQ_TIME_ACCOUNTING */ ++ ++static inline bool sched_stop_runnable(struct rq *rq) ++{ ++ return rq->stop && task_on_rq_queued(rq->stop); ++} ++ ++#ifdef CONFIG_SMP ++static inline int cpu_of(struct rq *rq) ++{ ++ return rq->cpu; ++} ++#else /* CONFIG_SMP */ ++static inline int cpu_of(struct rq *rq) ++{ ++ return 0; ++} ++#endif ++ ++#ifdef CONFIG_CPU_FREQ ++DECLARE_PER_CPU(struct update_util_data *, cpufreq_update_util_data); ++ ++static inline void cpufreq_trigger(struct rq *rq, unsigned int flags) ++{ ++ struct update_util_data *data; ++ ++ data = rcu_dereference_sched(*per_cpu_ptr(&cpufreq_update_util_data, ++ cpu_of(rq))); ++ ++ if (data) ++ data->func(data, rq->niffies, flags); ++} ++#else ++static inline void cpufreq_trigger(struct rq *rq, unsigned int flag) ++{ ++} ++#endif /* CONFIG_CPU_FREQ */ ++ ++static __always_inline ++unsigned int uclamp_util_with(struct rq __maybe_unused *rq, unsigned int util, ++ struct task_struct __maybe_unused *p) ++{ ++ return util; ++} ++ ++static inline unsigned int uclamp_util(struct rq *rq, unsigned int util) ++{ ++ return util; ++} ++ ++static inline bool uclamp_is_used(void) ++{ ++ return false; ++} ++ ++#ifdef arch_scale_freq_capacity ++#ifndef arch_scale_freq_invariant ++#define arch_scale_freq_invariant() (true) ++#endif ++#else /* arch_scale_freq_capacity */ ++#define arch_scale_freq_invariant() (false) ++#endif ++ ++#ifdef CONFIG_64BIT ++static inline u64 read_sum_exec_runtime(struct task_struct *t) ++{ ++ return tsk_seruntime(t); ++} ++#else ++static inline u64 read_sum_exec_runtime(struct task_struct *t) ++{ ++ struct rq_flags rf; ++ u64 ns; ++ struct rq *rq; ++ ++ rq = task_rq_lock(t, &rf); ++ ns = tsk_seruntime(t); ++ task_rq_unlock(rq, t, &rf); ++ ++ return ns; ++} ++#endif ++ ++#ifndef arch_scale_freq_capacity ++static __always_inline ++unsigned long arch_scale_freq_capacity(int cpu) ++{ ++ return SCHED_CAPACITY_SCALE; ++} ++#endif ++ ++#ifdef CONFIG_NO_HZ_FULL ++extern bool sched_can_stop_tick(struct rq *rq); ++extern int __init sched_tick_offload_init(void); ++ ++/* ++ * Tick may be needed by tasks in the runqueue depending on their policy and ++ * requirements. If tick is needed, lets send the target an IPI to kick it out of ++ * nohz mode if necessary. ++ */ ++static inline void sched_update_tick_dependency(struct rq *rq) ++{ ++ int cpu; ++ ++ if (!tick_nohz_full_enabled()) ++ return; ++ ++ cpu = cpu_of(rq); ++ ++ if (!tick_nohz_full_cpu(cpu)) ++ return; ++ ++ if (sched_can_stop_tick(rq)) ++ tick_nohz_dep_clear_cpu(cpu, TICK_DEP_BIT_SCHED); ++ else ++ tick_nohz_dep_set_cpu(cpu, TICK_DEP_BIT_SCHED); ++} ++#else ++static inline int sched_tick_offload_init(void) { return 0; } ++static inline void sched_update_tick_dependency(struct rq *rq) { } ++#endif ++ ++#define SCHED_FLAG_SUGOV 0x10000000 ++ ++static inline bool rt_rq_is_runnable(struct rq *rt_rq) ++{ ++ return rt_rq->rt_nr_running; ++} ++ ++/** ++ * enum schedutil_type - CPU utilization type ++ * @FREQUENCY_UTIL: Utilization used to select frequency ++ * @ENERGY_UTIL: Utilization used during energy calculation ++ * ++ * The utilization signals of all scheduling classes (CFS/RT/DL) and IRQ time ++ * need to be aggregated differently depending on the usage made of them. This ++ * enum is used within schedutil_freq_util() to differentiate the types of ++ * utilization expected by the callers, and adjust the aggregation accordingly. ++ */ ++enum schedutil_type { ++ FREQUENCY_UTIL, ++ ENERGY_UTIL, ++}; ++ ++#ifdef CONFIG_CPU_FREQ_GOV_SCHEDUTIL ++ ++unsigned long schedutil_cpu_util(int cpu, unsigned long util_cfs, ++ unsigned long max, enum schedutil_type type, ++ struct task_struct *p); ++ ++static inline unsigned long cpu_bw_dl(struct rq *rq) ++{ ++ return 0; ++} ++ ++static inline unsigned long cpu_util_dl(struct rq *rq) ++{ ++ return 0; ++} ++ ++static inline unsigned long cpu_util_cfs(struct rq *rq) ++{ ++ unsigned long ret = READ_ONCE(rq->load_avg); ++ ++ if (ret > SCHED_CAPACITY_SCALE) ++ ret = SCHED_CAPACITY_SCALE; ++ return ret; ++} ++ ++static inline unsigned long cpu_util_rt(struct rq *rq) ++{ ++ unsigned long ret = READ_ONCE(rq->rt_nr_running); ++ ++ if (ret > SCHED_CAPACITY_SCALE) ++ ret = SCHED_CAPACITY_SCALE; ++ return ret; ++} ++ ++#ifdef CONFIG_HAVE_SCHED_AVG_IRQ ++static inline unsigned long cpu_util_irq(struct rq *rq) ++{ ++ unsigned long ret = READ_ONCE(rq->irq_load_avg); ++ ++ if (ret > SCHED_CAPACITY_SCALE) ++ ret = SCHED_CAPACITY_SCALE; ++ return ret; ++} ++ ++static inline ++unsigned long scale_irq_capacity(unsigned long util, unsigned long irq, unsigned long max) ++{ ++ util *= (max - irq); ++ util /= max; ++ ++ return util; ++ ++} ++#else ++static inline unsigned long cpu_util_irq(struct rq *rq) ++{ ++ return 0; ++} ++ ++static inline ++unsigned long scale_irq_capacity(unsigned long util, unsigned long irq, unsigned long max) ++{ ++ return util; ++} ++#endif ++#endif ++ ++#if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL) ++#define perf_domain_span(pd) (to_cpumask(((pd)->em_pd->cpus))) ++ ++DECLARE_STATIC_KEY_FALSE(sched_energy_present); ++ ++static inline bool sched_energy_enabled(void) ++{ ++ return static_branch_unlikely(&sched_energy_present); ++} ++ ++#else /* ! (CONFIG_ENERGY_MODEL && CONFIG_CPU_FREQ_GOV_SCHEDUTIL) */ ++ ++#define perf_domain_span(pd) NULL ++static inline bool sched_energy_enabled(void) { return false; } ++ ++#endif /* CONFIG_ENERGY_MODEL && CONFIG_CPU_FREQ_GOV_SCHEDUTIL */ ++ ++#ifdef CONFIG_MEMBARRIER ++/* ++ * The scheduler provides memory barriers required by membarrier between: ++ * - prior user-space memory accesses and store to rq->membarrier_state, ++ * - store to rq->membarrier_state and following user-space memory accesses. ++ * In the same way it provides those guarantees around store to rq->curr. ++ */ ++static inline void membarrier_switch_mm(struct rq *rq, ++ struct mm_struct *prev_mm, ++ struct mm_struct *next_mm) ++{ ++ int membarrier_state; ++ ++ if (prev_mm == next_mm) ++ return; ++ ++ membarrier_state = atomic_read(&next_mm->membarrier_state); ++ if (READ_ONCE(rq->membarrier_state) == membarrier_state) ++ return; ++ ++ WRITE_ONCE(rq->membarrier_state, membarrier_state); ++} ++#else ++static inline void membarrier_switch_mm(struct rq *rq, ++ struct mm_struct *prev_mm, ++ struct mm_struct *next_mm) ++{ ++} ++#endif ++ ++#ifdef CONFIG_SMP ++static inline bool is_per_cpu_kthread(struct task_struct *p) ++{ ++ if (!(p->flags & PF_KTHREAD)) ++ return false; ++ ++ if (p->nr_cpus_allowed != 1) ++ return false; ++ ++ return true; ++} ++#endif ++ ++#endif /* MUQSS_SCHED_H */ +--- a/kernel/sched/cpufreq_schedutil.c ++++ b/kernel/sched/cpufreq_schedutil.c +@@ -183,6 +183,12 @@ static unsigned int get_next_freq(struct + return cpufreq_driver_resolve_freq(policy, freq); + } + ++#ifdef CONFIG_SCHED_MUQSS ++#define rt_rq_runnable(rq_rt) rt_rq_is_runnable(rq) ++#else ++#define rt_rq_runnable(rq_rt) rt_rq_is_runnable(&rq->rt) ++#endif ++ + /* + * This function computes an effective utilization for the given CPU, to be + * used for frequency selection given the linear relation: f = u * f_max. +@@ -211,7 +217,7 @@ unsigned long schedutil_cpu_util(int cpu + struct rq *rq = cpu_rq(cpu); + + if (!uclamp_is_used() && +- type == FREQUENCY_UTIL && rt_rq_is_runnable(&rq->rt)) { ++ type == FREQUENCY_UTIL && rt_rq_runnable(rq)) { + return max; + } + +@@ -664,7 +670,11 @@ static int sugov_kthread_create(struct s + struct task_struct *thread; + struct sched_attr attr = { + .size = sizeof(struct sched_attr), ++#ifdef CONFIG_SCHED_MUQSS ++ .sched_policy = SCHED_RR, ++#else + .sched_policy = SCHED_DEADLINE, ++#endif + .sched_flags = SCHED_FLAG_SUGOV, + .sched_nice = 0, + .sched_priority = 0, +--- a/kernel/sched/cpupri.h ++++ b/kernel/sched/cpupri.h +@@ -17,9 +17,11 @@ struct cpupri { + int *cpu_to_pri; + }; + ++#ifndef CONFIG_SCHED_MUQSS + #ifdef CONFIG_SMP + int cpupri_find(struct cpupri *cp, struct task_struct *p, struct cpumask *lowest_mask); + void cpupri_set(struct cpupri *cp, int cpu, int pri); + int cpupri_init(struct cpupri *cp); + void cpupri_cleanup(struct cpupri *cp); + #endif ++#endif +--- a/kernel/sched/cputime.c ++++ b/kernel/sched/cputime.c +@@ -266,26 +266,6 @@ static inline u64 account_other_time(u64 + return accounted; + } + +-#ifdef CONFIG_64BIT +-static inline u64 read_sum_exec_runtime(struct task_struct *t) +-{ +- return t->se.sum_exec_runtime; +-} +-#else +-static u64 read_sum_exec_runtime(struct task_struct *t) +-{ +- u64 ns; +- struct rq_flags rf; +- struct rq *rq; +- +- rq = task_rq_lock(t, &rf); +- ns = t->se.sum_exec_runtime; +- task_rq_unlock(rq, t, &rf); +- +- return ns; +-} +-#endif +- + /* + * Accumulate raw cputime values of dead tasks (sig->[us]time) and live + * tasks (sum on group iteration) belonging to @tsk's group. +@@ -663,7 +643,7 @@ out: + void task_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st) + { + struct task_cputime cputime = { +- .sum_exec_runtime = p->se.sum_exec_runtime, ++ .sum_exec_runtime = tsk_seruntime(p), + }; + + task_cputime(p, &cputime.utime, &cputime.stime); +--- a/kernel/sched/idle.c ++++ b/kernel/sched/idle.c +@@ -356,6 +356,7 @@ void cpu_startup_entry(enum cpuhp_state + do_idle(); + } + ++#ifndef CONFIG_SCHED_MUQSS + /* + * idle-task scheduling class. + */ +@@ -480,3 +481,4 @@ const struct sched_class idle_sched_clas + .switched_to = switched_to_idle, + .update_curr = update_curr_idle, + }; ++#endif /* CONFIG_SCHED_MUQSS */ +--- a/kernel/sched/sched.h ++++ b/kernel/sched/sched.h +@@ -2,6 +2,19 @@ + /* + * Scheduler internal types and methods: + */ ++#ifdef CONFIG_SCHED_MUQSS ++#include "MuQSS.h" ++ ++/* Begin compatibility wrappers for MuQSS/CFS differences */ ++#define rq_rt_nr_running(rq) ((rq)->rt_nr_running) ++#define rq_h_nr_running(rq) ((rq)->nr_running) ++ ++#else /* CONFIG_SCHED_MUQSS */ ++ ++#define rq_rt_nr_running(rq) ((rq)->rt.rt_nr_running) ++#define rq_h_nr_running(rq) ((rq)->cfs.h_nr_running) ++ ++ + #include + + #include +@@ -2551,3 +2564,25 @@ static inline void membarrier_switch_mm( + { + } + #endif ++ ++/* MuQSS compatibility functions */ ++#ifdef CONFIG_64BIT ++static inline u64 read_sum_exec_runtime(struct task_struct *t) ++{ ++ return t->se.sum_exec_runtime; ++} ++#else ++static inline u64 read_sum_exec_runtime(struct task_struct *t) ++{ ++ u64 ns; ++ struct rq_flags rf; ++ struct rq *rq; ++ ++ rq = task_rq_lock(t, &rf); ++ ns = t->se.sum_exec_runtime; ++ task_rq_unlock(rq, t, &rf); ++ ++ return ns; ++} ++#endif ++#endif /* CONFIG_SCHED_MUQSS */ +--- a/kernel/sched/topology.c ++++ b/kernel/sched/topology.c +@@ -442,7 +442,11 @@ void rq_attach_root(struct rq *rq, struc + struct root_domain *old_rd = NULL; + unsigned long flags; + ++#ifdef CONFIG_SCHED_MUQSS ++ raw_spin_lock_irqsave(rq->lock, flags); ++#else + raw_spin_lock_irqsave(&rq->lock, flags); ++#endif + + if (rq->rd) { + old_rd = rq->rd; +@@ -468,7 +472,11 @@ void rq_attach_root(struct rq *rq, struc + if (cpumask_test_cpu(rq->cpu, cpu_active_mask)) + set_rq_online(rq); + ++#ifdef CONFIG_SCHED_MUQSS ++ raw_spin_unlock_irqrestore(rq->lock, flags); ++#else + raw_spin_unlock_irqrestore(&rq->lock, flags); ++#endif + + if (old_rd) + call_rcu(&old_rd->rcu, free_rootdomain); +--- /dev/null ++++ b/kernel/skip_list.c +@@ -0,0 +1,148 @@ ++/* ++ Copyright (C) 2011,2016 Con Kolivas. ++ ++ Code based on example originally by William Pugh. ++ ++Skip Lists are a probabilistic alternative to balanced trees, as ++described in the June 1990 issue of CACM and were invented by ++William Pugh in 1987. ++ ++A couple of comments about this implementation: ++The routine randomLevel has been hard-coded to generate random ++levels using p=0.25. It can be easily changed. ++ ++The insertion routine has been implemented so as to use the ++dirty hack described in the CACM paper: if a random level is ++generated that is more than the current maximum level, the ++current maximum level plus one is used instead. ++ ++Levels start at zero and go up to MaxLevel (which is equal to ++MaxNumberOfLevels-1). ++ ++The routines defined in this file are: ++ ++init: defines slnode ++ ++new_skiplist: returns a new, empty list ++ ++randomLevel: Returns a random level based on a u64 random seed passed to it. ++In MuQSS, the "niffy" time is used for this purpose. ++ ++insert(l,key, value): inserts the binding (key, value) into l. This operation ++occurs in O(log n) time. ++ ++delnode(slnode, l, node): deletes any binding of key from the l based on the ++actual node value. This operation occurs in O(k) time where k is the ++number of levels of the node in question (max 8). The original delete ++function occurred in O(log n) time and involved a search. ++ ++MuQSS Notes: In this implementation of skiplists, there are bidirectional ++next/prev pointers and the insert function returns a pointer to the actual ++node the value is stored. The key here is chosen by the scheduler so as to ++sort tasks according to the priority list requirements and is no longer used ++by the scheduler after insertion. The scheduler lookup, however, occurs in ++O(1) time because it is always the first item in the level 0 linked list. ++Since the task struct stores a copy of the node pointer upon skiplist_insert, ++it can also remove it much faster than the original implementation with the ++aid of prev<->next pointer manipulation and no searching. ++ ++*/ ++ ++#include ++#include ++ ++#define MaxNumberOfLevels 8 ++#define MaxLevel (MaxNumberOfLevels - 1) ++ ++void skiplist_init(skiplist_node *slnode) ++{ ++ int i; ++ ++ slnode->key = 0xFFFFFFFFFFFFFFFF; ++ slnode->level = 0; ++ slnode->value = NULL; ++ for (i = 0; i < MaxNumberOfLevels; i++) ++ slnode->next[i] = slnode->prev[i] = slnode; ++} ++ ++skiplist *new_skiplist(skiplist_node *slnode) ++{ ++ skiplist *l = kzalloc(sizeof(skiplist), GFP_ATOMIC); ++ ++ BUG_ON(!l); ++ l->header = slnode; ++ return l; ++} ++ ++void free_skiplist(skiplist *l) ++{ ++ skiplist_node *p, *q; ++ ++ p = l->header; ++ do { ++ q = p->next[0]; ++ p->next[0]->prev[0] = q->prev[0]; ++ skiplist_node_init(p); ++ p = q; ++ } while (p != l->header); ++ kfree(l); ++} ++ ++void skiplist_node_init(skiplist_node *node) ++{ ++ memset(node, 0, sizeof(skiplist_node)); ++} ++ ++static inline unsigned int randomLevel(const long unsigned int randseed) ++{ ++ return find_first_bit(&randseed, MaxLevel) / 2; ++} ++ ++void skiplist_insert(skiplist *l, skiplist_node *node, keyType key, valueType value, unsigned int randseed) ++{ ++ skiplist_node *update[MaxNumberOfLevels]; ++ skiplist_node *p, *q; ++ int k = l->level; ++ ++ p = l->header; ++ do { ++ while (q = p->next[k], q->key <= key) ++ p = q; ++ update[k] = p; ++ } while (--k >= 0); ++ ++ ++l->entries; ++ k = randomLevel(randseed); ++ if (k > l->level) { ++ k = ++l->level; ++ update[k] = l->header; ++ } ++ ++ node->level = k; ++ node->key = key; ++ node->value = value; ++ do { ++ p = update[k]; ++ node->next[k] = p->next[k]; ++ p->next[k] = node; ++ node->prev[k] = p; ++ node->next[k]->prev[k] = node; ++ } while (--k >= 0); ++} ++ ++void skiplist_delete(skiplist *l, skiplist_node *node) ++{ ++ int k, m = node->level; ++ ++ for (k = 0; k <= m; k++) { ++ node->prev[k]->next[k] = node->next[k]; ++ node->next[k]->prev[k] = node->prev[k]; ++ } ++ skiplist_node_init(node); ++ if (m == l->level) { ++ while (l->header->next[m] == l->header && l->header->prev[m] == l->header && m > 0) ++ m--; ++ l->level = m; ++ } ++ l->entries--; ++} +--- a/kernel/sysctl.c ++++ b/kernel/sysctl.c +@@ -130,8 +130,16 @@ static int __maybe_unused four = 4; + static unsigned long zero_ul; + static unsigned long one_ul = 1; + static unsigned long long_max = LONG_MAX; +-static int one_hundred = 100; +-static int one_thousand = 1000; ++static int __read_mostly one_hundred = 100; ++static int __read_mostly one_thousand = 1000; ++static int zero = 0; ++static int one = 1; ++#ifdef CONFIG_SCHED_MUQSS ++extern int rr_interval; ++extern int sched_interactive; ++extern int sched_iso_cpu; ++extern int sched_yield_type; ++#endif + #ifdef CONFIG_PRINTK + static int ten_thousand = 10000; + #endif +@@ -300,7 +308,7 @@ static struct ctl_table sysctl_base_tabl + { } + }; + +-#ifdef CONFIG_SCHED_DEBUG ++#if defined(CONFIG_SCHED_DEBUG) && !defined(CONFIG_SCHED_MUQSS) + static int min_sched_granularity_ns = 100000; /* 100 usecs */ + static int max_sched_granularity_ns = NSEC_PER_SEC; /* 1 second */ + static int min_wakeup_granularity_ns; /* 0 usecs */ +@@ -317,6 +325,7 @@ static int max_extfrag_threshold = 1000; + #endif + + static struct ctl_table kern_table[] = { ++#ifndef CONFIG_SCHED_MUQSS + { + .procname = "sched_child_runs_first", + .data = &sysctl_sched_child_runs_first, +@@ -498,6 +507,7 @@ static struct ctl_table kern_table[] = { + .extra2 = SYSCTL_ONE, + }, + #endif ++#endif /* !CONFIG_SCHED_MUQSS */ + #ifdef CONFIG_PROVE_LOCKING + { + .procname = "prove_locking", +@@ -1070,6 +1080,44 @@ static struct ctl_table kern_table[] = { + .proc_handler = proc_dointvec, + }, + #endif ++#ifdef CONFIG_SCHED_MUQSS ++ { ++ .procname = "rr_interval", ++ .data = &rr_interval, ++ .maxlen = sizeof (int), ++ .mode = 0644, ++ .proc_handler = &proc_dointvec_minmax, ++ .extra1 = &one, ++ .extra2 = &one_thousand, ++ }, ++ { ++ .procname = "interactive", ++ .data = &sched_interactive, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = &proc_dointvec_minmax, ++ .extra1 = &zero, ++ .extra2 = &one, ++ }, ++ { ++ .procname = "iso_cpu", ++ .data = &sched_iso_cpu, ++ .maxlen = sizeof (int), ++ .mode = 0644, ++ .proc_handler = &proc_dointvec_minmax, ++ .extra1 = &zero, ++ .extra2 = &one_hundred, ++ }, ++ { ++ .procname = "yield_type", ++ .data = &sched_yield_type, ++ .maxlen = sizeof (int), ++ .mode = 0644, ++ .proc_handler = &proc_dointvec_minmax, ++ .extra1 = &zero, ++ .extra2 = &two, ++ }, ++#endif + #if defined(CONFIG_S390) && defined(CONFIG_SMP) + { + .procname = "spin_retry", +--- a/kernel/time/clockevents.c ++++ b/kernel/time/clockevents.c +@@ -190,8 +190,13 @@ int clockevents_tick_resume(struct clock + + #ifdef CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST + ++#ifdef CONFIG_SCHED_MUQSS ++/* Limit min_delta to 100us */ ++#define MIN_DELTA_LIMIT (NSEC_PER_SEC / 10000) ++#else + /* Limit min_delta to a jiffie */ + #define MIN_DELTA_LIMIT (NSEC_PER_SEC / HZ) ++#endif + + /** + * clockevents_increase_min_delta - raise minimum delta of a clock event device +--- a/kernel/time/posix-cpu-timers.c ++++ b/kernel/time/posix-cpu-timers.c +@@ -226,7 +226,7 @@ static void task_sample_cputime(struct t + u64 stime, utime; + + task_cputime(p, &utime, &stime); +- store_samples(samples, stime, utime, p->se.sum_exec_runtime); ++ store_samples(samples, stime, utime, tsk_seruntime(p)); + } + + static void proc_sample_cputime_atomic(struct task_cputime_atomic *at, +@@ -845,7 +845,7 @@ static void check_thread_timers(struct t + soft = task_rlimit(tsk, RLIMIT_RTTIME); + if (soft != RLIM_INFINITY) { + /* Task RT timeout is accounted in jiffies. RTTIME is usec */ +- unsigned long rttime = tsk->rt.timeout * (USEC_PER_SEC / HZ); ++ unsigned long rttime = tsk_rttimeout(tsk) * (USEC_PER_SEC / HZ); + unsigned long hard = task_rlimit_max(tsk, RLIMIT_RTTIME); + + /* At the hard limit, send SIGKILL. No further action. */ +--- a/kernel/time/timer.c ++++ b/kernel/time/timer.c +@@ -1581,7 +1581,7 @@ static unsigned long __next_timer_interr + * Check, if the next hrtimer event is before the next timer wheel + * event: + */ +-static u64 cmp_next_hrtimer_event(u64 basem, u64 expires) ++static u64 cmp_next_hrtimer_event(struct timer_base *base, u64 basem, u64 expires) + { + u64 nextevt = hrtimer_get_next_event(); + +@@ -1599,6 +1599,9 @@ static u64 cmp_next_hrtimer_event(u64 ba + if (nextevt <= basem) + return basem; + ++ if (nextevt < expires && nextevt - basem <= TICK_NSEC) ++ base->is_idle = false; ++ + /* + * Round up to the next jiffie. High resolution timers are + * off, so the hrtimers are expired in the tick and we need to +@@ -1668,7 +1671,7 @@ u64 get_next_timer_interrupt(unsigned lo + } + raw_spin_unlock(&base->lock); + +- return cmp_next_hrtimer_event(basem, expires); ++ return cmp_next_hrtimer_event(base, basem, expires); + } + + /** +--- a/kernel/trace/trace_selftest.c ++++ b/kernel/trace/trace_selftest.c +@@ -1053,10 +1053,15 @@ static int trace_wakeup_test_thread(void + { + /* Make this a -deadline thread */ + static const struct sched_attr attr = { ++#ifdef CONFIG_SCHED_MUQSS ++ /* No deadline on MuQSS, use RR */ ++ .sched_policy = SCHED_RR, ++#else + .sched_policy = SCHED_DEADLINE, + .sched_runtime = 100000ULL, + .sched_deadline = 10000000ULL, + .sched_period = 10000000ULL ++#endif + }; + struct wakeup_test_data *x = data; + +--- a/kernel/time/Kconfig ++++ b/kernel/time/Kconfig +@@ -123,7 +123,7 @@ config CONTEXT_TRACKING + + config CONTEXT_TRACKING_FORCE + bool "Force context tracking" +- depends on CONTEXT_TRACKING ++ depends on CONTEXT_TRACKING && !SCHED_MUQSS + default y if !NO_HZ_FULL + help + The major pre-requirement for full dynticks to work is to diff --git a/PATCH/MuQSS/0002-MuQSS-Fix-build-error-on-config-leak.patch b/PATCH/MuQSS/0002-MuQSS-Fix-build-error-on-config-leak.patch new file mode 100644 index 000000000..46e3095a2 --- /dev/null +++ b/PATCH/MuQSS/0002-MuQSS-Fix-build-error-on-config-leak.patch @@ -0,0 +1,21 @@ +From 6aefea555ae66883483540d43c2024acecf61599 Mon Sep 17 00:00:00 2001 +From: Steven Barrett +Date: Wed, 24 Jun 2020 12:48:00 -0500 +Subject: [PATCH] muqss: Fix build error on config leak + +Fixes build error: +error: include/uapi/linux/sched.h: leak CONFIG_SCHED_MUQSS to user-space +--- + scripts/headers_install.sh | 1 + + 1 file changed, 1 insertion(+) + +--- a/scripts/headers_install.sh ++++ b/scripts/headers_install.sh +@@ -94,6 +94,7 @@ include/uapi/linux/eventpoll.h:CONFIG_PM + include/uapi/linux/hw_breakpoint.h:CONFIG_HAVE_MIXED_BREAKPOINTS_REGS + include/uapi/linux/pktcdvd.h:CONFIG_CDROM_PKTCDVD_WCACHE + include/uapi/linux/raw.h:CONFIG_MAX_RAW_DEVS ++include/uapi/linux/sched.h:CONFIG_SCHED_MUQSS + " + + for c in $configs diff --git a/PATCH/MuQSS/0003-MuQSS-Revert-invocation-of-finish_cpu-when-offlining-core.patch b/PATCH/MuQSS/0003-MuQSS-Revert-invocation-of-finish_cpu-when-offlining-core.patch new file mode 100644 index 000000000..ec206a38e --- /dev/null +++ b/PATCH/MuQSS/0003-MuQSS-Revert-invocation-of-finish_cpu-when-offlining-core.patch @@ -0,0 +1,29 @@ +From fb7e2cfaf61cf5f9c2336331e73296f455bd2d51 Mon Sep 17 00:00:00 2001 +From: Steven Barrett +Date: Sat, 27 Jun 2020 17:32:41 -0500 +Subject: [PATCH] muqss: Revert invocation of "finish_cpu" when offlining core + +Backporting the equivalent change in sched/core.c to sched/MuQSS.c in +function, idle_task_exit, causes an oops at boot with MuQSS. + +Instead, make an exception for MuQSS so "finish_cpu" is not executed +while running MuQSS and retain the original "idle_task_exit" +implementation. +--- + kernel/cpu.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/kernel/cpu.c ++++ b/kernel/cpu.c +@@ -1503,7 +1503,11 @@ static struct cpuhp_step cpuhp_hp_states + [CPUHP_BRINGUP_CPU] = { + .name = "cpu:bringup", + .startup.single = bringup_cpu, ++#ifdef CONFIG_SCHED_MUQSS ++ .teardown.single = NULL, ++#else + .teardown.single = finish_cpu, ++#endif + .cant_stop = true, + }, + /* Final state before CPU kills itself */ diff --git a/README.md b/README.md index 8dfacf798..d40af29fe 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ - O3 编译,CFLAG优化 - 插件包含:SSRP,PassWall,OpenClash,AdguardHome,微信推送,网易云解锁,SQM,DNSProxy,网络唤醒,DDNS,迅雷快鸟,UPNP,FullCone(防火墙中开启,默认开启),流量分载,irq优化,京东签到,Zerotier,FRPC,FRPS,无线打印,流量监控,过滤军刀,R2S-OLED - ss协议在armv8上实现了aes硬件加速(请仅使用aead加密的连接方式) -- 集成并默认启用了UKSM,BBRv2,LRNG,以及CacULE Scheduler +- 集成并默认启用了BBRv2,LRNG,以及MuQSS Scheduler - 如有任何问题,请先尝试ssh进入后台,输入fuck后回车,等待机器重启后确认问题是否已经解决 ### 下载 diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 06b041ac8..fd91ba912 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -35,10 +35,19 @@ patch -p1 <../PATCH/BBRv2/openwrt-kmod-bbr2.patch cp -f ../PATCH/BBRv2/693-Add_BBRv2_congestion_control_for_Linux_TCP.patch ./target/linux/generic/hack-5.4/693-Add_BBRv2_congestion_control_for_Linux_TCP.patch wget -qO - https://github.com/openwrt/openwrt/commit/cfaf039.patch | patch -p1 # CacULE -wget -qO - https://github.com/QiuSimons/openwrt-NoTengoBattery/commit/7d44cab.patch | patch -p1 -wget https://github.com/hamadmarri/cacule-cpu-scheduler/raw/master/patches/CacULE/v5.4/cacule-5.4.patch -O ./target/linux/generic/hack-5.4/694-cacule-5.4.patch +#wget -qO - https://github.com/QiuSimons/openwrt-NoTengoBattery/commit/7d44cab.patch | patch -p1 +#wget https://github.com/hamadmarri/cacule-cpu-scheduler/raw/master/patches/CacULE/v5.4/cacule-5.4.patch -O ./target/linux/generic/hack-5.4/694-cacule-5.4.patch +# MuQSS +cp -f ../PATCH/MuQSS/0001-MultiQueue-Skiplist-Scheduler-v0.201.patch ./target/linux/generic/hack-5.4/694-0001-MultiQueue-Skiplist-Scheduler-v0.201.patch +cp -f ../PATCH/MuQSS/0002-MuQSS-Fix-build-error-on-config-leak.patch ./target/linux/generic/hack-5.4/694-0002-MuQSS-Fix-build-error-on-config-leak.patch +cp -f ../PATCH/MuQSS/0003-MuQSS-Revert-invocation-of-finish_cpu-when-offlining-core.patch ./target/linux/generic/hack-5.4/694-0003-MuQSS-Revert-invocation-of-finish_cpu-when-offlining-core.patch +# BMQ +#wget https://gitlab.com/alfredchen/projectc/-/raw/master/5.4/bmq_v5.4-r2.patch -O ./target/linux/generic/hack-5.4/694-bmq_v5.4-r2.patch +# PDS +#wget https://github.com/Frogging-Family/linux-tkg/raw/master/linux-tkg-patches/5.4/0005-v5.4_undead-pds099o.patch -O ./target/linux/generic/hack-5.4/694-0005-01-v5.4_undead-pds099o.patch +#wget https://github.com/Frogging-Family/linux-tkg/raw/master/linux-tkg-patches/5.4/0005-glitched-pds.patch -O ./target/linux/generic/hack-5.4/694-0005-02-glitched-pds.patch # UKSM -cp -f ../PATCH/UKSM/695-uksm-5.4.patch ./target/linux/generic/hack-5.4/695-uksm-5.4.patch +#cp -f ../PATCH/UKSM/695-uksm-5.4.patch ./target/linux/generic/hack-5.4/695-uksm-5.4.patch # LRNG cp -rf ../PATCH/LRNG/* ./target/linux/generic/hack-5.4/ echo ' diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index f0b1eff76..ba6025577 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -10,16 +10,16 @@ wget -P target/linux/rockchip/armv8/base-files/etc/init.d/ https://github.com/fr wget -P target/linux/rockchip/armv8/base-files/usr/bin/ https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3328/base-files/usr/bin/start-rk3328-pwm-fan.sh # CacULE -sed -i '/CONFIG_NR_CPUS/d' ./target/linux/rockchip/armv8/config-5.4 -echo ' -CONFIG_NR_CPUS=4 -' >>./target/linux/rockchip/armv8/config-5.4 +#sed -i '/CONFIG_NR_CPUS/d' ./target/linux/rockchip/armv8/config-5.4 +#echo ' +#CONFIG_NR_CPUS=4 +#' >>./target/linux/rockchip/armv8/config-5.4 # UKSM -echo ' -CONFIG_KSM=y -CONFIG_UKSM=y -' >>./target/linux/rockchip/armv8/config-5.4 +#echo ' +#CONFIG_KSM=y +#CONFIG_UKSM=y +#' >>./target/linux/rockchip/armv8/config-5.4 # 配置 IRQ 并默认关闭 eth0 offloading rx/rx sed -i '/set_interface_core 4 "eth1"/a\set_interface_core 8 "ff160000" "ff160000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index b69f273ef..f5c1d66be 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -11,16 +11,16 @@ wget -P target/linux/rockchip/armv8/base-files/etc/init.d/ https://github.com/fr wget -P target/linux/rockchip/armv8/base-files/usr/bin/ https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3399/base-files/usr/bin/start-rk3399-pwm-fan.sh # CacULE -sed -i '/CONFIG_NR_CPUS/d' ./target/linux/rockchip/armv8/config-5.4 -echo ' -CONFIG_NR_CPUS=6 -' >>./target/linux/rockchip/armv8/config-5.4 +#sed -i '/CONFIG_NR_CPUS/d' ./target/linux/rockchip/armv8/config-5.4 +#echo ' +#CONFIG_NR_CPUS=6 +#' >>./target/linux/rockchip/armv8/config-5.4 # UKSM -echo ' -CONFIG_KSM=y -CONFIG_UKSM=y -' >>./target/linux/rockchip/armv8/config-5.4 +#echo ' +#CONFIG_KSM=y +#CONFIG_UKSM=y +#' >>./target/linux/rockchip/armv8/config-5.4 # IRQ 调优 sed -i '/set_interface_core 20 "eth1"/a\set_interface_core 8 "ff3c0000" "ff3c0000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity diff --git a/SCRIPTS/X86/02_target_only.sh b/SCRIPTS/X86/02_target_only.sh index fd44a90eb..94d89235d 100644 --- a/SCRIPTS/X86/02_target_only.sh +++ b/SCRIPTS/X86/02_target_only.sh @@ -13,10 +13,10 @@ CONFIG_CRYPTO_AES_NI_INTEL=y ' >>./target/linux/x86/64/config-5.4 # UKSM -echo ' -CONFIG_KSM=y -CONFIG_UKSM=y -' >>./target/linux/x86/64/config-5.4 +#echo ' +#CONFIG_KSM=y +#CONFIG_UKSM=y +#' >>./target/linux/x86/64/config-5.4 #Vermagic latest_version="$(curl -s https://github.com/openwrt/openwrt/tags | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/[2-9][0-9]/p' | sed -n 1p | sed 's/v//g' | sed 's/.tar.gz//g')" From 7dcc37ea673aba1007dfefdbc54d231d4d1bcec3 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sat, 27 Nov 2021 00:03:21 +0800 Subject: [PATCH 208/244] MuQSS 0.196 --- ...ultiQueue-Skiplist-Scheduler-v0.196.patch} | 392 ++++++++++-------- ...on-of-finish_cpu-when-offlining-core.patch | 29 -- .../0003-Work-around-x86-only-llc-stuff.patch | 39 ++ SCRIPTS/02_prepare_package.sh | 4 +- 4 files changed, 255 insertions(+), 209 deletions(-) rename PATCH/MuQSS/{0001-MultiQueue-Skiplist-Scheduler-v0.201.patch => 0001-MultiQueue-Skiplist-Scheduler-v0.196.patch} (98%) delete mode 100644 PATCH/MuQSS/0003-MuQSS-Revert-invocation-of-finish_cpu-when-offlining-core.patch create mode 100644 PATCH/MuQSS/0003-Work-around-x86-only-llc-stuff.patch diff --git a/PATCH/MuQSS/0001-MultiQueue-Skiplist-Scheduler-v0.201.patch b/PATCH/MuQSS/0001-MultiQueue-Skiplist-Scheduler-v0.196.patch similarity index 98% rename from PATCH/MuQSS/0001-MultiQueue-Skiplist-Scheduler-v0.201.patch rename to PATCH/MuQSS/0001-MultiQueue-Skiplist-Scheduler-v0.196.patch index 2ca432894..e831d4e50 100644 --- a/PATCH/MuQSS/0001-MultiQueue-Skiplist-Scheduler-v0.201.patch +++ b/PATCH/MuQSS/0001-MultiQueue-Skiplist-Scheduler-v0.196.patch @@ -1,7 +1,7 @@ -From 6e142c237f00ff6968410d85417d710a0ceb21dc Mon Sep 17 00:00:00 2001 +From 7acac2e4000e75f3349106a8847cf1021651446b Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Fri, 25 Oct 2019 14:00:52 +1100 -Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 +Subject: [PATCH 01/16] MultiQueue Skiplist Scheduler v0.196. --- .../admin-guide/kernel-parameters.txt | 8 + @@ -36,7 +36,7 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 kernel/livepatch/transition.c | 6 +- kernel/sched/Makefile | 10 +- kernel/sched/MuQSS.c | 7606 +++++++++++++++++ - kernel/sched/MuQSS.h | 1022 +++ + kernel/sched/MuQSS.h | 1005 +++ kernel/sched/cpufreq_schedutil.c | 12 +- kernel/sched/cpupri.h | 2 + kernel/sched/cputime.c | 22 +- @@ -49,7 +49,7 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 kernel/time/posix-cpu-timers.c | 4 +- kernel/time/timer.c | 7 +- kernel/trace/trace_selftest.c | 5 + - 45 files changed, 10025 insertions(+), 52 deletions(-) + 45 files changed, 10010 insertions(+), 52 deletions(-) create mode 100644 Documentation/scheduler/sched-BFS.txt create mode 100644 Documentation/scheduler/sched-MuQSS.txt create mode 100644 include/linux/skip_list.h @@ -1609,7 +1609,7 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 obj-$(CONFIG_MEMBARRIER) += membarrier.o --- /dev/null +++ b/kernel/sched/MuQSS.c -@@ -0,0 +1,7594 @@ +@@ -0,0 +1,7606 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * kernel/sched/MuQSS.c, was kernel/sched.c @@ -1724,7 +1724,7 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + +void print_scheduler_version(void) +{ -+ printk(KERN_INFO "MuQSS CPU scheduler v0.200 by Con Kolivas.\n"); ++ printk(KERN_INFO "MuQSS CPU scheduler v0.196 by Con Kolivas.\n"); +} + +/* Define RQ share levels */ @@ -2286,6 +2286,13 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 +static void enqueue_task(struct rq *rq, struct task_struct *p, int flags); +static inline void resched_if_idle(struct rq *rq); + ++/* Dodgy workaround till we figure out where the softirqs are going */ ++static inline void do_pending_softirq(struct rq *rq, struct task_struct *next) ++{ ++ if (unlikely(next == rq->idle && local_softirq_pending() && !in_interrupt())) ++ do_softirq_own_stack(); ++} ++ +static inline bool deadline_before(u64 deadline, u64 time) +{ + return (deadline < time); @@ -2346,15 +2353,17 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 +static void update_load_avg(struct rq *rq, unsigned int flags) +{ + long us_interval, load; ++ unsigned long curload; + + us_interval = NS_TO_US(rq->niffies - rq->load_update); + if (unlikely(us_interval <= 0)) + return; + ++ curload = rq_load(rq); + load = rq->load_avg - (rq->load_avg * us_interval * 5 / 262144); + if (unlikely(load < 0)) + load = 0; -+ load += rq_load(rq) * SCHED_CAPACITY_SCALE * us_interval * 5 / 262144; ++ load += curload * curload * SCHED_CAPACITY_SCALE * us_interval * 5 / 262144; + rq->load_avg = load; + + rq->load_update = rq->niffies; @@ -2371,15 +2380,17 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 +static void update_irq_load_avg(struct rq *rq, long delta) +{ + long us_interval, load; ++ unsigned long curload; + + us_interval = NS_TO_US(rq->niffies - rq->irq_load_update); + if (unlikely(us_interval <= 0)) + return; + ++ curload = NS_TO_US(delta) / us_interval; + load = rq->irq_load_avg - (rq->irq_load_avg * us_interval * 5 / 262144); + if (unlikely(load < 0)) + load = 0; -+ load += NS_TO_US(delta) * SCHED_CAPACITY_SCALE * 5 / 262144; ++ load += curload * curload * SCHED_CAPACITY_SCALE * us_interval * 5 / 262144; + rq->irq_load_avg = load; + + rq->irq_load_update = rq->niffies; @@ -3179,6 +3190,17 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + +#ifdef CONFIG_SMP + ++static inline bool is_per_cpu_kthread(struct task_struct *p) ++{ ++ if (!(p->flags & PF_KTHREAD)) ++ return false; ++ ++ if (p->nr_cpus_allowed != 1) ++ return false; ++ ++ return true; ++} ++ +/* + * Per-CPU kthreads are allowed to run on !active && online CPUs, see + * __set_cpus_allowed_ptr(). @@ -3276,6 +3298,13 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 +} +#endif /* CONFIG_SMP */ + ++/* ++ * wake flags ++ */ ++#define WF_SYNC 0x01 /* waker goes to sleep after wakeup */ ++#define WF_FORK 0x02 /* child wakeup after fork */ ++#define WF_MIGRATED 0x04 /* internal use, task got migrated */ ++ +static void +ttwu_stat(struct task_struct *p, int cpu, int wake_flags) +{ @@ -3763,7 +3792,7 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + * Revert to default priority/policy on fork if requested. + */ + if (unlikely(p->sched_reset_on_fork)) { -+ if (p->policy == SCHED_FIFO || p->policy == SCHED_RR || p-> policy == SCHED_ISO) { ++ if (p->policy == SCHED_FIFO || p->policy == SCHED_RR) { + p->policy = SCHED_NORMAL; + p->normal_prio = normal_prio(p); + } @@ -4212,6 +4241,9 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + } +#endif + rq_unlock(rq); ++ ++ do_pending_softirq(rq, current); ++ + local_irq_enable(); +} + @@ -5059,32 +5091,28 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + * statistics and checks timeslices in a time-independent way, regardless + * of when exactly it is running. + */ -+ if (!tick_nohz_tick_stopped_cpu(cpu)) ++ if (idle_cpu(cpu) || !tick_nohz_tick_stopped_cpu(cpu)) + goto out_requeue; + + rq_lock_irq(rq); + curr = rq->curr; -+ if (cpu_is_offline(cpu)) ++ if (is_idle_task(curr) || cpu_is_offline(cpu)) + goto out_unlock; + -+ curr = rq->curr; + update_rq_clock(rq); ++ delta = rq_clock_task(rq) - curr->last_ran; + -+ if (!is_idle_task(curr)) { -+ /* -+ * Make sure the next tick runs within a reasonable -+ * amount of time. -+ */ -+ delta = rq_clock_task(rq) - curr->last_ran; -+ WARN_ON_ONCE(delta > (u64)NSEC_PER_SEC * 3); -+ } ++ /* ++ * Make sure the next tick runs within a reasonable ++ * amount of time. ++ */ ++ WARN_ON_ONCE(delta > (u64)NSEC_PER_SEC * 3); + task_tick(rq); + +out_unlock: + rq_unlock_irq(rq, NULL); + +out_requeue: -+ + /* + * Run the remote tick once per second (1Hz). This arbitrary + * frequency is large enough to avoid overload but short enough @@ -5727,6 +5755,7 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + } else { + check_siblings(rq); + rq_unlock(rq); ++ do_pending_softirq(rq, next); + local_irq_enable(); + } +} @@ -6466,12 +6495,10 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + } + + /* -+ * If not changing anything there's no need to proceed further, -+ * but store a possible modification of reset_on_fork. ++ * If not changing anything there's no need to proceed further: + */ + if (unlikely(policy == p->policy && (!is_rt_policy(policy) || + priority == p->rt_priority))) { -+ p->sched_reset_on_fork = reset_on_fork; + retval = 0; + goto unlock; + } @@ -7534,7 +7561,6 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + idle->state = TASK_RUNNING; + /* Setting prio to illegal value shouldn't matter when never queued */ + idle->prio = PRIO_LIMIT; -+ idle->flags |= PF_IDLE; + + kasan_unpoison_task_stack(idle); + @@ -7629,32 +7655,28 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + */ +int get_nohz_timer_target(void) +{ -+ int i, cpu = smp_processor_id(), default_cpu = -1; ++ int i, cpu = smp_processor_id(); + struct sched_domain *sd; + -+ if (housekeeping_cpu(cpu, HK_FLAG_TIMER)) { -+ if (!idle_cpu(cpu)) -+ return cpu; -+ default_cpu = cpu; -+ } ++ if (!idle_cpu(cpu) && housekeeping_cpu(cpu, HK_FLAG_TIMER)) ++ return cpu; + + rcu_read_lock(); + for_each_domain(cpu, sd) { -+ for_each_cpu_and(i, sched_domain_span(sd), -+ housekeeping_cpumask(HK_FLAG_TIMER)) { ++ for_each_cpu(i, sched_domain_span(sd)) { + if (cpu == i) + continue; + -+ if (!idle_cpu(i)) { ++ if (!idle_cpu(i) && housekeeping_cpu(i, HK_FLAG_TIMER)) { ++ cpu = i; + cpu = i; + goto unlock; + } + } + } + -+ if (default_cpu == -1) -+ default_cpu = housekeeping_any_cpu(HK_FLAG_TIMER); -+ cpu = default_cpu; ++ if (!housekeeping_cpu(cpu, HK_FLAG_TIMER)) ++ cpu = housekeeping_any_cpu(HK_FLAG_TIMER); +unlock: + rcu_read_unlock(); + return cpu; @@ -8345,11 +8367,7 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 +/* MC siblings CPU mask which share the same LLC */ +static const cpumask_t *llc_core_cpumask(int cpu) +{ -+#ifdef CONFIG_X86 + return per_cpu(cpu_llc_shared_map, cpu); -+#else -+ return topology_core_cpumask(cpu); -+#endif +} +#endif + @@ -8364,25 +8382,46 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + SD_LV_MAX +}; + -+/* -+ * Set up the relative cache distance of each online cpu from each -+ * other in a simple array for quick lookup. Locality is determined -+ * by the closest sched_domain that CPUs are separated by. CPUs with -+ * shared cache in SMT and MC are treated as local. Separate CPUs -+ * (within the same package or physically) within the same node are -+ * treated as not local. CPUs not even in the same domain (different -+ * nodes) are treated as very distant. -+ */ -+static void __init select_leaders(void) ++void __init sched_init_smp(void) +{ -+ struct rq *rq, *other_rq, *leader; ++ struct rq *rq, *other_rq, *leader = cpu_rq(0); + struct sched_domain *sd; -+ int cpu, other_cpu; ++ int cpu, other_cpu, i; +#ifdef CONFIG_SCHED_SMT + bool smt_threads = false; +#endif ++ sched_init_numa(); + -+ for (cpu = 0; cpu < num_online_cpus(); cpu++) { ++ /* ++ * There's no userspace yet to cause hotplug operations; hence all the ++ * cpu masks are stable and all blatant races in the below code cannot ++ * happen. ++ */ ++ mutex_lock(&sched_domains_mutex); ++ sched_init_domains(cpu_active_mask); ++ mutex_unlock(&sched_domains_mutex); ++ ++ /* Move init over to a non-isolated CPU */ ++ if (set_cpus_allowed_ptr(current, housekeeping_cpumask(HK_FLAG_DOMAIN)) < 0) ++ BUG(); ++ ++ local_irq_disable(); ++ mutex_lock(&sched_domains_mutex); ++ lock_all_rqs(); ++ ++ printk(KERN_INFO "MuQSS possible/present/online CPUs: %d/%d/%d\n", ++ num_possible_cpus(), num_present_cpus(), num_online_cpus()); ++ ++ /* ++ * Set up the relative cache distance of each online cpu from each ++ * other in a simple array for quick lookup. Locality is determined ++ * by the closest sched_domain that CPUs are separated by. CPUs with ++ * shared cache in SMT and MC are treated as local. Separate CPUs ++ * (within the same package or physically) within the same node are ++ * treated as not local. CPUs not even in the same domain (different ++ * nodes) are treated as very distant. ++ */ ++ for (cpu = num_online_cpus() - 1; cpu >= 0; cpu--) { + rq = cpu_rq(cpu); + leader = NULL; + /* First check if this cpu is in the same node */ @@ -8399,8 +8438,7 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + /* Set the smp_leader to the first CPU */ + if (!leader) + leader = rq; -+ if (!other_rq->smp_leader) -+ other_rq->smp_leader = leader; ++ other_rq->smp_leader = leader; + } + if (rq->cpu_locality[other_cpu] > LOCALITY_SMP) + rq->cpu_locality[other_cpu] = LOCALITY_SMP; @@ -8424,8 +8462,7 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + /* Set the mc_leader to the first CPU */ + if (!leader) + leader = rq; -+ if (!other_rq->mc_leader) -+ other_rq->mc_leader = leader; ++ other_rq->mc_leader = leader; + } + if (rq->cpu_locality[other_cpu] > LOCALITY_MC) { + /* this is to get LLC into play even in case LLC sharing is not used */ @@ -8450,8 +8487,7 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + /* Set the smt_leader to the first CPU */ + if (!leader) + leader = rq; -+ if (!other_rq->smt_leader) -+ other_rq->smt_leader = leader; ++ other_rq->smt_leader = leader; + } + if (rq->cpu_locality[other_cpu] > LOCALITY_SMT) + rq->cpu_locality[other_cpu] = LOCALITY_SMT; @@ -8469,6 +8505,8 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + smt_schedule = &smt_should_schedule; + } +#endif ++ unlock_all_rqs(); ++ mutex_unlock(&sched_domains_mutex); + + for_each_online_cpu(cpu) { + rq = cpu_rq(cpu); @@ -8476,29 +8514,6 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + printk(KERN_DEBUG "MuQSS locality CPU %d to %d: %d\n", cpu, other_cpu, rq->cpu_locality[other_cpu]); + } + } -+} -+ -+/* FIXME freeing locked spinlock */ -+static void __init share_and_free_rq(struct rq *leader, struct rq *rq) -+{ -+ WARN_ON(rq->nr_running > 0); -+ -+ kfree(rq->node); -+ kfree(rq->sl); -+ kfree(rq->lock); -+ rq->node = leader->node; -+ rq->sl = leader->sl; -+ rq->lock = leader->lock; -+ rq->is_leader = false; -+ barrier(); -+ /* To make up for not unlocking the freed runlock */ -+ preempt_enable(); -+} -+ -+static void __init share_rqs(void) -+{ -+ struct rq *rq, *leader; -+ int cpu; + + for_each_online_cpu(cpu) { + rq = cpu_rq(cpu); @@ -8508,7 +8523,15 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + if (leader && rq != leader) { + printk(KERN_INFO "MuQSS sharing SMP runqueue from CPU %d to CPU %d\n", + leader->cpu, rq->cpu); -+ share_and_free_rq(leader, rq); ++ kfree(rq->node); ++ kfree(rq->sl); ++ kfree(rq->lock); ++ rq->node = leader->node; ++ rq->sl = leader->sl; ++ rq->lock = leader->lock; ++ barrier(); ++ /* To make up for not unlocking the freed runlock */ ++ preempt_enable(); + } else + rq_unlock(rq); + } @@ -8522,7 +8545,15 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + if (leader && rq != leader) { + printk(KERN_INFO "MuQSS sharing MC runqueue from CPU %d to CPU %d\n", + leader->cpu, rq->cpu); -+ share_and_free_rq(leader, rq); ++ kfree(rq->node); ++ kfree(rq->sl); ++ kfree(rq->lock); ++ rq->node = leader->node; ++ rq->sl = leader->sl; ++ rq->lock = leader->lock; ++ barrier(); ++ /* To make up for not unlocking the freed runlock */ ++ preempt_enable(); + } else + rq_unlock(rq); + } @@ -8531,31 +8562,44 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 +#ifdef CONFIG_SCHED_SMT + for_each_online_cpu(cpu) { + rq = cpu_rq(cpu); ++ + leader = rq->smt_leader; + + rq_lock(rq); + if (leader && rq != leader) { + printk(KERN_INFO "MuQSS sharing SMT runqueue from CPU %d to CPU %d\n", + leader->cpu, rq->cpu); -+ share_and_free_rq(leader, rq); ++ kfree(rq->node); ++ kfree(rq->sl); ++ kfree(rq->lock); ++ rq->node = leader->node; ++ rq->sl = leader->sl; ++ rq->lock = leader->lock; ++ barrier(); ++ /* To make up for not unlocking the freed runlock */ ++ preempt_enable(); + } else + rq_unlock(rq); + } +#endif /* CONFIG_SCHED_SMT */ -+} + -+static void __init setup_rq_orders(void) -+{ -+ struct rq *rq, *other_rq; -+ int cpu, other_cpu, i; ++ local_irq_enable(); + + total_runqueues = 0; + for_each_online_cpu(cpu) { + int locality, total_rqs = 0, total_cpus = 0; + + rq = cpu_rq(cpu); -+ if (rq->is_leader) ++ if ( ++#ifdef CONFIG_SCHED_MC ++ (rq->mc_leader == rq) && ++#endif ++#ifdef CONFIG_SCHED_SMT ++ (rq->smt_leader == rq) && ++#endif ++ (rq->smp_leader == rq)) { + total_runqueues++; ++ } + + for (locality = LOCALITY_SAME; locality <= LOCALITY_DISTANT; locality++) { + int selected_cpus[NR_CPUS], selected_cpu_cnt, selected_cpu_idx, test_cpu_idx, cpu_idx, best_locality, test_cpu; @@ -8618,7 +8662,14 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + other_rq = cpu_rq(ordered_cpus[test_cpu]); + /* set up cpu orders */ + rq->cpu_order[total_cpus++] = other_rq; -+ if (other_rq->is_leader) { ++ if ( ++#ifdef CONFIG_SCHED_MC ++ (other_rq->mc_leader == other_rq) && ++#endif ++#ifdef CONFIG_SCHED_SMT ++ (other_rq->smt_leader == other_rq) && ++#endif ++ (other_rq->smp_leader == other_rq)) { + /* set up RQ orders */ + rq->rq_order[total_rqs++] = other_rq; + } @@ -8626,7 +8677,6 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + } + } + -+#ifdef CONFIG_X86 + for_each_online_cpu(cpu) { + rq = cpu_rq(cpu); + for (i = 0; i < total_runqueues; i++) { @@ -8642,43 +8692,6 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + rq->cpu_order[i]->cpu, per_cpu(cpu_llc_id, rq->cpu_order[i]->cpu)); + } + } -+#endif -+} -+ -+void __init sched_init_smp(void) -+{ -+ sched_init_numa(); -+ -+ /* -+ * There's no userspace yet to cause hotplug operations; hence all the -+ * cpu masks are stable and all blatant races in the below code cannot -+ * happen. -+ */ -+ mutex_lock(&sched_domains_mutex); -+ sched_init_domains(cpu_active_mask); -+ mutex_unlock(&sched_domains_mutex); -+ -+ /* Move init over to a non-isolated CPU */ -+ if (set_cpus_allowed_ptr(current, housekeeping_cpumask(HK_FLAG_DOMAIN)) < 0) -+ BUG(); -+ -+ local_irq_disable(); -+ mutex_lock(&sched_domains_mutex); -+ lock_all_rqs(); -+ -+ printk(KERN_INFO "MuQSS possible/present/online CPUs: %d/%d/%d\n", -+ num_possible_cpus(), num_present_cpus(), num_online_cpus()); -+ -+ select_leaders(); -+ -+ unlock_all_rqs(); -+ mutex_unlock(&sched_domains_mutex); -+ -+ share_rqs(); -+ -+ local_irq_enable(); -+ -+ setup_rq_orders(); + + switch (rqshare) { + case RQSHARE_ALL: @@ -8797,13 +8810,12 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + rq->iso_ticks = 0; + rq->iso_refractory = false; +#ifdef CONFIG_SMP -+ rq->is_leader = true; -+ rq->smp_leader = NULL; ++ rq->smp_leader = rq; +#ifdef CONFIG_SCHED_MC -+ rq->mc_leader = NULL; ++ rq->mc_leader = rq; +#endif +#ifdef CONFIG_SCHED_SMT -+ rq->smt_leader = NULL; ++ rq->smt_leader = rq; +#endif + rq->sd = NULL; + rq->rd = NULL; @@ -9206,7 +9218,7 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 +#undef CREATE_TRACE_POINTS --- /dev/null +++ b/kernel/sched/MuQSS.h -@@ -0,0 +1,1019 @@ +@@ -0,0 +1,1010 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef MUQSS_SCHED_H +#define MUQSS_SCHED_H @@ -9214,7 +9226,6 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 +#include +#include +#include -+#include +#include +#include +#include @@ -9238,6 +9249,7 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 +#include +#include +#include ++#include +#include +#include +#include @@ -9267,13 +9279,6 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 +# define SCHED_WARN_ON(x) ((void)(x)) +#endif + -+/* -+ * wake flags -+ */ -+#define WF_SYNC 0x01 /* waker goes to sleep after wakeup */ -+#define WF_FORK 0x02 /* child wakeup after fork */ -+#define WF_MIGRATED 0x04 /* internal use, task got migrated */ -+ +/* task_struct::on_rq states: */ +#define TASK_ON_RQ_QUEUED 1 +#define TASK_ON_RQ_MIGRATING 2 @@ -9386,9 +9391,7 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + raw_spinlock_t *lock; + raw_spinlock_t *orig_lock; + -+ struct task_struct __rcu *curr; -+ struct task_struct *idle; -+ struct task_struct *stop; ++ struct task_struct *curr, *idle, *stop; + struct mm_struct *prev_mm; + + unsigned int nr_running; @@ -9451,7 +9454,6 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 + struct rq **rq_order; /* Shared RQs ordered by relative cache distance */ + struct rq **cpu_order; /* RQs of discrete CPUs ordered by distance */ + -+ bool is_leader; + struct rq *smp_leader; /* First physical CPU per node */ +#ifdef CONFIG_SCHED_SMT + struct rq *smt_leader; /* First logical CPU in SMT siblings */ @@ -10017,6 +10019,20 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 +#define arch_scale_freq_invariant() (false) +#endif + ++/* ++ * This should only be called when current == rq->idle. Dodgy workaround for ++ * when softirqs are pending and we are in the idle loop. Setting current to ++ * resched will kick us out of the idle loop and the softirqs will be serviced ++ * on our next pass through schedule(). ++ */ ++static inline bool softirq_pending(int cpu) ++{ ++ if (likely(!local_softirq_pending())) ++ return false; ++ set_tsk_need_resched(current); ++ return true; ++} ++ +#ifdef CONFIG_64BIT +static inline u64 read_sum_exec_runtime(struct task_struct *t) +{ @@ -10212,19 +10228,6 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 +} +#endif + -+#ifdef CONFIG_SMP -+static inline bool is_per_cpu_kthread(struct task_struct *p) -+{ -+ if (!(p->flags & PF_KTHREAD)) -+ return false; -+ -+ if (p->nr_cpus_allowed != 1) -+ return false; -+ -+ return true; -+} -+#endif -+ +#endif /* MUQSS_SCHED_H */ --- a/kernel/sched/cpufreq_schedutil.c +++ b/kernel/sched/cpufreq_schedutil.c @@ -10316,7 +10319,38 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 task_cputime(p, &cputime.utime, &cputime.stime); --- a/kernel/sched/idle.c +++ b/kernel/sched/idle.c -@@ -356,6 +356,7 @@ void cpu_startup_entry(enum cpuhp_state +@@ -225,6 +225,8 @@ exit_idle: + static void do_idle(void) + { + int cpu = smp_processor_id(); ++ bool pending = false; ++ + /* + * If the arch has a polling bit, we maintain an invariant: + * +@@ -235,7 +237,10 @@ static void do_idle(void) + */ + + __current_set_polling(); +- tick_nohz_idle_enter(); ++ if (unlikely(softirq_pending(cpu))) ++ pending = true; ++ else ++ tick_nohz_idle_enter(); + + while (!need_resched()) { + rmb(); +@@ -274,7 +279,8 @@ static void do_idle(void) + * an IPI to fold the state for us. + */ + preempt_set_need_resched(); +- tick_nohz_idle_exit(); ++ if (!pending) ++ tick_nohz_idle_exit(); + __current_clr_polling(); + + /* +@@ -356,6 +362,7 @@ void cpu_startup_entry(enum cpuhp_state do_idle(); } @@ -10324,7 +10358,7 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 /* * idle-task scheduling class. */ -@@ -480,3 +481,4 @@ const struct sched_class idle_sched_clas +@@ -480,3 +487,4 @@ const struct sched_class idle_sched_clas .switched_to = switched_to_idle, .update_curr = update_curr_idle, }; @@ -10351,12 +10385,17 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 #include #include -@@ -2551,3 +2564,25 @@ static inline void membarrier_switch_mm( +@@ -2551,3 +2564,30 @@ static inline void membarrier_switch_mm( { } #endif + +/* MuQSS compatibility functions */ ++static inline bool softirq_pending(int cpu) ++{ ++ return false; ++} ++ +#ifdef CONFIG_64BIT +static inline u64 read_sum_exec_runtime(struct task_struct *t) +{ @@ -10379,7 +10418,15 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 +#endif /* CONFIG_SCHED_MUQSS */ --- a/kernel/sched/topology.c +++ b/kernel/sched/topology.c -@@ -442,7 +442,11 @@ void rq_attach_root(struct rq *rq, struc +@@ -3,6 +3,7 @@ + * Scheduler topology setup/handling methods + */ + #include "sched.h" ++#include "linux/sched/deadline.h" + + DEFINE_MUTEX(sched_domains_mutex); + +@@ -442,7 +443,11 @@ void rq_attach_root(struct rq *rq, struc struct root_domain *old_rd = NULL; unsigned long flags; @@ -10391,7 +10438,7 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 if (rq->rd) { old_rd = rq->rd; -@@ -468,7 +472,11 @@ void rq_attach_root(struct rq *rq, struc +@@ -468,7 +473,11 @@ void rq_attach_root(struct rq *rq, struc if (cpumask_test_cpu(rq->cpu, cpu_active_mask)) set_rq_online(rq); @@ -10564,9 +10611,9 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 -static int one_thousand = 1000; +static int __read_mostly one_hundred = 100; +static int __read_mostly one_thousand = 1000; ++#ifdef CONFIG_SCHED_MUQSS +static int zero = 0; +static int one = 1; -+#ifdef CONFIG_SCHED_MUQSS +extern int rr_interval; +extern int sched_interactive; +extern int sched_iso_cpu; @@ -10729,14 +10776,3 @@ Subject: [PATCH 01/11] MultiQueue Skiplist Scheduler v0.198 }; struct wakeup_test_data *x = data; ---- a/kernel/time/Kconfig -+++ b/kernel/time/Kconfig -@@ -123,7 +123,7 @@ config CONTEXT_TRACKING - - config CONTEXT_TRACKING_FORCE - bool "Force context tracking" -- depends on CONTEXT_TRACKING -+ depends on CONTEXT_TRACKING && !SCHED_MUQSS - default y if !NO_HZ_FULL - help - The major pre-requirement for full dynticks to work is to diff --git a/PATCH/MuQSS/0003-MuQSS-Revert-invocation-of-finish_cpu-when-offlining-core.patch b/PATCH/MuQSS/0003-MuQSS-Revert-invocation-of-finish_cpu-when-offlining-core.patch deleted file mode 100644 index ec206a38e..000000000 --- a/PATCH/MuQSS/0003-MuQSS-Revert-invocation-of-finish_cpu-when-offlining-core.patch +++ /dev/null @@ -1,29 +0,0 @@ -From fb7e2cfaf61cf5f9c2336331e73296f455bd2d51 Mon Sep 17 00:00:00 2001 -From: Steven Barrett -Date: Sat, 27 Jun 2020 17:32:41 -0500 -Subject: [PATCH] muqss: Revert invocation of "finish_cpu" when offlining core - -Backporting the equivalent change in sched/core.c to sched/MuQSS.c in -function, idle_task_exit, causes an oops at boot with MuQSS. - -Instead, make an exception for MuQSS so "finish_cpu" is not executed -while running MuQSS and retain the original "idle_task_exit" -implementation. ---- - kernel/cpu.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/kernel/cpu.c -+++ b/kernel/cpu.c -@@ -1503,7 +1503,11 @@ static struct cpuhp_step cpuhp_hp_states - [CPUHP_BRINGUP_CPU] = { - .name = "cpu:bringup", - .startup.single = bringup_cpu, -+#ifdef CONFIG_SCHED_MUQSS -+ .teardown.single = NULL, -+#else - .teardown.single = finish_cpu, -+#endif - .cant_stop = true, - }, - /* Final state before CPU kills itself */ diff --git a/PATCH/MuQSS/0003-Work-around-x86-only-llc-stuff.patch b/PATCH/MuQSS/0003-Work-around-x86-only-llc-stuff.patch new file mode 100644 index 000000000..5e7d02f41 --- /dev/null +++ b/PATCH/MuQSS/0003-Work-around-x86-only-llc-stuff.patch @@ -0,0 +1,39 @@ +From 8aa4eb8092e67fa7c3d764b199b8a1a833b40d89 Mon Sep 17 00:00:00 2001 +From: Serge Belyshev +Date: Sat, 26 Oct 2019 17:08:56 +0300 +Subject: [PATCH] Work around x86-only llc stuff + +--- + kernel/sched/MuQSS.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/kernel/sched/MuQSS.c ++++ b/kernel/sched/MuQSS.c +@@ -6755,7 +6755,11 @@ static bool cache_cpu_idle(struct rq *rq + /* MC siblings CPU mask which share the same LLC */ + static const cpumask_t *llc_core_cpumask(int cpu) + { ++#ifdef CONFIG_X86 + return per_cpu(cpu_llc_shared_map, cpu); ++#else ++ return topology_core_cpumask(cpu); ++#endif + } + #endif + +@@ -7065,6 +7069,7 @@ void __init sched_init_smp(void) + } + } + ++#ifdef CONFIG_X86 + for_each_online_cpu(cpu) { + rq = cpu_rq(cpu); + for (i = 0; i < total_runqueues; i++) { +@@ -7080,6 +7085,7 @@ void __init sched_init_smp(void) + rq->cpu_order[i]->cpu, per_cpu(cpu_llc_id, rq->cpu_order[i]->cpu)); + } + } ++#endif + + switch (rqshare) { + case RQSHARE_ALL: diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index fd91ba912..81b7d0780 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -38,9 +38,9 @@ wget -qO - https://github.com/openwrt/openwrt/commit/cfaf039.patch | patch -p1 #wget -qO - https://github.com/QiuSimons/openwrt-NoTengoBattery/commit/7d44cab.patch | patch -p1 #wget https://github.com/hamadmarri/cacule-cpu-scheduler/raw/master/patches/CacULE/v5.4/cacule-5.4.patch -O ./target/linux/generic/hack-5.4/694-cacule-5.4.patch # MuQSS -cp -f ../PATCH/MuQSS/0001-MultiQueue-Skiplist-Scheduler-v0.201.patch ./target/linux/generic/hack-5.4/694-0001-MultiQueue-Skiplist-Scheduler-v0.201.patch +cp -f ../PATCH/MuQSS/0001-MultiQueue-Skiplist-Scheduler-v0.196.patch ./target/linux/generic/hack-5.4/694-0001-MultiQueue-Skiplist-Scheduler-v0.196.patch cp -f ../PATCH/MuQSS/0002-MuQSS-Fix-build-error-on-config-leak.patch ./target/linux/generic/hack-5.4/694-0002-MuQSS-Fix-build-error-on-config-leak.patch -cp -f ../PATCH/MuQSS/0003-MuQSS-Revert-invocation-of-finish_cpu-when-offlining-core.patch ./target/linux/generic/hack-5.4/694-0003-MuQSS-Revert-invocation-of-finish_cpu-when-offlining-core.patch +cp -f ../PATCH/MuQSS/0003-Work-around-x86-only-llc-stuff.patch ./target/linux/generic/hack-5.4/694-0003-Work-around-x86-only-llc-stuff.patch # BMQ #wget https://gitlab.com/alfredchen/projectc/-/raw/master/5.4/bmq_v5.4-r2.patch -O ./target/linux/generic/hack-5.4/694-bmq_v5.4-r2.patch # PDS From cdee46aaa2cb174b771b5e06fd5aecb6aea0f090 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sat, 27 Nov 2021 00:44:52 +0800 Subject: [PATCH 209/244] BMQ r2 2 --- PATCH/BMQ/01-bmq_v5.4-r2.patch | 7757 ++++++++++++++++++++++++++++++++ README.md | 2 +- SCRIPTS/02_prepare_package.sh | 8 +- 3 files changed, 7762 insertions(+), 5 deletions(-) create mode 100644 PATCH/BMQ/01-bmq_v5.4-r2.patch diff --git a/PATCH/BMQ/01-bmq_v5.4-r2.patch b/PATCH/BMQ/01-bmq_v5.4-r2.patch new file mode 100644 index 000000000..79ca052cb --- /dev/null +++ b/PATCH/BMQ/01-bmq_v5.4-r2.patch @@ -0,0 +1,7757 @@ +diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst +index 032c7cd3cede..97ea247cc43a 100644 +--- a/Documentation/admin-guide/sysctl/kernel.rst ++++ b/Documentation/admin-guide/sysctl/kernel.rst +@@ -105,6 +105,7 @@ show up in /proc/sys/kernel: + - unknown_nmi_panic + - watchdog + - watchdog_thresh ++- yield_type + - version + + +@@ -1175,3 +1176,13 @@ is 10 seconds. + + The softlockup threshold is (2 * watchdog_thresh). Setting this + tunable to zero will disable lockup detection altogether. ++ ++yield_type: ++=========== ++ ++BMQ CPU scheduler only. This determines what type of yield calls to ++sched_yield will perform. ++ ++ 0 - No yield. ++ 1 - Deboost and requeue task. (default) ++ 2 - Set run queue skip task. +diff --git a/Documentation/scheduler/sched-BMQ.txt b/Documentation/scheduler/sched-BMQ.txt +new file mode 100644 +index 000000000000..05c84eec0f31 +--- /dev/null ++++ b/Documentation/scheduler/sched-BMQ.txt +@@ -0,0 +1,110 @@ ++ BitMap queue CPU Scheduler ++ -------------------------- ++ ++CONTENT ++======== ++ ++ Background ++ Design ++ Overview ++ Task policy ++ Priority management ++ BitMap Queue ++ CPU Assignment and Migration ++ ++ ++Background ++========== ++ ++BitMap Queue CPU scheduler, referred to as BMQ from here on, is an evolution ++of previous Priority and Deadline based Skiplist multiple queue scheduler(PDS), ++and inspired by Zircon scheduler. The goal of it is to keep the scheduler code ++simple, while efficiency and scalable for interactive tasks, such as desktop, ++movie playback and gaming etc. ++ ++Design ++====== ++ ++Overview ++-------- ++ ++BMQ use per CPU run queue design, each CPU(logical) has it's own run queue, ++each CPU is responsible for scheduling the tasks that are putting into it's ++run queue. ++ ++The run queue is a set of priority queues. Note that these queues are fifo ++queue for non-rt tasks or priority queue for rt tasks in data structure. See ++BitMap Queue below for details. BMQ is optimized for non-rt tasks in the fact ++that most applications are non-rt tasks. No matter the queue is fifo or ++priority, In each queue is an ordered list of runnable tasks awaiting execution ++and the data structures are the same. When it is time for a new task to run, ++the scheduler simply looks the lowest numbered queueue that contains a task, ++and runs the first task from the head of that queue. And per CPU idle task is ++also in the run queue, so the scheduler can always find a task to run on from ++its run queue. ++ ++Each task will assigned the same timeslice(default 4ms) when it is picked to ++start running. Task will be reinserted at the end of the appropriate priority ++queue when it uses its whole timeslice. When the scheduler selects a new task ++from the priority queue it sets the CPU's preemption timer for the remainder of ++the previous timeslice. When that timer fires the scheduler will stop execution ++on that task, select another task and start over again. ++ ++If a task blocks waiting for a shared resource then it's taken out of its ++priority queue and is placed in a wait queue for the shared resource. When it ++is unblocked it will be reinserted in the appropriate priority queue of an ++eligible CPU. ++ ++Task policy ++----------- ++ ++BMQ supports DEADLINE, FIFO, RR, NORMAL, BATCH and IDLE task policy like the ++mainline CFS scheduler. But BMQ is heavy optimized for non-rt task, that's ++NORMAL/BATCH/IDLE policy tasks. Below is the implementation detail of each ++policy. ++ ++DEADLINE ++ It is squashed as priority 0 FIFO task. ++ ++FIFO/RR ++ All RT tasks share one single priority queue in BMQ run queue designed. The ++complexity of insert operation is O(n). BMQ is not designed for system runs ++with major rt policy tasks. ++ ++NORMAL/BATCH/IDLE ++ BATCH and IDLE tasks are treated as the same policy. They compete CPU with ++NORMAL policy tasks, but they just don't boost. To control the priority of ++NORMAL/BATCH/IDLE tasks, simply use nice level. ++ ++ISO ++ ISO policy is not supported in BMQ. Please use nice level -20 NORMAL policy ++task instead. ++ ++Priority management ++------------------- ++ ++RT tasks have priority from 0-99. For non-rt tasks, there are three different ++factors used to determine the effective priority of a task. The effective ++priority being what is used to determine which queue it will be in. ++ ++The first factor is simply the task’s static priority. Which is assigned from ++task's nice level, within [-20, 19] in userland's point of view and [0, 39] ++internally. ++ ++The second factor is the priority boost. This is a value bounded between ++[-MAX_PRIORITY_ADJ, MAX_PRIORITY_ADJ] used to offset the base priority, it is ++modified by the following cases: ++ ++*When a thread has used up its entire timeslice, always deboost its boost by ++increasing by one. ++*When a thread gives up cpu control(voluntary or non-voluntary) to reschedule, ++and its switch-in time(time after last switch and run) below the thredhold ++based on its priority boost, will boost its boost by decreasing by one buti is ++capped at 0 (won’t go negative). ++ ++The intent in this system is to ensure that interactive threads are serviced ++quickly. These are usually the threads that interact directly with the user ++and cause user-perceivable latency. These threads usually do little work and ++spend most of their time blocked awaiting another user event. So they get the ++priority boost from unblocking while background threads that do most of the ++processing receive the priority penalty for using their entire timeslice. +diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c +index f18d5067cd0f..fe489fc01c73 100644 +--- a/arch/powerpc/platforms/cell/spufs/sched.c ++++ b/arch/powerpc/platforms/cell/spufs/sched.c +@@ -51,11 +51,6 @@ static struct task_struct *spusched_task; + static struct timer_list spusched_timer; + static struct timer_list spuloadavg_timer; + +-/* +- * Priority of a normal, non-rt, non-niced'd process (aka nice level 0). +- */ +-#define NORMAL_PRIO 120 +- + /* + * Frequency of the spu scheduler tick. By default we do one SPU scheduler + * tick for every 10 CPU scheduler ticks. +diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c +index b66e81c06a57..a294f8f5fd75 100644 +--- a/drivers/cpufreq/cpufreq_conservative.c ++++ b/drivers/cpufreq/cpufreq_conservative.c +@@ -28,8 +28,8 @@ struct cs_dbs_tuners { + }; + + /* Conservative governor macros */ +-#define DEF_FREQUENCY_UP_THRESHOLD (80) +-#define DEF_FREQUENCY_DOWN_THRESHOLD (20) ++#define DEF_FREQUENCY_UP_THRESHOLD (63) ++#define DEF_FREQUENCY_DOWN_THRESHOLD (26) + #define DEF_FREQUENCY_STEP (5) + #define DEF_SAMPLING_DOWN_FACTOR (1) + #define MAX_SAMPLING_DOWN_FACTOR (10) +diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c +index dced033875bf..d2cd03766b09 100644 +--- a/drivers/cpufreq/cpufreq_ondemand.c ++++ b/drivers/cpufreq/cpufreq_ondemand.c +@@ -18,7 +18,7 @@ + #include "cpufreq_ondemand.h" + + /* On-demand governor macros */ +-#define DEF_FREQUENCY_UP_THRESHOLD (80) ++#define DEF_FREQUENCY_UP_THRESHOLD (63) + #define DEF_SAMPLING_DOWN_FACTOR (1) + #define MAX_SAMPLING_DOWN_FACTOR (100000) + #define MICRO_FREQUENCY_UP_THRESHOLD (95) +@@ -127,7 +127,7 @@ static void dbs_freq_increase(struct cpufreq_policy *policy, unsigned int freq) + } + + /* +- * Every sampling_rate, we check, if current idle time is less than 20% ++ * Every sampling_rate, we check, if current idle time is less than 37% + * (default), then we try to increase frequency. Else, we adjust the frequency + * proportional to load. + */ +diff --git a/fs/proc/base.c b/fs/proc/base.c +index ebea9501afb8..51c9346a69fe 100644 +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -477,7 +477,7 @@ static int proc_pid_schedstat(struct seq_file *m, struct pid_namespace *ns, + seq_puts(m, "0 0 0\n"); + else + seq_printf(m, "%llu %llu %lu\n", +- (unsigned long long)task->se.sum_exec_runtime, ++ (unsigned long long)tsk_seruntime(task), + (unsigned long long)task->sched_info.run_delay, + task->sched_info.pcount); + +diff --git a/include/asm-generic/resource.h b/include/asm-generic/resource.h +index 8874f681b056..59eb72bf7d5f 100644 +--- a/include/asm-generic/resource.h ++++ b/include/asm-generic/resource.h +@@ -23,7 +23,7 @@ + [RLIMIT_LOCKS] = { RLIM_INFINITY, RLIM_INFINITY }, \ + [RLIMIT_SIGPENDING] = { 0, 0 }, \ + [RLIMIT_MSGQUEUE] = { MQ_BYTES_MAX, MQ_BYTES_MAX }, \ +- [RLIMIT_NICE] = { 0, 0 }, \ ++ [RLIMIT_NICE] = { 30, 30 }, \ + [RLIMIT_RTPRIO] = { 0, 0 }, \ + [RLIMIT_RTTIME] = { RLIM_INFINITY, RLIM_INFINITY }, \ + } +diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h +index 1b6d31da7cbc..dea181bdb1dd 100644 +--- a/include/linux/jiffies.h ++++ b/include/linux/jiffies.h +@@ -171,7 +171,7 @@ static inline u64 get_jiffies_64(void) + * Have the 32 bit jiffies value wrap 5 minutes after boot + * so jiffies wrap bugs show up earlier. + */ +-#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ)) ++#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-10*HZ)) + + /* + * Change timeval to jiffies, trying to avoid the +diff --git a/include/linux/sched.h b/include/linux/sched.h +index 67a1d86981a9..a38ec88efbad 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -644,13 +644,18 @@ struct task_struct { + unsigned int flags; + unsigned int ptrace; + +-#ifdef CONFIG_SMP ++#if defined(CONFIG_SMP) && !defined(CONFIG_SCHED_BMQ) + struct llist_node wake_entry; ++#endif ++#if defined(CONFIG_SMP) || defined(CONFIG_SCHED_BMQ) + int on_cpu; ++#endif ++#ifdef CONFIG_SMP + #ifdef CONFIG_THREAD_INFO_IN_TASK + /* Current CPU: */ + unsigned int cpu; + #endif ++#ifndef CONFIG_SCHED_BMQ + unsigned int wakee_flips; + unsigned long wakee_flip_decay_ts; + struct task_struct *last_wakee; +@@ -664,6 +669,7 @@ struct task_struct { + */ + int recent_used_cpu; + int wake_cpu; ++#endif /* !CONFIG_SCHED_BMQ */ + #endif + int on_rq; + +@@ -672,13 +678,23 @@ struct task_struct { + int normal_prio; + unsigned int rt_priority; + ++#ifdef CONFIG_SCHED_BMQ ++ u64 last_ran; ++ s64 time_slice; ++ int boost_prio; ++ int bmq_idx; ++ struct list_head bmq_node; ++ /* sched_clock time spent running */ ++ u64 sched_time; ++#else /* !CONFIG_SCHED_BMQ */ + const struct sched_class *sched_class; + struct sched_entity se; + struct sched_rt_entity rt; ++ struct sched_dl_entity dl; ++#endif + #ifdef CONFIG_CGROUP_SCHED + struct task_group *sched_task_group; + #endif +- struct sched_dl_entity dl; + + #ifdef CONFIG_UCLAMP_TASK + /* Clamp values requested for a scheduling entity */ +@@ -1283,6 +1299,15 @@ struct task_struct { + */ + }; + ++#ifdef CONFIG_SCHED_BMQ ++#define tsk_seruntime(t) ((t)->sched_time) ++/* replace the uncertian rt_timeout with 0UL */ ++#define tsk_rttimeout(t) (0UL) ++#else /* CFS */ ++#define tsk_seruntime(t) ((t)->se.sum_exec_runtime) ++#define tsk_rttimeout(t) ((t)->rt.timeout) ++#endif /* !CONFIG_SCHED_BMQ */ ++ + static inline struct pid *task_pid(struct task_struct *task) + { + return task->thread_pid; +diff --git a/include/linux/sched/deadline.h b/include/linux/sched/deadline.h +index 1aff00b65f3c..02a3c5d34ee4 100644 +--- a/include/linux/sched/deadline.h ++++ b/include/linux/sched/deadline.h +@@ -1,5 +1,22 @@ + /* SPDX-License-Identifier: GPL-2.0 */ + ++#ifdef CONFIG_SCHED_BMQ ++ ++#define __tsk_deadline(p) (0UL) ++ ++static inline int dl_prio(int prio) ++{ ++ return 0; ++} ++ ++static inline int dl_task(struct task_struct *p) ++{ ++ return (SCHED_NORMAL == p->policy); ++} ++#else ++ ++#define __tsk_deadline(p) ((p)->dl.deadline) ++ + /* + * SCHED_DEADLINE tasks has negative priorities, reflecting + * the fact that any of them has higher prio than RT and +@@ -19,6 +36,7 @@ static inline int dl_task(struct task_struct *p) + { + return dl_prio(p->prio); + } ++#endif /* CONFIG_SCHED_BMQ */ + + static inline bool dl_time_before(u64 a, u64 b) + { +diff --git a/include/linux/sched/prio.h b/include/linux/sched/prio.h +index 7d64feafc408..d9dc5d3ccd2e 100644 +--- a/include/linux/sched/prio.h ++++ b/include/linux/sched/prio.h +@@ -20,11 +20,17 @@ + */ + + #define MAX_USER_RT_PRIO 100 ++ + #define MAX_RT_PRIO MAX_USER_RT_PRIO + + #define MAX_PRIO (MAX_RT_PRIO + NICE_WIDTH) + #define DEFAULT_PRIO (MAX_RT_PRIO + NICE_WIDTH / 2) + ++#ifdef CONFIG_SCHED_BMQ ++/* +/- priority levels from the base priority */ ++#define MAX_PRIORITY_ADJ 4 ++#endif ++ + /* + * Convert user-nice values [ -20 ... 0 ... 19 ] + * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ], +diff --git a/include/linux/sched/rt.h b/include/linux/sched/rt.h +index e5af028c08b4..6387c8ea9832 100644 +--- a/include/linux/sched/rt.h ++++ b/include/linux/sched/rt.h +@@ -24,8 +24,10 @@ static inline bool task_is_realtime(struct task_struct *tsk) + + if (policy == SCHED_FIFO || policy == SCHED_RR) + return true; ++#ifndef CONFIG_SCHED_BMQ + if (policy == SCHED_DEADLINE) + return true; ++#endif + return false; + } + +diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h +index 4b1c3b664f51..f0f966219695 100644 +--- a/include/linux/sched/task.h ++++ b/include/linux/sched/task.h +@@ -99,7 +99,7 @@ extern long kernel_wait4(pid_t, int __user *, int, struct rusage *); + extern void free_task(struct task_struct *tsk); + + /* sched_exec is called by processes performing an exec */ +-#ifdef CONFIG_SMP ++#if defined(CONFIG_SMP) && !defined(CONFIG_SCHED_BMQ) + extern void sched_exec(void); + #else + #define sched_exec() {} +diff --git a/init/Kconfig b/init/Kconfig +index b4daad2bac23..f9faeb82f677 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -717,9 +717,28 @@ config GENERIC_SCHED_CLOCK + + menu "Scheduler features" + ++config SCHED_BMQ ++ bool "BMQ CPU scheduler" ++ help ++ The BitMap Queue CPU scheduler for excellent interactivity and ++ responsiveness on the desktop and solid scalability on normal ++ hardware and commodity servers. ++ ++ Say Y here. ++ default y ++ ++config SCHED_TIMESLICE ++ int "Scheduler Task time slice" ++ depends on SCHED_BMQ ++ help ++ Time slice in ms for BMQ CPU scheduler, default 4 ms. ++ default 2 if PREEMPT ++ default 4 if !PREEMPT ++ + config UCLAMP_TASK + bool "Enable utilization clamping for RT/FAIR tasks" + depends on CPU_FREQ_GOV_SCHEDUTIL ++ depends on !SCHED_BMQ + help + This feature enables the scheduler to track the clamped utilization + of each CPU based on RUNNABLE tasks scheduled on that CPU. +@@ -802,6 +821,7 @@ config NUMA_BALANCING + depends on ARCH_SUPPORTS_NUMA_BALANCING + depends on !ARCH_WANT_NUMA_VARIABLE_LOCALITY + depends on SMP && NUMA && MIGRATION ++ depends on !SCHED_BMQ + help + This option adds support for automatic NUMA aware memory/task placement. + The mechanism is quite primitive and is based on migrating memory when +@@ -903,7 +923,7 @@ menuconfig CGROUP_SCHED + bandwidth allocation to such task groups. It uses cgroups to group + tasks. + +-if CGROUP_SCHED ++if CGROUP_SCHED && !SCHED_BMQ + config FAIR_GROUP_SCHED + bool "Group scheduling for SCHED_OTHER" + depends on CGROUP_SCHED +@@ -1150,6 +1170,7 @@ config CHECKPOINT_RESTORE + + config SCHED_AUTOGROUP + bool "Automatic process group scheduling" ++ depends on !SCHED_BMQ + select CGROUPS + select CGROUP_SCHED + select FAIR_GROUP_SCHED +diff --git a/init/init_task.c b/init/init_task.c +index 9e5cbe5eab7b..c293de91d90f 100644 +--- a/init/init_task.c ++++ b/init/init_task.c +@@ -66,9 +66,15 @@ struct task_struct init_task + .stack = init_stack, + .usage = REFCOUNT_INIT(2), + .flags = PF_KTHREAD, ++#ifdef CONFIG_SCHED_BMQ ++ .prio = DEFAULT_PRIO + MAX_PRIORITY_ADJ, ++ .static_prio = DEFAULT_PRIO, ++ .normal_prio = DEFAULT_PRIO + MAX_PRIORITY_ADJ, ++#else + .prio = MAX_PRIO - 20, + .static_prio = MAX_PRIO - 20, + .normal_prio = MAX_PRIO - 20, ++#endif + .policy = SCHED_NORMAL, + .cpus_ptr = &init_task.cpus_mask, + .cpus_mask = CPU_MASK_ALL, +@@ -78,6 +84,12 @@ struct task_struct init_task + .restart_block = { + .fn = do_no_restart_syscall, + }, ++#ifdef CONFIG_SCHED_BMQ ++ .boost_prio = 0, ++ .bmq_idx = 15, ++ .bmq_node = LIST_HEAD_INIT(init_task.bmq_node), ++ .time_slice = HZ, ++#else + .se = { + .group_node = LIST_HEAD_INIT(init_task.se.group_node), + }, +@@ -85,6 +97,7 @@ struct task_struct init_task + .run_list = LIST_HEAD_INIT(init_task.rt.run_list), + .time_slice = RR_TIMESLICE, + }, ++#endif + .tasks = LIST_HEAD_INIT(init_task.tasks), + #ifdef CONFIG_SMP + .pushable_tasks = PLIST_NODE_INIT(init_task.pushable_tasks, MAX_PRIO), +diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c +index c87ee6412b36..45fac7b9c940 100644 +--- a/kernel/cgroup/cpuset.c ++++ b/kernel/cgroup/cpuset.c +@@ -632,7 +632,7 @@ static int validate_change(struct cpuset *cur, struct cpuset *trial) + return ret; + } + +-#ifdef CONFIG_SMP ++#if defined(CONFIG_SMP) && !defined(CONFIG_SCHED_BMQ) + /* + * Helper routine for generate_sched_domains(). + * Do cpusets a, b have overlapping effective cpus_allowed masks? +@@ -1007,7 +1007,7 @@ static void rebuild_sched_domains_locked(void) + /* Have scheduler rebuild the domains */ + partition_and_rebuild_sched_domains(ndoms, doms, attr); + } +-#else /* !CONFIG_SMP */ ++#else /* !CONFIG_SMP || CONFIG_SCHED_BMQ */ + static void rebuild_sched_domains_locked(void) + { + } +diff --git a/kernel/delayacct.c b/kernel/delayacct.c +index 27725754ac99..769d773c7182 100644 +--- a/kernel/delayacct.c ++++ b/kernel/delayacct.c +@@ -106,7 +106,7 @@ int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk) + */ + t1 = tsk->sched_info.pcount; + t2 = tsk->sched_info.run_delay; +- t3 = tsk->se.sum_exec_runtime; ++ t3 = tsk_seruntime(tsk); + + d->cpu_count += t1; + +diff --git a/kernel/exit.c b/kernel/exit.c +index a46a50d67002..58043176b285 100644 +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -131,7 +131,7 @@ static void __exit_signal(struct task_struct *tsk) + sig->curr_target = next_thread(tsk); + } + +- add_device_randomness((const void*) &tsk->se.sum_exec_runtime, ++ add_device_randomness((const void*) &tsk_seruntime(tsk), + sizeof(unsigned long long)); + + /* +@@ -152,7 +152,7 @@ static void __exit_signal(struct task_struct *tsk) + sig->inblock += task_io_get_inblock(tsk); + sig->oublock += task_io_get_oublock(tsk); + task_io_accounting_add(&sig->ioac, &tsk->ioac); +- sig->sum_sched_runtime += tsk->se.sum_exec_runtime; ++ sig->sum_sched_runtime += tsk_seruntime(tsk); + sig->nr_threads--; + __unhash_process(tsk, group_dead); + write_sequnlock(&sig->stats_lock); +diff --git a/kernel/livepatch/transition.c b/kernel/livepatch/transition.c +index cdf318d86dd6..b3bd1e65c002 100644 +--- a/kernel/livepatch/transition.c ++++ b/kernel/livepatch/transition.c +@@ -306,7 +306,11 @@ static bool klp_try_switch_task(struct task_struct *task) + */ + rq = task_rq_lock(task, &flags); + ++#ifdef CONFIG_SCHED_BMQ ++ if (task_running(task) && task != current) { ++#else + if (task_running(rq, task) && task != current) { ++#endif + snprintf(err_buf, STACK_ERR_BUF_SIZE, + "%s: %s:%d is running\n", __func__, task->comm, + task->pid); +diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c +index 2874bf556162..fad8a279fdfa 100644 +--- a/kernel/locking/rtmutex.c ++++ b/kernel/locking/rtmutex.c +@@ -229,7 +229,7 @@ static inline bool unlock_rt_mutex_safe(struct rt_mutex *lock, + * Only use with rt_mutex_waiter_{less,equal}() + */ + #define task_to_waiter(p) \ +- &(struct rt_mutex_waiter){ .prio = (p)->prio, .deadline = (p)->dl.deadline } ++ &(struct rt_mutex_waiter){ .prio = (p)->prio, .deadline = __tsk_deadline(p) } + + static inline int + rt_mutex_waiter_less(struct rt_mutex_waiter *left, +@@ -680,7 +680,7 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task, + * the values of the node being removed. + */ + waiter->prio = task->prio; +- waiter->deadline = task->dl.deadline; ++ waiter->deadline = __tsk_deadline(task); + + rt_mutex_enqueue(lock, waiter); + +@@ -953,7 +953,7 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock, + waiter->task = task; + waiter->lock = lock; + waiter->prio = task->prio; +- waiter->deadline = task->dl.deadline; ++ waiter->deadline = __tsk_deadline(task); + + /* Get the top priority waiter on the lock */ + if (rt_mutex_has_waiters(lock)) +diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile +index 21fb5a5662b5..cab4e5c5b38e 100644 +--- a/kernel/sched/Makefile ++++ b/kernel/sched/Makefile +@@ -16,14 +16,20 @@ ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y) + CFLAGS_core.o := $(PROFILING) -fno-omit-frame-pointer + endif + +-obj-y += core.o loadavg.o clock.o cputime.o +-obj-y += idle.o fair.o rt.o deadline.o +-obj-y += wait.o wait_bit.o swait.o completion.o +- +-obj-$(CONFIG_SMP) += cpupri.o cpudeadline.o topology.o stop_task.o pelt.o ++ifdef CONFIG_SCHED_BMQ ++obj-y += bmq.o ++else ++obj-y += core.o ++obj-y += fair.o rt.o deadline.o ++obj-$(CONFIG_SMP) += cpudeadline.o topology.o stop_task.o + obj-$(CONFIG_SCHED_AUTOGROUP) += autogroup.o +-obj-$(CONFIG_SCHEDSTATS) += stats.o + obj-$(CONFIG_SCHED_DEBUG) += debug.o ++endif ++obj-y += loadavg.o clock.o cputime.o ++obj-y += idle.o ++obj-y += wait.o wait_bit.o swait.o completion.o ++obj-$(CONFIG_SMP) += cpupri.o pelt.o ++obj-$(CONFIG_SCHEDSTATS) += stats.o + obj-$(CONFIG_CGROUP_CPUACCT) += cpuacct.o + obj-$(CONFIG_CPU_FREQ) += cpufreq.o + obj-$(CONFIG_CPU_FREQ_GOV_SCHEDUTIL) += cpufreq_schedutil.o +diff --git a/kernel/sched/bmq.c b/kernel/sched/bmq.c +new file mode 100644 +index 000000000000..42a2a5b3d172 +--- /dev/null ++++ b/kernel/sched/bmq.c +@@ -0,0 +1,6102 @@ ++/* ++ * kernel/sched/bmq.c ++ * ++ * BMQ Core kernel scheduler code and related syscalls ++ * ++ * Copyright (C) 1991-2002 Linus Torvalds ++ * ++ * 2009-08-13 Brainfuck deadline scheduling policy by Con Kolivas deletes ++ * a whole lot of those previous things. ++ * 2017-09-06 Priority and Deadline based Skip list multiple queue kernel ++ * scheduler by Alfred Chen. ++ * 2019-02-20 BMQ(BitMap Queue) kernel scheduler by Alfred Chen. ++ */ ++#include "bmq_sched.h" ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++#include "../workqueue_internal.h" ++#include "../smpboot.h" ++ ++#include "pelt.h" ++ ++#define CREATE_TRACE_POINTS ++#include ++ ++/* rt_prio(prio) defined in include/linux/sched/rt.h */ ++#define rt_task(p) rt_prio((p)->prio) ++#define rt_policy(policy) ((policy) == SCHED_FIFO || (policy) == SCHED_RR) ++#define task_has_rt_policy(p) (rt_policy((p)->policy)) ++ ++#define STOP_PRIO (MAX_RT_PRIO - 1) ++ ++#define SCHED_TIMESLICE_NS (CONFIG_SCHED_TIMESLICE * 1000 * 1000) ++ ++/* Reschedule if less than this many μs left */ ++#define RESCHED_NS (100 * 1000) ++ ++/* ++ * This allows printing both to /proc/sched_debug and ++ * to the console ++ */ ++#define SEQ_printf(m, x...) \ ++ do { \ ++ if (m) \ ++ seq_printf(m, x); \ ++ else \ ++ pr_cont(x); \ ++ } while (0) ++ ++static inline void print_scheduler_version(void) ++{ ++ printk(KERN_INFO "bmq: BMQ CPU Scheduler 5.4-r2 by Alfred Chen.\n"); ++} ++ ++/** ++ * sched_yield_type - Choose what sort of yield sched_yield will perform. ++ * 0: No yield. ++ * 1: Deboost and requeue task. (default) ++ * 2: Set rq skip task. ++ */ ++int sched_yield_type __read_mostly = 1; ++ ++#define rq_switch_time(rq) ((rq)->clock - (rq)->last_ts_switch) ++#define boost_threshold(p) (SCHED_TIMESLICE_NS >>\ ++ (10 - MAX_PRIORITY_ADJ - (p)->boost_prio)) ++ ++static inline void boost_task(struct task_struct *p) ++{ ++ int limit; ++ ++ switch (p->policy) { ++ case SCHED_NORMAL: ++ limit = -MAX_PRIORITY_ADJ; ++ break; ++ case SCHED_BATCH: ++ case SCHED_IDLE: ++ limit = 0; ++ break; ++ default: ++ return; ++ } ++ ++ if (p->boost_prio > limit) ++ p->boost_prio--; ++} ++ ++static inline void deboost_task(struct task_struct *p) ++{ ++ if (p->boost_prio < MAX_PRIORITY_ADJ) ++ p->boost_prio++; ++} ++ ++#ifdef CONFIG_SMP ++static cpumask_t sched_rq_pending_mask ____cacheline_aligned_in_smp; ++ ++enum { ++ BASE_CPU_AFFINITY_CHK_LEVEL = 1, ++#ifdef CONFIG_SCHED_SMT ++ SMT_CPU_AFFINITY_CHK_LEVEL_SPACE_HOLDER, ++#endif ++#ifdef CONFIG_SCHED_MC ++ MC_CPU_AFFINITY_CHK_LEVEL_SPACE_HOLDER, ++#endif ++ NR_CPU_AFFINITY_CHK_LEVEL ++}; ++ ++DEFINE_PER_CPU(cpumask_t [NR_CPU_AFFINITY_CHK_LEVEL], sched_cpu_affinity_masks); ++DEFINE_PER_CPU(cpumask_t *, sched_cpu_affinity_end_mask); ++ ++#ifdef CONFIG_SCHED_SMT ++DEFINE_STATIC_KEY_FALSE(sched_smt_present); ++EXPORT_SYMBOL_GPL(sched_smt_present); ++#endif ++ ++/* ++ * Keep a unique ID per domain (we use the first CPUs number in the cpumask of ++ * the domain), this allows us to quickly tell if two cpus are in the same cache ++ * domain, see cpus_share_cache(). ++ */ ++DEFINE_PER_CPU(int, sd_llc_id); ++ ++int __weak arch_sd_sibling_asym_packing(void) ++{ ++ return 0*SD_ASYM_PACKING; ++} ++#endif /* CONFIG_SMP */ ++ ++static DEFINE_MUTEX(sched_hotcpu_mutex); ++ ++DEFINE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues); ++ ++#ifndef prepare_arch_switch ++# define prepare_arch_switch(next) do { } while (0) ++#endif ++#ifndef finish_arch_post_lock_switch ++# define finish_arch_post_lock_switch() do { } while (0) ++#endif ++ ++#define IDLE_WM (IDLE_TASK_SCHED_PRIO) ++ ++static cpumask_t sched_sg_idle_mask ____cacheline_aligned_in_smp; ++static cpumask_t sched_rq_watermark[bmq_BITS] ____cacheline_aligned_in_smp; ++ ++#if (bmq_BITS <= BITS_PER_LONG) ++#define bmq_find_first_bit(bm) __ffs((bm[0])) ++#define bmq_find_next_bit(bm, start) __ffs(BITMAP_FIRST_WORD_MASK(start) & bm[0]) ++#else ++#define bmq_find_first_bit(bm) find_first_bit((bm), bmq_BITS) ++#define bmq_find_next_bit(bm, start) find_next_bit(bm, bmq_BITS, start) ++#endif ++ ++static inline void update_sched_rq_watermark(struct rq *rq) ++{ ++ unsigned long watermark = bmq_find_first_bit(rq->queue.bitmap); ++ unsigned long last_wm = rq->watermark; ++ unsigned long i; ++ int cpu; ++ ++ if (watermark == last_wm) ++ return; ++ ++ rq->watermark = watermark; ++ cpu = cpu_of(rq); ++ if (watermark < last_wm) { ++ for (i = watermark + 1; i <= last_wm; i++) ++ cpumask_andnot(&sched_rq_watermark[i], ++ &sched_rq_watermark[i], cpumask_of(cpu)); ++#ifdef CONFIG_SCHED_SMT ++ if (!static_branch_likely(&sched_smt_present)) ++ return; ++ if (IDLE_WM == last_wm) ++ cpumask_andnot(&sched_sg_idle_mask, ++ &sched_sg_idle_mask, cpu_smt_mask(cpu)); ++#endif ++ return; ++ } ++ /* last_wm < watermark */ ++ for (i = last_wm + 1; i <= watermark; i++) ++ cpumask_set_cpu(cpu, &sched_rq_watermark[i]); ++#ifdef CONFIG_SCHED_SMT ++ if (!static_branch_likely(&sched_smt_present)) ++ return; ++ if (IDLE_WM == watermark) { ++ cpumask_t tmp; ++ cpumask_and(&tmp, cpu_smt_mask(cpu), &sched_rq_watermark[IDLE_WM]); ++ if (cpumask_equal(&tmp, cpu_smt_mask(cpu))) ++ cpumask_or(&sched_sg_idle_mask, cpu_smt_mask(cpu), ++ &sched_sg_idle_mask); ++ } ++#endif ++} ++ ++static inline int task_sched_prio(struct task_struct *p) ++{ ++ return (p->prio < MAX_RT_PRIO)? 0:p->prio - MAX_RT_PRIO + p->boost_prio + 1; ++} ++ ++static inline void bmq_init(struct bmq *q) ++{ ++ int i; ++ ++ bitmap_zero(q->bitmap, bmq_BITS); ++ for(i = 0; i < bmq_BITS; i++) ++ INIT_LIST_HEAD(&q->heads[i]); ++} ++ ++static inline void bmq_init_idle(struct bmq *q, struct task_struct *idle) ++{ ++ INIT_LIST_HEAD(&q->heads[IDLE_TASK_SCHED_PRIO]); ++ list_add(&idle->bmq_node, &q->heads[IDLE_TASK_SCHED_PRIO]); ++ set_bit(IDLE_TASK_SCHED_PRIO, q->bitmap); ++} ++ ++static inline void bmq_add_task(struct task_struct *p, struct bmq *q, int idx) ++{ ++ struct list_head *n; ++ ++ if (likely(idx)) { ++ list_add_tail(&p->bmq_node, &q->heads[idx]); ++ return; ++ } ++ ++ list_for_each(n, &q->heads[idx]) ++ if (list_entry(n, struct task_struct, bmq_node)->prio > p->prio) ++ break; ++ __list_add(&p->bmq_node, n->prev, n); ++} ++ ++/* ++ * This routine used in bmq scheduler only which assume the idle task in the bmq ++ */ ++static inline struct task_struct *rq_first_bmq_task(struct rq *rq) ++{ ++ unsigned long idx = bmq_find_first_bit(rq->queue.bitmap); ++ const struct list_head *head = &rq->queue.heads[idx]; ++ ++ return list_first_entry(head, struct task_struct, bmq_node); ++} ++ ++static inline struct task_struct * ++rq_next_bmq_task(struct task_struct *p, struct rq *rq) ++{ ++ unsigned long idx = p->bmq_idx; ++ struct list_head *head = &rq->queue.heads[idx]; ++ ++ if (list_is_last(&p->bmq_node, head)) { ++ idx = bmq_find_next_bit(rq->queue.bitmap, idx + 1); ++ head = &rq->queue.heads[idx]; ++ ++ return list_first_entry(head, struct task_struct, bmq_node); ++ } ++ ++ return list_next_entry(p, bmq_node); ++} ++ ++static inline struct task_struct *rq_runnable_task(struct rq *rq) ++{ ++ struct task_struct *next = rq_first_bmq_task(rq); ++ ++ if (unlikely(next == rq->skip)) ++ next = rq_next_bmq_task(next, rq); ++ ++ return next; ++} ++ ++/* ++ * Context: p->pi_lock ++ */ ++static inline struct rq ++*__task_access_lock(struct task_struct *p, raw_spinlock_t **plock) ++{ ++ struct rq *rq; ++ for (;;) { ++ rq = task_rq(p); ++ if (p->on_cpu || task_on_rq_queued(p)) { ++ raw_spin_lock(&rq->lock); ++ if (likely((p->on_cpu || task_on_rq_queued(p)) ++ && rq == task_rq(p))) { ++ *plock = &rq->lock; ++ return rq; ++ } ++ raw_spin_unlock(&rq->lock); ++ } else if (task_on_rq_migrating(p)) { ++ do { ++ cpu_relax(); ++ } while (unlikely(task_on_rq_migrating(p))); ++ } else { ++ *plock = NULL; ++ return rq; ++ } ++ } ++} ++ ++static inline void ++__task_access_unlock(struct task_struct *p, raw_spinlock_t *lock) ++{ ++ if (NULL != lock) ++ raw_spin_unlock(lock); ++} ++ ++static inline struct rq ++*task_access_lock_irqsave(struct task_struct *p, raw_spinlock_t **plock, ++ unsigned long *flags) ++{ ++ struct rq *rq; ++ for (;;) { ++ rq = task_rq(p); ++ if (p->on_cpu || task_on_rq_queued(p)) { ++ raw_spin_lock_irqsave(&rq->lock, *flags); ++ if (likely((p->on_cpu || task_on_rq_queued(p)) ++ && rq == task_rq(p))) { ++ *plock = &rq->lock; ++ return rq; ++ } ++ raw_spin_unlock_irqrestore(&rq->lock, *flags); ++ } else if (task_on_rq_migrating(p)) { ++ do { ++ cpu_relax(); ++ } while (unlikely(task_on_rq_migrating(p))); ++ } else { ++ raw_spin_lock_irqsave(&p->pi_lock, *flags); ++ if (likely(!p->on_cpu && !p->on_rq && ++ rq == task_rq(p))) { ++ *plock = &p->pi_lock; ++ return rq; ++ } ++ raw_spin_unlock_irqrestore(&p->pi_lock, *flags); ++ } ++ } ++} ++ ++static inline void ++task_access_unlock_irqrestore(struct task_struct *p, raw_spinlock_t *lock, ++ unsigned long *flags) ++{ ++ raw_spin_unlock_irqrestore(lock, *flags); ++} ++ ++/* ++ * __task_rq_lock - lock the rq @p resides on. ++ */ ++struct rq *__task_rq_lock(struct task_struct *p, struct rq_flags *rf) ++ __acquires(rq->lock) ++{ ++ struct rq *rq; ++ ++ lockdep_assert_held(&p->pi_lock); ++ ++ for (;;) { ++ rq = task_rq(p); ++ raw_spin_lock(&rq->lock); ++ if (likely(rq == task_rq(p) && !task_on_rq_migrating(p))) ++ return rq; ++ raw_spin_unlock(&rq->lock); ++ ++ while (unlikely(task_on_rq_migrating(p))) ++ cpu_relax(); ++ } ++} ++ ++/* ++ * task_rq_lock - lock p->pi_lock and lock the rq @p resides on. ++ */ ++struct rq *task_rq_lock(struct task_struct *p, struct rq_flags *rf) ++ __acquires(p->pi_lock) ++ __acquires(rq->lock) ++{ ++ struct rq *rq; ++ ++ for (;;) { ++ raw_spin_lock_irqsave(&p->pi_lock, rf->flags); ++ rq = task_rq(p); ++ raw_spin_lock(&rq->lock); ++ /* ++ * move_queued_task() task_rq_lock() ++ * ++ * ACQUIRE (rq->lock) ++ * [S] ->on_rq = MIGRATING [L] rq = task_rq() ++ * WMB (__set_task_cpu()) ACQUIRE (rq->lock); ++ * [S] ->cpu = new_cpu [L] task_rq() ++ * [L] ->on_rq ++ * RELEASE (rq->lock) ++ * ++ * If we observe the old CPU in task_rq_lock(), the acquire of ++ * the old rq->lock will fully serialize against the stores. ++ * ++ * If we observe the new CPU in task_rq_lock(), the address ++ * dependency headed by '[L] rq = task_rq()' and the acquire ++ * will pair with the WMB to ensure we then also see migrating. ++ */ ++ if (likely(rq == task_rq(p) && !task_on_rq_migrating(p))) { ++ return rq; ++ } ++ raw_spin_unlock(&rq->lock); ++ raw_spin_unlock_irqrestore(&p->pi_lock, rf->flags); ++ ++ while (unlikely(task_on_rq_migrating(p))) ++ cpu_relax(); ++ } ++} ++ ++/* ++ * RQ-clock updating methods: ++ */ ++ ++static void update_rq_clock_task(struct rq *rq, s64 delta) ++{ ++/* ++ * In theory, the compile should just see 0 here, and optimize out the call ++ * to sched_rt_avg_update. But I don't trust it... ++ */ ++ s64 __maybe_unused steal = 0, irq_delta = 0; ++ ++#ifdef CONFIG_IRQ_TIME_ACCOUNTING ++ irq_delta = irq_time_read(cpu_of(rq)) - rq->prev_irq_time; ++ ++ /* ++ * Since irq_time is only updated on {soft,}irq_exit, we might run into ++ * this case when a previous update_rq_clock() happened inside a ++ * {soft,}irq region. ++ * ++ * When this happens, we stop ->clock_task and only update the ++ * prev_irq_time stamp to account for the part that fit, so that a next ++ * update will consume the rest. This ensures ->clock_task is ++ * monotonic. ++ * ++ * It does however cause some slight miss-attribution of {soft,}irq ++ * time, a more accurate solution would be to update the irq_time using ++ * the current rq->clock timestamp, except that would require using ++ * atomic ops. ++ */ ++ if (irq_delta > delta) ++ irq_delta = delta; ++ ++ rq->prev_irq_time += irq_delta; ++ delta -= irq_delta; ++#endif ++#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING ++ if (static_key_false((¶virt_steal_rq_enabled))) { ++ steal = paravirt_steal_clock(cpu_of(rq)); ++ steal -= rq->prev_steal_time_rq; ++ ++ if (unlikely(steal > delta)) ++ steal = delta; ++ ++ rq->prev_steal_time_rq += steal; ++ delta -= steal; ++ } ++#endif ++ ++ rq->clock_task += delta; ++ ++#ifdef CONFIG_HAVE_SCHED_AVG_IRQ ++ if ((irq_delta + steal)) ++ update_irq_load_avg(rq, irq_delta + steal); ++#endif ++} ++ ++static inline void update_rq_clock(struct rq *rq) ++{ ++ s64 delta = sched_clock_cpu(cpu_of(rq)) - rq->clock; ++ ++ if (unlikely(delta <= 0)) ++ return; ++ rq->clock += delta; ++ update_rq_clock_task(rq, delta); ++} ++ ++/* ++ * cmpxchg based fetch_or, macro so it works for different integer types ++ */ ++#define fetch_or(ptr, mask) \ ++ ({ \ ++ typeof(ptr) _ptr = (ptr); \ ++ typeof(mask) _mask = (mask); \ ++ typeof(*_ptr) _old, _val = *_ptr; \ ++ \ ++ for (;;) { \ ++ _old = cmpxchg(_ptr, _val, _val | _mask); \ ++ if (_old == _val) \ ++ break; \ ++ _val = _old; \ ++ } \ ++ _old; \ ++}) ++ ++#if defined(CONFIG_SMP) && defined(TIF_POLLING_NRFLAG) ++/* ++ * Atomically set TIF_NEED_RESCHED and test for TIF_POLLING_NRFLAG, ++ * this avoids any races wrt polling state changes and thereby avoids ++ * spurious IPIs. ++ */ ++static bool set_nr_and_not_polling(struct task_struct *p) ++{ ++ struct thread_info *ti = task_thread_info(p); ++ return !(fetch_or(&ti->flags, _TIF_NEED_RESCHED) & _TIF_POLLING_NRFLAG); ++} ++ ++/* ++ * Atomically set TIF_NEED_RESCHED if TIF_POLLING_NRFLAG is set. ++ * ++ * If this returns true, then the idle task promises to call ++ * sched_ttwu_pending() and reschedule soon. ++ */ ++static bool set_nr_if_polling(struct task_struct *p) ++{ ++ struct thread_info *ti = task_thread_info(p); ++ typeof(ti->flags) old, val = READ_ONCE(ti->flags); ++ ++ for (;;) { ++ if (!(val & _TIF_POLLING_NRFLAG)) ++ return false; ++ if (val & _TIF_NEED_RESCHED) ++ return true; ++ old = cmpxchg(&ti->flags, val, val | _TIF_NEED_RESCHED); ++ if (old == val) ++ break; ++ val = old; ++ } ++ return true; ++} ++ ++#else ++static bool set_nr_and_not_polling(struct task_struct *p) ++{ ++ set_tsk_need_resched(p); ++ return true; ++} ++ ++#ifdef CONFIG_SMP ++static bool set_nr_if_polling(struct task_struct *p) ++{ ++ return false; ++} ++#endif ++#endif ++ ++#ifdef CONFIG_NO_HZ_FULL ++/* ++ * Tick may be needed by tasks in the runqueue depending on their policy and ++ * requirements. If tick is needed, lets send the target an IPI to kick it out ++ * of nohz mode if necessary. ++ */ ++static inline void sched_update_tick_dependency(struct rq *rq) ++{ ++ int cpu; ++ ++ if (!tick_nohz_full_enabled()) ++ return; ++ ++ cpu = cpu_of(rq); ++ ++ if (!tick_nohz_full_cpu(cpu)) ++ return; ++ ++ if (rq->nr_running < 2) ++ tick_nohz_dep_clear_cpu(cpu, TICK_DEP_BIT_SCHED); ++ else ++ tick_nohz_dep_set_cpu(cpu, TICK_DEP_BIT_SCHED); ++} ++#else /* !CONFIG_NO_HZ_FULL */ ++static inline void sched_update_tick_dependency(struct rq *rq) { } ++#endif ++ ++/* ++ * Add/Remove/Requeue task to/from the runqueue routines ++ * Context: rq->lock ++ */ ++static inline void dequeue_task(struct task_struct *p, struct rq *rq, int flags) ++{ ++ lockdep_assert_held(&rq->lock); ++ ++ WARN_ONCE(task_rq(p) != rq, "bmq: dequeue task reside on cpu%d from cpu%d\n", ++ task_cpu(p), cpu_of(rq)); ++ ++ list_del(&p->bmq_node); ++ if (list_empty(&rq->queue.heads[p->bmq_idx])) { ++ clear_bit(p->bmq_idx, rq->queue.bitmap); ++ update_sched_rq_watermark(rq); ++ } ++ --rq->nr_running; ++#ifdef CONFIG_SMP ++ if (1 == rq->nr_running) ++ cpumask_clear_cpu(cpu_of(rq), &sched_rq_pending_mask); ++#endif ++ ++ sched_update_tick_dependency(rq); ++ psi_dequeue(p, flags & DEQUEUE_SLEEP); ++ ++ sched_info_dequeued(rq, p); ++} ++ ++static inline void enqueue_task(struct task_struct *p, struct rq *rq, int flags) ++{ ++ lockdep_assert_held(&rq->lock); ++ ++ WARN_ONCE(task_rq(p) != rq, "bmq: enqueue task reside on cpu%d to cpu%d\n", ++ task_cpu(p), cpu_of(rq)); ++ ++ p->bmq_idx = task_sched_prio(p); ++ bmq_add_task(p, &rq->queue, p->bmq_idx); ++ set_bit(p->bmq_idx, rq->queue.bitmap); ++ update_sched_rq_watermark(rq); ++ ++rq->nr_running; ++#ifdef CONFIG_SMP ++ if (2 == rq->nr_running) ++ cpumask_set_cpu(cpu_of(rq), &sched_rq_pending_mask); ++#endif ++ ++ sched_update_tick_dependency(rq); ++ ++ sched_info_queued(rq, p); ++ psi_enqueue(p, flags); ++ ++ /* ++ * If in_iowait is set, the code below may not trigger any cpufreq ++ * utilization updates, so do it here explicitly with the IOWAIT flag ++ * passed. ++ */ ++ if (p->in_iowait) ++ cpufreq_update_util(rq, SCHED_CPUFREQ_IOWAIT); ++} ++ ++static inline void requeue_task(struct task_struct *p, struct rq *rq) ++{ ++ int idx = task_sched_prio(p); ++ ++ lockdep_assert_held(&rq->lock); ++ WARN_ONCE(task_rq(p) != rq, "bmq: cpu[%d] requeue task reside on cpu%d\n", ++ cpu_of(rq), task_cpu(p)); ++ ++ list_del(&p->bmq_node); ++ bmq_add_task(p, &rq->queue, idx); ++ if (idx != p->bmq_idx) { ++ if (list_empty(&rq->queue.heads[p->bmq_idx])) ++ clear_bit(p->bmq_idx, rq->queue.bitmap); ++ p->bmq_idx = idx; ++ set_bit(p->bmq_idx, rq->queue.bitmap); ++ update_sched_rq_watermark(rq); ++ } ++} ++ ++/* ++ * resched_curr - mark rq's current task 'to be rescheduled now'. ++ * ++ * On UP this means the setting of the need_resched flag, on SMP it ++ * might also involve a cross-CPU call to trigger the scheduler on ++ * the target CPU. ++ */ ++void resched_curr(struct rq *rq) ++{ ++ struct task_struct *curr = rq->curr; ++ int cpu; ++ ++ lockdep_assert_held(&rq->lock); ++ ++ if (test_tsk_need_resched(curr)) ++ return; ++ ++ cpu = cpu_of(rq); ++ if (cpu == smp_processor_id()) { ++ set_tsk_need_resched(curr); ++ set_preempt_need_resched(); ++ return; ++ } ++ ++ if (set_nr_and_not_polling(curr)) ++ smp_send_reschedule(cpu); ++ else ++ trace_sched_wake_idle_without_ipi(cpu); ++} ++ ++void resched_cpu(int cpu) ++{ ++ struct rq *rq = cpu_rq(cpu); ++ unsigned long flags; ++ ++ raw_spin_lock_irqsave(&rq->lock, flags); ++ if (cpu_online(cpu) || cpu == smp_processor_id()) ++ resched_curr(cpu_rq(cpu)); ++ raw_spin_unlock_irqrestore(&rq->lock, flags); ++} ++ ++static inline void check_preempt_curr(struct rq *rq) ++{ ++ if (rq_first_bmq_task(rq) != rq->curr) ++ resched_curr(rq); ++} ++ ++#ifdef CONFIG_SCHED_HRTICK ++/* ++ * Use HR-timers to deliver accurate preemption points. ++ */ ++ ++static void hrtick_clear(struct rq *rq) ++{ ++ if (hrtimer_active(&rq->hrtick_timer)) ++ hrtimer_cancel(&rq->hrtick_timer); ++} ++ ++/* ++ * High-resolution timer tick. ++ * Runs from hardirq context with interrupts disabled. ++ */ ++static enum hrtimer_restart hrtick(struct hrtimer *timer) ++{ ++ struct rq *rq = container_of(timer, struct rq, hrtick_timer); ++ struct task_struct *p; ++ ++ WARN_ON_ONCE(cpu_of(rq) != smp_processor_id()); ++ ++ raw_spin_lock(&rq->lock); ++ p = rq->curr; ++ p->time_slice = 0; ++ resched_curr(rq); ++ raw_spin_unlock(&rq->lock); ++ ++ return HRTIMER_NORESTART; ++} ++ ++/* ++ * Use hrtick when: ++ * - enabled by features ++ * - hrtimer is actually high res ++ */ ++static inline int hrtick_enabled(struct rq *rq) ++{ ++ /** ++ * BMQ doesn't support sched_feat yet ++ if (!sched_feat(HRTICK)) ++ return 0; ++ */ ++ if (!cpu_active(cpu_of(rq))) ++ return 0; ++ return hrtimer_is_hres_active(&rq->hrtick_timer); ++} ++ ++#ifdef CONFIG_SMP ++ ++static void __hrtick_restart(struct rq *rq) ++{ ++ struct hrtimer *timer = &rq->hrtick_timer; ++ ++ hrtimer_start_expires(timer, HRTIMER_MODE_ABS_PINNED_HARD); ++} ++ ++/* ++ * called from hardirq (IPI) context ++ */ ++static void __hrtick_start(void *arg) ++{ ++ struct rq *rq = arg; ++ ++ raw_spin_lock(&rq->lock); ++ __hrtick_restart(rq); ++ rq->hrtick_csd_pending = 0; ++ raw_spin_unlock(&rq->lock); ++} ++ ++/* ++ * Called to set the hrtick timer state. ++ * ++ * called with rq->lock held and irqs disabled ++ */ ++void hrtick_start(struct rq *rq, u64 delay) ++{ ++ struct hrtimer *timer = &rq->hrtick_timer; ++ ktime_t time; ++ s64 delta; ++ ++ /* ++ * Don't schedule slices shorter than 10000ns, that just ++ * doesn't make sense and can cause timer DoS. ++ */ ++ delta = max_t(s64, delay, 10000LL); ++ time = ktime_add_ns(timer->base->get_time(), delta); ++ ++ hrtimer_set_expires(timer, time); ++ ++ if (rq == this_rq()) { ++ __hrtick_restart(rq); ++ } else if (!rq->hrtick_csd_pending) { ++ smp_call_function_single_async(cpu_of(rq), &rq->hrtick_csd); ++ rq->hrtick_csd_pending = 1; ++ } ++} ++ ++#else ++/* ++ * Called to set the hrtick timer state. ++ * ++ * called with rq->lock held and irqs disabled ++ */ ++void hrtick_start(struct rq *rq, u64 delay) ++{ ++ /* ++ * Don't schedule slices shorter than 10000ns, that just ++ * doesn't make sense. Rely on vruntime for fairness. ++ */ ++ delay = max_t(u64, delay, 10000LL); ++ hrtimer_start(&rq->hrtick_timer, ns_to_ktime(delay), ++ HRTIMER_MODE_REL_PINNED_HARD); ++} ++#endif /* CONFIG_SMP */ ++ ++static void hrtick_rq_init(struct rq *rq) ++{ ++#ifdef CONFIG_SMP ++ rq->hrtick_csd_pending = 0; ++ ++ rq->hrtick_csd.flags = 0; ++ rq->hrtick_csd.func = __hrtick_start; ++ rq->hrtick_csd.info = rq; ++#endif ++ ++ hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD); ++ rq->hrtick_timer.function = hrtick; ++} ++#else /* CONFIG_SCHED_HRTICK */ ++static inline int hrtick_enabled(struct rq *rq) ++{ ++ return 0; ++} ++ ++static inline void hrtick_clear(struct rq *rq) ++{ ++} ++ ++static inline void hrtick_rq_init(struct rq *rq) ++{ ++} ++#endif /* CONFIG_SCHED_HRTICK */ ++ ++static inline int normal_prio(struct task_struct *p) ++{ ++ if (task_has_rt_policy(p)) ++ return MAX_RT_PRIO - 1 - p->rt_priority; ++ ++ return p->static_prio + MAX_PRIORITY_ADJ; ++} ++ ++/* ++ * Calculate the current priority, i.e. the priority ++ * taken into account by the scheduler. This value might ++ * be boosted by RT tasks as it will be RT if the task got ++ * RT-boosted. If not then it returns p->normal_prio. ++ */ ++static int effective_prio(struct task_struct *p) ++{ ++ p->normal_prio = normal_prio(p); ++ /* ++ * If we are RT tasks or we were boosted to RT priority, ++ * keep the priority unchanged. Otherwise, update priority ++ * to the normal priority: ++ */ ++ if (!rt_prio(p->prio)) ++ return p->normal_prio; ++ return p->prio; ++} ++ ++/* ++ * activate_task - move a task to the runqueue. ++ * ++ * Context: rq->lock ++ */ ++static void activate_task(struct task_struct *p, struct rq *rq) ++{ ++ if (task_contributes_to_load(p)) ++ rq->nr_uninterruptible--; ++ enqueue_task(p, rq, ENQUEUE_WAKEUP); ++ p->on_rq = TASK_ON_RQ_QUEUED; ++ cpufreq_update_util(rq, 0); ++} ++ ++/* ++ * deactivate_task - remove a task from the runqueue. ++ * ++ * Context: rq->lock ++ */ ++static inline void deactivate_task(struct task_struct *p, struct rq *rq) ++{ ++ if (task_contributes_to_load(p)) ++ rq->nr_uninterruptible++; ++ dequeue_task(p, rq, DEQUEUE_SLEEP); ++ p->on_rq = 0; ++ cpufreq_update_util(rq, 0); ++} ++ ++static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu) ++{ ++#ifdef CONFIG_SMP ++ /* ++ * After ->cpu is set up to a new value, task_access_lock(p, ...) can be ++ * successfully executed on another CPU. We must ensure that updates of ++ * per-task data have been completed by this moment. ++ */ ++ smp_wmb(); ++ ++#ifdef CONFIG_THREAD_INFO_IN_TASK ++ WRITE_ONCE(p->cpu, cpu); ++#else ++ WRITE_ONCE(task_thread_info(p)->cpu, cpu); ++#endif ++#endif ++} ++ ++#ifdef CONFIG_SMP ++void set_task_cpu(struct task_struct *p, unsigned int new_cpu) ++{ ++#ifdef CONFIG_SCHED_DEBUG ++ /* ++ * We should never call set_task_cpu() on a blocked task, ++ * ttwu() will sort out the placement. ++ */ ++ WARN_ON_ONCE(p->state != TASK_RUNNING && p->state != TASK_WAKING && ++ !p->on_rq); ++#ifdef CONFIG_LOCKDEP ++ /* ++ * The caller should hold either p->pi_lock or rq->lock, when changing ++ * a task's CPU. ->pi_lock for waking tasks, rq->lock for runnable tasks. ++ * ++ * sched_move_task() holds both and thus holding either pins the cgroup, ++ * see task_group(). ++ */ ++ WARN_ON_ONCE(debug_locks && !(lockdep_is_held(&p->pi_lock) || ++ lockdep_is_held(&task_rq(p)->lock))); ++#endif ++ /* ++ * Clearly, migrating tasks to offline CPUs is a fairly daft thing. ++ */ ++ WARN_ON_ONCE(!cpu_online(new_cpu)); ++#endif ++ if (task_cpu(p) == new_cpu) ++ return; ++ trace_sched_migrate_task(p, new_cpu); ++ rseq_migrate(p); ++ perf_event_task_migrate(p); ++ ++ __set_task_cpu(p, new_cpu); ++} ++ ++static inline bool is_per_cpu_kthread(struct task_struct *p) ++{ ++ return ((p->flags & PF_KTHREAD) && (1 == p->nr_cpus_allowed)); ++} ++ ++/* ++ * Per-CPU kthreads are allowed to run on !active && online CPUs, see ++ * __set_cpus_allowed_ptr() and select_fallback_rq(). ++ */ ++static inline bool is_cpu_allowed(struct task_struct *p, int cpu) ++{ ++ if (!cpumask_test_cpu(cpu, p->cpus_ptr)) ++ return false; ++ ++ if (is_per_cpu_kthread(p)) ++ return cpu_online(cpu); ++ ++ return cpu_active(cpu); ++} ++ ++/* ++ * This is how migration works: ++ * ++ * 1) we invoke migration_cpu_stop() on the target CPU using ++ * stop_one_cpu(). ++ * 2) stopper starts to run (implicitly forcing the migrated thread ++ * off the CPU) ++ * 3) it checks whether the migrated task is still in the wrong runqueue. ++ * 4) if it's in the wrong runqueue then the migration thread removes ++ * it and puts it into the right queue. ++ * 5) stopper completes and stop_one_cpu() returns and the migration ++ * is done. ++ */ ++ ++/* ++ * move_queued_task - move a queued task to new rq. ++ * ++ * Returns (locked) new rq. Old rq's lock is released. ++ */ ++static struct rq *move_queued_task(struct rq *rq, struct task_struct *p, int ++ new_cpu) ++{ ++ lockdep_assert_held(&rq->lock); ++ ++ WRITE_ONCE(p->on_rq, TASK_ON_RQ_MIGRATING); ++ dequeue_task(p, rq, 0); ++ set_task_cpu(p, new_cpu); ++ raw_spin_unlock(&rq->lock); ++ ++ rq = cpu_rq(new_cpu); ++ ++ raw_spin_lock(&rq->lock); ++ BUG_ON(task_cpu(p) != new_cpu); ++ enqueue_task(p, rq, 0); ++ p->on_rq = TASK_ON_RQ_QUEUED; ++ check_preempt_curr(rq); ++ ++ return rq; ++} ++ ++struct migration_arg { ++ struct task_struct *task; ++ int dest_cpu; ++}; ++ ++/* ++ * Move (not current) task off this CPU, onto the destination CPU. We're doing ++ * this because either it can't run here any more (set_cpus_allowed() ++ * away from this CPU, or CPU going down), or because we're ++ * attempting to rebalance this task on exec (sched_exec). ++ * ++ * So we race with normal scheduler movements, but that's OK, as long ++ * as the task is no longer on this CPU. ++ */ ++static struct rq *__migrate_task(struct rq *rq, struct task_struct *p, int ++ dest_cpu) ++{ ++ /* Affinity changed (again). */ ++ if (!is_cpu_allowed(p, dest_cpu)) ++ return rq; ++ ++ update_rq_clock(rq); ++ return move_queued_task(rq, p, dest_cpu); ++} ++ ++/* ++ * migration_cpu_stop - this will be executed by a highprio stopper thread ++ * and performs thread migration by bumping thread off CPU then ++ * 'pushing' onto another runqueue. ++ */ ++static int migration_cpu_stop(void *data) ++{ ++ struct migration_arg *arg = data; ++ struct task_struct *p = arg->task; ++ struct rq *rq = this_rq(); ++ ++ /* ++ * The original target CPU might have gone down and we might ++ * be on another CPU but it doesn't matter. ++ */ ++ local_irq_disable(); ++ ++ raw_spin_lock(&p->pi_lock); ++ raw_spin_lock(&rq->lock); ++ /* ++ * If task_rq(p) != rq, it cannot be migrated here, because we're ++ * holding rq->lock, if p->on_rq == 0 it cannot get enqueued because ++ * we're holding p->pi_lock. ++ */ ++ if (task_rq(p) == rq && task_on_rq_queued(p)) ++ rq = __migrate_task(rq, p, arg->dest_cpu); ++ raw_spin_unlock(&rq->lock); ++ raw_spin_unlock(&p->pi_lock); ++ ++ local_irq_enable(); ++ return 0; ++} ++ ++static inline void ++set_cpus_allowed_common(struct task_struct *p, const struct cpumask *new_mask) ++{ ++ cpumask_copy(&p->cpus_mask, new_mask); ++ p->nr_cpus_allowed = cpumask_weight(new_mask); ++} ++ ++void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask) ++{ ++ set_cpus_allowed_common(p, new_mask); ++} ++#endif ++ ++/* Enter with rq lock held. We know p is on the local CPU */ ++static inline void __set_tsk_resched(struct task_struct *p) ++{ ++ set_tsk_need_resched(p); ++ set_preempt_need_resched(); ++} ++ ++/** ++ * task_curr - is this task currently executing on a CPU? ++ * @p: the task in question. ++ * ++ * Return: 1 if the task is currently executing. 0 otherwise. ++ */ ++inline int task_curr(const struct task_struct *p) ++{ ++ return cpu_curr(task_cpu(p)) == p; ++} ++ ++#ifdef CONFIG_SMP ++/* ++ * wait_task_inactive - wait for a thread to unschedule. ++ * ++ * If @match_state is nonzero, it's the @p->state value just checked and ++ * not expected to change. If it changes, i.e. @p might have woken up, ++ * then return zero. When we succeed in waiting for @p to be off its CPU, ++ * we return a positive number (its total switch count). If a second call ++ * a short while later returns the same number, the caller can be sure that ++ * @p has remained unscheduled the whole time. ++ * ++ * The caller must ensure that the task *will* unschedule sometime soon, ++ * else this function might spin for a *long* time. This function can't ++ * be called with interrupts off, or it may introduce deadlock with ++ * smp_call_function() if an IPI is sent by the same process we are ++ * waiting to become inactive. ++ */ ++unsigned long wait_task_inactive(struct task_struct *p, long match_state) ++{ ++ unsigned long flags; ++ bool running, on_rq; ++ unsigned long ncsw; ++ struct rq *rq; ++ raw_spinlock_t *lock; ++ ++ for (;;) { ++ rq = task_rq(p); ++ ++ /* ++ * If the task is actively running on another CPU ++ * still, just relax and busy-wait without holding ++ * any locks. ++ * ++ * NOTE! Since we don't hold any locks, it's not ++ * even sure that "rq" stays as the right runqueue! ++ * But we don't care, since this will return false ++ * if the runqueue has changed and p is actually now ++ * running somewhere else! ++ */ ++ while (task_running(p) && p == rq->curr) { ++ if (match_state && unlikely(p->state != match_state)) ++ return 0; ++ cpu_relax(); ++ } ++ ++ /* ++ * Ok, time to look more closely! We need the rq ++ * lock now, to be *sure*. If we're wrong, we'll ++ * just go back and repeat. ++ */ ++ task_access_lock_irqsave(p, &lock, &flags); ++ trace_sched_wait_task(p); ++ running = task_running(p); ++ on_rq = p->on_rq; ++ ncsw = 0; ++ if (!match_state || p->state == match_state) ++ ncsw = p->nvcsw | LONG_MIN; /* sets MSB */ ++ task_access_unlock_irqrestore(p, lock, &flags); ++ ++ /* ++ * If it changed from the expected state, bail out now. ++ */ ++ if (unlikely(!ncsw)) ++ break; ++ ++ /* ++ * Was it really running after all now that we ++ * checked with the proper locks actually held? ++ * ++ * Oops. Go back and try again.. ++ */ ++ if (unlikely(running)) { ++ cpu_relax(); ++ continue; ++ } ++ ++ /* ++ * It's not enough that it's not actively running, ++ * it must be off the runqueue _entirely_, and not ++ * preempted! ++ * ++ * So if it was still runnable (but just not actively ++ * running right now), it's preempted, and we should ++ * yield - it could be a while. ++ */ ++ if (unlikely(on_rq)) { ++ ktime_t to = NSEC_PER_SEC / HZ; ++ ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ schedule_hrtimeout(&to, HRTIMER_MODE_REL); ++ continue; ++ } ++ ++ /* ++ * Ahh, all good. It wasn't running, and it wasn't ++ * runnable, which means that it will never become ++ * running in the future either. We're all done! ++ */ ++ break; ++ } ++ ++ return ncsw; ++} ++ ++/*** ++ * kick_process - kick a running thread to enter/exit the kernel ++ * @p: the to-be-kicked thread ++ * ++ * Cause a process which is running on another CPU to enter ++ * kernel-mode, without any delay. (to get signals handled.) ++ * ++ * NOTE: this function doesn't have to take the runqueue lock, ++ * because all it wants to ensure is that the remote task enters ++ * the kernel. If the IPI races and the task has been migrated ++ * to another CPU then no harm is done and the purpose has been ++ * achieved as well. ++ */ ++void kick_process(struct task_struct *p) ++{ ++ int cpu; ++ ++ preempt_disable(); ++ cpu = task_cpu(p); ++ if ((cpu != smp_processor_id()) && task_curr(p)) ++ smp_send_reschedule(cpu); ++ preempt_enable(); ++} ++EXPORT_SYMBOL_GPL(kick_process); ++ ++/* ++ * ->cpus_ptr is protected by both rq->lock and p->pi_lock ++ * ++ * A few notes on cpu_active vs cpu_online: ++ * ++ * - cpu_active must be a subset of cpu_online ++ * ++ * - on CPU-up we allow per-CPU kthreads on the online && !active CPU, ++ * see __set_cpus_allowed_ptr(). At this point the newly online ++ * CPU isn't yet part of the sched domains, and balancing will not ++ * see it. ++ * ++ * - on cpu-down we clear cpu_active() to mask the sched domains and ++ * avoid the load balancer to place new tasks on the to be removed ++ * CPU. Existing tasks will remain running there and will be taken ++ * off. ++ * ++ * This means that fallback selection must not select !active CPUs. ++ * And can assume that any active CPU must be online. Conversely ++ * select_task_rq() below may allow selection of !active CPUs in order ++ * to satisfy the above rules. ++ */ ++static int select_fallback_rq(int cpu, struct task_struct *p) ++{ ++ int nid = cpu_to_node(cpu); ++ const struct cpumask *nodemask = NULL; ++ enum { cpuset, possible, fail } state = cpuset; ++ int dest_cpu; ++ ++ /* ++ * If the node that the CPU is on has been offlined, cpu_to_node() ++ * will return -1. There is no CPU on the node, and we should ++ * select the CPU on the other node. ++ */ ++ if (nid != -1) { ++ nodemask = cpumask_of_node(nid); ++ ++ /* Look for allowed, online CPU in same node. */ ++ for_each_cpu(dest_cpu, nodemask) { ++ if (!cpu_active(dest_cpu)) ++ continue; ++ if (cpumask_test_cpu(dest_cpu, p->cpus_ptr)) ++ return dest_cpu; ++ } ++ } ++ ++ for (;;) { ++ /* Any allowed, online CPU? */ ++ for_each_cpu(dest_cpu, p->cpus_ptr) { ++ if (!is_cpu_allowed(p, dest_cpu)) ++ continue; ++ goto out; ++ } ++ ++ /* No more Mr. Nice Guy. */ ++ switch (state) { ++ case cpuset: ++ if (IS_ENABLED(CONFIG_CPUSETS)) { ++ cpuset_cpus_allowed_fallback(p); ++ state = possible; ++ break; ++ } ++ /* Fall-through */ ++ case possible: ++ do_set_cpus_allowed(p, cpu_possible_mask); ++ state = fail; ++ break; ++ ++ case fail: ++ BUG(); ++ break; ++ } ++ } ++ ++out: ++ if (state != cpuset) { ++ /* ++ * Don't tell them about moving exiting tasks or ++ * kernel threads (both mm NULL), since they never ++ * leave kernel. ++ */ ++ if (p->mm && printk_ratelimit()) { ++ printk_deferred("process %d (%s) no longer affine to cpu%d\n", ++ task_pid_nr(p), p->comm, cpu); ++ } ++ } ++ ++ return dest_cpu; ++} ++ ++static inline int __best_mask_cpu(int cpu, const cpumask_t *cpumask) ++{ ++ cpumask_t *mask = &(per_cpu(sched_cpu_affinity_masks, cpu)[0]); ++ while ((cpu = cpumask_any_and(cpumask, mask)) >= nr_cpu_ids) ++ mask++; ++ return cpu; ++} ++ ++static inline int best_mask_cpu(int cpu, const cpumask_t *cpumask) ++{ ++ return cpumask_test_cpu(cpu, cpumask)? cpu:__best_mask_cpu(cpu, cpumask); ++} ++ ++/* ++ * wake flags ++ */ ++#define WF_SYNC 0x01 /* waker goes to sleep after wakeup */ ++#define WF_FORK 0x02 /* child wakeup after fork */ ++#define WF_MIGRATED 0x04 /* internal use, task got migrated */ ++ ++static inline int select_task_rq(struct task_struct *p) ++{ ++ cpumask_t chk_mask, tmp; ++ ++ if (unlikely(!cpumask_and(&chk_mask, p->cpus_ptr, cpu_online_mask))) ++ return select_fallback_rq(task_cpu(p), p); ++ ++ if ( ++#ifdef CONFIG_SCHED_SMT ++ cpumask_and(&tmp, &chk_mask, &sched_sg_idle_mask) || ++#endif ++ cpumask_and(&tmp, &chk_mask, &sched_rq_watermark[IDLE_WM]) || ++ cpumask_and(&tmp, &chk_mask, ++ &sched_rq_watermark[task_sched_prio(p) + 1])) ++ return best_mask_cpu(task_cpu(p), &tmp); ++ ++ return best_mask_cpu(task_cpu(p), &chk_mask); ++} ++#else /* CONFIG_SMP */ ++static inline int select_task_rq(struct task_struct *p) ++{ ++ return 0; ++} ++#endif /* CONFIG_SMP */ ++ ++static void ++ttwu_stat(struct task_struct *p, int cpu, int wake_flags) ++{ ++ struct rq *rq; ++ ++ if (!schedstat_enabled()) ++ return; ++ ++ rq= this_rq(); ++ ++#ifdef CONFIG_SMP ++ if (cpu == rq->cpu) ++ __schedstat_inc(rq->ttwu_local); ++ else { ++ /** BMQ ToDo: ++ * How to do ttwu_wake_remote ++ */ ++ } ++#endif /* CONFIG_SMP */ ++ ++ __schedstat_inc(rq->ttwu_count); ++} ++ ++/* ++ * Mark the task runnable and perform wakeup-preemption. ++ */ ++static inline void ++ttwu_do_wakeup(struct rq *rq, struct task_struct *p, int wake_flags) ++{ ++ p->state = TASK_RUNNING; ++ trace_sched_wakeup(p); ++} ++ ++static inline void ++ttwu_do_activate(struct rq *rq, struct task_struct *p, int wake_flags) ++{ ++#ifdef CONFIG_SMP ++ if (p->sched_contributes_to_load) ++ rq->nr_uninterruptible--; ++#endif ++ ++ activate_task(p, rq); ++ ttwu_do_wakeup(rq, p, 0); ++} ++ ++static inline void ttwu_queue(struct task_struct *p, int cpu, int wake_flags) ++{ ++ struct rq *rq = cpu_rq(cpu); ++ ++ raw_spin_lock(&rq->lock); ++ update_rq_clock(rq); ++ ttwu_do_activate(rq, p, wake_flags); ++ check_preempt_curr(rq); ++ raw_spin_unlock(&rq->lock); ++} ++ ++static int ttwu_remote(struct task_struct *p, int wake_flags) ++{ ++ struct rq *rq; ++ raw_spinlock_t *lock; ++ int ret = 0; ++ ++ rq = __task_access_lock(p, &lock); ++ if (task_on_rq_queued(p)) { ++ ttwu_do_wakeup(rq, p, wake_flags); ++ ret = 1; ++ } ++ __task_access_unlock(p, lock); ++ ++ return ret; ++} ++ ++/* ++ * Notes on Program-Order guarantees on SMP systems. ++ * ++ * MIGRATION ++ * ++ * The basic program-order guarantee on SMP systems is that when a task [t] ++ * migrates, all its activity on its old CPU [c0] happens-before any subsequent ++ * execution on its new CPU [c1]. ++ * ++ * For migration (of runnable tasks) this is provided by the following means: ++ * ++ * A) UNLOCK of the rq(c0)->lock scheduling out task t ++ * B) migration for t is required to synchronize *both* rq(c0)->lock and ++ * rq(c1)->lock (if not at the same time, then in that order). ++ * C) LOCK of the rq(c1)->lock scheduling in task ++ * ++ * Transitivity guarantees that B happens after A and C after B. ++ * Note: we only require RCpc transitivity. ++ * Note: the CPU doing B need not be c0 or c1 ++ * ++ * Example: ++ * ++ * CPU0 CPU1 CPU2 ++ * ++ * LOCK rq(0)->lock ++ * sched-out X ++ * sched-in Y ++ * UNLOCK rq(0)->lock ++ * ++ * LOCK rq(0)->lock // orders against CPU0 ++ * dequeue X ++ * UNLOCK rq(0)->lock ++ * ++ * LOCK rq(1)->lock ++ * enqueue X ++ * UNLOCK rq(1)->lock ++ * ++ * LOCK rq(1)->lock // orders against CPU2 ++ * sched-out Z ++ * sched-in X ++ * UNLOCK rq(1)->lock ++ * ++ * ++ * BLOCKING -- aka. SLEEP + WAKEUP ++ * ++ * For blocking we (obviously) need to provide the same guarantee as for ++ * migration. However the means are completely different as there is no lock ++ * chain to provide order. Instead we do: ++ * ++ * 1) smp_store_release(X->on_cpu, 0) ++ * 2) smp_cond_load_acquire(!X->on_cpu) ++ * ++ * Example: ++ * ++ * CPU0 (schedule) CPU1 (try_to_wake_up) CPU2 (schedule) ++ * ++ * LOCK rq(0)->lock LOCK X->pi_lock ++ * dequeue X ++ * sched-out X ++ * smp_store_release(X->on_cpu, 0); ++ * ++ * smp_cond_load_acquire(&X->on_cpu, !VAL); ++ * X->state = WAKING ++ * set_task_cpu(X,2) ++ * ++ * LOCK rq(2)->lock ++ * enqueue X ++ * X->state = RUNNING ++ * UNLOCK rq(2)->lock ++ * ++ * LOCK rq(2)->lock // orders against CPU1 ++ * sched-out Z ++ * sched-in X ++ * UNLOCK rq(2)->lock ++ * ++ * UNLOCK X->pi_lock ++ * UNLOCK rq(0)->lock ++ * ++ * ++ * However; for wakeups there is a second guarantee we must provide, namely we ++ * must observe the state that lead to our wakeup. That is, not only must our ++ * task observe its own prior state, it must also observe the stores prior to ++ * its wakeup. ++ * ++ * This means that any means of doing remote wakeups must order the CPU doing ++ * the wakeup against the CPU the task is going to end up running on. This, ++ * however, is already required for the regular Program-Order guarantee above, ++ * since the waking CPU is the one issueing the ACQUIRE (smp_cond_load_acquire). ++ * ++ */ ++ ++/*** ++ * try_to_wake_up - wake up a thread ++ * @p: the thread to be awakened ++ * @state: the mask of task states that can be woken ++ * @wake_flags: wake modifier flags (WF_*) ++ * ++ * Put it on the run-queue if it's not already there. The "current" ++ * thread is always on the run-queue (except when the actual ++ * re-schedule is in progress), and as such you're allowed to do ++ * the simpler "current->state = TASK_RUNNING" to mark yourself ++ * runnable without the overhead of this. ++ * ++ * Return: %true if @p was woken up, %false if it was already running. ++ * or @state didn't match @p's state. ++ */ ++static int try_to_wake_up(struct task_struct *p, unsigned int state, ++ int wake_flags) ++{ ++ unsigned long flags; ++ int cpu, success = 0; ++ ++ preempt_disable(); ++ if (p == current) { ++ /* ++ * We're waking current, this means 'p->on_rq' and 'task_cpu(p) ++ * == smp_processor_id()'. Together this means we can special ++ * case the whole 'p->on_rq && ttwu_remote()' case below ++ * without taking any locks. ++ * ++ * In particular: ++ * - we rely on Program-Order guarantees for all the ordering, ++ * - we're serialized against set_special_state() by virtue of ++ * it disabling IRQs (this allows not taking ->pi_lock). ++ */ ++ if (!(p->state & state)) ++ goto out; ++ ++ success = 1; ++ cpu = task_cpu(p); ++ trace_sched_waking(p); ++ p->state = TASK_RUNNING; ++ trace_sched_wakeup(p); ++ goto out; ++ } ++ ++ /* ++ * If we are going to wake up a thread waiting for CONDITION we ++ * need to ensure that CONDITION=1 done by the caller can not be ++ * reordered with p->state check below. This pairs with mb() in ++ * set_current_state() the waiting thread does. ++ */ ++ raw_spin_lock_irqsave(&p->pi_lock, flags); ++ smp_mb__after_spinlock(); ++ if (!(p->state & state)) ++ goto unlock; ++ ++ trace_sched_waking(p); ++ ++ /* We're going to change ->state: */ ++ success = 1; ++ cpu = task_cpu(p); ++ ++ /* ++ * Ensure we load p->on_rq _after_ p->state, otherwise it would ++ * be possible to, falsely, observe p->on_rq == 0 and get stuck ++ * in smp_cond_load_acquire() below. ++ * ++ * sched_ttwu_pending() try_to_wake_up() ++ * STORE p->on_rq = 1 LOAD p->state ++ * UNLOCK rq->lock ++ * ++ * __schedule() (switch to task 'p') ++ * LOCK rq->lock smp_rmb(); ++ * smp_mb__after_spinlock(); ++ * UNLOCK rq->lock ++ * ++ * [task p] ++ * STORE p->state = UNINTERRUPTIBLE LOAD p->on_rq ++ * ++ * Pairs with the LOCK+smp_mb__after_spinlock() on rq->lock in ++ * __schedule(). See the comment for smp_mb__after_spinlock(). ++ */ ++ smp_rmb(); ++ if (p->on_rq && ttwu_remote(p, wake_flags)) ++ goto unlock; ++ ++#ifdef CONFIG_SMP ++ /* ++ * Ensure we load p->on_cpu _after_ p->on_rq, otherwise it would be ++ * possible to, falsely, observe p->on_cpu == 0. ++ * ++ * One must be running (->on_cpu == 1) in order to remove oneself ++ * from the runqueue. ++ * ++ * __schedule() (switch to task 'p') try_to_wake_up() ++ * STORE p->on_cpu = 1 LOAD p->on_rq ++ * UNLOCK rq->lock ++ * ++ * __schedule() (put 'p' to sleep) ++ * LOCK rq->lock smp_rmb(); ++ * smp_mb__after_spinlock(); ++ * STORE p->on_rq = 0 LOAD p->on_cpu ++ * ++ * Pairs with the LOCK+smp_mb__after_spinlock() on rq->lock in ++ * __schedule(). See the comment for smp_mb__after_spinlock(). ++ */ ++ smp_rmb(); ++ ++ /* ++ * If the owning (remote) CPU is still in the middle of schedule() with ++ * this task as prev, wait until its done referencing the task. ++ * ++ * Pairs with the smp_store_release() in finish_task(). ++ * ++ * This ensures that tasks getting woken will be fully ordered against ++ * their previous state and preserve Program Order. ++ */ ++ smp_cond_load_acquire(&p->on_cpu, !VAL); ++ ++ p->sched_contributes_to_load = !!task_contributes_to_load(p); ++ p->state = TASK_WAKING; ++ ++ if (p->in_iowait) { ++ delayacct_blkio_end(p); ++ atomic_dec(&task_rq(p)->nr_iowait); ++ } ++ ++ if(cpu_rq(smp_processor_id())->clock - p->last_ran > SCHED_TIMESLICE_NS) ++ boost_task(p); ++ ++ cpu = select_task_rq(p); ++ ++ if (cpu != task_cpu(p)) { ++ wake_flags |= WF_MIGRATED; ++ psi_ttwu_dequeue(p); ++ set_task_cpu(p, cpu); ++ } ++#else /* CONFIG_SMP */ ++ if (p->in_iowait) { ++ delayacct_blkio_end(p); ++ atomic_dec(&task_rq(p)->nr_iowait); ++ } ++#endif /* CONFIG_SMP */ ++ ++ ttwu_queue(p, cpu, wake_flags); ++unlock: ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++out: ++ if (success) ++ ttwu_stat(p, cpu, wake_flags); ++ preempt_enable(); ++ ++ return success; ++} ++ ++/** ++ * wake_up_process - Wake up a specific process ++ * @p: The process to be woken up. ++ * ++ * Attempt to wake up the nominated process and move it to the set of runnable ++ * processes. ++ * ++ * Return: 1 if the process was woken up, 0 if it was already running. ++ * ++ * This function executes a full memory barrier before accessing the task state. ++ */ ++int wake_up_process(struct task_struct *p) ++{ ++ return try_to_wake_up(p, TASK_NORMAL, 0); ++} ++EXPORT_SYMBOL(wake_up_process); ++ ++int wake_up_state(struct task_struct *p, unsigned int state) ++{ ++ return try_to_wake_up(p, state, 0); ++} ++ ++/* ++ * Perform scheduler related setup for a newly forked process p. ++ * p is forked by current. ++ */ ++int sched_fork(unsigned long __maybe_unused clone_flags, struct task_struct *p) ++{ ++ unsigned long flags; ++ int cpu = get_cpu(); ++ struct rq *rq = this_rq(); ++ ++#ifdef CONFIG_PREEMPT_NOTIFIERS ++ INIT_HLIST_HEAD(&p->preempt_notifiers); ++#endif ++ /* Should be reset in fork.c but done here for ease of BMQ patching */ ++ p->on_cpu = ++ p->on_rq = ++ p->utime = ++ p->stime = ++ p->sched_time = 0; ++ ++#ifdef CONFIG_COMPACTION ++ p->capture_control = NULL; ++#endif ++ ++ /* ++ * We mark the process as NEW here. This guarantees that ++ * nobody will actually run it, and a signal or other external ++ * event cannot wake it up and insert it on the runqueue either. ++ */ ++ p->state = TASK_NEW; ++ ++ /* ++ * Make sure we do not leak PI boosting priority to the child. ++ */ ++ p->prio = current->normal_prio; ++ ++ /* ++ * Revert to default priority/policy on fork if requested. ++ */ ++ if (unlikely(p->sched_reset_on_fork)) { ++ if (task_has_rt_policy(p)) { ++ p->policy = SCHED_NORMAL; ++ p->static_prio = NICE_TO_PRIO(0); ++ p->rt_priority = 0; ++ } else if (PRIO_TO_NICE(p->static_prio) < 0) ++ p->static_prio = NICE_TO_PRIO(0); ++ ++ p->prio = p->normal_prio = normal_prio(p); ++ ++ /* ++ * We don't need the reset flag anymore after the fork. It has ++ * fulfilled its duty: ++ */ ++ p->sched_reset_on_fork = 0; ++ } ++ ++ p->boost_prio = (p->boost_prio < 0) ? ++ p->boost_prio + MAX_PRIORITY_ADJ : MAX_PRIORITY_ADJ; ++ /* ++ * Share the timeslice between parent and child, thus the ++ * total amount of pending timeslices in the system doesn't change, ++ * resulting in more scheduling fairness. ++ */ ++ raw_spin_lock_irqsave(&rq->lock, flags); ++ rq->curr->time_slice /= 2; ++ p->time_slice = rq->curr->time_slice; ++#ifdef CONFIG_SCHED_HRTICK ++ hrtick_start(rq, rq->curr->time_slice); ++#endif ++ ++ if (p->time_slice < RESCHED_NS) { ++ p->time_slice = SCHED_TIMESLICE_NS; ++ resched_curr(rq); ++ } ++ raw_spin_unlock_irqrestore(&rq->lock, flags); ++ ++ /* ++ * The child is not yet in the pid-hash so no cgroup attach races, ++ * and the cgroup is pinned to this child due to cgroup_fork() ++ * is ran before sched_fork(). ++ * ++ * Silence PROVE_RCU. ++ */ ++ raw_spin_lock_irqsave(&p->pi_lock, flags); ++ /* ++ * We're setting the CPU for the first time, we don't migrate, ++ * so use __set_task_cpu(). ++ */ ++ __set_task_cpu(p, cpu); ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++ ++#ifdef CONFIG_SCHED_INFO ++ if (unlikely(sched_info_on())) ++ memset(&p->sched_info, 0, sizeof(p->sched_info)); ++#endif ++ init_task_preempt_count(p); ++ ++ put_cpu(); ++ return 0; ++} ++ ++#ifdef CONFIG_SCHEDSTATS ++ ++DEFINE_STATIC_KEY_FALSE(sched_schedstats); ++static bool __initdata __sched_schedstats = false; ++ ++static void set_schedstats(bool enabled) ++{ ++ if (enabled) ++ static_branch_enable(&sched_schedstats); ++ else ++ static_branch_disable(&sched_schedstats); ++} ++ ++void force_schedstat_enabled(void) ++{ ++ if (!schedstat_enabled()) { ++ pr_info("kernel profiling enabled schedstats, disable via kernel.sched_schedstats.\n"); ++ static_branch_enable(&sched_schedstats); ++ } ++} ++ ++static int __init setup_schedstats(char *str) ++{ ++ int ret = 0; ++ if (!str) ++ goto out; ++ ++ /* ++ * This code is called before jump labels have been set up, so we can't ++ * change the static branch directly just yet. Instead set a temporary ++ * variable so init_schedstats() can do it later. ++ */ ++ if (!strcmp(str, "enable")) { ++ __sched_schedstats = true; ++ ret = 1; ++ } else if (!strcmp(str, "disable")) { ++ __sched_schedstats = false; ++ ret = 1; ++ } ++out: ++ if (!ret) ++ pr_warn("Unable to parse schedstats=\n"); ++ ++ return ret; ++} ++__setup("schedstats=", setup_schedstats); ++ ++static void __init init_schedstats(void) ++{ ++ set_schedstats(__sched_schedstats); ++} ++ ++#ifdef CONFIG_PROC_SYSCTL ++int sysctl_schedstats(struct ctl_table *table, int write, ++ void __user *buffer, size_t *lenp, loff_t *ppos) ++{ ++ struct ctl_table t; ++ int err; ++ int state = static_branch_likely(&sched_schedstats); ++ ++ if (write && !capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ ++ t = *table; ++ t.data = &state; ++ err = proc_dointvec_minmax(&t, write, buffer, lenp, ppos); ++ if (err < 0) ++ return err; ++ if (write) ++ set_schedstats(state); ++ return err; ++} ++#endif /* CONFIG_PROC_SYSCTL */ ++#else /* !CONFIG_SCHEDSTATS */ ++static inline void init_schedstats(void) {} ++#endif /* CONFIG_SCHEDSTATS */ ++ ++/* ++ * wake_up_new_task - wake up a newly created task for the first time. ++ * ++ * This function will do some initial scheduler statistics housekeeping ++ * that must be done for every newly created context, then puts the task ++ * on the runqueue and wakes it. ++ */ ++void wake_up_new_task(struct task_struct *p) ++{ ++ unsigned long flags; ++ struct rq *rq; ++ ++ raw_spin_lock_irqsave(&p->pi_lock, flags); ++ ++ p->state = TASK_RUNNING; ++ ++ rq = cpu_rq(select_task_rq(p)); ++#ifdef CONFIG_SMP ++ /* ++ * Fork balancing, do it here and not earlier because: ++ * - cpus_ptr can change in the fork path ++ * - any previously selected CPU might disappear through hotplug ++ * Use __set_task_cpu() to avoid calling sched_class::migrate_task_rq, ++ * as we're not fully set-up yet. ++ */ ++ __set_task_cpu(p, cpu_of(rq)); ++#endif ++ ++ raw_spin_lock(&rq->lock); ++ ++ update_rq_clock(rq); ++ activate_task(p, rq); ++ trace_sched_wakeup_new(p); ++ check_preempt_curr(rq); ++ ++ raw_spin_unlock(&rq->lock); ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++} ++ ++#ifdef CONFIG_PREEMPT_NOTIFIERS ++ ++static DEFINE_STATIC_KEY_FALSE(preempt_notifier_key); ++ ++void preempt_notifier_inc(void) ++{ ++ static_branch_inc(&preempt_notifier_key); ++} ++EXPORT_SYMBOL_GPL(preempt_notifier_inc); ++ ++void preempt_notifier_dec(void) ++{ ++ static_branch_dec(&preempt_notifier_key); ++} ++EXPORT_SYMBOL_GPL(preempt_notifier_dec); ++ ++/** ++ * preempt_notifier_register - tell me when current is being preempted & rescheduled ++ * @notifier: notifier struct to register ++ */ ++void preempt_notifier_register(struct preempt_notifier *notifier) ++{ ++ if (!static_branch_unlikely(&preempt_notifier_key)) ++ WARN(1, "registering preempt_notifier while notifiers disabled\n"); ++ ++ hlist_add_head(¬ifier->link, ¤t->preempt_notifiers); ++} ++EXPORT_SYMBOL_GPL(preempt_notifier_register); ++ ++/** ++ * preempt_notifier_unregister - no longer interested in preemption notifications ++ * @notifier: notifier struct to unregister ++ * ++ * This is *not* safe to call from within a preemption notifier. ++ */ ++void preempt_notifier_unregister(struct preempt_notifier *notifier) ++{ ++ hlist_del(¬ifier->link); ++} ++EXPORT_SYMBOL_GPL(preempt_notifier_unregister); ++ ++static void __fire_sched_in_preempt_notifiers(struct task_struct *curr) ++{ ++ struct preempt_notifier *notifier; ++ ++ hlist_for_each_entry(notifier, &curr->preempt_notifiers, link) ++ notifier->ops->sched_in(notifier, raw_smp_processor_id()); ++} ++ ++static __always_inline void fire_sched_in_preempt_notifiers(struct task_struct *curr) ++{ ++ if (static_branch_unlikely(&preempt_notifier_key)) ++ __fire_sched_in_preempt_notifiers(curr); ++} ++ ++static void ++__fire_sched_out_preempt_notifiers(struct task_struct *curr, ++ struct task_struct *next) ++{ ++ struct preempt_notifier *notifier; ++ ++ hlist_for_each_entry(notifier, &curr->preempt_notifiers, link) ++ notifier->ops->sched_out(notifier, next); ++} ++ ++static __always_inline void ++fire_sched_out_preempt_notifiers(struct task_struct *curr, ++ struct task_struct *next) ++{ ++ if (static_branch_unlikely(&preempt_notifier_key)) ++ __fire_sched_out_preempt_notifiers(curr, next); ++} ++ ++#else /* !CONFIG_PREEMPT_NOTIFIERS */ ++ ++static inline void fire_sched_in_preempt_notifiers(struct task_struct *curr) ++{ ++} ++ ++static inline void ++fire_sched_out_preempt_notifiers(struct task_struct *curr, ++ struct task_struct *next) ++{ ++} ++ ++#endif /* CONFIG_PREEMPT_NOTIFIERS */ ++ ++static inline void prepare_task(struct task_struct *next) ++{ ++ /* ++ * Claim the task as running, we do this before switching to it ++ * such that any running task will have this set. ++ */ ++ next->on_cpu = 1; ++} ++ ++static inline void finish_task(struct task_struct *prev) ++{ ++#ifdef CONFIG_SMP ++ /* ++ * After ->on_cpu is cleared, the task can be moved to a different CPU. ++ * We must ensure this doesn't happen until the switch is completely ++ * finished. ++ * ++ * In particular, the load of prev->state in finish_task_switch() must ++ * happen before this. ++ * ++ * Pairs with the smp_cond_load_acquire() in try_to_wake_up(). ++ */ ++ smp_store_release(&prev->on_cpu, 0); ++#else ++ prev->on_cpu = 0; ++#endif ++} ++ ++static inline void ++prepare_lock_switch(struct rq *rq, struct task_struct *next) ++{ ++ /* ++ * Since the runqueue lock will be released by the next ++ * task (which is an invalid locking op but in the case ++ * of the scheduler it's an obvious special-case), so we ++ * do an early lockdep release here: ++ */ ++ spin_release(&rq->lock.dep_map, 1, _THIS_IP_); ++#ifdef CONFIG_DEBUG_SPINLOCK ++ /* this is a valid case when another task releases the spinlock */ ++ rq->lock.owner = next; ++#endif ++} ++ ++static inline void finish_lock_switch(struct rq *rq) ++{ ++ /* ++ * If we are tracking spinlock dependencies then we have to ++ * fix up the runqueue lock - which gets 'carried over' from ++ * prev into current: ++ */ ++ spin_acquire(&rq->lock.dep_map, 0, 0, _THIS_IP_); ++ raw_spin_unlock_irq(&rq->lock); ++} ++ ++/** ++ * prepare_task_switch - prepare to switch tasks ++ * @rq: the runqueue preparing to switch ++ * @next: the task we are going to switch to. ++ * ++ * This is called with the rq lock held and interrupts off. It must ++ * be paired with a subsequent finish_task_switch after the context ++ * switch. ++ * ++ * prepare_task_switch sets up locking and calls architecture specific ++ * hooks. ++ */ ++static inline void ++prepare_task_switch(struct rq *rq, struct task_struct *prev, ++ struct task_struct *next) ++{ ++ kcov_prepare_switch(prev); ++ sched_info_switch(rq, prev, next); ++ perf_event_task_sched_out(prev, next); ++ rseq_preempt(prev); ++ fire_sched_out_preempt_notifiers(prev, next); ++ prepare_task(next); ++ prepare_arch_switch(next); ++} ++ ++/** ++ * finish_task_switch - clean up after a task-switch ++ * @rq: runqueue associated with task-switch ++ * @prev: the thread we just switched away from. ++ * ++ * finish_task_switch must be called after the context switch, paired ++ * with a prepare_task_switch call before the context switch. ++ * finish_task_switch will reconcile locking set up by prepare_task_switch, ++ * and do any other architecture-specific cleanup actions. ++ * ++ * Note that we may have delayed dropping an mm in context_switch(). If ++ * so, we finish that here outside of the runqueue lock. (Doing it ++ * with the lock held can cause deadlocks; see schedule() for ++ * details.) ++ * ++ * The context switch have flipped the stack from under us and restored the ++ * local variables which were saved when this task called schedule() in the ++ * past. prev == current is still correct but we need to recalculate this_rq ++ * because prev may have moved to another CPU. ++ */ ++static struct rq *finish_task_switch(struct task_struct *prev) ++ __releases(rq->lock) ++{ ++ struct rq *rq = this_rq(); ++ struct mm_struct *mm = rq->prev_mm; ++ long prev_state; ++ ++ /* ++ * The previous task will have left us with a preempt_count of 2 ++ * because it left us after: ++ * ++ * schedule() ++ * preempt_disable(); // 1 ++ * __schedule() ++ * raw_spin_lock_irq(&rq->lock) // 2 ++ * ++ * Also, see FORK_PREEMPT_COUNT. ++ */ ++ if (WARN_ONCE(preempt_count() != 2*PREEMPT_DISABLE_OFFSET, ++ "corrupted preempt_count: %s/%d/0x%x\n", ++ current->comm, current->pid, preempt_count())) ++ preempt_count_set(FORK_PREEMPT_COUNT); ++ ++ rq->prev_mm = NULL; ++ ++ /* ++ * A task struct has one reference for the use as "current". ++ * If a task dies, then it sets TASK_DEAD in tsk->state and calls ++ * schedule one last time. The schedule call will never return, and ++ * the scheduled task must drop that reference. ++ * ++ * We must observe prev->state before clearing prev->on_cpu (in ++ * finish_task), otherwise a concurrent wakeup can get prev ++ * running on another CPU and we could rave with its RUNNING -> DEAD ++ * transition, resulting in a double drop. ++ */ ++ prev_state = prev->state; ++ vtime_task_switch(prev); ++ perf_event_task_sched_in(prev, current); ++ finish_task(prev); ++ finish_lock_switch(rq); ++ finish_arch_post_lock_switch(); ++ kcov_finish_switch(current); ++ ++ fire_sched_in_preempt_notifiers(current); ++ /* ++ * When switching through a kernel thread, the loop in ++ * membarrier_{private,global}_expedited() may have observed that ++ * kernel thread and not issued an IPI. It is therefore possible to ++ * schedule between user->kernel->user threads without passing though ++ * switch_mm(). Membarrier requires a barrier after storing to ++ * rq->curr, before returning to userspace, so provide them here: ++ * ++ * - a full memory barrier for {PRIVATE,GLOBAL}_EXPEDITED, implicitly ++ * provided by mmdrop(), ++ * - a sync_core for SYNC_CORE. ++ */ ++ if (mm) { ++ membarrier_mm_sync_core_before_usermode(mm); ++ mmdrop(mm); ++ } ++ if (unlikely(prev_state == TASK_DEAD)) { ++ /* ++ * Remove function-return probe instances associated with this ++ * task and put them back on the free list. ++ */ ++ kprobe_flush_task(prev); ++ ++ /* Task is done with its stack. */ ++ put_task_stack(prev); ++ ++ put_task_struct_rcu_user(prev); ++ } ++ ++ tick_nohz_task_switch(); ++ return rq; ++} ++ ++/** ++ * schedule_tail - first thing a freshly forked thread must call. ++ * @prev: the thread we just switched away from. ++ */ ++asmlinkage __visible void schedule_tail(struct task_struct *prev) ++ __releases(rq->lock) ++{ ++ struct rq *rq; ++ ++ /* ++ * New tasks start with FORK_PREEMPT_COUNT, see there and ++ * finish_task_switch() for details. ++ * ++ * finish_task_switch() will drop rq->lock() and lower preempt_count ++ * and the preempt_enable() will end up enabling preemption (on ++ * PREEMPT_COUNT kernels). ++ */ ++ ++ rq = finish_task_switch(prev); ++ preempt_enable(); ++ ++ if (current->set_child_tid) ++ put_user(task_pid_vnr(current), current->set_child_tid); ++ ++ calculate_sigpending(); ++} ++ ++/* ++ * context_switch - switch to the new MM and the new thread's register state. ++ */ ++static __always_inline struct rq * ++context_switch(struct rq *rq, struct task_struct *prev, ++ struct task_struct *next) ++{ ++ prepare_task_switch(rq, prev, next); ++ ++ /* ++ * For paravirt, this is coupled with an exit in switch_to to ++ * combine the page table reload and the switch backend into ++ * one hypercall. ++ */ ++ arch_start_context_switch(prev); ++ ++ /* ++ * kernel -> kernel lazy + transfer active ++ * user -> kernel lazy + mmgrab() active ++ * ++ * kernel -> user switch + mmdrop() active ++ * user -> user switch ++ */ ++ if (!next->mm) { // to kernel ++ enter_lazy_tlb(prev->active_mm, next); ++ ++ next->active_mm = prev->active_mm; ++ if (prev->mm) // from user ++ mmgrab(prev->active_mm); ++ else ++ prev->active_mm = NULL; ++ } else { // to user ++ membarrier_switch_mm(rq, prev->active_mm, next->mm); ++ /* ++ * sys_membarrier() requires an smp_mb() between setting ++ * rq->curr / membarrier_switch_mm() and returning to userspace. ++ * ++ * The below provides this either through switch_mm(), or in ++ * case 'prev->active_mm == next->mm' through ++ * finish_task_switch()'s mmdrop(). ++ */ ++ switch_mm_irqs_off(prev->active_mm, next->mm, next); ++ ++ if (!prev->mm) { // from kernel ++ /* will mmdrop() in finish_task_switch(). */ ++ rq->prev_mm = prev->active_mm; ++ prev->active_mm = NULL; ++ } ++ } ++ ++ prepare_lock_switch(rq, next); ++ ++ /* Here we just switch the register state and the stack. */ ++ switch_to(prev, next, prev); ++ barrier(); ++ ++ return finish_task_switch(prev); ++} ++ ++/* ++ * nr_running, nr_uninterruptible and nr_context_switches: ++ * ++ * externally visible scheduler statistics: current number of runnable ++ * threads, total number of context switches performed since bootup. ++ */ ++unsigned long nr_running(void) ++{ ++ unsigned long i, sum = 0; ++ ++ for_each_online_cpu(i) ++ sum += cpu_rq(i)->nr_running; ++ ++ return sum; ++} ++ ++/* ++ * Check if only the current task is running on the CPU. ++ * ++ * Caution: this function does not check that the caller has disabled ++ * preemption, thus the result might have a time-of-check-to-time-of-use ++ * race. The caller is responsible to use it correctly, for example: ++ * ++ * - from a non-preemptible section (of course) ++ * ++ * - from a thread that is bound to a single CPU ++ * ++ * - in a loop with very short iterations (e.g. a polling loop) ++ */ ++bool single_task_running(void) ++{ ++ return raw_rq()->nr_running == 1; ++} ++EXPORT_SYMBOL(single_task_running); ++ ++unsigned long long nr_context_switches(void) ++{ ++ int i; ++ unsigned long long sum = 0; ++ ++ for_each_possible_cpu(i) ++ sum += cpu_rq(i)->nr_switches; ++ ++ return sum; ++} ++ ++/* ++ * Consumers of these two interfaces, like for example the cpuidle menu ++ * governor, are using nonsensical data. Preferring shallow idle state selection ++ * for a CPU that has IO-wait which might not even end up running the task when ++ * it does become runnable. ++ */ ++ ++unsigned long nr_iowait_cpu(int cpu) ++{ ++ return atomic_read(&cpu_rq(cpu)->nr_iowait); ++} ++ ++/* ++ * IO-wait accounting, and how its mostly bollocks (on SMP). ++ * ++ * The idea behind IO-wait account is to account the idle time that we could ++ * have spend running if it were not for IO. That is, if we were to improve the ++ * storage performance, we'd have a proportional reduction in IO-wait time. ++ * ++ * This all works nicely on UP, where, when a task blocks on IO, we account ++ * idle time as IO-wait, because if the storage were faster, it could've been ++ * running and we'd not be idle. ++ * ++ * This has been extended to SMP, by doing the same for each CPU. This however ++ * is broken. ++ * ++ * Imagine for instance the case where two tasks block on one CPU, only the one ++ * CPU will have IO-wait accounted, while the other has regular idle. Even ++ * though, if the storage were faster, both could've ran at the same time, ++ * utilising both CPUs. ++ * ++ * This means, that when looking globally, the current IO-wait accounting on ++ * SMP is a lower bound, by reason of under accounting. ++ * ++ * Worse, since the numbers are provided per CPU, they are sometimes ++ * interpreted per CPU, and that is nonsensical. A blocked task isn't strictly ++ * associated with any one particular CPU, it can wake to another CPU than it ++ * blocked on. This means the per CPU IO-wait number is meaningless. ++ * ++ * Task CPU affinities can make all that even more 'interesting'. ++ */ ++ ++unsigned long nr_iowait(void) ++{ ++ unsigned long i, sum = 0; ++ ++ for_each_possible_cpu(i) ++ sum += nr_iowait_cpu(i); ++ ++ return sum; ++} ++ ++DEFINE_PER_CPU(struct kernel_stat, kstat); ++DEFINE_PER_CPU(struct kernel_cpustat, kernel_cpustat); ++ ++EXPORT_PER_CPU_SYMBOL(kstat); ++EXPORT_PER_CPU_SYMBOL(kernel_cpustat); ++ ++static inline void update_curr(struct rq *rq, struct task_struct *p) ++{ ++ s64 ns = rq->clock_task - p->last_ran; ++ ++ p->sched_time += ns; ++ account_group_exec_runtime(p, ns); ++ ++ p->time_slice -= ns; ++ p->last_ran = rq->clock_task; ++} ++ ++/* ++ * Return accounted runtime for the task. ++ * Return separately the current's pending runtime that have not been ++ * accounted yet. ++ */ ++unsigned long long task_sched_runtime(struct task_struct *p) ++{ ++ unsigned long flags; ++ struct rq *rq; ++ raw_spinlock_t *lock; ++ u64 ns; ++ ++#if defined(CONFIG_64BIT) && defined(CONFIG_SMP) ++ /* ++ * 64-bit doesn't need locks to atomically read a 64-bit value. ++ * So we have a optimization chance when the task's delta_exec is 0. ++ * Reading ->on_cpu is racy, but this is ok. ++ * ++ * If we race with it leaving CPU, we'll take a lock. So we're correct. ++ * If we race with it entering CPU, unaccounted time is 0. This is ++ * indistinguishable from the read occurring a few cycles earlier. ++ * If we see ->on_cpu without ->on_rq, the task is leaving, and has ++ * been accounted, so we're correct here as well. ++ */ ++ if (!p->on_cpu || !task_on_rq_queued(p)) ++ return tsk_seruntime(p); ++#endif ++ ++ rq = task_access_lock_irqsave(p, &lock, &flags); ++ /* ++ * Must be ->curr _and_ ->on_rq. If dequeued, we would ++ * project cycles that may never be accounted to this ++ * thread, breaking clock_gettime(). ++ */ ++ if (p == rq->curr && task_on_rq_queued(p)) { ++ update_rq_clock(rq); ++ update_curr(rq, p); ++ } ++ ns = tsk_seruntime(p); ++ task_access_unlock_irqrestore(p, lock, &flags); ++ ++ return ns; ++} ++ ++/* This manages tasks that have run out of timeslice during a scheduler_tick */ ++static inline void scheduler_task_tick(struct rq *rq) ++{ ++ struct task_struct *p = rq->curr; ++ ++ if (is_idle_task(p)) ++ return; ++ ++ update_curr(rq, p); ++ cpufreq_update_util(rq, 0); ++ ++ /* ++ * Tasks have less than RESCHED_NS of time slice left they will be ++ * rescheduled. ++ */ ++ if (p->time_slice >= RESCHED_NS) ++ return; ++ __set_tsk_resched(p); ++} ++ ++#ifdef CONFIG_SCHED_SMT ++static inline int active_load_balance_cpu_stop(void *data) ++{ ++ struct rq *rq = this_rq(); ++ struct task_struct *p = data; ++ cpumask_t tmp; ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ ++ raw_spin_lock(&p->pi_lock); ++ raw_spin_lock(&rq->lock); ++ ++ rq->active_balance = 0; ++ /* _something_ may have changed the task, double check again */ ++ if (task_on_rq_queued(p) && task_rq(p) == rq && ++ cpumask_and(&tmp, p->cpus_ptr, &sched_sg_idle_mask)) ++ rq = move_queued_task(rq, p, __best_mask_cpu(cpu_of(rq), &tmp)); ++ ++ raw_spin_unlock(&rq->lock); ++ raw_spin_unlock(&p->pi_lock); ++ ++ local_irq_restore(flags); ++ ++ return 0; ++} ++ ++/* sg_balance_trigger - trigger slibing group balance for @cpu */ ++static inline int sg_balance_trigger(const int cpu, struct rq *rq) ++{ ++ unsigned long flags; ++ struct task_struct *curr; ++ int res; ++ ++ if (!raw_spin_trylock_irqsave(&rq->lock, flags)) ++ return 0; ++ curr = rq->curr; ++ res = (!is_idle_task(curr)) && (1 == rq->nr_running) &&\ ++ cpumask_intersects(curr->cpus_ptr, &sched_sg_idle_mask) &&\ ++ (!rq->active_balance); ++ ++ if (res) ++ rq->active_balance = 1; ++ ++ raw_spin_unlock_irqrestore(&rq->lock, flags); ++ ++ if (res) ++ stop_one_cpu_nowait(cpu, active_load_balance_cpu_stop, ++ curr, &rq->active_balance_work); ++ return res; ++} ++ ++/* ++ * sg_balance_check - slibing group balance check for run queue @rq ++ */ ++static inline void sg_balance_check(struct rq *rq) ++{ ++ cpumask_t chk; ++ int cpu; ++ ++ /* exit when no sg in idle */ ++ if (cpumask_empty(&sched_sg_idle_mask)) ++ return; ++ ++ cpu = cpu_of(rq); ++ /* Only cpu in slibing idle group will do the checking */ ++ if (cpumask_test_cpu(cpu, &sched_sg_idle_mask)) { ++ /* Find potential cpus which can migrate the currently running task */ ++ if (cpumask_andnot(&chk, cpu_online_mask, &sched_rq_pending_mask) && ++ cpumask_andnot(&chk, &chk, &sched_rq_watermark[IDLE_WM])) { ++ int i, tried = 0; ++ ++ for_each_cpu_wrap(i, &chk, cpu) { ++ /* skip the cpu which has idle slibing cpu */ ++ if (cpumask_intersects(cpu_smt_mask(i), ++ &sched_rq_watermark[IDLE_WM])) ++ continue; ++ if (cpumask_intersects(cpu_smt_mask(i), ++ &sched_rq_pending_mask)) ++ continue; ++ if (sg_balance_trigger(i, cpu_rq(i))) ++ return; ++ if (tried) ++ return; ++ tried++; ++ } ++ } ++ return; ++ } ++ ++ if (1 != rq->nr_running) ++ return; ++ ++ if (cpumask_andnot(&chk, cpu_smt_mask(cpu), &sched_rq_pending_mask) && ++ cpumask_andnot(&chk, &chk, &sched_rq_watermark[IDLE_WM]) && ++ cpumask_equal(&chk, cpu_smt_mask(cpu))) ++ sg_balance_trigger(cpu, rq); ++} ++#endif /* CONFIG_SCHED_SMT */ ++ ++/* ++ * This function gets called by the timer code, with HZ frequency. ++ * We call it with interrupts disabled. ++ */ ++void scheduler_tick(void) ++{ ++ int cpu __maybe_unused = smp_processor_id(); ++ struct rq *rq = cpu_rq(cpu); ++ ++ sched_clock_tick(); ++ ++ raw_spin_lock(&rq->lock); ++ update_rq_clock(rq); ++ ++ scheduler_task_tick(rq); ++ calc_global_load_tick(rq); ++ psi_task_tick(rq); ++ ++ rq->last_tick = rq->clock; ++ raw_spin_unlock(&rq->lock); ++ ++ perf_event_task_tick(); ++} ++ ++#ifdef CONFIG_NO_HZ_FULL ++struct tick_work { ++ int cpu; ++ atomic_t state; ++ struct delayed_work work; ++}; ++/* Values for ->state, see diagram below. */ ++#define TICK_SCHED_REMOTE_OFFLINE 0 ++#define TICK_SCHED_REMOTE_OFFLINING 1 ++#define TICK_SCHED_REMOTE_RUNNING 2 ++ ++/* ++ * State diagram for ->state: ++ * ++ * ++ * TICK_SCHED_REMOTE_OFFLINE ++ * | ^ ++ * | | ++ * | | sched_tick_remote() ++ * | | ++ * | | ++ * +--TICK_SCHED_REMOTE_OFFLINING ++ * | ^ ++ * | | ++ * sched_tick_start() | | sched_tick_stop() ++ * | | ++ * V | ++ * TICK_SCHED_REMOTE_RUNNING ++ * ++ * ++ * Other transitions get WARN_ON_ONCE(), except that sched_tick_remote() ++ * and sched_tick_start() are happy to leave the state in RUNNING. ++ */ ++ ++static struct tick_work __percpu *tick_work_cpu; ++ ++static void sched_tick_remote(struct work_struct *work) ++{ ++ struct delayed_work *dwork = to_delayed_work(work); ++ struct tick_work *twork = container_of(dwork, struct tick_work, work); ++ int cpu = twork->cpu; ++ struct rq *rq = cpu_rq(cpu); ++ struct task_struct *curr; ++ unsigned long flags; ++ u64 delta; ++ int os; ++ ++ /* ++ * Handle the tick only if it appears the remote CPU is running in full ++ * dynticks mode. The check is racy by nature, but missing a tick or ++ * having one too much is no big deal because the scheduler tick updates ++ * statistics and checks timeslices in a time-independent way, regardless ++ * of when exactly it is running. ++ */ ++ if (idle_cpu(cpu) || !tick_nohz_tick_stopped_cpu(cpu)) ++ goto out_requeue; ++ ++ raw_spin_lock_irqsave(&rq->lock, flags); ++ curr = rq->curr; ++ ++ if (is_idle_task(curr) || cpu_is_offline(cpu)) ++ goto out_unlock; ++ ++ update_rq_clock(rq); ++ delta = rq_clock_task(rq) - curr->last_ran; ++ ++ /* ++ * Make sure the next tick runs within a reasonable ++ * amount of time. ++ */ ++ WARN_ON_ONCE(delta > (u64)NSEC_PER_SEC * 3); ++ scheduler_task_tick(rq); ++ ++out_unlock: ++ raw_spin_unlock_irqrestore(&rq->lock, flags); ++ ++out_requeue: ++ /* ++ * Run the remote tick once per second (1Hz). This arbitrary ++ * frequency is large enough to avoid overload but short enough ++ * to keep scheduler internal stats reasonably up to date. But ++ * first update state to reflect hotplug activity if required. ++ */ ++ os = atomic_fetch_add_unless(&twork->state, -1, TICK_SCHED_REMOTE_RUNNING); ++ WARN_ON_ONCE(os == TICK_SCHED_REMOTE_OFFLINE); ++ if (os == TICK_SCHED_REMOTE_RUNNING) ++ queue_delayed_work(system_unbound_wq, dwork, HZ); ++} ++ ++static void sched_tick_start(int cpu) ++{ ++ int os; ++ struct tick_work *twork; ++ ++ if (housekeeping_cpu(cpu, HK_FLAG_TICK)) ++ return; ++ ++ WARN_ON_ONCE(!tick_work_cpu); ++ ++ twork = per_cpu_ptr(tick_work_cpu, cpu); ++ os = atomic_xchg(&twork->state, TICK_SCHED_REMOTE_RUNNING); ++ WARN_ON_ONCE(os == TICK_SCHED_REMOTE_RUNNING); ++ if (os == TICK_SCHED_REMOTE_OFFLINE) { ++ twork->cpu = cpu; ++ INIT_DELAYED_WORK(&twork->work, sched_tick_remote); ++ queue_delayed_work(system_unbound_wq, &twork->work, HZ); ++ } ++} ++ ++#ifdef CONFIG_HOTPLUG_CPU ++static void sched_tick_stop(int cpu) ++{ ++ struct tick_work *twork; ++ ++ if (housekeeping_cpu(cpu, HK_FLAG_TICK)) ++ return; ++ ++ WARN_ON_ONCE(!tick_work_cpu); ++ ++ twork = per_cpu_ptr(tick_work_cpu, cpu); ++ cancel_delayed_work_sync(&twork->work); ++} ++#endif /* CONFIG_HOTPLUG_CPU */ ++ ++int __init sched_tick_offload_init(void) ++{ ++ tick_work_cpu = alloc_percpu(struct tick_work); ++ BUG_ON(!tick_work_cpu); ++ return 0; ++} ++ ++#else /* !CONFIG_NO_HZ_FULL */ ++static inline void sched_tick_start(int cpu) { } ++static inline void sched_tick_stop(int cpu) { } ++#endif ++ ++#if defined(CONFIG_PREEMPTION) && (defined(CONFIG_DEBUG_PREEMPT) || \ ++ defined(CONFIG_PREEMPT_TRACER)) ++/* ++ * If the value passed in is equal to the current preempt count ++ * then we just disabled preemption. Start timing the latency. ++ */ ++static inline void preempt_latency_start(int val) ++{ ++ if (preempt_count() == val) { ++ unsigned long ip = get_lock_parent_ip(); ++#ifdef CONFIG_DEBUG_PREEMPT ++ current->preempt_disable_ip = ip; ++#endif ++ trace_preempt_off(CALLER_ADDR0, ip); ++ } ++} ++ ++void preempt_count_add(int val) ++{ ++#ifdef CONFIG_DEBUG_PREEMPT ++ /* ++ * Underflow? ++ */ ++ if (DEBUG_LOCKS_WARN_ON((preempt_count() < 0))) ++ return; ++#endif ++ __preempt_count_add(val); ++#ifdef CONFIG_DEBUG_PREEMPT ++ /* ++ * Spinlock count overflowing soon? ++ */ ++ DEBUG_LOCKS_WARN_ON((preempt_count() & PREEMPT_MASK) >= ++ PREEMPT_MASK - 10); ++#endif ++ preempt_latency_start(val); ++} ++EXPORT_SYMBOL(preempt_count_add); ++NOKPROBE_SYMBOL(preempt_count_add); ++ ++/* ++ * If the value passed in equals to the current preempt count ++ * then we just enabled preemption. Stop timing the latency. ++ */ ++static inline void preempt_latency_stop(int val) ++{ ++ if (preempt_count() == val) ++ trace_preempt_on(CALLER_ADDR0, get_lock_parent_ip()); ++} ++ ++void preempt_count_sub(int val) ++{ ++#ifdef CONFIG_DEBUG_PREEMPT ++ /* ++ * Underflow? ++ */ ++ if (DEBUG_LOCKS_WARN_ON(val > preempt_count())) ++ return; ++ /* ++ * Is the spinlock portion underflowing? ++ */ ++ if (DEBUG_LOCKS_WARN_ON((val < PREEMPT_MASK) && ++ !(preempt_count() & PREEMPT_MASK))) ++ return; ++#endif ++ ++ preempt_latency_stop(val); ++ __preempt_count_sub(val); ++} ++EXPORT_SYMBOL(preempt_count_sub); ++NOKPROBE_SYMBOL(preempt_count_sub); ++ ++#else ++static inline void preempt_latency_start(int val) { } ++static inline void preempt_latency_stop(int val) { } ++#endif ++ ++/* ++ * Timeslices below RESCHED_NS are considered as good as expired as there's no ++ * point rescheduling when there's so little time left. ++ */ ++static inline void check_curr(struct task_struct *p, struct rq *rq) ++{ ++ if (rq->idle == p) ++ return; ++ ++ update_curr(rq, p); ++ ++ if (p->time_slice < RESCHED_NS) { ++ p->time_slice = SCHED_TIMESLICE_NS; ++ if (SCHED_FIFO != p->policy && task_on_rq_queued(p)) { ++ if (SCHED_RR != p->policy) ++ deboost_task(p); ++ requeue_task(p, rq); ++ } ++ } ++} ++ ++#ifdef CONFIG_SMP ++ ++#define SCHED_RQ_NR_MIGRATION (32UL) ++/* ++ * Migrate pending tasks in @rq to @dest_cpu ++ * Will try to migrate mininal of half of @rq nr_running tasks and ++ * SCHED_RQ_NR_MIGRATION to @dest_cpu ++ */ ++static inline int ++migrate_pending_tasks(struct rq *rq, struct rq *dest_rq, const int dest_cpu) ++{ ++ struct task_struct *p, *skip = rq->curr; ++ int nr_migrated = 0; ++ int nr_tries = min(rq->nr_running / 2, SCHED_RQ_NR_MIGRATION); ++ ++ while (skip != rq->idle && nr_tries && ++ (p = rq_next_bmq_task(skip, rq)) != rq->idle) { ++ skip = rq_next_bmq_task(p, rq); ++ if (cpumask_test_cpu(dest_cpu, p->cpus_ptr)) { ++ dequeue_task(p, rq, 0); ++ set_task_cpu(p, dest_cpu); ++ enqueue_task(p, dest_rq, 0); ++ nr_migrated++; ++ } ++ nr_tries--; ++ } ++ ++ return nr_migrated; ++} ++ ++static inline int take_other_rq_tasks(struct rq *rq, int cpu) ++{ ++ struct cpumask *affinity_mask, *end_mask; ++ ++ if (cpumask_empty(&sched_rq_pending_mask)) ++ return 0; ++ ++ affinity_mask = &(per_cpu(sched_cpu_affinity_masks, cpu)[0]); ++ end_mask = per_cpu(sched_cpu_affinity_end_mask, cpu); ++ do { ++ int i; ++ for_each_cpu_and(i, &sched_rq_pending_mask, affinity_mask) { ++ int nr_migrated; ++ struct rq *src_rq; ++ ++ src_rq = cpu_rq(i); ++ if (!do_raw_spin_trylock(&src_rq->lock)) ++ continue; ++ spin_acquire(&src_rq->lock.dep_map, ++ SINGLE_DEPTH_NESTING, 1, _RET_IP_); ++ ++ nr_migrated = migrate_pending_tasks(src_rq, rq, cpu); ++ ++ spin_release(&src_rq->lock.dep_map, 1, _RET_IP_); ++ do_raw_spin_unlock(&src_rq->lock); ++ ++ if (nr_migrated) { ++ cpufreq_update_util(rq, 0); ++ return 1; ++ } ++ } ++ } while (++affinity_mask < end_mask); ++ ++ return 0; ++} ++#endif ++ ++static inline struct task_struct * ++choose_next_task(struct rq *rq, int cpu, struct task_struct *prev) ++{ ++ struct task_struct *next; ++ ++ if (unlikely(rq->skip)) { ++ next = rq_runnable_task(rq); ++#ifdef CONFIG_SMP ++ if (likely(rq->online)) ++ if (next == rq->idle && take_other_rq_tasks(rq, cpu)) ++ next = rq_runnable_task(rq); ++#endif ++ rq->skip = NULL; ++ return next; ++ } ++ ++ next = rq_first_bmq_task(rq); ++#ifdef CONFIG_SMP ++ if (likely(rq->online)) ++ if (next == rq->idle && take_other_rq_tasks(rq, cpu)) ++ return rq_first_bmq_task(rq); ++#endif ++ return next; ++} ++ ++static inline unsigned long get_preempt_disable_ip(struct task_struct *p) ++{ ++#ifdef CONFIG_DEBUG_PREEMPT ++ return p->preempt_disable_ip; ++#else ++ return 0; ++#endif ++} ++ ++/* ++ * Print scheduling while atomic bug: ++ */ ++static noinline void __schedule_bug(struct task_struct *prev) ++{ ++ /* Save this before calling printk(), since that will clobber it */ ++ unsigned long preempt_disable_ip = get_preempt_disable_ip(current); ++ ++ if (oops_in_progress) ++ return; ++ ++ printk(KERN_ERR "BUG: scheduling while atomic: %s/%d/0x%08x\n", ++ prev->comm, prev->pid, preempt_count()); ++ ++ debug_show_held_locks(prev); ++ print_modules(); ++ if (irqs_disabled()) ++ print_irqtrace_events(prev); ++ if (IS_ENABLED(CONFIG_DEBUG_PREEMPT) ++ && in_atomic_preempt_off()) { ++ pr_err("Preemption disabled at:"); ++ print_ip_sym(preempt_disable_ip); ++ pr_cont("\n"); ++ } ++ if (panic_on_warn) ++ panic("scheduling while atomic\n"); ++ ++ dump_stack(); ++ add_taint(TAINT_WARN, LOCKDEP_STILL_OK); ++} ++ ++/* ++ * Various schedule()-time debugging checks and statistics: ++ */ ++static inline void schedule_debug(struct task_struct *prev, bool preempt) ++{ ++#ifdef CONFIG_SCHED_STACK_END_CHECK ++ if (task_stack_end_corrupted(prev)) ++ panic("corrupted stack end detected inside scheduler\n"); ++#endif ++ ++#ifdef CONFIG_DEBUG_ATOMIC_SLEEP ++ if (!preempt && prev->state && prev->non_block_count) { ++ printk(KERN_ERR "BUG: scheduling in a non-blocking section: %s/%d/%i\n", ++ prev->comm, prev->pid, prev->non_block_count); ++ dump_stack(); ++ add_taint(TAINT_WARN, LOCKDEP_STILL_OK); ++ } ++#endif ++ ++ if (unlikely(in_atomic_preempt_off())) { ++ __schedule_bug(prev); ++ preempt_count_set(PREEMPT_DISABLED); ++ } ++ rcu_sleep_check(); ++ ++ profile_hit(SCHED_PROFILING, __builtin_return_address(0)); ++ ++ schedstat_inc(this_rq()->sched_count); ++} ++ ++static inline void set_rq_task(struct rq *rq, struct task_struct *p) ++{ ++ p->last_ran = rq->clock_task; ++ ++ if (unlikely(SCHED_TIMESLICE_NS == p->time_slice)) ++ rq->last_ts_switch = rq->clock; ++#ifdef CONFIG_HIGH_RES_TIMERS ++ if (p != rq->idle) ++ hrtick_start(rq, p->time_slice); ++#endif ++} ++ ++/* ++ * schedule() is the main scheduler function. ++ * ++ * The main means of driving the scheduler and thus entering this function are: ++ * ++ * 1. Explicit blocking: mutex, semaphore, waitqueue, etc. ++ * ++ * 2. TIF_NEED_RESCHED flag is checked on interrupt and userspace return ++ * paths. For example, see arch/x86/entry_64.S. ++ * ++ * To drive preemption between tasks, the scheduler sets the flag in timer ++ * interrupt handler scheduler_tick(). ++ * ++ * 3. Wakeups don't really cause entry into schedule(). They add a ++ * task to the run-queue and that's it. ++ * ++ * Now, if the new task added to the run-queue preempts the current ++ * task, then the wakeup sets TIF_NEED_RESCHED and schedule() gets ++ * called on the nearest possible occasion: ++ * ++ * - If the kernel is preemptible (CONFIG_PREEMPTION=y): ++ * ++ * - in syscall or exception context, at the next outmost ++ * preempt_enable(). (this might be as soon as the wake_up()'s ++ * spin_unlock()!) ++ * ++ * - in IRQ context, return from interrupt-handler to ++ * preemptible context ++ * ++ * - If the kernel is not preemptible (CONFIG_PREEMPTION is not set) ++ * then at the next: ++ * ++ * - cond_resched() call ++ * - explicit schedule() call ++ * - return from syscall or exception to user-space ++ * - return from interrupt-handler to user-space ++ * ++ * WARNING: must be called with preemption disabled! ++ */ ++static void __sched notrace __schedule(bool preempt) ++{ ++ struct task_struct *prev, *next; ++ unsigned long *switch_count; ++ struct rq *rq; ++ int cpu; ++ ++ cpu = smp_processor_id(); ++ rq = cpu_rq(cpu); ++ prev = rq->curr; ++ ++ schedule_debug(prev, preempt); ++ ++ /* by passing sched_feat(HRTICK) checking which BMQ doesn't support */ ++ hrtick_clear(rq); ++ ++ local_irq_disable(); ++ rcu_note_context_switch(preempt); ++ ++ /* ++ * Make sure that signal_pending_state()->signal_pending() below ++ * can't be reordered with __set_current_state(TASK_INTERRUPTIBLE) ++ * done by the caller to avoid the race with signal_wake_up(). ++ * ++ * The membarrier system call requires a full memory barrier ++ * after coming from user-space, before storing to rq->curr. ++ */ ++ raw_spin_lock(&rq->lock); ++ smp_mb__after_spinlock(); ++ ++ update_rq_clock(rq); ++ ++ switch_count = &prev->nivcsw; ++ if (!preempt && prev->state) { ++ if (signal_pending_state(prev->state, prev)) { ++ prev->state = TASK_RUNNING; ++ } else { ++ if (rq_switch_time(rq) < boost_threshold(prev)) ++ boost_task(prev); ++ deactivate_task(prev, rq); ++ ++ if (prev->in_iowait) { ++ atomic_inc(&rq->nr_iowait); ++ delayacct_blkio_start(); ++ } ++ } ++ switch_count = &prev->nvcsw; ++ } ++ ++ clear_tsk_need_resched(prev); ++ clear_preempt_need_resched(); ++ ++ check_curr(prev, rq); ++ ++ next = choose_next_task(rq, cpu, prev); ++ ++ set_rq_task(rq, next); ++ ++ if (prev != next) { ++ if (MAX_PRIO == next->prio) ++ schedstat_inc(rq->sched_goidle); ++ ++ /* ++ * RCU users of rcu_dereference(rq->curr) may not see ++ * changes to task_struct made by pick_next_task(). ++ */ ++ RCU_INIT_POINTER(rq->curr, next); ++ /* ++ * The membarrier system call requires each architecture ++ * to have a full memory barrier after updating ++ * rq->curr, before returning to user-space. ++ * ++ * Here are the schemes providing that barrier on the ++ * various architectures: ++ * - mm ? switch_mm() : mmdrop() for x86, s390, sparc, PowerPC. ++ * switch_mm() rely on membarrier_arch_switch_mm() on PowerPC. ++ * - finish_lock_switch() for weakly-ordered ++ * architectures where spin_unlock is a full barrier, ++ * - switch_to() for arm64 (weakly-ordered, spin_unlock ++ * is a RELEASE barrier), ++ */ ++ ++*switch_count; ++ rq->nr_switches++; ++ rq->last_ts_switch = rq->clock; ++ ++ trace_sched_switch(preempt, prev, next); ++ ++ /* Also unlocks the rq: */ ++ rq = context_switch(rq, prev, next); ++#ifdef CONFIG_SCHED_SMT ++ sg_balance_check(rq); ++#endif ++ } else ++ raw_spin_unlock_irq(&rq->lock); ++} ++ ++void __noreturn do_task_dead(void) ++{ ++ /* Causes final put_task_struct in finish_task_switch(): */ ++ set_special_state(TASK_DEAD); ++ ++ /* Tell freezer to ignore us: */ ++ current->flags |= PF_NOFREEZE; ++ __schedule(false); ++ ++ BUG(); ++ ++ /* Avoid "noreturn function does return" - but don't continue if BUG() is a NOP: */ ++ for (;;) ++ cpu_relax(); ++} ++ ++static inline void sched_submit_work(struct task_struct *tsk) ++{ ++ if (!tsk->state) ++ return; ++ ++ /* ++ * If a worker went to sleep, notify and ask workqueue whether ++ * it wants to wake up a task to maintain concurrency. ++ * As this function is called inside the schedule() context, ++ * we disable preemption to avoid it calling schedule() again ++ * in the possible wakeup of a kworker. ++ */ ++ if (tsk->flags & PF_WQ_WORKER) { ++ preempt_disable(); ++ wq_worker_sleeping(tsk); ++ preempt_enable_no_resched(); ++ } ++ ++ if (tsk_is_pi_blocked(tsk)) ++ return; ++ ++ /* ++ * If we are going to sleep and we have plugged IO queued, ++ * make sure to submit it to avoid deadlocks. ++ */ ++ if (blk_needs_flush_plug(tsk)) ++ blk_schedule_flush_plug(tsk); ++} ++ ++static void sched_update_worker(struct task_struct *tsk) ++{ ++ if (tsk->flags & PF_WQ_WORKER) ++ wq_worker_running(tsk); ++} ++ ++asmlinkage __visible void __sched schedule(void) ++{ ++ struct task_struct *tsk = current; ++ ++ sched_submit_work(tsk); ++ do { ++ preempt_disable(); ++ __schedule(false); ++ sched_preempt_enable_no_resched(); ++ } while (need_resched()); ++ sched_update_worker(tsk); ++} ++EXPORT_SYMBOL(schedule); ++ ++/* ++ * synchronize_rcu_tasks() makes sure that no task is stuck in preempted ++ * state (have scheduled out non-voluntarily) by making sure that all ++ * tasks have either left the run queue or have gone into user space. ++ * As idle tasks do not do either, they must not ever be preempted ++ * (schedule out non-voluntarily). ++ * ++ * schedule_idle() is similar to schedule_preempt_disable() except that it ++ * never enables preemption because it does not call sched_submit_work(). ++ */ ++void __sched schedule_idle(void) ++{ ++ /* ++ * As this skips calling sched_submit_work(), which the idle task does ++ * regardless because that function is a nop when the task is in a ++ * TASK_RUNNING state, make sure this isn't used someplace that the ++ * current task can be in any other state. Note, idle is always in the ++ * TASK_RUNNING state. ++ */ ++ WARN_ON_ONCE(current->state); ++ do { ++ __schedule(false); ++ } while (need_resched()); ++} ++ ++#ifdef CONFIG_CONTEXT_TRACKING ++asmlinkage __visible void __sched schedule_user(void) ++{ ++ /* ++ * If we come here after a random call to set_need_resched(), ++ * or we have been woken up remotely but the IPI has not yet arrived, ++ * we haven't yet exited the RCU idle mode. Do it here manually until ++ * we find a better solution. ++ * ++ * NB: There are buggy callers of this function. Ideally we ++ * should warn if prev_state != CONTEXT_USER, but that will trigger ++ * too frequently to make sense yet. ++ */ ++ enum ctx_state prev_state = exception_enter(); ++ schedule(); ++ exception_exit(prev_state); ++} ++#endif ++ ++/** ++ * schedule_preempt_disabled - called with preemption disabled ++ * ++ * Returns with preemption disabled. Note: preempt_count must be 1 ++ */ ++void __sched schedule_preempt_disabled(void) ++{ ++ sched_preempt_enable_no_resched(); ++ schedule(); ++ preempt_disable(); ++} ++ ++static void __sched notrace preempt_schedule_common(void) ++{ ++ do { ++ /* ++ * Because the function tracer can trace preempt_count_sub() ++ * and it also uses preempt_enable/disable_notrace(), if ++ * NEED_RESCHED is set, the preempt_enable_notrace() called ++ * by the function tracer will call this function again and ++ * cause infinite recursion. ++ * ++ * Preemption must be disabled here before the function ++ * tracer can trace. Break up preempt_disable() into two ++ * calls. One to disable preemption without fear of being ++ * traced. The other to still record the preemption latency, ++ * which can also be traced by the function tracer. ++ */ ++ preempt_disable_notrace(); ++ preempt_latency_start(1); ++ __schedule(true); ++ preempt_latency_stop(1); ++ preempt_enable_no_resched_notrace(); ++ ++ /* ++ * Check again in case we missed a preemption opportunity ++ * between schedule and now. ++ */ ++ } while (need_resched()); ++} ++ ++#ifdef CONFIG_PREEMPTION ++/* ++ * This is the entry point to schedule() from in-kernel preemption ++ * off of preempt_enable. ++ */ ++asmlinkage __visible void __sched notrace preempt_schedule(void) ++{ ++ /* ++ * If there is a non-zero preempt_count or interrupts are disabled, ++ * we do not want to preempt the current task. Just return.. ++ */ ++ if (likely(!preemptible())) ++ return; ++ ++ preempt_schedule_common(); ++} ++NOKPROBE_SYMBOL(preempt_schedule); ++EXPORT_SYMBOL(preempt_schedule); ++ ++/** ++ * preempt_schedule_notrace - preempt_schedule called by tracing ++ * ++ * The tracing infrastructure uses preempt_enable_notrace to prevent ++ * recursion and tracing preempt enabling caused by the tracing ++ * infrastructure itself. But as tracing can happen in areas coming ++ * from userspace or just about to enter userspace, a preempt enable ++ * can occur before user_exit() is called. This will cause the scheduler ++ * to be called when the system is still in usermode. ++ * ++ * To prevent this, the preempt_enable_notrace will use this function ++ * instead of preempt_schedule() to exit user context if needed before ++ * calling the scheduler. ++ */ ++asmlinkage __visible void __sched notrace preempt_schedule_notrace(void) ++{ ++ enum ctx_state prev_ctx; ++ ++ if (likely(!preemptible())) ++ return; ++ ++ do { ++ /* ++ * Because the function tracer can trace preempt_count_sub() ++ * and it also uses preempt_enable/disable_notrace(), if ++ * NEED_RESCHED is set, the preempt_enable_notrace() called ++ * by the function tracer will call this function again and ++ * cause infinite recursion. ++ * ++ * Preemption must be disabled here before the function ++ * tracer can trace. Break up preempt_disable() into two ++ * calls. One to disable preemption without fear of being ++ * traced. The other to still record the preemption latency, ++ * which can also be traced by the function tracer. ++ */ ++ preempt_disable_notrace(); ++ preempt_latency_start(1); ++ /* ++ * Needs preempt disabled in case user_exit() is traced ++ * and the tracer calls preempt_enable_notrace() causing ++ * an infinite recursion. ++ */ ++ prev_ctx = exception_enter(); ++ __schedule(true); ++ exception_exit(prev_ctx); ++ ++ preempt_latency_stop(1); ++ preempt_enable_no_resched_notrace(); ++ } while (need_resched()); ++} ++EXPORT_SYMBOL_GPL(preempt_schedule_notrace); ++ ++#endif /* CONFIG_PREEMPTION */ ++ ++/* ++ * This is the entry point to schedule() from kernel preemption ++ * off of irq context. ++ * Note, that this is called and return with irqs disabled. This will ++ * protect us against recursive calling from irq. ++ */ ++asmlinkage __visible void __sched preempt_schedule_irq(void) ++{ ++ enum ctx_state prev_state; ++ ++ /* Catch callers which need to be fixed */ ++ BUG_ON(preempt_count() || !irqs_disabled()); ++ ++ prev_state = exception_enter(); ++ ++ do { ++ preempt_disable(); ++ local_irq_enable(); ++ __schedule(true); ++ local_irq_disable(); ++ sched_preempt_enable_no_resched(); ++ } while (need_resched()); ++ ++ exception_exit(prev_state); ++} ++ ++int default_wake_function(wait_queue_entry_t *curr, unsigned mode, int wake_flags, ++ void *key) ++{ ++ return try_to_wake_up(curr->private, mode, wake_flags); ++} ++EXPORT_SYMBOL(default_wake_function); ++ ++static inline void check_task_changed(struct rq *rq, struct task_struct *p) ++{ ++ /* Trigger resched if task sched_prio has been modified. */ ++ if (task_on_rq_queued(p) && task_sched_prio(p) != p->bmq_idx) { ++ requeue_task(p, rq); ++ check_preempt_curr(rq); ++ } ++} ++ ++#ifdef CONFIG_RT_MUTEXES ++ ++static inline int __rt_effective_prio(struct task_struct *pi_task, int prio) ++{ ++ if (pi_task) ++ prio = min(prio, pi_task->prio); ++ ++ return prio; ++} ++ ++static inline int rt_effective_prio(struct task_struct *p, int prio) ++{ ++ struct task_struct *pi_task = rt_mutex_get_top_task(p); ++ ++ return __rt_effective_prio(pi_task, prio); ++} ++ ++/* ++ * rt_mutex_setprio - set the current priority of a task ++ * @p: task to boost ++ * @pi_task: donor task ++ * ++ * This function changes the 'effective' priority of a task. It does ++ * not touch ->normal_prio like __setscheduler(). ++ * ++ * Used by the rt_mutex code to implement priority inheritance ++ * logic. Call site only calls if the priority of the task changed. ++ */ ++void rt_mutex_setprio(struct task_struct *p, struct task_struct *pi_task) ++{ ++ int prio; ++ struct rq *rq; ++ raw_spinlock_t *lock; ++ ++ /* XXX used to be waiter->prio, not waiter->task->prio */ ++ prio = __rt_effective_prio(pi_task, p->normal_prio); ++ ++ /* ++ * If nothing changed; bail early. ++ */ ++ if (p->pi_top_task == pi_task && prio == p->prio) ++ return; ++ ++ rq = __task_access_lock(p, &lock); ++ /* ++ * Set under pi_lock && rq->lock, such that the value can be used under ++ * either lock. ++ * ++ * Note that there is loads of tricky to make this pointer cache work ++ * right. rt_mutex_slowunlock()+rt_mutex_postunlock() work together to ++ * ensure a task is de-boosted (pi_task is set to NULL) before the ++ * task is allowed to run again (and can exit). This ensures the pointer ++ * points to a blocked task -- which guaratees the task is present. ++ */ ++ p->pi_top_task = pi_task; ++ ++ /* ++ * For FIFO/RR we only need to set prio, if that matches we're done. ++ */ ++ if (prio == p->prio) ++ goto out_unlock; ++ ++ /* ++ * Idle task boosting is a nono in general. There is one ++ * exception, when PREEMPT_RT and NOHZ is active: ++ * ++ * The idle task calls get_next_timer_interrupt() and holds ++ * the timer wheel base->lock on the CPU and another CPU wants ++ * to access the timer (probably to cancel it). We can safely ++ * ignore the boosting request, as the idle CPU runs this code ++ * with interrupts disabled and will complete the lock ++ * protected section without being interrupted. So there is no ++ * real need to boost. ++ */ ++ if (unlikely(p == rq->idle)) { ++ WARN_ON(p != rq->curr); ++ WARN_ON(p->pi_blocked_on); ++ goto out_unlock; ++ } ++ ++ trace_sched_pi_setprio(p, pi_task); ++ p->prio = prio; ++ ++ check_task_changed(rq, p); ++out_unlock: ++ __task_access_unlock(p, lock); ++} ++#else ++static inline int rt_effective_prio(struct task_struct *p, int prio) ++{ ++ return prio; ++} ++#endif ++ ++void set_user_nice(struct task_struct *p, long nice) ++{ ++ unsigned long flags; ++ struct rq *rq; ++ raw_spinlock_t *lock; ++ ++ if (task_nice(p) == nice || nice < MIN_NICE || nice > MAX_NICE) ++ return; ++ /* ++ * We have to be careful, if called from sys_setpriority(), ++ * the task might be in the middle of scheduling on another CPU. ++ */ ++ raw_spin_lock_irqsave(&p->pi_lock, flags); ++ rq = __task_access_lock(p, &lock); ++ ++ p->static_prio = NICE_TO_PRIO(nice); ++ /* ++ * The RT priorities are set via sched_setscheduler(), but we still ++ * allow the 'normal' nice value to be set - but as expected ++ * it wont have any effect on scheduling until the task is ++ * not SCHED_NORMAL/SCHED_BATCH: ++ */ ++ if (task_has_rt_policy(p)) ++ goto out_unlock; ++ ++ p->prio = effective_prio(p); ++ check_task_changed(rq, p); ++out_unlock: ++ __task_access_unlock(p, lock); ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++} ++EXPORT_SYMBOL(set_user_nice); ++ ++/* ++ * can_nice - check if a task can reduce its nice value ++ * @p: task ++ * @nice: nice value ++ */ ++int can_nice(const struct task_struct *p, const int nice) ++{ ++ /* Convert nice value [19,-20] to rlimit style value [1,40] */ ++ int nice_rlim = nice_to_rlimit(nice); ++ ++ return (nice_rlim <= task_rlimit(p, RLIMIT_NICE) || ++ capable(CAP_SYS_NICE)); ++} ++ ++#ifdef __ARCH_WANT_SYS_NICE ++ ++/* ++ * sys_nice - change the priority of the current process. ++ * @increment: priority increment ++ * ++ * sys_setpriority is a more generic, but much slower function that ++ * does similar things. ++ */ ++SYSCALL_DEFINE1(nice, int, increment) ++{ ++ long nice, retval; ++ ++ /* ++ * Setpriority might change our priority at the same moment. ++ * We don't have to worry. Conceptually one call occurs first ++ * and we have a single winner. ++ */ ++ ++ increment = clamp(increment, -NICE_WIDTH, NICE_WIDTH); ++ nice = task_nice(current) + increment; ++ ++ nice = clamp_val(nice, MIN_NICE, MAX_NICE); ++ if (increment < 0 && !can_nice(current, nice)) ++ return -EPERM; ++ ++ retval = security_task_setnice(current, nice); ++ if (retval) ++ return retval; ++ ++ set_user_nice(current, nice); ++ return 0; ++} ++ ++#endif ++ ++/** ++ * task_prio - return the priority value of a given task. ++ * @p: the task in question. ++ * ++ * Return: The priority value as seen by users in /proc. ++ * RT tasks are offset by -100. Normal tasks are centered around 1, value goes ++ * from 0(SCHED_ISO) up to 82 (nice +19 SCHED_IDLE). ++ */ ++int task_prio(const struct task_struct *p) ++{ ++ if (p->prio < MAX_RT_PRIO) ++ return (p->prio - MAX_RT_PRIO); ++ return (p->prio - MAX_RT_PRIO + p->boost_prio); ++} ++ ++/** ++ * idle_cpu - is a given CPU idle currently? ++ * @cpu: the processor in question. ++ * ++ * Return: 1 if the CPU is currently idle. 0 otherwise. ++ */ ++int idle_cpu(int cpu) ++{ ++ return cpu_curr(cpu) == cpu_rq(cpu)->idle; ++} ++ ++/** ++ * idle_task - return the idle task for a given CPU. ++ * @cpu: the processor in question. ++ * ++ * Return: The idle task for the cpu @cpu. ++ */ ++struct task_struct *idle_task(int cpu) ++{ ++ return cpu_rq(cpu)->idle; ++} ++ ++/** ++ * find_process_by_pid - find a process with a matching PID value. ++ * @pid: the pid in question. ++ * ++ * The task of @pid, if found. %NULL otherwise. ++ */ ++static inline struct task_struct *find_process_by_pid(pid_t pid) ++{ ++ return pid ? find_task_by_vpid(pid) : current; ++} ++ ++#ifdef CONFIG_SMP ++void sched_set_stop_task(int cpu, struct task_struct *stop) ++{ ++ struct sched_param stop_param = { .sched_priority = STOP_PRIO }; ++ struct sched_param start_param = { .sched_priority = 0 }; ++ struct task_struct *old_stop = cpu_rq(cpu)->stop; ++ ++ if (stop) { ++ /* ++ * Make it appear like a SCHED_FIFO task, its something ++ * userspace knows about and won't get confused about. ++ * ++ * Also, it will make PI more or less work without too ++ * much confusion -- but then, stop work should not ++ * rely on PI working anyway. ++ */ ++ sched_setscheduler_nocheck(stop, SCHED_FIFO, &stop_param); ++ } ++ ++ cpu_rq(cpu)->stop = stop; ++ ++ if (old_stop) { ++ /* ++ * Reset it back to a normal scheduling policy so that ++ * it can die in pieces. ++ */ ++ sched_setscheduler_nocheck(old_stop, SCHED_NORMAL, &start_param); ++ } ++} ++ ++/* ++ * Change a given task's CPU affinity. Migrate the thread to a ++ * proper CPU and schedule it away if the CPU it's executing on ++ * is removed from the allowed bitmask. ++ * ++ * NOTE: the caller must have a valid reference to the task, the ++ * task must not exit() & deallocate itself prematurely. The ++ * call is not atomic; no spinlocks may be held. ++ */ ++static int __set_cpus_allowed_ptr(struct task_struct *p, ++ const struct cpumask *new_mask, bool check) ++{ ++ const struct cpumask *cpu_valid_mask = cpu_active_mask; ++ int dest_cpu; ++ unsigned long flags; ++ struct rq *rq; ++ raw_spinlock_t *lock; ++ int ret = 0; ++ ++ raw_spin_lock_irqsave(&p->pi_lock, flags); ++ rq = __task_access_lock(p, &lock); ++ ++ if (p->flags & PF_KTHREAD) { ++ /* ++ * Kernel threads are allowed on online && !active CPUs ++ */ ++ cpu_valid_mask = cpu_online_mask; ++ } ++ ++ /* ++ * Must re-check here, to close a race against __kthread_bind(), ++ * sched_setaffinity() is not guaranteed to observe the flag. ++ */ ++ if (check && (p->flags & PF_NO_SETAFFINITY)) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ if (cpumask_equal(p->cpus_ptr, new_mask)) ++ goto out; ++ ++ dest_cpu = cpumask_any_and(cpu_valid_mask, new_mask); ++ if (dest_cpu >= nr_cpu_ids) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ do_set_cpus_allowed(p, new_mask); ++ ++ if (p->flags & PF_KTHREAD) { ++ /* ++ * For kernel threads that do indeed end up on online && ++ * !active we want to ensure they are strict per-CPU threads. ++ */ ++ WARN_ON(cpumask_intersects(new_mask, cpu_online_mask) && ++ !cpumask_intersects(new_mask, cpu_active_mask) && ++ p->nr_cpus_allowed != 1); ++ } ++ ++ /* Can the task run on the task's current CPU? If so, we're done */ ++ if (cpumask_test_cpu(task_cpu(p), new_mask)) ++ goto out; ++ ++ if (task_running(p) || p->state == TASK_WAKING) { ++ struct migration_arg arg = { p, dest_cpu }; ++ ++ /* Need help from migration thread: drop lock and wait. */ ++ __task_access_unlock(p, lock); ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++ stop_one_cpu(cpu_of(rq), migration_cpu_stop, &arg); ++ return 0; ++ } ++ if (task_on_rq_queued(p)) { ++ /* ++ * OK, since we're going to drop the lock immediately ++ * afterwards anyway. ++ */ ++ update_rq_clock(rq); ++ rq = move_queued_task(rq, p, dest_cpu); ++ lock = &rq->lock; ++ } ++ ++out: ++ __task_access_unlock(p, lock); ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++ ++ return ret; ++} ++ ++int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask) ++{ ++ return __set_cpus_allowed_ptr(p, new_mask, false); ++} ++EXPORT_SYMBOL_GPL(set_cpus_allowed_ptr); ++ ++#else ++static inline int ++__set_cpus_allowed_ptr(struct task_struct *p, ++ const struct cpumask *new_mask, bool check) ++{ ++ return set_cpus_allowed_ptr(p, new_mask); ++} ++#endif ++ ++/* ++ * sched_setparam() passes in -1 for its policy, to let the functions ++ * it calls know not to change it. ++ */ ++#define SETPARAM_POLICY -1 ++ ++static void __setscheduler_params(struct task_struct *p, ++ const struct sched_attr *attr) ++{ ++ int policy = attr->sched_policy; ++ ++ if (policy == SETPARAM_POLICY) ++ policy = p->policy; ++ ++ p->policy = policy; ++ ++ /* ++ * allow normal nice value to be set, but will not have any ++ * effect on scheduling until the task not SCHED_NORMAL/ ++ * SCHED_BATCH ++ */ ++ p->static_prio = NICE_TO_PRIO(attr->sched_nice); ++ ++ /* ++ * __sched_setscheduler() ensures attr->sched_priority == 0 when ++ * !rt_policy. Always setting this ensures that things like ++ * getparam()/getattr() don't report silly values for !rt tasks. ++ */ ++ p->rt_priority = attr->sched_priority; ++ p->normal_prio = normal_prio(p); ++} ++ ++/* Actually do priority change: must hold rq lock. */ ++static void __setscheduler(struct rq *rq, struct task_struct *p, ++ const struct sched_attr *attr, bool keep_boost) ++{ ++ __setscheduler_params(p, attr); ++ ++ /* ++ * Keep a potential priority boosting if called from ++ * sched_setscheduler(). ++ */ ++ p->prio = normal_prio(p); ++ if (keep_boost) ++ p->prio = rt_effective_prio(p, p->prio); ++} ++ ++/* ++ * check the target process has a UID that matches the current process's ++ */ ++static bool check_same_owner(struct task_struct *p) ++{ ++ const struct cred *cred = current_cred(), *pcred; ++ bool match; ++ ++ rcu_read_lock(); ++ pcred = __task_cred(p); ++ match = (uid_eq(cred->euid, pcred->euid) || ++ uid_eq(cred->euid, pcred->uid)); ++ rcu_read_unlock(); ++ return match; ++} ++ ++static int __sched_setscheduler(struct task_struct *p, ++ const struct sched_attr *attr, ++ bool user, bool pi) ++{ ++ const struct sched_attr dl_squash_attr = { ++ .size = sizeof(struct sched_attr), ++ .sched_policy = SCHED_FIFO, ++ .sched_nice = 0, ++ .sched_priority = 99, ++ }; ++ int newprio = MAX_RT_PRIO - 1 - attr->sched_priority; ++ int retval, oldpolicy = -1; ++ int policy = attr->sched_policy; ++ unsigned long flags; ++ struct rq *rq; ++ int reset_on_fork; ++ raw_spinlock_t *lock; ++ ++ /* The pi code expects interrupts enabled */ ++ BUG_ON(pi && in_interrupt()); ++ ++ /* ++ * BMQ supports SCHED_DEADLINE by squash it as prio 0 SCHED_FIFO ++ */ ++ if (unlikely(SCHED_DEADLINE == policy)) { ++ attr = &dl_squash_attr; ++ policy = attr->sched_policy; ++ newprio = MAX_RT_PRIO - 1 - attr->sched_priority; ++ } ++recheck: ++ /* Double check policy once rq lock held */ ++ if (policy < 0) { ++ reset_on_fork = p->sched_reset_on_fork; ++ policy = oldpolicy = p->policy; ++ } else { ++ reset_on_fork = !!(attr->sched_flags & SCHED_RESET_ON_FORK); ++ ++ if (policy > SCHED_IDLE) ++ return -EINVAL; ++ } ++ ++ if (attr->sched_flags & ~(SCHED_FLAG_ALL)) ++ return -EINVAL; ++ ++ /* ++ * Valid priorities for SCHED_FIFO and SCHED_RR are ++ * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL and ++ * SCHED_BATCH and SCHED_IDLE is 0. ++ */ ++ if (attr->sched_priority < 0 || ++ (p->mm && attr->sched_priority > MAX_USER_RT_PRIO - 1) || ++ (!p->mm && attr->sched_priority > MAX_RT_PRIO - 1)) ++ return -EINVAL; ++ if ((SCHED_RR == policy || SCHED_FIFO == policy) != ++ (attr->sched_priority != 0)) ++ return -EINVAL; ++ ++ /* ++ * Allow unprivileged RT tasks to decrease priority: ++ */ ++ if (user && !capable(CAP_SYS_NICE)) { ++ if (SCHED_FIFO == policy || SCHED_RR == policy) { ++ unsigned long rlim_rtprio = ++ task_rlimit(p, RLIMIT_RTPRIO); ++ ++ /* Can't set/change the rt policy */ ++ if (policy != p->policy && !rlim_rtprio) ++ return -EPERM; ++ ++ /* Can't increase priority */ ++ if (attr->sched_priority > p->rt_priority && ++ attr->sched_priority > rlim_rtprio) ++ return -EPERM; ++ } ++ ++ /* Can't change other user's priorities */ ++ if (!check_same_owner(p)) ++ return -EPERM; ++ ++ /* Normal users shall not reset the sched_reset_on_fork flag */ ++ if (p->sched_reset_on_fork && !reset_on_fork) ++ return -EPERM; ++ } ++ ++ if (user) { ++ retval = security_task_setscheduler(p); ++ if (retval) ++ return retval; ++ } ++ ++ if (pi) ++ cpuset_read_lock(); ++ ++ /* ++ * Make sure no PI-waiters arrive (or leave) while we are ++ * changing the priority of the task: ++ */ ++ raw_spin_lock_irqsave(&p->pi_lock, flags); ++ ++ /* ++ * To be able to change p->policy safely, task_access_lock() ++ * must be called. ++ * IF use task_access_lock() here: ++ * For the task p which is not running, reading rq->stop is ++ * racy but acceptable as ->stop doesn't change much. ++ * An enhancemnet can be made to read rq->stop saftly. ++ */ ++ rq = __task_access_lock(p, &lock); ++ ++ /* ++ * Changing the policy of the stop threads its a very bad idea ++ */ ++ if (p == rq->stop) { ++ retval = -EINVAL; ++ goto unlock; ++ } ++ ++ /* ++ * If not changing anything there's no need to proceed further: ++ */ ++ if (unlikely(policy == p->policy)) { ++ if (rt_policy(policy) && attr->sched_priority != p->rt_priority) ++ goto change; ++ if (!rt_policy(policy) && ++ NICE_TO_PRIO(attr->sched_nice) != p->static_prio) ++ goto change; ++ ++ p->sched_reset_on_fork = reset_on_fork; ++ retval = 0; ++ goto unlock; ++ } ++change: ++ ++ /* Re-check policy now with rq lock held */ ++ if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) { ++ policy = oldpolicy = -1; ++ __task_access_unlock(p, lock); ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++ if (pi) ++ cpuset_read_unlock(); ++ goto recheck; ++ } ++ ++ p->sched_reset_on_fork = reset_on_fork; ++ ++ if (pi) { ++ /* ++ * Take priority boosted tasks into account. If the new ++ * effective priority is unchanged, we just store the new ++ * normal parameters and do not touch the scheduler class and ++ * the runqueue. This will be done when the task deboost ++ * itself. ++ */ ++ if (rt_effective_prio(p, newprio) == p->prio) { ++ __setscheduler_params(p, attr); ++ retval = 0; ++ goto unlock; ++ } ++ } ++ ++ __setscheduler(rq, p, attr, pi); ++ ++ check_task_changed(rq, p); ++ ++ /* Avoid rq from going away on us: */ ++ preempt_disable(); ++ __task_access_unlock(p, lock); ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++ ++ if (pi) { ++ cpuset_read_unlock(); ++ rt_mutex_adjust_pi(p); ++ } ++ ++ preempt_enable(); ++ ++ return 0; ++ ++unlock: ++ __task_access_unlock(p, lock); ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++ if (pi) ++ cpuset_read_unlock(); ++ return retval; ++} ++ ++static int _sched_setscheduler(struct task_struct *p, int policy, ++ const struct sched_param *param, bool check) ++{ ++ struct sched_attr attr = { ++ .sched_policy = policy, ++ .sched_priority = param->sched_priority, ++ .sched_nice = PRIO_TO_NICE(p->static_prio), ++ }; ++ ++ /* Fixup the legacy SCHED_RESET_ON_FORK hack. */ ++ if ((policy != SETPARAM_POLICY) && (policy & SCHED_RESET_ON_FORK)) { ++ attr.sched_flags |= SCHED_FLAG_RESET_ON_FORK; ++ policy &= ~SCHED_RESET_ON_FORK; ++ attr.sched_policy = policy; ++ } ++ ++ return __sched_setscheduler(p, &attr, check, true); ++} ++ ++/** ++ * sched_setscheduler - change the scheduling policy and/or RT priority of a thread. ++ * @p: the task in question. ++ * @policy: new policy. ++ * @param: structure containing the new RT priority. ++ * ++ * Return: 0 on success. An error code otherwise. ++ * ++ * NOTE that the task may be already dead. ++ */ ++int sched_setscheduler(struct task_struct *p, int policy, ++ const struct sched_param *param) ++{ ++ return _sched_setscheduler(p, policy, param, true); ++} ++ ++EXPORT_SYMBOL_GPL(sched_setscheduler); ++ ++int sched_setattr(struct task_struct *p, const struct sched_attr *attr) ++{ ++ return __sched_setscheduler(p, attr, true, true); ++} ++EXPORT_SYMBOL_GPL(sched_setattr); ++ ++int sched_setattr_nocheck(struct task_struct *p, const struct sched_attr *attr) ++{ ++ return __sched_setscheduler(p, attr, false, true); ++} ++ ++/** ++ * sched_setscheduler_nocheck - change the scheduling policy and/or RT priority of a thread from kernelspace. ++ * @p: the task in question. ++ * @policy: new policy. ++ * @param: structure containing the new RT priority. ++ * ++ * Just like sched_setscheduler, only don't bother checking if the ++ * current context has permission. For example, this is needed in ++ * stop_machine(): we create temporary high priority worker threads, ++ * but our caller might not have that capability. ++ * ++ * Return: 0 on success. An error code otherwise. ++ */ ++int sched_setscheduler_nocheck(struct task_struct *p, int policy, ++ const struct sched_param *param) ++{ ++ return _sched_setscheduler(p, policy, param, false); ++} ++EXPORT_SYMBOL_GPL(sched_setscheduler_nocheck); ++ ++static int ++do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param) ++{ ++ struct sched_param lparam; ++ struct task_struct *p; ++ int retval; ++ ++ if (!param || pid < 0) ++ return -EINVAL; ++ if (copy_from_user(&lparam, param, sizeof(struct sched_param))) ++ return -EFAULT; ++ ++ rcu_read_lock(); ++ retval = -ESRCH; ++ p = find_process_by_pid(pid); ++ if (likely(p)) ++ get_task_struct(p); ++ rcu_read_unlock(); ++ ++ if (likely(p)) { ++ retval = sched_setscheduler(p, policy, &lparam); ++ put_task_struct(p); ++ } ++ ++ return retval; ++} ++ ++/* ++ * Mimics kernel/events/core.c perf_copy_attr(). ++ */ ++static int sched_copy_attr(struct sched_attr __user *uattr, struct sched_attr *attr) ++{ ++ u32 size; ++ int ret; ++ ++ /* Zero the full structure, so that a short copy will be nice: */ ++ memset(attr, 0, sizeof(*attr)); ++ ++ ret = get_user(size, &uattr->size); ++ if (ret) ++ return ret; ++ ++ /* ABI compatibility quirk: */ ++ if (!size) ++ size = SCHED_ATTR_SIZE_VER0; ++ ++ if (size < SCHED_ATTR_SIZE_VER0 || size > PAGE_SIZE) ++ goto err_size; ++ ++ ret = copy_struct_from_user(attr, sizeof(*attr), uattr, size); ++ if (ret) { ++ if (ret == -E2BIG) ++ goto err_size; ++ return ret; ++ } ++ ++ /* ++ * XXX: Do we want to be lenient like existing syscalls; or do we want ++ * to be strict and return an error on out-of-bounds values? ++ */ ++ attr->sched_nice = clamp(attr->sched_nice, -20, 19); ++ ++ /* sched/core.c uses zero here but we already know ret is zero */ ++ return 0; ++ ++err_size: ++ put_user(sizeof(*attr), &uattr->size); ++ return -E2BIG; ++} ++ ++/** ++ * sys_sched_setscheduler - set/change the scheduler policy and RT priority ++ * @pid: the pid in question. ++ * @policy: new policy. ++ * ++ * Return: 0 on success. An error code otherwise. ++ * @param: structure containing the new RT priority. ++ */ ++SYSCALL_DEFINE3(sched_setscheduler, pid_t, pid, int, policy, struct sched_param __user *, param) ++{ ++ if (policy < 0) ++ return -EINVAL; ++ ++ return do_sched_setscheduler(pid, policy, param); ++} ++ ++/** ++ * sys_sched_setparam - set/change the RT priority of a thread ++ * @pid: the pid in question. ++ * @param: structure containing the new RT priority. ++ * ++ * Return: 0 on success. An error code otherwise. ++ */ ++SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param) ++{ ++ return do_sched_setscheduler(pid, SETPARAM_POLICY, param); ++} ++ ++/** ++ * sys_sched_setattr - same as above, but with extended sched_attr ++ * @pid: the pid in question. ++ * @uattr: structure containing the extended parameters. ++ */ ++SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr, ++ unsigned int, flags) ++{ ++ struct sched_attr attr; ++ struct task_struct *p; ++ int retval; ++ ++ if (!uattr || pid < 0 || flags) ++ return -EINVAL; ++ ++ retval = sched_copy_attr(uattr, &attr); ++ if (retval) ++ return retval; ++ ++ if ((int)attr.sched_policy < 0) ++ return -EINVAL; ++ ++ rcu_read_lock(); ++ retval = -ESRCH; ++ p = find_process_by_pid(pid); ++ if (p != NULL) ++ retval = sched_setattr(p, &attr); ++ rcu_read_unlock(); ++ ++ return retval; ++} ++ ++/** ++ * sys_sched_getscheduler - get the policy (scheduling class) of a thread ++ * @pid: the pid in question. ++ * ++ * Return: On success, the policy of the thread. Otherwise, a negative error ++ * code. ++ */ ++SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid) ++{ ++ struct task_struct *p; ++ int retval = -EINVAL; ++ ++ if (pid < 0) ++ goto out_nounlock; ++ ++ retval = -ESRCH; ++ rcu_read_lock(); ++ p = find_process_by_pid(pid); ++ if (p) { ++ retval = security_task_getscheduler(p); ++ if (!retval) ++ retval = p->policy; ++ } ++ rcu_read_unlock(); ++ ++out_nounlock: ++ return retval; ++} ++ ++/** ++ * sys_sched_getscheduler - get the RT priority of a thread ++ * @pid: the pid in question. ++ * @param: structure containing the RT priority. ++ * ++ * Return: On success, 0 and the RT priority is in @param. Otherwise, an error ++ * code. ++ */ ++SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param) ++{ ++ struct sched_param lp = { .sched_priority = 0 }; ++ struct task_struct *p; ++ int retval = -EINVAL; ++ ++ if (!param || pid < 0) ++ goto out_nounlock; ++ ++ rcu_read_lock(); ++ p = find_process_by_pid(pid); ++ retval = -ESRCH; ++ if (!p) ++ goto out_unlock; ++ ++ retval = security_task_getscheduler(p); ++ if (retval) ++ goto out_unlock; ++ ++ if (task_has_rt_policy(p)) ++ lp.sched_priority = p->rt_priority; ++ rcu_read_unlock(); ++ ++ /* ++ * This one might sleep, we cannot do it with a spinlock held ... ++ */ ++ retval = copy_to_user(param, &lp, sizeof(*param)) ? -EFAULT : 0; ++ ++out_nounlock: ++ return retval; ++ ++out_unlock: ++ rcu_read_unlock(); ++ return retval; ++} ++ ++/* ++ * Copy the kernel size attribute structure (which might be larger ++ * than what user-space knows about) to user-space. ++ * ++ * Note that all cases are valid: user-space buffer can be larger or ++ * smaller than the kernel-space buffer. The usual case is that both ++ * have the same size. ++ */ ++static int ++sched_attr_copy_to_user(struct sched_attr __user *uattr, ++ struct sched_attr *kattr, ++ unsigned int usize) ++{ ++ unsigned int ksize = sizeof(*kattr); ++ ++ if (!access_ok(uattr, usize)) ++ return -EFAULT; ++ ++ /* ++ * sched_getattr() ABI forwards and backwards compatibility: ++ * ++ * If usize == ksize then we just copy everything to user-space and all is good. ++ * ++ * If usize < ksize then we only copy as much as user-space has space for, ++ * this keeps ABI compatibility as well. We skip the rest. ++ * ++ * If usize > ksize then user-space is using a newer version of the ABI, ++ * which part the kernel doesn't know about. Just ignore it - tooling can ++ * detect the kernel's knowledge of attributes from the attr->size value ++ * which is set to ksize in this case. ++ */ ++ kattr->size = min(usize, ksize); ++ ++ if (copy_to_user(uattr, kattr, kattr->size)) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++/** ++ * sys_sched_getattr - similar to sched_getparam, but with sched_attr ++ * @pid: the pid in question. ++ * @uattr: structure containing the extended parameters. ++ * @usize: sizeof(attr) for fwd/bwd comp. ++ * @flags: for future extension. ++ */ ++SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr, ++ unsigned int, usize, unsigned int, flags) ++{ ++ struct sched_attr kattr = { }; ++ struct task_struct *p; ++ int retval; ++ ++ if (!uattr || pid < 0 || usize > PAGE_SIZE || ++ usize < SCHED_ATTR_SIZE_VER0 || flags) ++ return -EINVAL; ++ ++ rcu_read_lock(); ++ p = find_process_by_pid(pid); ++ retval = -ESRCH; ++ if (!p) ++ goto out_unlock; ++ ++ retval = security_task_getscheduler(p); ++ if (retval) ++ goto out_unlock; ++ ++ kattr.sched_policy = p->policy; ++ if (p->sched_reset_on_fork) ++ kattr.sched_flags |= SCHED_FLAG_RESET_ON_FORK; ++ if (task_has_rt_policy(p)) ++ kattr.sched_priority = p->rt_priority; ++ else ++ kattr.sched_nice = task_nice(p); ++ ++#ifdef CONFIG_UCLAMP_TASK ++ kattr.sched_util_min = p->uclamp_req[UCLAMP_MIN].value; ++ kattr.sched_util_max = p->uclamp_req[UCLAMP_MAX].value; ++#endif ++ ++ rcu_read_unlock(); ++ ++ return sched_attr_copy_to_user(uattr, &kattr, usize); ++ ++out_unlock: ++ rcu_read_unlock(); ++ return retval; ++} ++ ++long sched_setaffinity(pid_t pid, const struct cpumask *in_mask) ++{ ++ cpumask_var_t cpus_allowed, new_mask; ++ struct task_struct *p; ++ int retval; ++ ++ get_online_cpus(); ++ rcu_read_lock(); ++ ++ p = find_process_by_pid(pid); ++ if (!p) { ++ rcu_read_unlock(); ++ put_online_cpus(); ++ return -ESRCH; ++ } ++ ++ /* Prevent p going away */ ++ get_task_struct(p); ++ rcu_read_unlock(); ++ ++ if (p->flags & PF_NO_SETAFFINITY) { ++ retval = -EINVAL; ++ goto out_put_task; ++ } ++ if (!alloc_cpumask_var(&cpus_allowed, GFP_KERNEL)) { ++ retval = -ENOMEM; ++ goto out_put_task; ++ } ++ if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) { ++ retval = -ENOMEM; ++ goto out_free_cpus_allowed; ++ } ++ retval = -EPERM; ++ if (!check_same_owner(p)) { ++ rcu_read_lock(); ++ if (!ns_capable(__task_cred(p)->user_ns, CAP_SYS_NICE)) { ++ rcu_read_unlock(); ++ goto out_unlock; ++ } ++ rcu_read_unlock(); ++ } ++ ++ retval = security_task_setscheduler(p); ++ if (retval) ++ goto out_unlock; ++ ++ cpuset_cpus_allowed(p, cpus_allowed); ++ cpumask_and(new_mask, in_mask, cpus_allowed); ++again: ++ retval = __set_cpus_allowed_ptr(p, new_mask, true); ++ ++ if (!retval) { ++ cpuset_cpus_allowed(p, cpus_allowed); ++ if (!cpumask_subset(new_mask, cpus_allowed)) { ++ /* ++ * We must have raced with a concurrent cpuset ++ * update. Just reset the cpus_allowed to the ++ * cpuset's cpus_allowed ++ */ ++ cpumask_copy(new_mask, cpus_allowed); ++ goto again; ++ } ++ } ++out_unlock: ++ free_cpumask_var(new_mask); ++out_free_cpus_allowed: ++ free_cpumask_var(cpus_allowed); ++out_put_task: ++ put_task_struct(p); ++ put_online_cpus(); ++ return retval; ++} ++ ++static int get_user_cpu_mask(unsigned long __user *user_mask_ptr, unsigned len, ++ struct cpumask *new_mask) ++{ ++ if (len < cpumask_size()) ++ cpumask_clear(new_mask); ++ else if (len > cpumask_size()) ++ len = cpumask_size(); ++ ++ return copy_from_user(new_mask, user_mask_ptr, len) ? -EFAULT : 0; ++} ++ ++/** ++ * sys_sched_setaffinity - set the CPU affinity of a process ++ * @pid: pid of the process ++ * @len: length in bytes of the bitmask pointed to by user_mask_ptr ++ * @user_mask_ptr: user-space pointer to the new CPU mask ++ * ++ * Return: 0 on success. An error code otherwise. ++ */ ++SYSCALL_DEFINE3(sched_setaffinity, pid_t, pid, unsigned int, len, ++ unsigned long __user *, user_mask_ptr) ++{ ++ cpumask_var_t new_mask; ++ int retval; ++ ++ if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) ++ return -ENOMEM; ++ ++ retval = get_user_cpu_mask(user_mask_ptr, len, new_mask); ++ if (retval == 0) ++ retval = sched_setaffinity(pid, new_mask); ++ free_cpumask_var(new_mask); ++ return retval; ++} ++ ++long sched_getaffinity(pid_t pid, cpumask_t *mask) ++{ ++ struct task_struct *p; ++ raw_spinlock_t *lock; ++ unsigned long flags; ++ int retval; ++ ++ rcu_read_lock(); ++ ++ retval = -ESRCH; ++ p = find_process_by_pid(pid); ++ if (!p) ++ goto out_unlock; ++ ++ retval = security_task_getscheduler(p); ++ if (retval) ++ goto out_unlock; ++ ++ task_access_lock_irqsave(p, &lock, &flags); ++ cpumask_and(mask, &p->cpus_mask, cpu_active_mask); ++ task_access_unlock_irqrestore(p, lock, &flags); ++ ++out_unlock: ++ rcu_read_unlock(); ++ ++ return retval; ++} ++ ++/** ++ * sys_sched_getaffinity - get the CPU affinity of a process ++ * @pid: pid of the process ++ * @len: length in bytes of the bitmask pointed to by user_mask_ptr ++ * @user_mask_ptr: user-space pointer to hold the current CPU mask ++ * ++ * Return: size of CPU mask copied to user_mask_ptr on success. An ++ * error code otherwise. ++ */ ++SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len, ++ unsigned long __user *, user_mask_ptr) ++{ ++ int ret; ++ cpumask_var_t mask; ++ ++ if ((len * BITS_PER_BYTE) < nr_cpu_ids) ++ return -EINVAL; ++ if (len & (sizeof(unsigned long)-1)) ++ return -EINVAL; ++ ++ if (!alloc_cpumask_var(&mask, GFP_KERNEL)) ++ return -ENOMEM; ++ ++ ret = sched_getaffinity(pid, mask); ++ if (ret == 0) { ++ unsigned int retlen = min_t(size_t, len, cpumask_size()); ++ ++ if (copy_to_user(user_mask_ptr, mask, retlen)) ++ ret = -EFAULT; ++ else ++ ret = retlen; ++ } ++ free_cpumask_var(mask); ++ ++ return ret; ++} ++ ++/** ++ * sys_sched_yield - yield the current processor to other threads. ++ * ++ * This function yields the current CPU to other tasks. It does this by ++ * scheduling away the current task. If it still has the earliest deadline ++ * it will be scheduled again as the next task. ++ * ++ * Return: 0. ++ */ ++static void do_sched_yield(void) ++{ ++ struct rq *rq; ++ struct rq_flags rf; ++ ++ if (!sched_yield_type) ++ return; ++ ++ rq = this_rq_lock_irq(&rf); ++ ++ schedstat_inc(rq->yld_count); ++ ++ if (1 == sched_yield_type) { ++ if (!rt_task(current)) { ++ current->boost_prio = MAX_PRIORITY_ADJ; ++ requeue_task(current, rq); ++ } ++ } else if (2 == sched_yield_type) { ++ if (rq->nr_running > 1) ++ rq->skip = current; ++ } ++ ++ /* ++ * Since we are going to call schedule() anyway, there's ++ * no need to preempt or enable interrupts: ++ */ ++ preempt_disable(); ++ raw_spin_unlock(&rq->lock); ++ sched_preempt_enable_no_resched(); ++ ++ schedule(); ++} ++ ++SYSCALL_DEFINE0(sched_yield) ++{ ++ do_sched_yield(); ++ return 0; ++} ++ ++#ifndef CONFIG_PREEMPTION ++int __sched _cond_resched(void) ++{ ++ if (should_resched(0)) { ++ preempt_schedule_common(); ++ return 1; ++ } ++ rcu_all_qs(); ++ return 0; ++} ++EXPORT_SYMBOL(_cond_resched); ++#endif ++ ++/* ++ * __cond_resched_lock() - if a reschedule is pending, drop the given lock, ++ * call schedule, and on return reacquire the lock. ++ * ++ * This works OK both with and without CONFIG_PREEMPTION. We do strange low-level ++ * operations here to prevent schedule() from being called twice (once via ++ * spin_unlock(), once by hand). ++ */ ++int __cond_resched_lock(spinlock_t *lock) ++{ ++ int resched = should_resched(PREEMPT_LOCK_OFFSET); ++ int ret = 0; ++ ++ lockdep_assert_held(lock); ++ ++ if (spin_needbreak(lock) || resched) { ++ spin_unlock(lock); ++ if (resched) ++ preempt_schedule_common(); ++ else ++ cpu_relax(); ++ ret = 1; ++ spin_lock(lock); ++ } ++ return ret; ++} ++EXPORT_SYMBOL(__cond_resched_lock); ++ ++/** ++ * yield - yield the current processor to other threads. ++ * ++ * Do not ever use this function, there's a 99% chance you're doing it wrong. ++ * ++ * The scheduler is at all times free to pick the calling task as the most ++ * eligible task to run, if removing the yield() call from your code breaks ++ * it, its already broken. ++ * ++ * Typical broken usage is: ++ * ++ * while (!event) ++ * yield(); ++ * ++ * where one assumes that yield() will let 'the other' process run that will ++ * make event true. If the current task is a SCHED_FIFO task that will never ++ * happen. Never use yield() as a progress guarantee!! ++ * ++ * If you want to use yield() to wait for something, use wait_event(). ++ * If you want to use yield() to be 'nice' for others, use cond_resched(). ++ * If you still want to use yield(), do not! ++ */ ++void __sched yield(void) ++{ ++ set_current_state(TASK_RUNNING); ++ do_sched_yield(); ++} ++EXPORT_SYMBOL(yield); ++ ++/** ++ * yield_to - yield the current processor to another thread in ++ * your thread group, or accelerate that thread toward the ++ * processor it's on. ++ * @p: target task ++ * @preempt: whether task preemption is allowed or not ++ * ++ * It's the caller's job to ensure that the target task struct ++ * can't go away on us before we can do any checks. ++ * ++ * In BMQ, yield_to is not supported. ++ * ++ * Return: ++ * true (>0) if we indeed boosted the target task. ++ * false (0) if we failed to boost the target. ++ * -ESRCH if there's no task to yield to. ++ */ ++int __sched yield_to(struct task_struct *p, bool preempt) ++{ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(yield_to); ++ ++int io_schedule_prepare(void) ++{ ++ int old_iowait = current->in_iowait; ++ ++ current->in_iowait = 1; ++ blk_schedule_flush_plug(current); ++ ++ return old_iowait; ++} ++ ++void io_schedule_finish(int token) ++{ ++ current->in_iowait = token; ++} ++ ++/* ++ * This task is about to go to sleep on IO. Increment rq->nr_iowait so ++ * that process accounting knows that this is a task in IO wait state. ++ * ++ * But don't do that if it is a deliberate, throttling IO wait (this task ++ * has set its backing_dev_info: the queue against which it should throttle) ++ */ ++ ++long __sched io_schedule_timeout(long timeout) ++{ ++ int token; ++ long ret; ++ ++ token = io_schedule_prepare(); ++ ret = schedule_timeout(timeout); ++ io_schedule_finish(token); ++ ++ return ret; ++} ++EXPORT_SYMBOL(io_schedule_timeout); ++ ++void __sched io_schedule(void) ++{ ++ int token; ++ ++ token = io_schedule_prepare(); ++ schedule(); ++ io_schedule_finish(token); ++} ++EXPORT_SYMBOL(io_schedule); ++ ++/** ++ * sys_sched_get_priority_max - return maximum RT priority. ++ * @policy: scheduling class. ++ * ++ * Return: On success, this syscall returns the maximum ++ * rt_priority that can be used by a given scheduling class. ++ * On failure, a negative error code is returned. ++ */ ++SYSCALL_DEFINE1(sched_get_priority_max, int, policy) ++{ ++ int ret = -EINVAL; ++ ++ switch (policy) { ++ case SCHED_FIFO: ++ case SCHED_RR: ++ ret = MAX_USER_RT_PRIO-1; ++ break; ++ case SCHED_NORMAL: ++ case SCHED_BATCH: ++ case SCHED_IDLE: ++ ret = 0; ++ break; ++ } ++ return ret; ++} ++ ++/** ++ * sys_sched_get_priority_min - return minimum RT priority. ++ * @policy: scheduling class. ++ * ++ * Return: On success, this syscall returns the minimum ++ * rt_priority that can be used by a given scheduling class. ++ * On failure, a negative error code is returned. ++ */ ++SYSCALL_DEFINE1(sched_get_priority_min, int, policy) ++{ ++ int ret = -EINVAL; ++ ++ switch (policy) { ++ case SCHED_FIFO: ++ case SCHED_RR: ++ ret = 1; ++ break; ++ case SCHED_NORMAL: ++ case SCHED_BATCH: ++ case SCHED_IDLE: ++ ret = 0; ++ break; ++ } ++ return ret; ++} ++ ++static int sched_rr_get_interval(pid_t pid, struct timespec64 *t) ++{ ++ struct task_struct *p; ++ int retval; ++ ++ if (pid < 0) ++ return -EINVAL; ++ ++ retval = -ESRCH; ++ rcu_read_lock(); ++ p = find_process_by_pid(pid); ++ if (!p) ++ goto out_unlock; ++ ++ retval = security_task_getscheduler(p); ++ if (retval) ++ goto out_unlock; ++ rcu_read_unlock(); ++ ++ *t = ns_to_timespec64(SCHED_TIMESLICE_NS); ++ return 0; ++ ++out_unlock: ++ rcu_read_unlock(); ++ return retval; ++} ++ ++/** ++ * sys_sched_rr_get_interval - return the default timeslice of a process. ++ * @pid: pid of the process. ++ * @interval: userspace pointer to the timeslice value. ++ * ++ * ++ * Return: On success, 0 and the timeslice is in @interval. Otherwise, ++ * an error code. ++ */ ++SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid, ++ struct __kernel_timespec __user *, interval) ++{ ++ struct timespec64 t; ++ int retval = sched_rr_get_interval(pid, &t); ++ ++ if (retval == 0) ++ retval = put_timespec64(&t, interval); ++ ++ return retval; ++} ++ ++#ifdef CONFIG_COMPAT_32BIT_TIME ++SYSCALL_DEFINE2(sched_rr_get_interval_time32, pid_t, pid, ++ struct old_timespec32 __user *, interval) ++{ ++ struct timespec64 t; ++ int retval = sched_rr_get_interval(pid, &t); ++ ++ if (retval == 0) ++ retval = put_old_timespec32(&t, interval); ++ return retval; ++} ++#endif ++ ++void sched_show_task(struct task_struct *p) ++{ ++ unsigned long free = 0; ++ int ppid; ++ ++ if (!try_get_task_stack(p)) ++ return; ++ ++ printk(KERN_INFO "%-15.15s %c", p->comm, task_state_to_char(p)); ++ ++ if (p->state == TASK_RUNNING) ++ printk(KERN_CONT " running task "); ++#ifdef CONFIG_DEBUG_STACK_USAGE ++ free = stack_not_used(p); ++#endif ++ ppid = 0; ++ rcu_read_lock(); ++ if (pid_alive(p)) ++ ppid = task_pid_nr(rcu_dereference(p->real_parent)); ++ rcu_read_unlock(); ++ printk(KERN_CONT "%5lu %5d %6d 0x%08lx\n", free, ++ task_pid_nr(p), ppid, ++ (unsigned long)task_thread_info(p)->flags); ++ ++ print_worker_info(KERN_INFO, p); ++ show_stack(p, NULL); ++ put_task_stack(p); ++} ++EXPORT_SYMBOL_GPL(sched_show_task); ++ ++static inline bool ++state_filter_match(unsigned long state_filter, struct task_struct *p) ++{ ++ /* no filter, everything matches */ ++ if (!state_filter) ++ return true; ++ ++ /* filter, but doesn't match */ ++ if (!(p->state & state_filter)) ++ return false; ++ ++ /* ++ * When looking for TASK_UNINTERRUPTIBLE skip TASK_IDLE (allows ++ * TASK_KILLABLE). ++ */ ++ if (state_filter == TASK_UNINTERRUPTIBLE && p->state == TASK_IDLE) ++ return false; ++ ++ return true; ++} ++ ++ ++void show_state_filter(unsigned long state_filter) ++{ ++ struct task_struct *g, *p; ++ ++#if BITS_PER_LONG == 32 ++ printk(KERN_INFO ++ " task PC stack pid father\n"); ++#else ++ printk(KERN_INFO ++ " task PC stack pid father\n"); ++#endif ++ rcu_read_lock(); ++ for_each_process_thread(g, p) { ++ /* ++ * reset the NMI-timeout, listing all files on a slow ++ * console might take a lot of time: ++ * Also, reset softlockup watchdogs on all CPUs, because ++ * another CPU might be blocked waiting for us to process ++ * an IPI. ++ */ ++ touch_nmi_watchdog(); ++ touch_all_softlockup_watchdogs(); ++ if (state_filter_match(state_filter, p)) ++ sched_show_task(p); ++ } ++ ++#ifdef CONFIG_SCHED_DEBUG ++ /* TODO: BMQ should support this ++ if (!state_filter) ++ sysrq_sched_debug_show(); ++ */ ++#endif ++ rcu_read_unlock(); ++ /* ++ * Only show locks if all tasks are dumped: ++ */ ++ if (!state_filter) ++ debug_show_all_locks(); ++} ++ ++void dump_cpu_task(int cpu) ++{ ++ pr_info("Task dump for CPU %d:\n", cpu); ++ sched_show_task(cpu_curr(cpu)); ++} ++ ++/** ++ * init_idle - set up an idle thread for a given CPU ++ * @idle: task in question ++ * @cpu: cpu the idle task belongs to ++ * ++ * NOTE: this function does not set the idle thread's NEED_RESCHED ++ * flag, to make booting more robust. ++ */ ++void init_idle(struct task_struct *idle, int cpu) ++{ ++ struct rq *rq = cpu_rq(cpu); ++ unsigned long flags; ++ ++ raw_spin_lock_irqsave(&idle->pi_lock, flags); ++ raw_spin_lock(&rq->lock); ++ update_rq_clock(rq); ++ ++ idle->last_ran = rq->clock_task; ++ idle->state = TASK_RUNNING; ++ idle->flags |= PF_IDLE; ++ /* Setting prio to illegal value shouldn't matter when never queued */ ++ idle->prio = MAX_PRIO; ++ ++ idle->bmq_idx = IDLE_TASK_SCHED_PRIO; ++ bmq_init_idle(&rq->queue, idle); ++ ++ kasan_unpoison_task_stack(idle); ++ ++#ifdef CONFIG_SMP ++ /* ++ * It's possible that init_idle() gets called multiple times on a task, ++ * in that case do_set_cpus_allowed() will not do the right thing. ++ * ++ * And since this is boot we can forgo the serialisation. ++ */ ++ set_cpus_allowed_common(idle, cpumask_of(cpu)); ++#endif ++ ++ /* Silence PROVE_RCU */ ++ rcu_read_lock(); ++ __set_task_cpu(idle, cpu); ++ rcu_read_unlock(); ++ ++ rq->idle = idle; ++ rcu_assign_pointer(rq->curr, idle); ++ idle->on_cpu = 1; ++ ++ raw_spin_unlock(&rq->lock); ++ raw_spin_unlock_irqrestore(&idle->pi_lock, flags); ++ ++ /* Set the preempt count _outside_ the spinlocks! */ ++ init_idle_preempt_count(idle, cpu); ++ ++ ftrace_graph_init_idle_task(idle, cpu); ++ vtime_init_idle(idle, cpu); ++#ifdef CONFIG_SMP ++ sprintf(idle->comm, "%s/%d", INIT_TASK_COMM, cpu); ++#endif ++} ++ ++static bool __wake_q_add(struct wake_q_head *head, struct task_struct *task) ++{ ++ struct wake_q_node *node = &task->wake_q; ++ ++ /* ++ * Atomically grab the task, if ->wake_q is !nil already it means ++ * its already queued (either by us or someone else) and will get the ++ * wakeup due to that. ++ * ++ * In order to ensure that a pending wakeup will observe our pending ++ * state, even in the failed case, an explicit smp_mb() must be used. ++ */ ++ smp_mb__before_atomic(); ++ if (unlikely(cmpxchg_relaxed(&node->next, NULL, WAKE_Q_TAIL))) ++ return false; ++ ++ /* ++ * The head is context local, there can be no concurrency. ++ */ ++ *head->lastp = node; ++ head->lastp = &node->next; ++ return true; ++} ++ ++/** ++ * wake_q_add() - queue a wakeup for 'later' waking. ++ * @head: the wake_q_head to add @task to ++ * @task: the task to queue for 'later' wakeup ++ * ++ * Queue a task for later wakeup, most likely by the wake_up_q() call in the ++ * same context, _HOWEVER_ this is not guaranteed, the wakeup can come ++ * instantly. ++ * ++ * This function must be used as-if it were wake_up_process(); IOW the task ++ * must be ready to be woken at this location. ++ */ ++void wake_q_add(struct wake_q_head *head, struct task_struct *task) ++{ ++ if (__wake_q_add(head, task)) ++ get_task_struct(task); ++} ++ ++/** ++ * wake_q_add_safe() - safely queue a wakeup for 'later' waking. ++ * @head: the wake_q_head to add @task to ++ * @task: the task to queue for 'later' wakeup ++ * ++ * Queue a task for later wakeup, most likely by the wake_up_q() call in the ++ * same context, _HOWEVER_ this is not guaranteed, the wakeup can come ++ * instantly. ++ * ++ * This function must be used as-if it were wake_up_process(); IOW the task ++ * must be ready to be woken at this location. ++ * ++ * This function is essentially a task-safe equivalent to wake_q_add(). Callers ++ * that already hold reference to @task can call the 'safe' version and trust ++ * wake_q to do the right thing depending whether or not the @task is already ++ * queued for wakeup. ++ */ ++void wake_q_add_safe(struct wake_q_head *head, struct task_struct *task) ++{ ++ if (!__wake_q_add(head, task)) ++ put_task_struct(task); ++} ++ ++void wake_up_q(struct wake_q_head *head) ++{ ++ struct wake_q_node *node = head->first; ++ ++ while (node != WAKE_Q_TAIL) { ++ struct task_struct *task; ++ ++ task = container_of(node, struct task_struct, wake_q); ++ BUG_ON(!task); ++ /* task can safely be re-inserted now: */ ++ node = node->next; ++ task->wake_q.next = NULL; ++ ++ /* ++ * wake_up_process() executes a full barrier, which pairs with ++ * the queueing in wake_q_add() so as not to miss wakeups. ++ */ ++ wake_up_process(task); ++ put_task_struct(task); ++ } ++} ++ ++#ifdef CONFIG_SMP ++ ++int cpuset_cpumask_can_shrink(const struct cpumask __maybe_unused *cur, ++ const struct cpumask __maybe_unused *trial) ++{ ++ return 1; ++} ++ ++int task_can_attach(struct task_struct *p, ++ const struct cpumask *cs_cpus_allowed) ++{ ++ int ret = 0; ++ ++ /* ++ * Kthreads which disallow setaffinity shouldn't be moved ++ * to a new cpuset; we don't want to change their CPU ++ * affinity and isolating such threads by their set of ++ * allowed nodes is unnecessary. Thus, cpusets are not ++ * applicable for such threads. This prevents checking for ++ * success of set_cpus_allowed_ptr() on all attached tasks ++ * before cpus_mask may be changed. ++ */ ++ if (p->flags & PF_NO_SETAFFINITY) ++ ret = -EINVAL; ++ ++ return ret; ++} ++ ++static bool sched_smp_initialized __read_mostly; ++ ++#ifdef CONFIG_NO_HZ_COMMON ++void nohz_balance_enter_idle(int cpu) ++{ ++} ++ ++void select_nohz_load_balancer(int stop_tick) ++{ ++} ++ ++void set_cpu_sd_state_idle(void) {} ++ ++/* ++ * In the semi idle case, use the nearest busy CPU for migrating timers ++ * from an idle CPU. This is good for power-savings. ++ * ++ * We don't do similar optimization for completely idle system, as ++ * selecting an idle CPU will add more delays to the timers than intended ++ * (as that CPU's timer base may not be uptodate wrt jiffies etc). ++ */ ++int get_nohz_timer_target(void) ++{ ++ int i, cpu = smp_processor_id(); ++ struct cpumask *mask; ++ ++ if (!idle_cpu(cpu) && housekeeping_cpu(cpu, HK_FLAG_TIMER)) ++ return cpu; ++ ++ for (mask = &(per_cpu(sched_cpu_affinity_masks, cpu)[0]); ++ mask < per_cpu(sched_cpu_affinity_end_mask, cpu); mask++) ++ for_each_cpu(i, mask) ++ if (!idle_cpu(i) && housekeeping_cpu(i, HK_FLAG_TIMER)) ++ return i; ++ ++ if (!housekeeping_cpu(cpu, HK_FLAG_TIMER)) ++ cpu = housekeeping_any_cpu(HK_FLAG_TIMER); ++ ++ return cpu; ++} ++ ++/* ++ * When add_timer_on() enqueues a timer into the timer wheel of an ++ * idle CPU then this timer might expire before the next timer event ++ * which is scheduled to wake up that CPU. In case of a completely ++ * idle system the next event might even be infinite time into the ++ * future. wake_up_idle_cpu() ensures that the CPU is woken up and ++ * leaves the inner idle loop so the newly added timer is taken into ++ * account when the CPU goes back to idle and evaluates the timer ++ * wheel for the next timer event. ++ */ ++void wake_up_idle_cpu(int cpu) ++{ ++ if (cpu == smp_processor_id()) ++ return; ++ ++ set_tsk_need_resched(cpu_rq(cpu)->idle); ++ smp_send_reschedule(cpu); ++} ++ ++void wake_up_nohz_cpu(int cpu) ++{ ++ wake_up_idle_cpu(cpu); ++} ++#endif /* CONFIG_NO_HZ_COMMON */ ++ ++#ifdef CONFIG_HOTPLUG_CPU ++/* ++ * Ensures that the idle task is using init_mm right before its CPU goes ++ * offline. ++ */ ++void idle_task_exit(void) ++{ ++ struct mm_struct *mm = current->active_mm; ++ ++ BUG_ON(cpu_online(smp_processor_id())); ++ ++ if (mm != &init_mm) { ++ switch_mm(mm, &init_mm, current); ++ current->active_mm = &init_mm; ++ finish_arch_post_lock_switch(); ++ } ++ mmdrop(mm); ++} ++ ++/* ++ * Migrate all tasks from the rq, sleeping tasks will be migrated by ++ * try_to_wake_up()->select_task_rq(). ++ * ++ * Called with rq->lock held even though we'er in stop_machine() and ++ * there's no concurrency possible, we hold the required locks anyway ++ * because of lock validation efforts. ++ */ ++static void migrate_tasks(struct rq *dead_rq) ++{ ++ struct rq *rq = dead_rq; ++ struct task_struct *p, *stop = rq->stop; ++ int count = 0; ++ ++ /* ++ * Fudge the rq selection such that the below task selection loop ++ * doesn't get stuck on the currently eligible stop task. ++ * ++ * We're currently inside stop_machine() and the rq is either stuck ++ * in the stop_machine_cpu_stop() loop, or we're executing this code, ++ * either way we should never end up calling schedule() until we're ++ * done here. ++ */ ++ rq->stop = NULL; ++ ++ p = rq_first_bmq_task(rq); ++ while (p != rq->idle) { ++ int dest_cpu; ++ ++ /* skip the running task */ ++ if (task_running(p) || 1 == p->nr_cpus_allowed) { ++ p = rq_next_bmq_task(p, rq); ++ continue; ++ } ++ ++ /* ++ * Rules for changing task_struct::cpus_allowed are holding ++ * both pi_lock and rq->lock, such that holding either ++ * stabilizes the mask. ++ * ++ * Drop rq->lock is not quite as disastrous as it usually is ++ * because !cpu_active at this point, which means load-balance ++ * will not interfere. Also, stop-machine. ++ */ ++ raw_spin_unlock(&rq->lock); ++ raw_spin_lock(&p->pi_lock); ++ raw_spin_lock(&rq->lock); ++ ++ /* ++ * Since we're inside stop-machine, _nothing_ should have ++ * changed the task, WARN if weird stuff happened, because in ++ * that case the above rq->lock drop is a fail too. ++ */ ++ if (WARN_ON(task_rq(p) != rq || !task_on_rq_queued(p))) { ++ raw_spin_unlock(&p->pi_lock); ++ p = rq_next_bmq_task(p, rq); ++ continue; ++ } ++ ++ count++; ++ /* Find suitable destination for @next, with force if needed. */ ++ dest_cpu = select_fallback_rq(dead_rq->cpu, p); ++ rq = __migrate_task(rq, p, dest_cpu); ++ raw_spin_unlock(&rq->lock); ++ raw_spin_unlock(&p->pi_lock); ++ ++ rq = dead_rq; ++ raw_spin_lock(&rq->lock); ++ /* Check queued task all over from the header again */ ++ p = rq_first_bmq_task(rq); ++ } ++ ++ rq->stop = stop; ++} ++ ++static void set_rq_offline(struct rq *rq) ++{ ++ if (rq->online) ++ rq->online = false; ++} ++#endif /* CONFIG_HOTPLUG_CPU */ ++ ++static void set_rq_online(struct rq *rq) ++{ ++ if (!rq->online) ++ rq->online = true; ++} ++ ++#ifdef CONFIG_SCHED_DEBUG ++ ++static __read_mostly int sched_debug_enabled; ++ ++static int __init sched_debug_setup(char *str) ++{ ++ sched_debug_enabled = 1; ++ ++ return 0; ++} ++early_param("sched_debug", sched_debug_setup); ++ ++static inline bool sched_debug(void) ++{ ++ return sched_debug_enabled; ++} ++#else /* !CONFIG_SCHED_DEBUG */ ++static inline bool sched_debug(void) ++{ ++ return false; ++} ++#endif /* CONFIG_SCHED_DEBUG */ ++ ++#ifdef CONFIG_SMP ++void scheduler_ipi(void) ++{ ++ /* ++ * Fold TIF_NEED_RESCHED into the preempt_count; anybody setting ++ * TIF_NEED_RESCHED remotely (for the first time) will also send ++ * this IPI. ++ */ ++ preempt_fold_need_resched(); ++ ++ if (!idle_cpu(smp_processor_id()) || need_resched()) ++ return; ++ ++ irq_enter(); ++ irq_exit(); ++} ++ ++void wake_up_if_idle(int cpu) ++{ ++ struct rq *rq = cpu_rq(cpu); ++ unsigned long flags; ++ ++ rcu_read_lock(); ++ ++ if (!is_idle_task(rcu_dereference(rq->curr))) ++ goto out; ++ ++ if (set_nr_if_polling(rq->idle)) { ++ trace_sched_wake_idle_without_ipi(cpu); ++ } else { ++ raw_spin_lock_irqsave(&rq->lock, flags); ++ if (is_idle_task(rq->curr)) ++ smp_send_reschedule(cpu); ++ /* Else CPU is not idle, do nothing here */ ++ raw_spin_unlock_irqrestore(&rq->lock, flags); ++ } ++ ++out: ++ rcu_read_unlock(); ++} ++ ++bool cpus_share_cache(int this_cpu, int that_cpu) ++{ ++ return per_cpu(sd_llc_id, this_cpu) == per_cpu(sd_llc_id, that_cpu); ++} ++#endif /* CONFIG_SMP */ ++ ++/* ++ * Topology list, bottom-up. ++ */ ++static struct sched_domain_topology_level default_topology[] = { ++#ifdef CONFIG_SCHED_SMT ++ { cpu_smt_mask, cpu_smt_flags, SD_INIT_NAME(SMT) }, ++#endif ++#ifdef CONFIG_SCHED_MC ++ { cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) }, ++#endif ++ { cpu_cpu_mask, SD_INIT_NAME(DIE) }, ++ { NULL, }, ++}; ++ ++static struct sched_domain_topology_level *sched_domain_topology = ++ default_topology; ++ ++#define for_each_sd_topology(tl) \ ++ for (tl = sched_domain_topology; tl->mask; tl++) ++ ++void set_sched_topology(struct sched_domain_topology_level *tl) ++{ ++ if (WARN_ON_ONCE(sched_smp_initialized)) ++ return; ++ ++ sched_domain_topology = tl; ++} ++ ++/* ++ * Initializers for schedule domains ++ * Non-inlined to reduce accumulated stack pressure in build_sched_domains() ++ */ ++ ++int sched_domain_level_max; ++ ++/* ++ * Partition sched domains as specified by the 'ndoms_new' ++ * cpumasks in the array doms_new[] of cpumasks. This compares ++ * doms_new[] to the current sched domain partitioning, doms_cur[]. ++ * It destroys each deleted domain and builds each new domain. ++ * ++ * 'doms_new' is an array of cpumask_var_t's of length 'ndoms_new'. ++ * The masks don't intersect (don't overlap.) We should setup one ++ * sched domain for each mask. CPUs not in any of the cpumasks will ++ * not be load balanced. If the same cpumask appears both in the ++ * current 'doms_cur' domains and in the new 'doms_new', we can leave ++ * it as it is. ++ * ++ * The passed in 'doms_new' should be allocated using ++ * alloc_sched_domains. This routine takes ownership of it and will ++ * free_sched_domains it when done with it. If the caller failed the ++ * alloc call, then it can pass in doms_new == NULL && ndoms_new == 1, ++ * and partition_sched_domains() will fallback to the single partition ++ * 'fallback_doms', it also forces the domains to be rebuilt. ++ * ++ * If doms_new == NULL it will be replaced with cpu_online_mask. ++ * ndoms_new == 0 is a special case for destroying existing domains, ++ * and it will not create the default domain. ++ * ++ * Call with hotplug lock held ++ */ ++void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[], ++ struct sched_domain_attr *dattr_new) ++{ ++ /** ++ * BMQ doesn't depend on sched domains, but just keep this api ++ */ ++} ++ ++/* ++ * used to mark begin/end of suspend/resume: ++ */ ++static int num_cpus_frozen; ++ ++#ifdef CONFIG_NUMA ++int __read_mostly node_reclaim_distance = RECLAIM_DISTANCE; ++ ++/* ++ * sched_numa_find_closest() - given the NUMA topology, find the cpu ++ * closest to @cpu from @cpumask. ++ * cpumask: cpumask to find a cpu from ++ * cpu: cpu to be close to ++ * ++ * returns: cpu, or nr_cpu_ids when nothing found. ++ */ ++int sched_numa_find_closest(const struct cpumask *cpus, int cpu) ++{ ++ return best_mask_cpu(cpu, cpus); ++} ++#endif /* CONFIG_NUMA */ ++ ++/* ++ * Update cpusets according to cpu_active mask. If cpusets are ++ * disabled, cpuset_update_active_cpus() becomes a simple wrapper ++ * around partition_sched_domains(). ++ * ++ * If we come here as part of a suspend/resume, don't touch cpusets because we ++ * want to restore it back to its original state upon resume anyway. ++ */ ++static void cpuset_cpu_active(void) ++{ ++ if (cpuhp_tasks_frozen) { ++ /* ++ * num_cpus_frozen tracks how many CPUs are involved in suspend ++ * resume sequence. As long as this is not the last online ++ * operation in the resume sequence, just build a single sched ++ * domain, ignoring cpusets. ++ */ ++ partition_sched_domains(1, NULL, NULL); ++ if (--num_cpus_frozen) ++ return; ++ /* ++ * This is the last CPU online operation. So fall through and ++ * restore the original sched domains by considering the ++ * cpuset configurations. ++ */ ++ cpuset_force_rebuild(); ++ } ++ ++ cpuset_update_active_cpus(); ++} ++ ++static int cpuset_cpu_inactive(unsigned int cpu) ++{ ++ if (!cpuhp_tasks_frozen) { ++ cpuset_update_active_cpus(); ++ } else { ++ num_cpus_frozen++; ++ partition_sched_domains(1, NULL, NULL); ++ } ++ return 0; ++} ++ ++int sched_cpu_activate(unsigned int cpu) ++{ ++ struct rq *rq = cpu_rq(cpu); ++ unsigned long flags; ++ ++#ifdef CONFIG_SCHED_SMT ++ /* ++ * When going up, increment the number of cores with SMT present. ++ */ ++ if (cpumask_weight(cpu_smt_mask(cpu)) == 2) ++ static_branch_inc_cpuslocked(&sched_smt_present); ++#endif ++ set_cpu_active(cpu, true); ++ ++ if (sched_smp_initialized) ++ cpuset_cpu_active(); ++ ++ /* ++ * Put the rq online, if not already. This happens: ++ * ++ * 1) In the early boot process, because we build the real domains ++ * after all cpus have been brought up. ++ * ++ * 2) At runtime, if cpuset_cpu_active() fails to rebuild the ++ * domains. ++ */ ++ raw_spin_lock_irqsave(&rq->lock, flags); ++ set_rq_online(rq); ++ raw_spin_unlock_irqrestore(&rq->lock, flags); ++ ++ return 0; ++} ++ ++int sched_cpu_deactivate(unsigned int cpu) ++{ ++ int ret; ++ ++ set_cpu_active(cpu, false); ++ /* ++ * We've cleared cpu_active_mask, wait for all preempt-disabled and RCU ++ * users of this state to go away such that all new such users will ++ * observe it. ++ * ++ * Do sync before park smpboot threads to take care the rcu boost case. ++ */ ++ synchronize_rcu(); ++ ++#ifdef CONFIG_SCHED_SMT ++ /* ++ * When going down, decrement the number of cores with SMT present. ++ */ ++ if (cpumask_weight(cpu_smt_mask(cpu)) == 2) { ++ static_branch_dec_cpuslocked(&sched_smt_present); ++ if (!static_branch_likely(&sched_smt_present)) ++ cpumask_clear(&sched_sg_idle_mask); ++ } ++#endif ++ ++ if (!sched_smp_initialized) ++ return 0; ++ ++ ret = cpuset_cpu_inactive(cpu); ++ if (ret) { ++ set_cpu_active(cpu, true); ++ return ret; ++ } ++ return 0; ++} ++ ++static void sched_rq_cpu_starting(unsigned int cpu) ++{ ++ struct rq *rq = cpu_rq(cpu); ++ ++ rq->calc_load_update = calc_load_update; ++} ++ ++int sched_cpu_starting(unsigned int cpu) ++{ ++ sched_rq_cpu_starting(cpu); ++ sched_tick_start(cpu); ++ return 0; ++} ++ ++#ifdef CONFIG_HOTPLUG_CPU ++int sched_cpu_dying(unsigned int cpu) ++{ ++ struct rq *rq = cpu_rq(cpu); ++ unsigned long flags; ++ ++ sched_tick_stop(cpu); ++ raw_spin_lock_irqsave(&rq->lock, flags); ++ set_rq_offline(rq); ++ migrate_tasks(rq); ++ raw_spin_unlock_irqrestore(&rq->lock, flags); ++ ++ hrtick_clear(rq); ++ return 0; ++} ++#endif ++ ++#ifdef CONFIG_SMP ++static void sched_init_topology_cpumask_early(void) ++{ ++ int cpu, level; ++ cpumask_t *tmp; ++ ++ for_each_possible_cpu(cpu) { ++ for (level = 0; level < NR_CPU_AFFINITY_CHK_LEVEL; level++) { ++ tmp = &(per_cpu(sched_cpu_affinity_masks, cpu)[level]); ++ cpumask_copy(tmp, cpu_possible_mask); ++ cpumask_clear_cpu(cpu, tmp); ++ } ++ per_cpu(sched_cpu_affinity_end_mask, cpu) = ++ &(per_cpu(sched_cpu_affinity_masks, cpu)[1]); ++ } ++} ++ ++static void sched_init_topology_cpumask(void) ++{ ++ int cpu; ++ cpumask_t *chk; ++ ++ for_each_online_cpu(cpu) { ++ chk = &(per_cpu(sched_cpu_affinity_masks, cpu)[0]); ++ ++#ifdef CONFIG_SCHED_SMT ++ cpumask_setall(chk); ++ cpumask_clear_cpu(cpu, chk); ++ if (cpumask_and(chk, chk, topology_sibling_cpumask(cpu))) { ++ printk(KERN_INFO "bmq: cpu #%d affinity check mask - smt 0x%08lx", ++ cpu, (chk++)->bits[0]); ++ } ++ cpumask_complement(chk, topology_sibling_cpumask(cpu)); ++#else ++ cpumask_clear_cpu(cpu, chk); ++#endif ++#ifdef CONFIG_SCHED_MC ++ if (cpumask_and(chk, chk, cpu_coregroup_mask(cpu))) ++ printk(KERN_INFO "bmq: cpu #%d affinity check mask - coregroup 0x%08lx", ++ cpu, (chk++)->bits[0]); ++ cpumask_complement(chk, cpu_coregroup_mask(cpu)); ++ ++ /** ++ * Set up sd_llc_id per CPU ++ */ ++ per_cpu(sd_llc_id, cpu) = ++ cpumask_first(cpu_coregroup_mask(cpu)); ++#else ++ per_cpu(sd_llc_id, cpu) = ++ cpumask_first(topology_core_cpumask(cpu)); ++ ++ cpumask_setall(chk); ++ cpumask_clear_cpu(cpu, chk); ++#endif /* NOT CONFIG_SCHED_MC */ ++ if (cpumask_and(chk, chk, topology_core_cpumask(cpu))) ++ printk(KERN_INFO "bmq: cpu #%d affinity check mask - core 0x%08lx", ++ cpu, (chk++)->bits[0]); ++ cpumask_complement(chk, topology_core_cpumask(cpu)); ++ ++ if (cpumask_and(chk, chk, cpu_online_mask)) ++ printk(KERN_INFO "bmq: cpu #%d affinity check mask - others 0x%08lx", ++ cpu, (chk++)->bits[0]); ++ ++ per_cpu(sched_cpu_affinity_end_mask, cpu) = chk; ++ } ++} ++#endif ++ ++void __init sched_init_smp(void) ++{ ++ /* Move init over to a non-isolated CPU */ ++ if (set_cpus_allowed_ptr(current, housekeeping_cpumask(HK_FLAG_DOMAIN)) < 0) ++ BUG(); ++ ++ sched_init_topology_cpumask(); ++ ++ sched_smp_initialized = true; ++} ++#else ++void __init sched_init_smp(void) ++{ ++} ++#endif /* CONFIG_SMP */ ++ ++int in_sched_functions(unsigned long addr) ++{ ++ return in_lock_functions(addr) || ++ (addr >= (unsigned long)__sched_text_start ++ && addr < (unsigned long)__sched_text_end); ++} ++ ++#ifdef CONFIG_CGROUP_SCHED ++/* task group related information */ ++struct task_group { ++ struct cgroup_subsys_state css; ++ ++ struct rcu_head rcu; ++ struct list_head list; ++ ++ struct task_group *parent; ++ struct list_head siblings; ++ struct list_head children; ++}; ++ ++/* ++ * Default task group. ++ * Every task in system belongs to this group at bootup. ++ */ ++struct task_group root_task_group; ++LIST_HEAD(task_groups); ++ ++/* Cacheline aligned slab cache for task_group */ ++static struct kmem_cache *task_group_cache __read_mostly; ++#endif /* CONFIG_CGROUP_SCHED */ ++ ++void __init sched_init(void) ++{ ++ int i; ++ struct rq *rq; ++ ++ print_scheduler_version(); ++ ++ wait_bit_init(); ++ ++#ifdef CONFIG_SMP ++ for (i = 0; i < bmq_BITS; i++) ++ cpumask_copy(&sched_rq_watermark[i], cpu_present_mask); ++#endif ++ ++#ifdef CONFIG_CGROUP_SCHED ++ task_group_cache = KMEM_CACHE(task_group, 0); ++ ++ list_add(&root_task_group.list, &task_groups); ++ INIT_LIST_HEAD(&root_task_group.children); ++ INIT_LIST_HEAD(&root_task_group.siblings); ++#endif /* CONFIG_CGROUP_SCHED */ ++ for_each_possible_cpu(i) { ++ rq = cpu_rq(i); ++ ++ bmq_init(&rq->queue); ++ rq->watermark = IDLE_WM; ++ rq->skip = NULL; ++ ++ raw_spin_lock_init(&rq->lock); ++ rq->nr_running = rq->nr_uninterruptible = 0; ++ rq->calc_load_active = 0; ++ rq->calc_load_update = jiffies + LOAD_FREQ; ++#ifdef CONFIG_SMP ++ rq->online = false; ++ rq->cpu = i; ++ ++#ifdef CONFIG_SCHED_SMT ++ rq->active_balance = 0; ++#endif ++#endif ++ rq->nr_switches = 0; ++ atomic_set(&rq->nr_iowait, 0); ++ hrtick_rq_init(rq); ++ } ++#ifdef CONFIG_SMP ++ /* Set rq->online for cpu 0 */ ++ cpu_rq(0)->online = true; ++#endif ++ ++ /* ++ * The boot idle thread does lazy MMU switching as well: ++ */ ++ mmgrab(&init_mm); ++ enter_lazy_tlb(&init_mm, current); ++ ++ /* ++ * Make us the idle thread. Technically, schedule() should not be ++ * called from this thread, however somewhere below it might be, ++ * but because we are the idle thread, we just pick up running again ++ * when this runqueue becomes "idle". ++ */ ++ init_idle(current, smp_processor_id()); ++ ++ calc_load_update = jiffies + LOAD_FREQ; ++ ++#ifdef CONFIG_SMP ++ idle_thread_set_boot_cpu(); ++ ++ sched_init_topology_cpumask_early(); ++#endif /* SMP */ ++ ++ init_schedstats(); ++ ++ psi_init(); ++} ++ ++#ifdef CONFIG_DEBUG_ATOMIC_SLEEP ++static inline int preempt_count_equals(int preempt_offset) ++{ ++ int nested = preempt_count() + rcu_preempt_depth(); ++ ++ return (nested == preempt_offset); ++} ++ ++void __might_sleep(const char *file, int line, int preempt_offset) ++{ ++ /* ++ * Blocking primitives will set (and therefore destroy) current->state, ++ * since we will exit with TASK_RUNNING make sure we enter with it, ++ * otherwise we will destroy state. ++ */ ++ WARN_ONCE(current->state != TASK_RUNNING && current->task_state_change, ++ "do not call blocking ops when !TASK_RUNNING; " ++ "state=%lx set at [<%p>] %pS\n", ++ current->state, ++ (void *)current->task_state_change, ++ (void *)current->task_state_change); ++ ++ ___might_sleep(file, line, preempt_offset); ++} ++EXPORT_SYMBOL(__might_sleep); ++ ++void ___might_sleep(const char *file, int line, int preempt_offset) ++{ ++ /* Ratelimiting timestamp: */ ++ static unsigned long prev_jiffy; ++ ++ unsigned long preempt_disable_ip; ++ ++ /* WARN_ON_ONCE() by default, no rate limit required: */ ++ rcu_sleep_check(); ++ ++ if ((preempt_count_equals(preempt_offset) && !irqs_disabled() && ++ !is_idle_task(current) && !current->non_block_count) || ++ system_state == SYSTEM_BOOTING || system_state > SYSTEM_RUNNING || ++ oops_in_progress) ++ return; ++ if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy) ++ return; ++ prev_jiffy = jiffies; ++ ++ /* Save this before calling printk(), since that will clobber it: */ ++ preempt_disable_ip = get_preempt_disable_ip(current); ++ ++ printk(KERN_ERR ++ "BUG: sleeping function called from invalid context at %s:%d\n", ++ file, line); ++ printk(KERN_ERR ++ "in_atomic(): %d, irqs_disabled(): %d, non_block: %d, pid: %d, name: %s\n", ++ in_atomic(), irqs_disabled(), current->non_block_count, ++ current->pid, current->comm); ++ ++ if (task_stack_end_corrupted(current)) ++ printk(KERN_EMERG "Thread overran stack, or stack corrupted\n"); ++ ++ debug_show_held_locks(current); ++ if (irqs_disabled()) ++ print_irqtrace_events(current); ++#ifdef CONFIG_DEBUG_PREEMPT ++ if (!preempt_count_equals(preempt_offset)) { ++ pr_err("Preemption disabled at:"); ++ print_ip_sym(preempt_disable_ip); ++ pr_cont("\n"); ++ } ++#endif ++ dump_stack(); ++ add_taint(TAINT_WARN, LOCKDEP_STILL_OK); ++} ++EXPORT_SYMBOL(___might_sleep); ++ ++void __cant_sleep(const char *file, int line, int preempt_offset) ++{ ++ static unsigned long prev_jiffy; ++ ++ if (irqs_disabled()) ++ return; ++ ++ if (!IS_ENABLED(CONFIG_PREEMPT_COUNT)) ++ return; ++ ++ if (preempt_count() > preempt_offset) ++ return; ++ ++ if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy) ++ return; ++ prev_jiffy = jiffies; ++ ++ printk(KERN_ERR "BUG: assuming atomic context at %s:%d\n", file, line); ++ printk(KERN_ERR "in_atomic(): %d, irqs_disabled(): %d, pid: %d, name: %s\n", ++ in_atomic(), irqs_disabled(), ++ current->pid, current->comm); ++ ++ debug_show_held_locks(current); ++ dump_stack(); ++ add_taint(TAINT_WARN, LOCKDEP_STILL_OK); ++} ++EXPORT_SYMBOL_GPL(__cant_sleep); ++#endif ++ ++#ifdef CONFIG_MAGIC_SYSRQ ++void normalize_rt_tasks(void) ++{ ++ struct task_struct *g, *p; ++ struct sched_attr attr = { ++ .sched_policy = SCHED_NORMAL, ++ }; ++ ++ read_lock(&tasklist_lock); ++ for_each_process_thread(g, p) { ++ /* ++ * Only normalize user tasks: ++ */ ++ if (p->flags & PF_KTHREAD) ++ continue; ++ ++ if (!rt_task(p)) { ++ /* ++ * Renice negative nice level userspace ++ * tasks back to 0: ++ */ ++ if (task_nice(p) < 0) ++ set_user_nice(p, 0); ++ continue; ++ } ++ ++ __sched_setscheduler(p, &attr, false, false); ++ } ++ read_unlock(&tasklist_lock); ++} ++#endif /* CONFIG_MAGIC_SYSRQ */ ++ ++#if defined(CONFIG_IA64) || defined(CONFIG_KGDB_KDB) ++/* ++ * These functions are only useful for the IA64 MCA handling, or kdb. ++ * ++ * They can only be called when the whole system has been ++ * stopped - every CPU needs to be quiescent, and no scheduling ++ * activity can take place. Using them for anything else would ++ * be a serious bug, and as a result, they aren't even visible ++ * under any other configuration. ++ */ ++ ++/** ++ * curr_task - return the current task for a given CPU. ++ * @cpu: the processor in question. ++ * ++ * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED! ++ * ++ * Return: The current task for @cpu. ++ */ ++struct task_struct *curr_task(int cpu) ++{ ++ return cpu_curr(cpu); ++} ++ ++#endif /* defined(CONFIG_IA64) || defined(CONFIG_KGDB_KDB) */ ++ ++#ifdef CONFIG_IA64 ++/** ++ * ia64_set_curr_task - set the current task for a given CPU. ++ * @cpu: the processor in question. ++ * @p: the task pointer to set. ++ * ++ * Description: This function must only be used when non-maskable interrupts ++ * are serviced on a separate stack. It allows the architecture to switch the ++ * notion of the current task on a CPU in a non-blocking manner. This function ++ * must be called with all CPU's synchronised, and interrupts disabled, the ++ * and caller must save the original value of the current task (see ++ * curr_task() above) and restore that value before reenabling interrupts and ++ * re-starting the system. ++ * ++ * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED! ++ */ ++void ia64_set_curr_task(int cpu, struct task_struct *p) ++{ ++ cpu_curr(cpu) = p; ++} ++ ++#endif ++ ++#ifdef CONFIG_SCHED_DEBUG ++void proc_sched_show_task(struct task_struct *p, struct pid_namespace *ns, ++ struct seq_file *m) ++{ ++ SEQ_printf(m, "%s (%d, #threads: %d)\n", p->comm, task_pid_nr_ns(p, ns), ++ get_nr_threads(p)); ++} ++ ++void proc_sched_set_task(struct task_struct *p) ++{} ++#endif ++ ++#ifdef CONFIG_CGROUP_SCHED ++static void sched_free_group(struct task_group *tg) ++{ ++ kmem_cache_free(task_group_cache, tg); ++} ++ ++/* allocate runqueue etc for a new task group */ ++struct task_group *sched_create_group(struct task_group *parent) ++{ ++ struct task_group *tg; ++ ++ tg = kmem_cache_alloc(task_group_cache, GFP_KERNEL | __GFP_ZERO); ++ if (!tg) ++ return ERR_PTR(-ENOMEM); ++ ++ return tg; ++} ++ ++void sched_online_group(struct task_group *tg, struct task_group *parent) ++{ ++} ++ ++/* rcu callback to free various structures associated with a task group */ ++static void sched_free_group_rcu(struct rcu_head *rhp) ++{ ++ /* Now it should be safe to free those cfs_rqs */ ++ sched_free_group(container_of(rhp, struct task_group, rcu)); ++} ++ ++void sched_destroy_group(struct task_group *tg) ++{ ++ /* Wait for possible concurrent references to cfs_rqs complete */ ++ call_rcu(&tg->rcu, sched_free_group_rcu); ++} ++ ++void sched_offline_group(struct task_group *tg) ++{ ++} ++ ++static inline struct task_group *css_tg(struct cgroup_subsys_state *css) ++{ ++ return css ? container_of(css, struct task_group, css) : NULL; ++} ++ ++static struct cgroup_subsys_state * ++cpu_cgroup_css_alloc(struct cgroup_subsys_state *parent_css) ++{ ++ struct task_group *parent = css_tg(parent_css); ++ struct task_group *tg; ++ ++ if (!parent) { ++ /* This is early initialization for the top cgroup */ ++ return &root_task_group.css; ++ } ++ ++ tg = sched_create_group(parent); ++ if (IS_ERR(tg)) ++ return ERR_PTR(-ENOMEM); ++ return &tg->css; ++} ++ ++/* Expose task group only after completing cgroup initialization */ ++static int cpu_cgroup_css_online(struct cgroup_subsys_state *css) ++{ ++ struct task_group *tg = css_tg(css); ++ struct task_group *parent = css_tg(css->parent); ++ ++ if (parent) ++ sched_online_group(tg, parent); ++ return 0; ++} ++ ++static void cpu_cgroup_css_released(struct cgroup_subsys_state *css) ++{ ++ struct task_group *tg = css_tg(css); ++ ++ sched_offline_group(tg); ++} ++ ++static void cpu_cgroup_css_free(struct cgroup_subsys_state *css) ++{ ++ struct task_group *tg = css_tg(css); ++ ++ /* ++ * Relies on the RCU grace period between css_released() and this. ++ */ ++ sched_free_group(tg); ++} ++ ++static void cpu_cgroup_fork(struct task_struct *task) ++{ ++} ++ ++static int cpu_cgroup_can_attach(struct cgroup_taskset *tset) ++{ ++ return 0; ++} ++ ++static void cpu_cgroup_attach(struct cgroup_taskset *tset) ++{ ++} ++ ++static struct cftype cpu_legacy_files[] = { ++ { } /* Terminate */ ++}; ++ ++static struct cftype cpu_files[] = { ++ { } /* terminate */ ++}; ++ ++static int cpu_extra_stat_show(struct seq_file *sf, ++ struct cgroup_subsys_state *css) ++{ ++ return 0; ++} ++ ++struct cgroup_subsys cpu_cgrp_subsys = { ++ .css_alloc = cpu_cgroup_css_alloc, ++ .css_online = cpu_cgroup_css_online, ++ .css_released = cpu_cgroup_css_released, ++ .css_free = cpu_cgroup_css_free, ++ .css_extra_stat_show = cpu_extra_stat_show, ++ .fork = cpu_cgroup_fork, ++ .can_attach = cpu_cgroup_can_attach, ++ .attach = cpu_cgroup_attach, ++ .legacy_cftypes = cpu_files, ++ .legacy_cftypes = cpu_legacy_files, ++ .dfl_cftypes = cpu_files, ++ .early_init = true, ++ .threaded = true, ++}; ++#endif /* CONFIG_CGROUP_SCHED */ ++ ++#undef CREATE_TRACE_POINTS +diff --git a/kernel/sched/bmq_sched.h b/kernel/sched/bmq_sched.h +new file mode 100644 +index 000000000000..ed08dd0b8227 +--- /dev/null ++++ b/kernel/sched/bmq_sched.h +@@ -0,0 +1,473 @@ ++#ifndef BMQ_SCHED_H ++#define BMQ_SCHED_H ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#ifdef CONFIG_PARAVIRT ++# include ++#endif ++ ++#include "cpupri.h" ++ ++/* task_struct::on_rq states: */ ++#define TASK_ON_RQ_QUEUED 1 ++#define TASK_ON_RQ_MIGRATING 2 ++ ++static inline int task_on_rq_queued(struct task_struct *p) ++{ ++ return p->on_rq == TASK_ON_RQ_QUEUED; ++} ++ ++static inline int task_on_rq_migrating(struct task_struct *p) ++{ ++ return READ_ONCE(p->on_rq) == TASK_ON_RQ_MIGRATING; ++} ++ ++/* bits: ++ * RT, Low prio adj range, nice width, high prio adj range, cpu idle task */ ++#define bmq_BITS (NICE_WIDTH + 2 * MAX_PRIORITY_ADJ + 2) ++#define IDLE_TASK_SCHED_PRIO (bmq_BITS - 1) ++ ++struct bmq { ++ DECLARE_BITMAP(bitmap, bmq_BITS); ++ struct list_head heads[bmq_BITS]; ++}; ++ ++/* ++ * This is the main, per-CPU runqueue data structure. ++ * This data should only be modified by the local cpu. ++ */ ++struct rq { ++ /* runqueue lock: */ ++ raw_spinlock_t lock; ++ ++ struct task_struct *curr, *idle, *stop, *skip; ++ struct mm_struct *prev_mm; ++ ++ struct bmq queue; ++ unsigned long watermark; ++ ++ /* switch count */ ++ u64 nr_switches; ++ ++ atomic_t nr_iowait; ++ ++#ifdef CONFIG_MEMBARRIER ++ int membarrier_state; ++#endif ++ ++#ifdef CONFIG_SMP ++ int cpu; /* cpu of this runqueue */ ++ bool online; ++ ++#ifdef CONFIG_HAVE_SCHED_AVG_IRQ ++ struct sched_avg avg_irq; ++#endif ++ ++#ifdef CONFIG_SCHED_SMT ++ int active_balance; ++ struct cpu_stop_work active_balance_work; ++#endif ++#endif /* CONFIG_SMP */ ++#ifdef CONFIG_IRQ_TIME_ACCOUNTING ++ u64 prev_irq_time; ++#endif /* CONFIG_IRQ_TIME_ACCOUNTING */ ++#ifdef CONFIG_PARAVIRT ++ u64 prev_steal_time; ++#endif /* CONFIG_PARAVIRT */ ++#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING ++ u64 prev_steal_time_rq; ++#endif /* CONFIG_PARAVIRT_TIME_ACCOUNTING */ ++ ++ /* calc_load related fields */ ++ unsigned long calc_load_update; ++ long calc_load_active; ++ ++ u64 clock, last_tick; ++ u64 last_ts_switch; ++ u64 clock_task; ++ ++ unsigned long nr_running; ++ unsigned long nr_uninterruptible; ++ ++#ifdef CONFIG_SCHED_HRTICK ++#ifdef CONFIG_SMP ++ int hrtick_csd_pending; ++ call_single_data_t hrtick_csd; ++#endif ++ struct hrtimer hrtick_timer; ++#endif ++ ++#ifdef CONFIG_SCHEDSTATS ++ ++ /* latency stats */ ++ struct sched_info rq_sched_info; ++ unsigned long long rq_cpu_time; ++ /* could above be rq->cfs_rq.exec_clock + rq->rt_rq.rt_runtime ? */ ++ ++ /* sys_sched_yield() stats */ ++ unsigned int yld_count; ++ ++ /* schedule() stats */ ++ unsigned int sched_switch; ++ unsigned int sched_count; ++ unsigned int sched_goidle; ++ ++ /* try_to_wake_up() stats */ ++ unsigned int ttwu_count; ++ unsigned int ttwu_local; ++#endif /* CONFIG_SCHEDSTATS */ ++#ifdef CONFIG_CPU_IDLE ++ /* Must be inspected within a rcu lock section */ ++ struct cpuidle_state *idle_state; ++#endif ++}; ++ ++extern unsigned long calc_load_update; ++extern atomic_long_t calc_load_tasks; ++ ++extern void calc_global_load_tick(struct rq *this_rq); ++extern long calc_load_fold_active(struct rq *this_rq, long adjust); ++ ++DECLARE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues); ++#define cpu_rq(cpu) (&per_cpu(runqueues, (cpu))) ++#define this_rq() this_cpu_ptr(&runqueues) ++#define task_rq(p) cpu_rq(task_cpu(p)) ++#define cpu_curr(cpu) (cpu_rq(cpu)->curr) ++#define raw_rq() raw_cpu_ptr(&runqueues) ++ ++#ifdef CONFIG_SMP ++#if defined(CONFIG_SCHED_DEBUG) && defined(CONFIG_SYSCTL) ++void register_sched_domain_sysctl(void); ++void unregister_sched_domain_sysctl(void); ++#else ++static inline void register_sched_domain_sysctl(void) ++{ ++} ++static inline void unregister_sched_domain_sysctl(void) ++{ ++} ++#endif ++#endif /* CONFIG_SMP */ ++ ++#ifndef arch_scale_freq_capacity ++static __always_inline ++unsigned long arch_scale_freq_capacity(int cpu) ++{ ++ return SCHED_CAPACITY_SCALE; ++} ++#endif ++ ++static inline u64 __rq_clock_broken(struct rq *rq) ++{ ++ return READ_ONCE(rq->clock); ++} ++ ++static inline u64 rq_clock(struct rq *rq) ++{ ++ /* ++ * Relax lockdep_assert_held() checking as in VRQ, call to ++ * sched_info_xxxx() may not held rq->lock ++ * lockdep_assert_held(&rq->lock); ++ */ ++ return rq->clock; ++} ++ ++static inline u64 rq_clock_task(struct rq *rq) ++{ ++ /* ++ * Relax lockdep_assert_held() checking as in VRQ, call to ++ * sched_info_xxxx() may not held rq->lock ++ * lockdep_assert_held(&rq->lock); ++ */ ++ return rq->clock_task; ++} ++ ++/* ++ * {de,en}queue flags: ++ * ++ * DEQUEUE_SLEEP - task is no longer runnable ++ * ENQUEUE_WAKEUP - task just became runnable ++ * ++ */ ++ ++#define DEQUEUE_SLEEP 0x01 ++ ++#define ENQUEUE_WAKEUP 0x01 ++ ++ ++/* ++ * Below are scheduler API which using in other kernel code ++ * It use the dummy rq_flags ++ * ToDo : BMQ need to support these APIs for compatibility with mainline ++ * scheduler code. ++ */ ++struct rq_flags { ++ unsigned long flags; ++}; ++ ++struct rq *__task_rq_lock(struct task_struct *p, struct rq_flags *rf) ++ __acquires(rq->lock); ++ ++struct rq *task_rq_lock(struct task_struct *p, struct rq_flags *rf) ++ __acquires(p->pi_lock) ++ __acquires(rq->lock); ++ ++static inline void __task_rq_unlock(struct rq *rq, struct rq_flags *rf) ++ __releases(rq->lock) ++{ ++ raw_spin_unlock(&rq->lock); ++} ++ ++static inline void ++task_rq_unlock(struct rq *rq, struct task_struct *p, struct rq_flags *rf) ++ __releases(rq->lock) ++ __releases(p->pi_lock) ++{ ++ raw_spin_unlock(&rq->lock); ++ raw_spin_unlock_irqrestore(&p->pi_lock, rf->flags); ++} ++ ++static inline void ++rq_unlock_irq(struct rq *rq, struct rq_flags *rf) ++ __releases(rq->lock) ++{ ++ raw_spin_unlock_irq(&rq->lock); ++} ++ ++static inline struct rq * ++this_rq_lock_irq(struct rq_flags *rf) ++ __acquires(rq->lock) ++{ ++ struct rq *rq; ++ ++ local_irq_disable(); ++ rq = this_rq(); ++ raw_spin_lock(&rq->lock); ++ ++ return rq; ++} ++ ++static inline bool task_running(struct task_struct *p) ++{ ++ return p->on_cpu; ++} ++ ++extern struct static_key_false sched_schedstats; ++ ++static inline void sched_ttwu_pending(void) { } ++ ++#ifdef CONFIG_CPU_IDLE ++static inline void idle_set_state(struct rq *rq, ++ struct cpuidle_state *idle_state) ++{ ++ rq->idle_state = idle_state; ++} ++ ++static inline struct cpuidle_state *idle_get_state(struct rq *rq) ++{ ++ WARN_ON(!rcu_read_lock_held()); ++ return rq->idle_state; ++} ++#else ++static inline void idle_set_state(struct rq *rq, ++ struct cpuidle_state *idle_state) ++{ ++} ++ ++static inline struct cpuidle_state *idle_get_state(struct rq *rq) ++{ ++ return NULL; ++} ++#endif ++ ++static inline int cpu_of(const struct rq *rq) ++{ ++#ifdef CONFIG_SMP ++ return rq->cpu; ++#else ++ return 0; ++#endif ++} ++ ++#include "stats.h" ++ ++#ifdef CONFIG_IRQ_TIME_ACCOUNTING ++struct irqtime { ++ u64 total; ++ u64 tick_delta; ++ u64 irq_start_time; ++ struct u64_stats_sync sync; ++}; ++ ++DECLARE_PER_CPU(struct irqtime, cpu_irqtime); ++ ++/* ++ * Returns the irqtime minus the softirq time computed by ksoftirqd. ++ * Otherwise ksoftirqd's sum_exec_runtime is substracted its own runtime ++ * and never move forward. ++ */ ++static inline u64 irq_time_read(int cpu) ++{ ++ struct irqtime *irqtime = &per_cpu(cpu_irqtime, cpu); ++ unsigned int seq; ++ u64 total; ++ ++ do { ++ seq = __u64_stats_fetch_begin(&irqtime->sync); ++ total = irqtime->total; ++ } while (__u64_stats_fetch_retry(&irqtime->sync, seq)); ++ ++ return total; ++} ++#endif /* CONFIG_IRQ_TIME_ACCOUNTING */ ++ ++#ifdef CONFIG_CPU_FREQ ++DECLARE_PER_CPU(struct update_util_data __rcu *, cpufreq_update_util_data); ++ ++/** ++ * cpufreq_update_util - Take a note about CPU utilization changes. ++ * @rq: Runqueue to carry out the update for. ++ * @flags: Update reason flags. ++ * ++ * This function is called by the scheduler on the CPU whose utilization is ++ * being updated. ++ * ++ * It can only be called from RCU-sched read-side critical sections. ++ * ++ * The way cpufreq is currently arranged requires it to evaluate the CPU ++ * performance state (frequency/voltage) on a regular basis to prevent it from ++ * being stuck in a completely inadequate performance level for too long. ++ * That is not guaranteed to happen if the updates are only triggered from CFS ++ * and DL, though, because they may not be coming in if only RT tasks are ++ * active all the time (or there are RT tasks only). ++ * ++ * As a workaround for that issue, this function is called periodically by the ++ * RT sched class to trigger extra cpufreq updates to prevent it from stalling, ++ * but that really is a band-aid. Going forward it should be replaced with ++ * solutions targeted more specifically at RT tasks. ++ */ ++static inline void cpufreq_update_util(struct rq *rq, unsigned int flags) ++{ ++ struct update_util_data *data; ++ ++ data = rcu_dereference_sched(*per_cpu_ptr(&cpufreq_update_util_data, ++ cpu_of(rq))); ++ if (data) ++ data->func(data, rq_clock(rq), flags); ++} ++#else ++static inline void cpufreq_update_util(struct rq *rq, unsigned int flags) {} ++#endif /* CONFIG_CPU_FREQ */ ++ ++#ifdef CONFIG_NO_HZ_FULL ++extern int __init sched_tick_offload_init(void); ++#else ++static inline int sched_tick_offload_init(void) { return 0; } ++#endif ++ ++#ifdef arch_scale_freq_capacity ++#ifndef arch_scale_freq_invariant ++#define arch_scale_freq_invariant() (true) ++#endif ++#else /* arch_scale_freq_capacity */ ++#define arch_scale_freq_invariant() (false) ++#endif ++ ++extern void schedule_idle(void); ++ ++/* ++ * !! For sched_setattr_nocheck() (kernel) only !! ++ * ++ * This is actually gross. :( ++ * ++ * It is used to make schedutil kworker(s) higher priority than SCHED_DEADLINE ++ * tasks, but still be able to sleep. We need this on platforms that cannot ++ * atomically change clock frequency. Remove once fast switching will be ++ * available on such platforms. ++ * ++ * SUGOV stands for SchedUtil GOVernor. ++ */ ++#define SCHED_FLAG_SUGOV 0x10000000 ++ ++#ifdef CONFIG_MEMBARRIER ++/* ++ * The scheduler provides memory barriers required by membarrier between: ++ * - prior user-space memory accesses and store to rq->membarrier_state, ++ * - store to rq->membarrier_state and following user-space memory accesses. ++ * In the same way it provides those guarantees around store to rq->curr. ++ */ ++static inline void membarrier_switch_mm(struct rq *rq, ++ struct mm_struct *prev_mm, ++ struct mm_struct *next_mm) ++{ ++ int membarrier_state; ++ ++ if (prev_mm == next_mm) ++ return; ++ ++ membarrier_state = atomic_read(&next_mm->membarrier_state); ++ if (READ_ONCE(rq->membarrier_state) == membarrier_state) ++ return; ++ ++ WRITE_ONCE(rq->membarrier_state, membarrier_state); ++} ++#else ++static inline void membarrier_switch_mm(struct rq *rq, ++ struct mm_struct *prev_mm, ++ struct mm_struct *next_mm) ++{ ++} ++#endif ++ ++static inline int task_running_nice(struct task_struct *p) ++{ ++ return (p->prio + p->boost_prio > DEFAULT_PRIO + MAX_PRIORITY_ADJ); ++} ++ ++#ifdef CONFIG_NUMA ++extern int sched_numa_find_closest(const struct cpumask *cpus, int cpu); ++#else ++static inline int sched_numa_find_closest(const struct cpumask *cpus, int cpu) ++{ ++ return nr_cpu_ids; ++} ++#endif ++#endif /* BMQ_SCHED_H */ +diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c +index 86800b4d5453..a816aafa6ba3 100644 +--- a/kernel/sched/cpufreq_schedutil.c ++++ b/kernel/sched/cpufreq_schedutil.c +@@ -185,6 +185,7 @@ static unsigned int get_next_freq(struct sugov_policy *sg_policy, + return cpufreq_driver_resolve_freq(policy, freq); + } + ++#ifndef CONFIG_SCHED_BMQ + /* + * This function computes an effective utilization for the given CPU, to be + * used for frequency selection given the linear relation: f = u * f_max. +@@ -302,6 +303,13 @@ static unsigned long sugov_get_util(struct sugov_cpu *sg_cpu) + + return schedutil_cpu_util(sg_cpu->cpu, util, max, FREQUENCY_UTIL, NULL); + } ++#else /* CONFIG_SCHED_BMQ */ ++static unsigned long sugov_get_util(struct sugov_cpu *sg_cpu) ++{ ++ sg_cpu->max = arch_scale_cpu_capacity(sg_cpu->cpu); ++ return sg_cpu->max; ++} ++#endif + + /** + * sugov_iowait_reset() - Reset the IO boost status of a CPU. +@@ -445,7 +453,9 @@ static inline bool sugov_cpu_is_busy(struct sugov_cpu *sg_cpu) { return false; } + */ + static inline void ignore_dl_rate_limit(struct sugov_cpu *sg_cpu, struct sugov_policy *sg_policy) + { ++#ifndef CONFIG_SCHED_BMQ + if (cpu_bw_dl(cpu_rq(sg_cpu->cpu)) > sg_cpu->bw_dl) ++#endif + sg_policy->limits_changed = true; + } + +@@ -688,6 +698,7 @@ static int sugov_kthread_create(struct sugov_policy *sg_policy) + } + + ret = sched_setattr_nocheck(thread, &attr); ++ + if (ret) { + kthread_stop(thread); + pr_warn("%s: failed to set SCHED_DEADLINE\n", __func__); +@@ -918,6 +929,7 @@ static int __init sugov_register(void) + fs_initcall(sugov_register); + + #ifdef CONFIG_ENERGY_MODEL ++#ifndef CONFIG_SCHED_BMQ + extern bool sched_energy_update; + extern struct mutex sched_energy_mutex; + +@@ -948,4 +960,10 @@ void sched_cpufreq_governor_change(struct cpufreq_policy *policy, + } + + } ++#else /* CONFIG_SCHED_BMQ */ ++void sched_cpufreq_governor_change(struct cpufreq_policy *policy, ++ struct cpufreq_governor *old_gov) ++{ ++} ++#endif + #endif +diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c +index 46ed4e1383e2..51460a446da0 100644 +--- a/kernel/sched/cputime.c ++++ b/kernel/sched/cputime.c +@@ -122,7 +122,7 @@ void account_user_time(struct task_struct *p, u64 cputime) + p->utime += cputime; + account_group_user_time(p, cputime); + +- index = (task_nice(p) > 0) ? CPUTIME_NICE : CPUTIME_USER; ++ index = task_running_nice(p) ? CPUTIME_NICE : CPUTIME_USER; + + /* Add user time to cpustat. */ + task_group_account_field(p, index, cputime); +@@ -146,7 +146,7 @@ void account_guest_time(struct task_struct *p, u64 cputime) + p->gtime += cputime; + + /* Add guest time to cpustat. */ +- if (task_nice(p) > 0) { ++ if (task_running_nice(p)) { + cpustat[CPUTIME_NICE] += cputime; + cpustat[CPUTIME_GUEST_NICE] += cputime; + } else { +@@ -269,7 +269,7 @@ static inline u64 account_other_time(u64 max) + #ifdef CONFIG_64BIT + static inline u64 read_sum_exec_runtime(struct task_struct *t) + { +- return t->se.sum_exec_runtime; ++ return tsk_seruntime(t); + } + #else + static u64 read_sum_exec_runtime(struct task_struct *t) +@@ -279,7 +279,7 @@ static u64 read_sum_exec_runtime(struct task_struct *t) + struct rq *rq; + + rq = task_rq_lock(t, &rf); +- ns = t->se.sum_exec_runtime; ++ ns = tsk_seruntime(t); + task_rq_unlock(rq, t, &rf); + + return ns; +@@ -663,7 +663,7 @@ void cputime_adjust(struct task_cputime *curr, struct prev_cputime *prev, + void task_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st) + { + struct task_cputime cputime = { +- .sum_exec_runtime = p->se.sum_exec_runtime, ++ .sum_exec_runtime = tsk_seruntime(p), + }; + + task_cputime(p, &cputime.utime, &cputime.stime); +diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c +index f65ef1e2f204..77bf219444fa 100644 +--- a/kernel/sched/idle.c ++++ b/kernel/sched/idle.c +@@ -355,6 +355,7 @@ void cpu_startup_entry(enum cpuhp_state state) + do_idle(); + } + ++#ifndef CONFIG_SCHED_BMQ + /* + * idle-task scheduling class. + */ +@@ -479,3 +480,4 @@ const struct sched_class idle_sched_class = { + .switched_to = switched_to_idle, + .update_curr = update_curr_idle, + }; ++#endif +diff --git a/kernel/sched/pelt.c b/kernel/sched/pelt.c +index a96db50d40e0..22c20e28b613 100644 +--- a/kernel/sched/pelt.c ++++ b/kernel/sched/pelt.c +@@ -236,6 +236,7 @@ ___update_load_avg(struct sched_avg *sa, unsigned long load, unsigned long runna + WRITE_ONCE(sa->util_avg, sa->util_sum / divider); + } + ++#ifndef CONFIG_SCHED_BMQ + /* + * sched_entity: + * +@@ -352,6 +353,7 @@ int update_dl_rq_load_avg(u64 now, struct rq *rq, int running) + + return 0; + } ++#endif + + #ifdef CONFIG_HAVE_SCHED_AVG_IRQ + /* +diff --git a/kernel/sched/pelt.h b/kernel/sched/pelt.h +index afff644da065..4da52afaeff8 100644 +--- a/kernel/sched/pelt.h ++++ b/kernel/sched/pelt.h +@@ -1,11 +1,13 @@ + #ifdef CONFIG_SMP + #include "sched-pelt.h" + ++#ifndef CONFIG_SCHED_BMQ + int __update_load_avg_blocked_se(u64 now, struct sched_entity *se); + int __update_load_avg_se(u64 now, struct cfs_rq *cfs_rq, struct sched_entity *se); + int __update_load_avg_cfs_rq(u64 now, struct cfs_rq *cfs_rq); + int update_rt_rq_load_avg(u64 now, struct rq *rq, int running); + int update_dl_rq_load_avg(u64 now, struct rq *rq, int running); ++#endif + + #ifdef CONFIG_HAVE_SCHED_AVG_IRQ + int update_irq_load_avg(struct rq *rq, u64 running); +@@ -17,6 +19,7 @@ update_irq_load_avg(struct rq *rq, u64 running) + } + #endif + ++#ifndef CONFIG_SCHED_BMQ + /* + * When a task is dequeued, its estimated utilization should not be update if + * its util_avg has not been updated at least once. +@@ -137,9 +140,11 @@ static inline u64 cfs_rq_clock_pelt(struct cfs_rq *cfs_rq) + return rq_clock_pelt(rq_of(cfs_rq)); + } + #endif ++#endif /* CONFIG_SCHED_BMQ */ + + #else + ++#ifndef CONFIG_SCHED_BMQ + static inline int + update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq) + { +@@ -157,6 +162,7 @@ update_dl_rq_load_avg(u64 now, struct rq *rq, int running) + { + return 0; + } ++#endif + + static inline int + update_irq_load_avg(struct rq *rq, u64 running) +diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h +index c8870c5bd7df..4bca9838b6f0 100644 +--- a/kernel/sched/sched.h ++++ b/kernel/sched/sched.h +@@ -2,6 +2,10 @@ + /* + * Scheduler internal types and methods: + */ ++#ifdef CONFIG_SCHED_BMQ ++#include "bmq_sched.h" ++#else ++ + #include + + #include +@@ -2496,3 +2500,9 @@ static inline void membarrier_switch_mm(struct rq *rq, + { + } + #endif ++ ++static inline int task_running_nice(struct task_struct *p) ++{ ++ return (task_nice(p) > 0); ++} ++#endif /* !CONFIG_SCHED_BMQ */ +diff --git a/kernel/sched/stats.c b/kernel/sched/stats.c +index 750fb3c67eed..0cc040a28d3f 100644 +--- a/kernel/sched/stats.c ++++ b/kernel/sched/stats.c +@@ -22,8 +22,10 @@ static int show_schedstat(struct seq_file *seq, void *v) + } else { + struct rq *rq; + #ifdef CONFIG_SMP ++#ifndef CONFIG_SCHED_BMQ + struct sched_domain *sd; + int dcount = 0; ++#endif + #endif + cpu = (unsigned long)(v - 2); + rq = cpu_rq(cpu); +@@ -40,6 +42,7 @@ static int show_schedstat(struct seq_file *seq, void *v) + seq_printf(seq, "\n"); + + #ifdef CONFIG_SMP ++#ifndef CONFIG_SCHED_BMQ + /* domain-specific stats */ + rcu_read_lock(); + for_each_domain(cpu, sd) { +@@ -68,6 +71,7 @@ static int show_schedstat(struct seq_file *seq, void *v) + sd->ttwu_move_balance); + } + rcu_read_unlock(); ++#endif + #endif + } + return 0; +diff --git a/kernel/sysctl.c b/kernel/sysctl.c +index b6f2f35d0bcf..435440943455 100644 +--- a/kernel/sysctl.c ++++ b/kernel/sysctl.c +@@ -132,6 +132,10 @@ static unsigned long one_ul = 1; + static unsigned long long_max = LONG_MAX; + static int one_hundred = 100; + static int one_thousand = 1000; ++#ifdef CONFIG_SCHED_BMQ ++static int __maybe_unused zero = 0; ++extern int sched_yield_type; ++#endif + #ifdef CONFIG_PRINTK + static int ten_thousand = 10000; + #endif +@@ -300,7 +304,7 @@ static struct ctl_table sysctl_base_table[] = { + { } + }; + +-#ifdef CONFIG_SCHED_DEBUG ++#if defined(CONFIG_SCHED_DEBUG) && !defined(CONFIG_SCHED_BMQ) + static int min_sched_granularity_ns = 100000; /* 100 usecs */ + static int max_sched_granularity_ns = NSEC_PER_SEC; /* 1 second */ + static int min_wakeup_granularity_ns; /* 0 usecs */ +@@ -317,6 +321,7 @@ static int max_extfrag_threshold = 1000; + #endif + + static struct ctl_table kern_table[] = { ++#ifndef CONFIG_SCHED_BMQ + { + .procname = "sched_child_runs_first", + .data = &sysctl_sched_child_runs_first, +@@ -498,6 +503,7 @@ static struct ctl_table kern_table[] = { + .extra2 = SYSCTL_ONE, + }, + #endif ++#endif /* !CONFIG_SCHED_BMQ */ + #ifdef CONFIG_PROVE_LOCKING + { + .procname = "prove_locking", +@@ -1070,6 +1076,17 @@ static struct ctl_table kern_table[] = { + .proc_handler = proc_dointvec, + }, + #endif ++#ifdef CONFIG_SCHED_BMQ ++ { ++ .procname = "yield_type", ++ .data = &sched_yield_type, ++ .maxlen = sizeof (int), ++ .mode = 0644, ++ .proc_handler = &proc_dointvec_minmax, ++ .extra1 = &zero, ++ .extra2 = &two, ++ }, ++#endif + #if defined(CONFIG_S390) && defined(CONFIG_SMP) + { + .procname = "spin_retry", +diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c +index 42d512fcfda2..70b97fe0ff44 100644 +--- a/kernel/time/posix-cpu-timers.c ++++ b/kernel/time/posix-cpu-timers.c +@@ -226,7 +226,7 @@ static void task_sample_cputime(struct task_struct *p, u64 *samples) + u64 stime, utime; + + task_cputime(p, &utime, &stime); +- store_samples(samples, stime, utime, p->se.sum_exec_runtime); ++ store_samples(samples, stime, utime, tsk_seruntime(p)); + } + + static void proc_sample_cputime_atomic(struct task_cputime_atomic *at, +@@ -796,6 +796,7 @@ static void collect_posix_cputimers(struct posix_cputimers *pct, u64 *samples, + } + } + ++#ifndef CONFIG_SCHED_BMQ + static inline void check_dl_overrun(struct task_struct *tsk) + { + if (tsk->dl.dl_overrun) { +@@ -803,6 +804,7 @@ static inline void check_dl_overrun(struct task_struct *tsk) + __group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk); + } + } ++#endif + + static bool check_rlimit(u64 time, u64 limit, int signo, bool rt, bool hard) + { +@@ -830,8 +832,10 @@ static void check_thread_timers(struct task_struct *tsk, + u64 samples[CPUCLOCK_MAX]; + unsigned long soft; + ++#ifndef CONFIG_SCHED_BMQ + if (dl_task(tsk)) + check_dl_overrun(tsk); ++#endif + + if (expiry_cache_is_inactive(pct)) + return; +@@ -845,7 +849,7 @@ static void check_thread_timers(struct task_struct *tsk, + soft = task_rlimit(tsk, RLIMIT_RTTIME); + if (soft != RLIM_INFINITY) { + /* Task RT timeout is accounted in jiffies. RTTIME is usec */ +- unsigned long rttime = tsk->rt.timeout * (USEC_PER_SEC / HZ); ++ unsigned long rttime = tsk_rttimeout(tsk) * (USEC_PER_SEC / HZ); + unsigned long hard = task_rlimit_max(tsk, RLIMIT_RTTIME); + + /* At the hard limit, send SIGKILL. No further action. */ +@@ -1099,8 +1103,10 @@ static inline bool fastpath_timer_check(struct task_struct *tsk) + return true; + } + ++#ifndef CONFIG_SCHED_BMQ + if (dl_task(tsk) && tsk->dl.dl_overrun) + return true; ++#endif + + return false; + } +diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c +index 69ee8ef12cee..208788fcbb0e 100644 +--- a/kernel/trace/trace_selftest.c ++++ b/kernel/trace/trace_selftest.c +@@ -1048,10 +1048,15 @@ static int trace_wakeup_test_thread(void *data) + { + /* Make this a -deadline thread */ + static const struct sched_attr attr = { ++#ifdef CONFIG_SCHED_BMQ ++ /* No deadline on BMQ, use RR */ ++ .sched_policy = SCHED_RR, ++#else + .sched_policy = SCHED_DEADLINE, + .sched_runtime = 100000ULL, + .sched_deadline = 10000000ULL, + .sched_period = 10000000ULL ++#endif + }; + struct wakeup_test_data *x = data; + + +diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c +index 2faae37f4820..37f4166f1a56 100644 +--- a/kernel/sched/cpufreq_schedutil.c ++++ b/kernel/sched/cpufreq_schedutil.c +@@ -304,8 +304,11 @@ + #else /* CONFIG_SCHED_BMQ */ + static unsigned long sugov_get_util(struct sugov_cpu *sg_cpu) + { +- sg_cpu->max = arch_scale_cpu_capacity(sg_cpu->cpu); +- return sg_cpu->max; ++ unsigned long max = arch_scale_cpu_capacity(sg_cpu->cpu); ++ ++ sg_cpu->max = max; ++ sg_cpu->bw_dl = 0; ++ return cpu_rq(sg_cpu->cpu)->nr_running ? max:0UL; + } + #endif + +@@ -453,8 +456,8 @@ + { + #ifndef CONFIG_SCHED_BMQ + if (cpu_bw_dl(cpu_rq(sg_cpu->cpu)) > sg_cpu->bw_dl) +-#endif + sg_policy->limits_changed = true; ++#endif + } + + static void sugov_update_single(struct update_util_data *hook, u64 time, + +--- a/kernel/sched/bmq.c 2021-11-27 13:52:36.449325000 +0800 ++++ b/kernel/sched/bmq.c 2021-11-27 13:55:59.249109829 +0800 +@@ -630,14 +630,6 @@ + + sched_info_queued(rq, p); + psi_enqueue(p, flags); +- +- /* +- * If in_iowait is set, the code below may not trigger any cpufreq +- * utilization updates, so do it here explicitly with the IOWAIT flag +- * passed. +- */ +- if (p->in_iowait) +- cpufreq_update_util(rq, SCHED_CPUFREQ_IOWAIT); + } + + static inline void requeue_task(struct task_struct *p, struct rq *rq) +@@ -888,7 +880,12 @@ + rq->nr_uninterruptible--; + enqueue_task(p, rq, ENQUEUE_WAKEUP); + p->on_rq = TASK_ON_RQ_QUEUED; +- cpufreq_update_util(rq, 0); ++ /* ++ * If in_iowait is set, the code below may not trigger any cpufreq ++ * utilization updates, so do it here explicitly with the IOWAIT flag ++ * passed. ++ */ ++ cpufreq_update_util(rq, SCHED_CPUFREQ_IOWAIT * p->in_iowait); + } + + /* + +--- a/kernel/sched/cpufreq_schedutil.c 2021-11-27 13:52:36.453325000 +0800 ++++ b/kernel/sched/cpufreq_schedutil.c 2021-11-27 14:00:29.514065276 +0800 +@@ -55,6 +55,13 @@ + + unsigned long bw_dl; + unsigned long max; ++ ++#ifdef CONFIG_SCHED_BMQ ++ /* For genenal cpu load util */ ++ s32 load_history; ++ u64 load_block; ++ u64 load_stamp; ++#endif + + /* The field below is for single-CPU policies only: */ + #ifdef CONFIG_NO_HZ_COMMON +@@ -302,15 +309,52 @@ + return schedutil_cpu_util(sg_cpu->cpu, util, max, FREQUENCY_UTIL, NULL); + } + #else /* CONFIG_SCHED_BMQ */ ++ ++#define SG_CPU_LOAD_HISTORY_BITS (sizeof(s32) * 8ULL) ++#define SG_CPU_UTIL_SHIFT (8) ++#define SG_CPU_LOAD_HISTORY_SHIFT (SG_CPU_LOAD_HISTORY_BITS - 1 - SG_CPU_UTIL_SHIFT) ++#define SG_CPU_LOAD_HISTORY_TO_UTIL(l) (((l) >> SG_CPU_LOAD_HISTORY_SHIFT) & 0xff) ++ ++#define LOAD_BLOCK(t) ((t) >> 17) ++#define LOAD_HALF_BLOCK(t) ((t) >> 16) ++#define BLOCK_MASK(t) ((t) & ((0x01 << 18) - 1)) ++#define LOAD_BLOCK_BIT(b) (1UL << (SG_CPU_LOAD_HISTORY_BITS - 1 - (b))) ++#define CURRENT_LOAD_BIT LOAD_BLOCK_BIT(0) ++ + static unsigned long sugov_get_util(struct sugov_cpu *sg_cpu) + { + unsigned long max = arch_scale_cpu_capacity(sg_cpu->cpu); + + sg_cpu->max = max; + sg_cpu->bw_dl = 0; +- return cpu_rq(sg_cpu->cpu)->nr_running ? max:0UL; ++ return SG_CPU_LOAD_HISTORY_TO_UTIL(sg_cpu->load_history) * ++ (max >> SG_CPU_UTIL_SHIFT); + } +-#endif ++static inline void sugov_cpu_load_update(struct sugov_cpu *sg_cpu, u64 time) ++{ ++ u64 delta = min(LOAD_BLOCK(time) - LOAD_BLOCK(sg_cpu->load_stamp), ++ SG_CPU_LOAD_HISTORY_BITS - 1); ++ u64 prev = !!(sg_cpu->load_history & CURRENT_LOAD_BIT); ++ u64 curr = !!cpu_rq(sg_cpu->cpu)->nr_running; ++ ++ if (delta) { ++ sg_cpu->load_history = sg_cpu->load_history >> delta; ++ ++ if (delta <= SG_CPU_UTIL_SHIFT) { ++ sg_cpu->load_block += (~BLOCK_MASK(sg_cpu->load_stamp)) * prev; ++ if (!!LOAD_HALF_BLOCK(sg_cpu->load_block) ^ curr) ++ sg_cpu->load_history ^= LOAD_BLOCK_BIT(delta); ++ } ++ ++ sg_cpu->load_block = BLOCK_MASK(time) * prev; ++ } else { ++ sg_cpu->load_block += (time - sg_cpu->load_stamp) * prev; ++ } ++ if (prev ^ curr) ++ sg_cpu->load_history ^= CURRENT_LOAD_BIT; ++ sg_cpu->load_stamp = time; ++} ++#endif /* CONFIG_SCHED_BMQ */ + + /** + * sugov_iowait_reset() - Reset the IO boost status of a CPU. +@@ -469,6 +513,10 @@ + unsigned int next_f; + bool busy; + ++#ifdef CONFIG_SCHED_BMQ ++ sugov_cpu_load_update(sg_cpu, time); ++#endif /* CONFIG_SCHED_BMQ */ ++ + sugov_iowait_boost(sg_cpu, time, flags); + sg_cpu->last_update = time; + +@@ -542,6 +590,10 @@ + + raw_spin_lock(&sg_policy->update_lock); + ++#ifdef CONFIG_SCHED_BMQ ++ sugov_cpu_load_update(sg_cpu, time); ++#endif /* CONFIG_SCHED_BMQ */ ++ + sugov_iowait_boost(sg_cpu, time, flags); + sg_cpu->last_update = time; + diff --git a/README.md b/README.md index d40af29fe..d0d8079b5 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ - O3 编译,CFLAG优化 - 插件包含:SSRP,PassWall,OpenClash,AdguardHome,微信推送,网易云解锁,SQM,DNSProxy,网络唤醒,DDNS,迅雷快鸟,UPNP,FullCone(防火墙中开启,默认开启),流量分载,irq优化,京东签到,Zerotier,FRPC,FRPS,无线打印,流量监控,过滤军刀,R2S-OLED - ss协议在armv8上实现了aes硬件加速(请仅使用aead加密的连接方式) -- 集成并默认启用了BBRv2,LRNG,以及MuQSS Scheduler +- 集成并默认启用了BBRv2,LRNG,以及BMQ Scheduler - 如有任何问题,请先尝试ssh进入后台,输入fuck后回车,等待机器重启后确认问题是否已经解决 ### 下载 diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 81b7d0780..234f77cc3 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -38,11 +38,11 @@ wget -qO - https://github.com/openwrt/openwrt/commit/cfaf039.patch | patch -p1 #wget -qO - https://github.com/QiuSimons/openwrt-NoTengoBattery/commit/7d44cab.patch | patch -p1 #wget https://github.com/hamadmarri/cacule-cpu-scheduler/raw/master/patches/CacULE/v5.4/cacule-5.4.patch -O ./target/linux/generic/hack-5.4/694-cacule-5.4.patch # MuQSS -cp -f ../PATCH/MuQSS/0001-MultiQueue-Skiplist-Scheduler-v0.196.patch ./target/linux/generic/hack-5.4/694-0001-MultiQueue-Skiplist-Scheduler-v0.196.patch -cp -f ../PATCH/MuQSS/0002-MuQSS-Fix-build-error-on-config-leak.patch ./target/linux/generic/hack-5.4/694-0002-MuQSS-Fix-build-error-on-config-leak.patch -cp -f ../PATCH/MuQSS/0003-Work-around-x86-only-llc-stuff.patch ./target/linux/generic/hack-5.4/694-0003-Work-around-x86-only-llc-stuff.patch +#cp -f ../PATCH/MuQSS/0001-MultiQueue-Skiplist-Scheduler-v0.196.patch ./target/linux/generic/hack-5.4/694-0001-MultiQueue-Skiplist-Scheduler-v0.196.patch +#cp -f ../PATCH/MuQSS/0002-MuQSS-Fix-build-error-on-config-leak.patch ./target/linux/generic/hack-5.4/694-0002-MuQSS-Fix-build-error-on-config-leak.patch +#cp -f ../PATCH/MuQSS/0003-Work-around-x86-only-llc-stuff.patch ./target/linux/generic/hack-5.4/694-0003-Work-around-x86-only-llc-stuff.patch # BMQ -#wget https://gitlab.com/alfredchen/projectc/-/raw/master/5.4/bmq_v5.4-r2.patch -O ./target/linux/generic/hack-5.4/694-bmq_v5.4-r2.patch +cp -f ../PATCH/BMQ/01-bmq_v5.4-r2.patch ./target/linux/generic/hack-5.4/694-01-bmq_v5.4-r2.patch # PDS #wget https://github.com/Frogging-Family/linux-tkg/raw/master/linux-tkg-patches/5.4/0005-v5.4_undead-pds099o.patch -O ./target/linux/generic/hack-5.4/694-0005-01-v5.4_undead-pds099o.patch #wget https://github.com/Frogging-Family/linux-tkg/raw/master/linux-tkg-patches/5.4/0005-glitched-pds.patch -O ./target/linux/generic/hack-5.4/694-0005-02-glitched-pds.patch From 7b84145e1edb2883820ba37737afae9266dbaea3 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sat, 27 Nov 2021 09:41:25 +0800 Subject: [PATCH 210/244] PDS --- PATCH/PDS/v5.4_undead-pds099o.patch | 8456 +++++++++++++++++++++++++++ README.md | 2 +- SCRIPTS/02_prepare_package.sh | 4 +- 3 files changed, 8459 insertions(+), 3 deletions(-) create mode 100644 PATCH/PDS/v5.4_undead-pds099o.patch diff --git a/PATCH/PDS/v5.4_undead-pds099o.patch b/PATCH/PDS/v5.4_undead-pds099o.patch new file mode 100644 index 000000000..0b556e2e3 --- /dev/null +++ b/PATCH/PDS/v5.4_undead-pds099o.patch @@ -0,0 +1,8456 @@ +From 89067d28ca90681fc6cf108de79b9aedb93dfa9d Mon Sep 17 00:00:00 2001 +From: Tk-Glitch +Date: Mon, 25 Nov 2019 21:46:23 +0100 +Subject: PDS 099o, 5.4 rebase + + +--- a/Documentation/admin-guide/sysctl/kernel.rst ++++ b/Documentation/admin-guide/sysctl/kernel.rst +@@ -82,6 +82,7 @@ show up in /proc/sys/kernel: + - randomize_va_space + - real-root-dev ==> Documentation/admin-guide/initrd.rst + - reboot-cmd [ SPARC only ] ++- rr_interval + - rtsig-max + - rtsig-nr + - sched_energy_aware +@@ -105,6 +106,7 @@ show up in /proc/sys/kernel: + - unknown_nmi_panic + - watchdog + - watchdog_thresh ++- yield_type + - version + + +--- /dev/null ++++ b/Documentation/scheduler/sched-PDS-mq.txt +@@ -0,0 +1,56 @@ ++ Priority and Deadline based Skiplist multiple queue Scheduler ++ ------------------------------------------------------------- ++ ++CONTENT ++======== ++ ++ 0. Development ++ 1. Overview ++ 1.1 Design goal ++ 1.2 Design summary ++ 2. Design Detail ++ 2.1 Skip list implementation ++ 2.2 Task preempt ++ 2.3 Task policy, priority and deadline ++ 2.4 Task selection ++ 2.5 Run queue balance ++ 2.6 Task migration ++ ++ ++0. Development ++============== ++ ++Priority and Deadline based Skiplist multiple queue scheduler, referred to as ++PDS from here on, is developed upon the enhancement patchset VRQ(Variable Run ++Queue) for BFS(Brain Fuck Scheduler by Con Kolivas). PDS inherits the existing ++design from VRQ and inspired by the introduction of skiplist data structure ++to the scheduler by Con Kolivas. However, PDS is different from MuQSS(Multiple ++Queue Skiplist Scheduler, the successor after BFS) in many ways. ++ ++1. Overview ++=========== ++ ++1.1 Design goal ++--------------- ++ ++PDS is designed to make the cpu process scheduler code to be simple, but while ++efficiency and scalable. Be Simple, the scheduler code will be easy to be read ++and the behavious of scheduler will be easy to predict. Be efficiency, the ++scheduler shall be well balance the thoughput performance and task interactivity ++at the same time for different properties the tasks behave. Be scalable, the ++performance of the scheduler should be in good shape with the glowing of ++workload or with the growing of the cpu numbers. ++ ++1.2 Design summary ++------------------ ++ ++PDS is described as a multiple run queues cpu scheduler. Each cpu has its own ++run queue. A heavry customized skiplist is used as the backend data structure ++of the cpu run queue. Tasks in run queue is sorted by priority then virtual ++deadline(simplfy to just deadline from here on). In PDS, balance action among ++run queues are kept as less as possible to reduce the migration cost. Cpumask ++data structure is widely used in cpu affinity checking and cpu preemption/ ++selection to make PDS scalable with increasing cpu number. ++ ++ ++To be continued... +--- a/arch/powerpc/platforms/cell/spufs/sched.c ++++ b/arch/powerpc/platforms/cell/spufs/sched.c +@@ -52,11 +52,6 @@ static struct timer_list spusched_timer; + static struct timer_list spuloadavg_timer; + + /* +- * Priority of a normal, non-rt, non-niced'd process (aka nice level 0). +- */ +-#define NORMAL_PRIO 120 +- +-/* + * Frequency of the spu scheduler tick. By default we do one SPU scheduler + * tick for every 10 CPU scheduler ticks. + */ +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -1035,6 +1035,22 @@ config NR_CPUS + config SCHED_SMT + def_bool y if SMP + ++config SMT_NICE ++ bool "SMT (Hyperthreading) aware nice priority and policy support" ++ depends on SCHED_PDS && SCHED_SMT ++ default y ++ ---help--- ++ Enabling Hyperthreading on Intel CPUs decreases the effectiveness ++ of the use of 'nice' levels and different scheduling policies ++ (e.g. realtime) due to sharing of CPU power between hyperthreads. ++ SMT nice support makes each logical CPU aware of what is running on ++ its hyperthread siblings, maintaining appropriate distribution of ++ CPU according to nice levels and scheduling policies at the expense ++ of slightly increased overhead. ++ ++ If unsure say Y here. ++ ++ + config SCHED_MC + def_bool y + prompt "Multi-core scheduler support" +--- a/drivers/cpufreq/cpufreq_conservative.c ++++ b/drivers/cpufreq/cpufreq_conservative.c +@@ -28,8 +28,8 @@ struct cs_dbs_tuners { + }; + + /* Conservative governor macros */ +-#define DEF_FREQUENCY_UP_THRESHOLD (80) +-#define DEF_FREQUENCY_DOWN_THRESHOLD (20) ++#define DEF_FREQUENCY_UP_THRESHOLD (63) ++#define DEF_FREQUENCY_DOWN_THRESHOLD (26) + #define DEF_FREQUENCY_STEP (5) + #define DEF_SAMPLING_DOWN_FACTOR (1) + #define MAX_SAMPLING_DOWN_FACTOR (10) +--- a/drivers/cpufreq/cpufreq_ondemand.c ++++ b/drivers/cpufreq/cpufreq_ondemand.c +@@ -18,7 +18,7 @@ + #include "cpufreq_ondemand.h" + + /* On-demand governor macros */ +-#define DEF_FREQUENCY_UP_THRESHOLD (80) ++#define DEF_FREQUENCY_UP_THRESHOLD (63) + #define DEF_SAMPLING_DOWN_FACTOR (1) + #define MAX_SAMPLING_DOWN_FACTOR (100000) + #define MICRO_FREQUENCY_UP_THRESHOLD (95) +@@ -127,7 +127,7 @@ static void dbs_freq_increase(struct cpu + } + + /* +- * Every sampling_rate, we check, if current idle time is less than 20% ++ * Every sampling_rate, we check, if current idle time is less than 37% + * (default), then we try to increase frequency. Else, we adjust the frequency + * proportional to load. + */ +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -477,7 +477,7 @@ static int proc_pid_schedstat(struct seq + seq_puts(m, "0 0 0\n"); + else + seq_printf(m, "%llu %llu %lu\n", +- (unsigned long long)task->se.sum_exec_runtime, ++ (unsigned long long)tsk_seruntime(task), + (unsigned long long)task->sched_info.run_delay, + task->sched_info.pcount); + +--- a/include/linux/init_task.h ++++ b/include/linux/init_task.h +@@ -36,7 +36,11 @@ extern struct cred init_cred; + #define INIT_PREV_CPUTIME(x) + #endif + ++#ifdef CONFIG_SCHED_PDS ++#define INIT_TASK_COMM "PDS" ++#else + #define INIT_TASK_COMM "swapper" ++#endif /* !CONFIG_SCHED_PDS */ + + /* Attach to the init_task data structure for proper alignment */ + #ifdef CONFIG_ARCH_TASK_STRUCT_ON_STACK +--- a/include/linux/jiffies.h ++++ b/include/linux/jiffies.h +@@ -171,7 +171,7 @@ static inline u64 get_jiffies_64(void) + * Have the 32 bit jiffies value wrap 5 minutes after boot + * so jiffies wrap bugs show up earlier. + */ +-#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ)) ++#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-10*HZ)) + + /* + * Change timeval to jiffies, trying to avoid the +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + + /* task_struct member predeclarations (sorted alphabetically): */ + struct audit_context; +@@ -644,9 +645,13 @@ struct task_struct { + unsigned int flags; + unsigned int ptrace; + +-#ifdef CONFIG_SMP ++#if defined(CONFIG_SMP) && !defined(CONFIG_SCHED_PDS) + struct llist_node wake_entry; ++#endif ++#if defined(CONFIG_SMP) || defined(CONFIG_SCHED_PDS) + int on_cpu; ++#endif ++#ifdef CONFIG_SMP + #ifdef CONFIG_THREAD_INFO_IN_TASK + /* Current CPU: */ + unsigned int cpu; +@@ -655,6 +660,7 @@ struct task_struct { + unsigned long wakee_flip_decay_ts; + struct task_struct *last_wakee; + ++#ifndef CONFIG_SCHED_PDS + /* + * recent_used_cpu is initially set as the last CPU used by a task + * that wakes affine another task. Waker/wakee relationships can +@@ -663,6 +669,7 @@ struct task_struct { + * used CPU that may be idle. + */ + int recent_used_cpu; ++#endif /* CONFIG_SCHED_PDS */ + int wake_cpu; + #endif + int on_rq; +@@ -672,13 +679,27 @@ struct task_struct { + int normal_prio; + unsigned int rt_priority; + ++#ifdef CONFIG_SCHED_PDS ++ int time_slice; ++ u64 deadline; ++ /* skip list level */ ++ int sl_level; ++ /* skip list node */ ++ struct skiplist_node sl_node; ++ /* 8bits prio and 56bits deadline for quick processing */ ++ u64 priodl; ++ u64 last_ran; ++ /* sched_clock time spent running */ ++ u64 sched_time; ++#else /* CONFIG_SCHED_PDS */ + const struct sched_class *sched_class; + struct sched_entity se; + struct sched_rt_entity rt; ++ struct sched_dl_entity dl; ++#endif + #ifdef CONFIG_CGROUP_SCHED + struct task_group *sched_task_group; + #endif +- struct sched_dl_entity dl; + + #ifdef CONFIG_UCLAMP_TASK + /* Clamp values requested for a scheduling entity */ +@@ -1285,6 +1306,29 @@ struct task_struct { + */ + }; + ++#ifdef CONFIG_SCHED_PDS ++void cpu_scaling(int cpu); ++void cpu_nonscaling(int cpu); ++#define tsk_seruntime(t) ((t)->sched_time) ++/* replace the uncertian rt_timeout with 0UL */ ++#define tsk_rttimeout(t) (0UL) ++ ++#define task_running_idle(p) ((p)->prio == IDLE_PRIO) ++#else /* CFS */ ++extern int runqueue_is_locked(int cpu); ++static inline void cpu_scaling(int cpu) ++{ ++} ++ ++static inline void cpu_nonscaling(int cpu) ++{ ++} ++#define tsk_seruntime(t) ((t)->se.sum_exec_runtime) ++#define tsk_rttimeout(t) ((t)->rt.timeout) ++ ++#define iso_task(p) (false) ++#endif /* CONFIG_SCHED_PDS */ ++ + static inline struct pid *task_pid(struct task_struct *task) + { + return task->thread_pid; +--- a/include/linux/sched/deadline.h ++++ b/include/linux/sched/deadline.h +@@ -1,5 +1,22 @@ + /* SPDX-License-Identifier: GPL-2.0 */ + ++#ifdef CONFIG_SCHED_PDS ++ ++#define __tsk_deadline(p) ((p)->deadline) ++ ++static inline int dl_prio(int prio) ++{ ++ return 1; ++} ++ ++static inline int dl_task(struct task_struct *p) ++{ ++ return 1; ++} ++#else ++ ++#define __tsk_deadline(p) ((p)->dl.deadline) ++ + /* + * SCHED_DEADLINE tasks has negative priorities, reflecting + * the fact that any of them has higher prio than RT and +@@ -19,6 +36,7 @@ static inline int dl_task(struct task_st + { + return dl_prio(p->prio); + } ++#endif /* CONFIG_SCHED_PDS */ + + static inline bool dl_time_before(u64 a, u64 b) + { +--- a/include/linux/sched/prio.h ++++ b/include/linux/sched/prio.h +@@ -20,7 +20,18 @@ + */ + + #define MAX_USER_RT_PRIO 100 ++ ++#ifdef CONFIG_SCHED_PDS ++#define ISO_PRIO (MAX_USER_RT_PRIO) ++ ++#define MAX_RT_PRIO ((MAX_USER_RT_PRIO) + 1) ++ ++#define NORMAL_PRIO (MAX_RT_PRIO) ++#define IDLE_PRIO ((MAX_RT_PRIO) + 1) ++#define PRIO_LIMIT ((IDLE_PRIO) + 1) ++#else /* !CONFIG_SCHED_PDS */ + #define MAX_RT_PRIO MAX_USER_RT_PRIO ++#endif /* CONFIG_SCHED_PDS */ + + #define MAX_PRIO (MAX_RT_PRIO + NICE_WIDTH) + #define DEFAULT_PRIO (MAX_RT_PRIO + NICE_WIDTH / 2) +--- a/include/linux/sched/rt.h ++++ b/include/linux/sched/rt.h +@@ -24,8 +24,10 @@ static inline bool task_is_realtime(stru + + if (policy == SCHED_FIFO || policy == SCHED_RR) + return true; ++#ifndef CONFIG_SCHED_PDS + if (policy == SCHED_DEADLINE) + return true; ++#endif + return false; + } + +--- a/include/linux/sched/task.h ++++ b/include/linux/sched/task.h +@@ -99,7 +99,7 @@ extern long kernel_wait4(pid_t, int __us + extern void free_task(struct task_struct *tsk); + + /* sched_exec is called by processes performing an exec */ +-#ifdef CONFIG_SMP ++#if defined(CONFIG_SMP) && !defined(CONFIG_SCHED_PDS) + extern void sched_exec(void); + #else + #define sched_exec() {} +--- /dev/null ++++ b/include/linux/skip_list.h +@@ -0,0 +1,177 @@ ++/* ++ Copyright (C) 2016 Alfred Chen. ++ ++ Code based on Con Kolivas's skip list implementation for BFS, and ++ which is based on example originally by William Pugh. ++ ++Skip Lists are a probabilistic alternative to balanced trees, as ++described in the June 1990 issue of CACM and were invented by ++William Pugh in 1987. ++ ++A couple of comments about this implementation: ++ ++This file only provides a infrastructure of skip list. ++ ++skiplist_node is embedded into container data structure, to get rid the ++dependency of kmalloc/kfree operation in scheduler code. ++ ++A customized search function should be defined using DEFINE_SKIPLIST_INSERT ++macro and be used for skip list insert operation. ++ ++Random Level is also not defined in this file, instead, it should be customized ++implemented and set to node->level then pass to the customized skiplist_insert ++function. ++ ++Levels start at zero and go up to (NUM_SKIPLIST_LEVEL -1) ++ ++NUM_SKIPLIST_LEVEL in this implementation is 8 instead of origin 16, ++considering that there will be 256 entries to enable the top level when using ++random level p=0.5, and that number is more than enough for a run queue usage ++in a scheduler usage. And it also help to reduce the memory usage of the ++embedded skip list node in task_struct to about 50%. ++ ++The insertion routine has been implemented so as to use the ++dirty hack described in the CACM paper: if a random level is ++generated that is more than the current maximum level, the ++current maximum level plus one is used instead. ++ ++BFS Notes: In this implementation of skiplists, there are bidirectional ++next/prev pointers and the insert function returns a pointer to the actual ++node the value is stored. The key here is chosen by the scheduler so as to ++sort tasks according to the priority list requirements and is no longer used ++by the scheduler after insertion. The scheduler lookup, however, occurs in ++O(1) time because it is always the first item in the level 0 linked list. ++Since the task struct stores a copy of the node pointer upon skiplist_insert, ++it can also remove it much faster than the original implementation with the ++aid of prev<->next pointer manipulation and no searching. ++*/ ++#ifndef _LINUX_SKIP_LIST_H ++#define _LINUX_SKIP_LIST_H ++ ++#include ++ ++#define NUM_SKIPLIST_LEVEL (8) ++ ++struct skiplist_node { ++ int level; /* Levels in this node */ ++ struct skiplist_node *next[NUM_SKIPLIST_LEVEL]; ++ struct skiplist_node *prev[NUM_SKIPLIST_LEVEL]; ++}; ++ ++#define SKIPLIST_NODE_INIT(name) { 0,\ ++ {&name, &name, &name, &name,\ ++ &name, &name, &name, &name},\ ++ {&name, &name, &name, &name,\ ++ &name, &name, &name, &name},\ ++ } ++ ++static inline void INIT_SKIPLIST_NODE(struct skiplist_node *node) ++{ ++ /* only level 0 ->next matters in skiplist_empty()*/ ++ WRITE_ONCE(node->next[0], node); ++} ++ ++/** ++ * FULL_INIT_SKIPLIST_NODE -- fully init a skiplist_node, expecially for header ++ * @node: the skip list node to be inited. ++ */ ++static inline void FULL_INIT_SKIPLIST_NODE(struct skiplist_node *node) ++{ ++ int i; ++ ++ node->level = 0; ++ for (i = 0; i < NUM_SKIPLIST_LEVEL; i++) { ++ WRITE_ONCE(node->next[i], node); ++ node->prev[i] = node; ++ } ++} ++ ++/** ++ * skiplist_empty - test whether a skip list is empty ++ * @head: the skip list to test. ++ */ ++static inline int skiplist_empty(const struct skiplist_node *head) ++{ ++ return READ_ONCE(head->next[0]) == head; ++} ++ ++/** ++ * skiplist_entry - get the struct for this entry ++ * @ptr: the &struct skiplist_node pointer. ++ * @type: the type of the struct this is embedded in. ++ * @member: the name of the skiplist_node within the struct. ++ */ ++#define skiplist_entry(ptr, type, member) \ ++ container_of(ptr, type, member) ++ ++/** ++ * DEFINE_SKIPLIST_INSERT_FUNC -- macro to define a customized skip list insert ++ * function, which takes two parameters, first one is the header node of the ++ * skip list, second one is the skip list node to be inserted ++ * @func_name: the customized skip list insert function name ++ * @search_func: the search function to be used, which takes two parameters, ++ * 1st one is the itrator of skiplist_node in the list, the 2nd is the skip list ++ * node to be inserted, the function should return true if search should be ++ * continued, otherwise return false. ++ * Returns 1 if @node is inserted as the first item of skip list at level zero, ++ * otherwise 0 ++ */ ++#define DEFINE_SKIPLIST_INSERT_FUNC(func_name, search_func)\ ++static inline int func_name(struct skiplist_node *head, struct skiplist_node *node)\ ++{\ ++ struct skiplist_node *update[NUM_SKIPLIST_LEVEL];\ ++ struct skiplist_node *p, *q;\ ++ int k = head->level;\ ++\ ++ p = head;\ ++ do {\ ++ while (q = p->next[k], q != head && search_func(q, node))\ ++ p = q;\ ++ update[k] = p;\ ++ } while (--k >= 0);\ ++\ ++ k = node->level;\ ++ if (unlikely(k > head->level)) {\ ++ node->level = k = ++head->level;\ ++ update[k] = head;\ ++ }\ ++\ ++ do {\ ++ p = update[k];\ ++ q = p->next[k];\ ++ node->next[k] = q;\ ++ p->next[k] = node;\ ++ node->prev[k] = p;\ ++ q->prev[k] = node;\ ++ } while (--k >= 0);\ ++\ ++ return (p == head);\ ++} ++ ++/** ++ * skiplist_del_init -- delete skip list node from a skip list and reset it's ++ * init state ++ * @head: the header node of the skip list to be deleted from. ++ * @node: the skip list node to be deleted, the caller need to ensure @node is ++ * in skip list which @head represent. ++ * Returns 1 if @node is the first item of skip level at level zero, otherwise 0 ++ */ ++static inline int ++skiplist_del_init(struct skiplist_node *head, struct skiplist_node *node) ++{ ++ int l, m = node->level; ++ ++ for (l = 0; l <= m; l++) { ++ node->prev[l]->next[l] = node->next[l]; ++ node->next[l]->prev[l] = node->prev[l]; ++ } ++ if (m == head->level && m > 0) { ++ while (head->next[m] == head && m > 0) ++ m--; ++ head->level = m; ++ } ++ INIT_SKIPLIST_NODE(node); ++ ++ return (node->prev[0] == head); ++} ++#endif /* _LINUX_SKIP_LIST_H */ +--- a/include/uapi/linux/sched.h ++++ b/include/uapi/linux/sched.h +@@ -84,7 +84,10 @@ struct clone_args { + #define SCHED_FIFO 1 + #define SCHED_RR 2 + #define SCHED_BATCH 3 +-/* SCHED_ISO: reserved but not implemented yet */ ++/* SCHED_ISO: Implemented in BFS/MuQSSPDS only */ ++#ifdef CONFIG_SCHED_PDS ++#define SCHED_ISO 4 ++#endif + #define SCHED_IDLE 5 + #define SCHED_DEADLINE 6 + +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -61,6 +61,21 @@ config THREAD_INFO_IN_TASK + + menu "General setup" + ++config SCHED_PDS ++ bool "PDS-mq cpu scheduler" ++ help ++ The Priority and Deadline based Skip list multiple queue CPU ++ Scheduler for excellent interactivity and responsiveness on the ++ desktop and solid scalability on normal hardware and commodity ++ servers. ++ ++ Currently incompatible with the Group CPU scheduler, and RCU TORTURE ++ TEST so these options are disabled. ++ ++ Say Y here. ++ default y ++ ++ + config BROKEN + bool + +@@ -770,6 +785,7 @@ config NUMA_BALANCING + depends on ARCH_SUPPORTS_NUMA_BALANCING + depends on !ARCH_WANT_NUMA_VARIABLE_LOCALITY + depends on SMP && NUMA && MIGRATION ++ depends on !SCHED_PDS + help + This option adds support for automatic NUMA aware memory/task placement. + The mechanism is quite primitive and is based on migrating memory when +@@ -871,7 +887,7 @@ menuconfig CGROUP_SCHED + bandwidth allocation to such task groups. It uses cgroups to group + tasks. + +-if CGROUP_SCHED ++if CGROUP_SCHED && !SCHED_PDS + config FAIR_GROUP_SCHED + bool "Group scheduling for SCHED_OTHER" + depends on CGROUP_SCHED +@@ -1000,6 +1016,7 @@ config CGROUP_DEVICE + + config CGROUP_CPUACCT + bool "Simple CPU accounting controller" ++ depends on !SCHED_PDS + help + Provides a simple controller for monitoring the + total CPU consumed by the tasks in a cgroup. +@@ -1118,6 +1135,7 @@ config CHECKPOINT_RESTORE + + config SCHED_AUTOGROUP + bool "Automatic process group scheduling" ++ depends on !SCHED_PDS + select CGROUPS + select CGROUP_SCHED + select FAIR_GROUP_SCHED +--- a/init/init_task.c ++++ b/init/init_task.c +@@ -59,6 +59,126 @@ struct task_struct init_task + __init_task_data + #endif + = { ++#ifdef CONFIG_SCHED_PDS ++#ifdef CONFIG_THREAD_INFO_IN_TASK ++ .thread_info = INIT_THREAD_INFO(init_task), ++ .stack_refcount = ATOMIC_INIT(1), ++#endif ++ .state = 0, ++ .stack = init_stack, ++ .usage = ATOMIC_INIT(2), ++ .flags = PF_KTHREAD, ++ .prio = NORMAL_PRIO, ++ .static_prio = MAX_PRIO - 20, ++ .normal_prio = NORMAL_PRIO, ++ .deadline = 0, /* PDS only */ ++ .policy = SCHED_NORMAL, ++ .cpus_ptr = &init_task.cpus_mask, ++ .cpus_mask = CPU_MASK_ALL, ++ .nr_cpus_allowed= NR_CPUS, ++ .mm = NULL, ++ .active_mm = &init_mm, ++ .restart_block = { ++ .fn = do_no_restart_syscall, ++ }, ++ .sl_level = 0, /* PDS only */ ++ .sl_node = SKIPLIST_NODE_INIT(init_task.sl_node), /* PDS only */ ++ .time_slice = HZ, /* PDS only */ ++ .tasks = LIST_HEAD_INIT(init_task.tasks), ++#ifdef CONFIG_SMP ++ .pushable_tasks = PLIST_NODE_INIT(init_task.pushable_tasks, MAX_PRIO), ++#endif ++#ifdef CONFIG_CGROUP_SCHED ++ .sched_task_group = &root_task_group, ++#endif ++ .ptraced = LIST_HEAD_INIT(init_task.ptraced), ++ .ptrace_entry = LIST_HEAD_INIT(init_task.ptrace_entry), ++ .real_parent = &init_task, ++ .parent = &init_task, ++ .children = LIST_HEAD_INIT(init_task.children), ++ .sibling = LIST_HEAD_INIT(init_task.sibling), ++ .group_leader = &init_task, ++ RCU_POINTER_INITIALIZER(real_cred, &init_cred), ++ RCU_POINTER_INITIALIZER(cred, &init_cred), ++ .comm = INIT_TASK_COMM, ++ .thread = INIT_THREAD, ++ .fs = &init_fs, ++ .files = &init_files, ++ .signal = &init_signals, ++ .sighand = &init_sighand, ++ .nsproxy = &init_nsproxy, ++ .pending = { ++ .list = LIST_HEAD_INIT(init_task.pending.list), ++ .signal = {{0}} ++ }, ++ .blocked = {{0}}, ++ .alloc_lock = __SPIN_LOCK_UNLOCKED(init_task.alloc_lock), ++ .journal_info = NULL, ++ INIT_CPU_TIMERS(init_task) ++ .pi_lock = __RAW_SPIN_LOCK_UNLOCKED(init_task.pi_lock), ++ .timer_slack_ns = 50000, /* 50 usec default slack */ ++ .thread_pid = &init_struct_pid, ++ .thread_group = LIST_HEAD_INIT(init_task.thread_group), ++ .thread_node = LIST_HEAD_INIT(init_signals.thread_head), ++#ifdef CONFIG_AUDITSYSCALL ++ .loginuid = INVALID_UID, ++ .sessionid = AUDIT_SID_UNSET, ++#endif ++#ifdef CONFIG_PERF_EVENTS ++ .perf_event_mutex = __MUTEX_INITIALIZER(init_task.perf_event_mutex), ++ .perf_event_list = LIST_HEAD_INIT(init_task.perf_event_list), ++#endif ++#ifdef CONFIG_PREEMPT_RCU ++ .rcu_read_lock_nesting = 0, ++ .rcu_read_unlock_special.s = 0, ++ .rcu_node_entry = LIST_HEAD_INIT(init_task.rcu_node_entry), ++ .rcu_blocked_node = NULL, ++#endif ++#ifdef CONFIG_TASKS_RCU ++ .rcu_tasks_holdout = false, ++ .rcu_tasks_holdout_list = LIST_HEAD_INIT(init_task.rcu_tasks_holdout_list), ++ .rcu_tasks_idle_cpu = -1, ++#endif ++#ifdef CONFIG_CPUSETS ++ .mems_allowed_seq = SEQCNT_ZERO(init_task.mems_allowed_seq), ++#endif ++#ifdef CONFIG_RT_MUTEXES ++ .pi_waiters = RB_ROOT_CACHED, ++ .pi_top_task = NULL, ++#endif ++ INIT_PREV_CPUTIME(init_task) ++#ifdef CONFIG_VIRT_CPU_ACCOUNTING_GEN ++ .vtime.seqcount = SEQCNT_ZERO(init_task.vtime_seqcount), ++ .vtime.starttime = 0, ++ .vtime.state = VTIME_SYS, ++#endif ++#ifdef CONFIG_NUMA_BALANCING ++ .numa_preferred_nid = -1, ++ .numa_group = NULL, ++ .numa_faults = NULL, ++#endif ++#ifdef CONFIG_KASAN ++ .kasan_depth = 1, ++#endif ++#ifdef CONFIG_TRACE_IRQFLAGS ++ .softirqs_enabled = 1, ++#endif ++#ifdef CONFIG_LOCKDEP ++ .lockdep_recursion = 0, ++#endif ++#ifdef CONFIG_FUNCTION_GRAPH_TRACER ++ .ret_stack = NULL, ++#endif ++#if defined(CONFIG_TRACING) && defined(CONFIG_PREEMPT) ++ .trace_recursion = 0, ++#endif ++#ifdef CONFIG_LIVEPATCH ++ .patch_state = KLP_UNDEFINED, ++#endif ++#ifdef CONFIG_SECURITY ++ .security = NULL, ++#endif ++#else /* CONFIG_SCHED_PDS */ + #ifdef CONFIG_THREAD_INFO_IN_TASK + .thread_info = INIT_THREAD_INFO(init_task), + .stack_refcount = REFCOUNT_INIT(1), +@@ -183,6 +303,7 @@ struct task_struct init_task + #ifdef CONFIG_SECURITY + .security = NULL, + #endif ++#endif /* CONFIG_SCHED_PDS */ + }; + EXPORT_SYMBOL(init_task); + +--- a/kernel/cgroup/cpuset.c ++++ b/kernel/cgroup/cpuset.c +@@ -632,7 +632,7 @@ out: + return ret; + } + +-#ifdef CONFIG_SMP ++#if defined(CONFIG_SMP) && !defined(CONFIG_SCHED_PDS) + /* + * Helper routine for generate_sched_domains(). + * Do cpusets a, b have overlapping effective cpus_allowed masks? +@@ -1030,7 +1030,7 @@ static void rebuild_sched_domains_locked + /* Have scheduler rebuild the domains */ + partition_and_rebuild_sched_domains(ndoms, doms, attr); + } +-#else /* !CONFIG_SMP */ ++#else /* !CONFIG_SMP || CONFIG_SCHED_PDS */ + static void rebuild_sched_domains_locked(void) + { + } +--- a/kernel/delayacct.c ++++ b/kernel/delayacct.c +@@ -106,7 +106,7 @@ int __delayacct_add_tsk(struct taskstats + */ + t1 = tsk->sched_info.pcount; + t2 = tsk->sched_info.run_delay; +- t3 = tsk->se.sum_exec_runtime; ++ t3 = tsk_seruntime(tsk); + + d->cpu_count += t1; + +--- a/kernel/exit.c ++++ b/kernel/exit.c +@@ -131,7 +131,7 @@ static void __exit_signal(struct task_st + sig->curr_target = next_thread(tsk); + } + +- add_device_randomness((const void*) &tsk->se.sum_exec_runtime, ++ add_device_randomness((const void*) &tsk_seruntime(tsk), + sizeof(unsigned long long)); + + /* +@@ -152,7 +152,7 @@ static void __exit_signal(struct task_st + sig->inblock += task_io_get_inblock(tsk); + sig->oublock += task_io_get_oublock(tsk); + task_io_accounting_add(&sig->ioac, &tsk->ioac); +- sig->sum_sched_runtime += tsk->se.sum_exec_runtime; ++ sig->sum_sched_runtime += tsk_seruntime(tsk); + sig->nr_threads--; + __unhash_process(tsk, group_dead); + write_sequnlock(&sig->stats_lock); +--- a/kernel/livepatch/transition.c ++++ b/kernel/livepatch/transition.c +@@ -306,7 +306,11 @@ static bool klp_try_switch_task(struct t + */ + rq = task_rq_lock(task, &flags); + ++#ifdef CONFIG_SCHED_PDS ++ if (task_running(task) && task != current) { ++#else + if (task_running(rq, task) && task != current) { ++#endif + snprintf(err_buf, STACK_ERR_BUF_SIZE, + "%s: %s:%d is running\n", __func__, task->comm, + task->pid); +--- a/kernel/locking/rtmutex.c ++++ b/kernel/locking/rtmutex.c +@@ -229,7 +229,7 @@ static inline bool unlock_rt_mutex_safe( + * Only use with rt_mutex_waiter_{less,equal}() + */ + #define task_to_waiter(p) \ +- &(struct rt_mutex_waiter){ .prio = (p)->prio, .deadline = (p)->dl.deadline } ++ &(struct rt_mutex_waiter){ .prio = (p)->prio, .deadline = __tsk_deadline(p) } + + static inline int + rt_mutex_waiter_less(struct rt_mutex_waiter *left, +@@ -680,7 +680,7 @@ static int rt_mutex_adjust_prio_chain(st + * the values of the node being removed. + */ + waiter->prio = task->prio; +- waiter->deadline = task->dl.deadline; ++ waiter->deadline = __tsk_deadline(task); + + rt_mutex_enqueue(lock, waiter); + +@@ -953,7 +953,7 @@ static int task_blocks_on_rt_mutex(struc + waiter->task = task; + waiter->lock = lock; + waiter->prio = task->prio; +- waiter->deadline = task->dl.deadline; ++ waiter->deadline = __tsk_deadline(task); + + /* Get the top priority waiter on the lock */ + if (rt_mutex_has_waiters(lock)) +--- a/kernel/sched/Makefile ++++ b/kernel/sched/Makefile +@@ -16,15 +16,21 @@ ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER + CFLAGS_core.o := $(PROFILING) -fno-omit-frame-pointer + endif + +-obj-y += core.o loadavg.o clock.o cputime.o +-obj-y += idle.o fair.o rt.o deadline.o +-obj-y += wait.o wait_bit.o swait.o completion.o +- +-obj-$(CONFIG_SMP) += cpupri.o cpudeadline.o topology.o stop_task.o pelt.o ++ifdef CONFIG_SCHED_PDS ++obj-y += pds.o ++else ++obj-y += core.o ++obj-y += fair.o rt.o deadline.o ++obj-$(CONFIG_SMP) += cpudeadline.o topology.o stop_task.o + obj-$(CONFIG_SCHED_AUTOGROUP) += autogroup.o +-obj-$(CONFIG_SCHEDSTATS) += stats.o + obj-$(CONFIG_SCHED_DEBUG) += debug.o + obj-$(CONFIG_CGROUP_CPUACCT) += cpuacct.o ++endif ++obj-y += loadavg.o clock.o cputime.o ++obj-y += idle.o ++obj-y += wait.o wait_bit.o swait.o completion.o ++obj-$(CONFIG_SMP) += cpupri.o pelt.o ++obj-$(CONFIG_SCHEDSTATS) += stats.o + obj-$(CONFIG_CPU_FREQ) += cpufreq.o + obj-$(CONFIG_CPU_FREQ_GOV_SCHEDUTIL) += cpufreq_schedutil.o + obj-$(CONFIG_MEMBARRIER) += membarrier.o +--- a/kernel/sched/cpufreq_schedutil.c ++++ b/kernel/sched/cpufreq_schedutil.c +@@ -183,6 +183,7 @@ static unsigned int get_next_freq(struct + return cpufreq_driver_resolve_freq(policy, freq); + } + ++#ifndef CONFIG_SCHED_PDS + /* + * This function computes an effective utilization for the given CPU, to be + * used for frequency selection given the linear relation: f = u * f_max. +@@ -300,6 +301,16 @@ static unsigned long sugov_get_util(stru + + return schedutil_cpu_util(sg_cpu->cpu, util, max, FREQUENCY_UTIL, NULL); + } ++#else /* CONFIG_SCHED_PDS */ ++static unsigned long sugov_get_util(struct sugov_cpu *sg_cpu) ++{ ++ unsigned long max = arch_scale_cpu_capacity(sg_cpu->cpu); ++ sg_cpu->max = max; ++ sg_cpu->bw_dl = 0; ++ return cpu_rq(sg_cpu->cpu)->nr_running ? max:0UL; ++ ++} ++#endif + + /** + * sugov_iowait_reset() - Reset the IO boost status of a CPU. +@@ -443,8 +454,10 @@ static inline bool sugov_cpu_is_busy(str + */ + static inline void ignore_dl_rate_limit(struct sugov_cpu *sg_cpu, struct sugov_policy *sg_policy) + { ++#ifndef CONFIG_SCHED_PDS + if (cpu_bw_dl(cpu_rq(sg_cpu->cpu)) > sg_cpu->bw_dl) + sg_policy->limits_changed = true; ++#endif + } + + static void sugov_update_single(struct update_util_data *hook, u64 time, +@@ -694,6 +707,7 @@ static int sugov_kthread_create(struct s + } + + ret = sched_setattr_nocheck(thread, &attr); ++ + if (ret) { + kthread_stop(thread); + pr_warn("%s: failed to set SCHED_DEADLINE\n", __func__); +@@ -922,6 +936,7 @@ static int __init sugov_register(void) + fs_initcall(sugov_register); + + #ifdef CONFIG_ENERGY_MODEL ++#ifndef CONFIG_SCHED_PDS + extern bool sched_energy_update; + extern struct mutex sched_energy_mutex; + +@@ -952,4 +967,10 @@ void sched_cpufreq_governor_change(struc + } + + } ++#else /* CONFIG_SCHED_PDS */ ++void sched_cpufreq_governor_change(struct cpufreq_policy *policy, ++ struct cpufreq_governor *old_gov) ++{ ++} ++#endif + #endif +--- a/kernel/sched/cputime.c ++++ b/kernel/sched/cputime.c +@@ -122,7 +122,12 @@ void account_user_time(struct task_struc + p->utime += cputime; + account_group_user_time(p, cputime); + ++#ifdef CONFIG_SCHED_PDS ++ index = (task_nice(p) > 0 || task_running_idle(p)) ? CPUTIME_NICE : ++ CPUTIME_USER; ++#else + index = (task_nice(p) > 0) ? CPUTIME_NICE : CPUTIME_USER; ++#endif + + /* Add user time to cpustat. */ + task_group_account_field(p, index, cputime); +@@ -146,7 +151,11 @@ void account_guest_time(struct task_stru + p->gtime += cputime; + + /* Add guest time to cpustat. */ ++#ifdef CONFIG_SCHED_PDS ++ if (task_nice(p) > 0 || task_running_idle(p)) { ++#else + if (task_nice(p) > 0) { ++#endif + cpustat[CPUTIME_NICE] += cputime; + cpustat[CPUTIME_GUEST_NICE] += cputime; + } else { +@@ -269,7 +278,7 @@ static inline u64 account_other_time(u64 + #ifdef CONFIG_64BIT + static inline u64 read_sum_exec_runtime(struct task_struct *t) + { +- return t->se.sum_exec_runtime; ++ return tsk_seruntime(t); + } + #else + static u64 read_sum_exec_runtime(struct task_struct *t) +@@ -279,7 +288,7 @@ static u64 read_sum_exec_runtime(struct + struct rq *rq; + + rq = task_rq_lock(t, &rf); +- ns = t->se.sum_exec_runtime; ++ ns = tsk_seruntime(t); + task_rq_unlock(rq, t, &rf); + + return ns; +@@ -663,7 +672,7 @@ out: + void task_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st) + { + struct task_cputime cputime = { +- .sum_exec_runtime = p->se.sum_exec_runtime, ++ .sum_exec_runtime = tsk_seruntime(p), + }; + + task_cputime(p, &cputime.utime, &cputime.stime); +--- a/kernel/sched/idle.c ++++ b/kernel/sched/idle.c +@@ -356,6 +356,7 @@ void cpu_startup_entry(enum cpuhp_state + do_idle(); + } + ++#ifndef CONFIG_SCHED_PDS + /* + * idle-task scheduling class. + */ +@@ -480,3 +481,4 @@ const struct sched_class idle_sched_clas + .switched_to = switched_to_idle, + .update_curr = update_curr_idle, + }; ++#endif +--- /dev/null ++++ b/kernel/sched/pds.c +@@ -0,0 +1,6567 @@ ++/* ++ * kernel/sched/pds.c, was kernel/sched.c ++ * ++ * PDS-mq Core kernel scheduler code and related syscalls ++ * ++ * Copyright (C) 1991-2002 Linus Torvalds ++ * ++ * 2009-08-13 Brainfuck deadline scheduling policy by Con Kolivas deletes ++ * a whole lot of those previous things. ++ * 2017-09-06 Priority and Deadline based Skip list multiple queue kernel ++ * scheduler by Alfred Chen. ++ */ ++#include "pds_sched.h" ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++ ++#include "../workqueue_internal.h" ++#include "../smpboot.h" ++ ++#include "pelt.h" ++ ++#define CREATE_TRACE_POINTS ++#include ++ ++ ++#define rt_prio(prio) ((prio) < MAX_RT_PRIO) ++#define rt_task(p) rt_prio((p)->prio) ++#define rt_policy(policy) ((policy) == SCHED_FIFO || \ ++ (policy) == SCHED_RR || \ ++ (policy) == SCHED_ISO) ++#define task_has_rt_policy(p) (rt_policy((p)->policy)) ++ ++#define idle_policy(policy) ((policy) == SCHED_IDLE) ++#define idleprio_task(p) unlikely(idle_policy((p)->policy)) ++ ++#define STOP_PRIO (MAX_RT_PRIO - 1) ++ ++/* ++ * Some helpers for converting to/from various scales. Use shifts to get ++ * approximate multiples of ten for less overhead. ++ */ ++#define JIFFIES_TO_NS(TIME) ((TIME) * (1000000000 / HZ)) ++#define JIFFY_NS (1000000000 / HZ) ++#define HALF_JIFFY_NS (1000000000 / HZ / 2) ++#define HALF_JIFFY_US (1000000 / HZ / 2) ++#define MS_TO_NS(TIME) ((TIME) << 20) ++#define MS_TO_US(TIME) ((TIME) << 10) ++#define NS_TO_MS(TIME) ((TIME) >> 20) ++#define NS_TO_US(TIME) ((TIME) >> 10) ++#define US_TO_NS(TIME) ((TIME) << 10) ++ ++#define RESCHED_US (100) /* Reschedule if less than this many μs left */ ++ ++enum { ++ BASE_CPU_AFFINITY_CHK_LEVEL = 1, ++#ifdef CONFIG_SCHED_SMT ++ SMT_CPU_AFFINITY_CHK_LEVEL_SPACE_HOLDER, ++#endif ++#ifdef CONFIG_SCHED_MC ++ MC_CPU_AFFINITY_CHK_LEVEL_SPACE_HOLDER, ++#endif ++ NR_CPU_AFFINITY_CHK_LEVEL ++}; ++ ++static inline void print_scheduler_version(void) ++{ ++ printk(KERN_INFO "pds: PDS-mq CPU Scheduler 0.99o by Alfred Chen and kept alive artificially by Tk-Glitch.\n"); ++} ++ ++/* ++ * This is the time all tasks within the same priority round robin. ++ * Value is in ms and set to a minimum of 6ms. Scales with number of cpus. ++ * Tunable via /proc interface. ++ */ ++#define SCHED_DEFAULT_RR (4) ++int rr_interval __read_mostly = SCHED_DEFAULT_RR; ++ ++static int __init rr_interval_set(char *str) ++{ ++ u32 rr; ++ ++ pr_info("rr_interval: "); ++ if (kstrtouint(str, 0, &rr)) { ++ pr_cont("using default of %u, unable to parse %s\n", ++ rr_interval, str); ++ return 1; ++ } ++ ++ rr_interval = rr; ++ pr_cont("%d\n", rr_interval); ++ ++ return 1; ++} ++__setup("rr_interval=", rr_interval_set); ++ ++ ++static const u64 sched_prio2deadline[NICE_WIDTH] = { ++/* -20 */ 6291456, 6920601, 7612661, 8373927, 9211319, ++/* -15 */ 10132450, 11145695, 12260264, 13486290, 14834919, ++/* -10 */ 16318410, 17950251, 19745276, 21719803, 23891783, ++/* -5 */ 26280961, 28909057, 31799962, 34979958, 38477953, ++/* 0 */ 42325748, 46558322, 51214154, 56335569, 61969125, ++/* 5 */ 68166037, 74982640, 82480904, 90728994, 99801893, ++/* 10 */ 109782082, 120760290, 132836319, 146119950, 160731945, ++/* 15 */ 176805139, 194485652, 213934217, 235327638, 258860401 ++}; ++ ++/** ++ * sched_yield_type - Choose what sort of yield sched_yield will perform. ++ * 0: No yield. ++ * 1: Yield only to better priority/deadline tasks. (default) ++ * 2: Expire timeslice and recalculate deadline. ++ */ ++int sched_yield_type __read_mostly = 1; ++ ++/* ++ * The quota handed out to tasks of all priority levels when refilling their ++ * time_slice. ++ */ ++static inline int timeslice(void) ++{ ++ return MS_TO_US(rr_interval); ++} ++ ++#ifdef CONFIG_SMP ++enum { ++SCHED_RQ_EMPTY = 0, ++SCHED_RQ_IDLE, ++SCHED_RQ_NORMAL_0, ++SCHED_RQ_NORMAL_1, ++SCHED_RQ_NORMAL_2, ++SCHED_RQ_NORMAL_3, ++SCHED_RQ_NORMAL_4, ++SCHED_RQ_NORMAL_5, ++SCHED_RQ_NORMAL_6, ++SCHED_RQ_NORMAL_7, ++SCHED_RQ_ISO, ++SCHED_RQ_RT, ++NR_SCHED_RQ_QUEUED_LEVEL ++}; ++ ++static cpumask_t sched_rq_queued_masks[NR_SCHED_RQ_QUEUED_LEVEL] ++____cacheline_aligned_in_smp; ++ ++static DECLARE_BITMAP(sched_rq_queued_masks_bitmap, NR_SCHED_RQ_QUEUED_LEVEL) ++____cacheline_aligned_in_smp; ++ ++static cpumask_t sched_rq_pending_masks[NR_SCHED_RQ_QUEUED_LEVEL] ++____cacheline_aligned_in_smp; ++ ++static DECLARE_BITMAP(sched_rq_pending_masks_bitmap, NR_SCHED_RQ_QUEUED_LEVEL) ++____cacheline_aligned_in_smp; ++ ++DEFINE_PER_CPU(cpumask_t [NR_CPU_AFFINITY_CHK_LEVEL], sched_cpu_affinity_chk_masks); ++DEFINE_PER_CPU(cpumask_t *, sched_cpu_llc_start_mask); ++DEFINE_PER_CPU(cpumask_t *, sched_cpu_affinity_chk_end_masks); ++ ++#ifdef CONFIG_SCHED_SMT ++DEFINE_PER_CPU(int, sched_sibling_cpu); ++DEFINE_STATIC_KEY_FALSE(sched_smt_present); ++EXPORT_SYMBOL_GPL(sched_smt_present); ++ ++static cpumask_t sched_cpu_sg_idle_mask ____cacheline_aligned_in_smp; ++ ++#ifdef CONFIG_SMT_NICE ++/* ++ * Preemptible sibling group mask ++ * Which all sibling cpus are running at PRIO_LIMIT or IDLE_PRIO ++ */ ++static cpumask_t sched_cpu_psg_mask ____cacheline_aligned_in_smp; ++/* ++ * SMT supressed mask ++ * When a cpu is running task with NORMAL/ISO/RT policy, its sibling cpu ++ * will be supressed to run IDLE priority task. ++ */ ++static cpumask_t sched_smt_supressed_mask ____cacheline_aligned_in_smp; ++#endif /* CONFIG_SMT_NICE */ ++#endif ++ ++static int sched_rq_prio[NR_CPUS] ____cacheline_aligned; ++ ++/* ++ * Keep a unique ID per domain (we use the first CPUs number in the cpumask of ++ * the domain), this allows us to quickly tell if two cpus are in the same cache ++ * domain, see cpus_share_cache(). ++ */ ++DEFINE_PER_CPU(int, sd_llc_id); ++ ++int __weak arch_sd_sibling_asym_packing(void) ++{ ++ return 0*SD_ASYM_PACKING; ++} ++#else ++struct rq *uprq; ++#endif /* CONFIG_SMP */ ++ ++static DEFINE_MUTEX(sched_hotcpu_mutex); ++ ++DEFINE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues); ++ ++#ifndef prepare_arch_switch ++# define prepare_arch_switch(next) do { } while (0) ++#endif ++#ifndef finish_arch_post_lock_switch ++# define finish_arch_post_lock_switch() do { } while (0) ++#endif ++ ++/* ++ * Context: p->pi_lock ++ */ ++static inline struct rq ++*__task_access_lock(struct task_struct *p, raw_spinlock_t **plock) ++{ ++ struct rq *rq; ++ for (;;) { ++ rq = task_rq(p); ++ if (p->on_cpu || task_on_rq_queued(p)) { ++ raw_spin_lock(&rq->lock); ++ if (likely((p->on_cpu || task_on_rq_queued(p)) ++ && rq == task_rq(p))) { ++ *plock = &rq->lock; ++ return rq; ++ } ++ raw_spin_unlock(&rq->lock); ++ } else if (task_on_rq_migrating(p)) { ++ do { ++ cpu_relax(); ++ } while (unlikely(task_on_rq_migrating(p))); ++ } else { ++ *plock = NULL; ++ return rq; ++ } ++ } ++} ++ ++static inline void ++__task_access_unlock(struct task_struct *p, raw_spinlock_t *lock) ++{ ++ if (NULL != lock) ++ raw_spin_unlock(lock); ++} ++ ++static inline struct rq ++*task_access_lock_irqsave(struct task_struct *p, raw_spinlock_t **plock, ++ unsigned long *flags) ++{ ++ struct rq *rq; ++ for (;;) { ++ rq = task_rq(p); ++ if (p->on_cpu || task_on_rq_queued(p)) { ++ raw_spin_lock_irqsave(&rq->lock, *flags); ++ if (likely((p->on_cpu || task_on_rq_queued(p)) ++ && rq == task_rq(p))) { ++ *plock = &rq->lock; ++ return rq; ++ } ++ raw_spin_unlock_irqrestore(&rq->lock, *flags); ++ } else if (task_on_rq_migrating(p)) { ++ do { ++ cpu_relax(); ++ } while (unlikely(task_on_rq_migrating(p))); ++ } else { ++ raw_spin_lock_irqsave(&p->pi_lock, *flags); ++ if (likely(!p->on_cpu && !p->on_rq && ++ rq == task_rq(p))) { ++ *plock = &p->pi_lock; ++ return rq; ++ } ++ raw_spin_unlock_irqrestore(&p->pi_lock, *flags); ++ } ++ } ++} ++ ++static inline void ++task_access_unlock_irqrestore(struct task_struct *p, raw_spinlock_t *lock, ++ unsigned long *flags) ++{ ++ raw_spin_unlock_irqrestore(lock, *flags); ++} ++ ++/* ++ * __task_rq_lock - lock the rq @p resides on. ++ */ ++struct rq *__task_rq_lock(struct task_struct *p, struct rq_flags *rf) ++ __acquires(rq->lock) ++{ ++ struct rq *rq; ++ ++ lockdep_assert_held(&p->pi_lock); ++ ++ for (;;) { ++ rq = task_rq(p); ++ raw_spin_lock(&rq->lock); ++ if (likely(rq == task_rq(p) && !task_on_rq_migrating(p))) ++ return rq; ++ raw_spin_unlock(&rq->lock); ++ ++ while (unlikely(task_on_rq_migrating(p))) ++ cpu_relax(); ++ } ++} ++ ++/* ++ * task_rq_lock - lock p->pi_lock and lock the rq @p resides on. ++ */ ++struct rq *task_rq_lock(struct task_struct *p, struct rq_flags *rf) ++ __acquires(p->pi_lock) ++ __acquires(rq->lock) ++{ ++ struct rq *rq; ++ ++ for (;;) { ++ raw_spin_lock_irqsave(&p->pi_lock, rf->flags); ++ rq = task_rq(p); ++ raw_spin_lock(&rq->lock); ++ /* ++ * move_queued_task() task_rq_lock() ++ * ++ * ACQUIRE (rq->lock) ++ * [S] ->on_rq = MIGRATING [L] rq = task_rq() ++ * WMB (__set_task_cpu()) ACQUIRE (rq->lock); ++ * [S] ->cpu = new_cpu [L] task_rq() ++ * [L] ->on_rq ++ * RELEASE (rq->lock) ++ * ++ * If we observe the old CPU in task_rq_lock(), the acquire of ++ * the old rq->lock will fully serialize against the stores. ++ * ++ * If we observe the new CPU in task_rq_lock(), the address ++ * dependency headed by '[L] rq = task_rq()' and the acquire ++ * will pair with the WMB to ensure we then also see migrating. ++ */ ++ if (likely(rq == task_rq(p) && !task_on_rq_migrating(p))) { ++ return rq; ++ } ++ raw_spin_unlock(&rq->lock); ++ raw_spin_unlock_irqrestore(&p->pi_lock, rf->flags); ++ ++ while (unlikely(task_on_rq_migrating(p))) ++ cpu_relax(); ++ } ++} ++ ++/* ++ * RQ-clock updating methods: ++ */ ++ ++static void update_rq_clock_task(struct rq *rq, s64 delta) ++{ ++/* ++ * In theory, the compile should just see 0 here, and optimize out the call ++ * to sched_rt_avg_update. But I don't trust it... ++ */ ++ s64 __maybe_unused steal = 0, irq_delta = 0; ++ ++#ifdef CONFIG_IRQ_TIME_ACCOUNTING ++ irq_delta = irq_time_read(cpu_of(rq)) - rq->prev_irq_time; ++ ++ /* ++ * Since irq_time is only updated on {soft,}irq_exit, we might run into ++ * this case when a previous update_rq_clock() happened inside a ++ * {soft,}irq region. ++ * ++ * When this happens, we stop ->clock_task and only update the ++ * prev_irq_time stamp to account for the part that fit, so that a next ++ * update will consume the rest. This ensures ->clock_task is ++ * monotonic. ++ * ++ * It does however cause some slight miss-attribution of {soft,}irq ++ * time, a more accurate solution would be to update the irq_time using ++ * the current rq->clock timestamp, except that would require using ++ * atomic ops. ++ */ ++ if (irq_delta > delta) ++ irq_delta = delta; ++ ++ rq->prev_irq_time += irq_delta; ++ delta -= irq_delta; ++#endif ++#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING ++ if (static_key_false((¶virt_steal_rq_enabled))) { ++ steal = paravirt_steal_clock(cpu_of(rq)); ++ steal -= rq->prev_steal_time_rq; ++ ++ if (unlikely(steal > delta)) ++ steal = delta; ++ ++ rq->prev_steal_time_rq += steal; ++ ++ delta -= steal; ++ } ++#endif ++ ++ rq->clock_task += delta; ++ ++#ifdef CONFIG_HAVE_SCHED_AVG_IRQ ++ if ((irq_delta + steal)) ++ update_irq_load_avg(rq, irq_delta + steal); ++#endif ++} ++ ++static inline void update_rq_clock(struct rq *rq) ++{ ++ s64 delta = sched_clock_cpu(cpu_of(rq)) - rq->clock; ++ ++ if (unlikely(delta <= 0)) ++ return; ++ rq->clock += delta; ++ update_rq_clock_task(rq, delta); ++} ++ ++static inline void update_task_priodl(struct task_struct *p) ++{ ++ p->priodl = (((u64) (p->prio))<<56) | ((p->deadline)>>8); ++} ++ ++/* ++ * Deadline is "now" in niffies + (offset by priority). Setting the deadline ++ * is the key to everything. It distributes CPU fairly amongst tasks of the ++ * same nice value, it proportions CPU according to nice level, it means the ++ * task that last woke up the longest ago has the earliest deadline, thus ++ * ensuring that interactive tasks get low latency on wake up. The CPU ++ * proportion works out to the square of the virtual deadline difference, so ++ * this equation will give nice 19 3% CPU compared to nice 0. ++ */ ++static inline u64 task_deadline_diff(const struct task_struct *p) ++{ ++ return sched_prio2deadline[TASK_USER_PRIO(p)]; ++} ++ ++static inline u64 static_deadline_diff(int static_prio) ++{ ++ return sched_prio2deadline[USER_PRIO(static_prio)]; ++} ++ ++/* ++ * The time_slice is only refilled when it is empty and that is when we set a ++ * new deadline for non-rt tasks. ++ */ ++static inline void time_slice_expired(struct task_struct *p, struct rq *rq) ++{ ++ p->time_slice = timeslice(); ++ if (p->prio >= NORMAL_PRIO) ++ p->deadline = rq->clock + task_deadline_diff(p); ++ ++ update_task_priodl(p); ++} ++ ++static inline struct task_struct *rq_first_queued_task(struct rq *rq) ++{ ++ struct skiplist_node *node = rq->sl_header.next[0]; ++ ++ if (node == &rq->sl_header) ++ return rq->idle; ++ ++ return skiplist_entry(node, struct task_struct, sl_node); ++} ++ ++static inline struct task_struct *rq_second_queued_task(struct rq *rq) ++{ ++ struct skiplist_node *node = rq->sl_header.next[0]->next[0]; ++ ++ if (node == &rq->sl_header) ++ return rq->idle; ++ ++ return skiplist_entry(node, struct task_struct, sl_node); ++} ++ ++static inline int is_second_in_rq(struct task_struct *p, struct rq *rq) ++{ ++ return (p->sl_node.prev[0]->prev[0] == &rq->sl_header); ++} ++ ++static const int task_dl_hash_tbl[] = { ++/* 0 4 8 12 */ ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, ++/* 16 20 24 28 */ ++ 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 6, 7 ++}; ++ ++static inline int ++task_deadline_level(const struct task_struct *p, const struct rq *rq) ++{ ++ u64 delta = (rq->clock + sched_prio2deadline[39] - p->deadline) >> 23; ++ ++ delta = min((size_t)delta, ARRAY_SIZE(task_dl_hash_tbl) - 1); ++ return task_dl_hash_tbl[delta]; ++} ++ ++/* ++ * cmpxchg based fetch_or, macro so it works for different integer types ++ */ ++#define fetch_or(ptr, mask) \ ++ ({ \ ++ typeof(ptr) _ptr = (ptr); \ ++ typeof(mask) _mask = (mask); \ ++ typeof(*_ptr) _old, _val = *_ptr; \ ++ \ ++ for (;;) { \ ++ _old = cmpxchg(_ptr, _val, _val | _mask); \ ++ if (_old == _val) \ ++ break; \ ++ _val = _old; \ ++ } \ ++ _old; \ ++}) ++ ++#if defined(CONFIG_SMP) && defined(TIF_POLLING_NRFLAG) ++/* ++ * Atomically set TIF_NEED_RESCHED and test for TIF_POLLING_NRFLAG, ++ * this avoids any races wrt polling state changes and thereby avoids ++ * spurious IPIs. ++ */ ++static bool set_nr_and_not_polling(struct task_struct *p) ++{ ++ struct thread_info *ti = task_thread_info(p); ++ return !(fetch_or(&ti->flags, _TIF_NEED_RESCHED) & _TIF_POLLING_NRFLAG); ++} ++ ++/* ++ * Atomically set TIF_NEED_RESCHED if TIF_POLLING_NRFLAG is set. ++ * ++ * If this returns true, then the idle task promises to call ++ * sched_ttwu_pending() and reschedule soon. ++ */ ++static bool set_nr_if_polling(struct task_struct *p) ++{ ++ struct thread_info *ti = task_thread_info(p); ++ typeof(ti->flags) old, val = READ_ONCE(ti->flags); ++ ++ for (;;) { ++ if (!(val & _TIF_POLLING_NRFLAG)) ++ return false; ++ if (val & _TIF_NEED_RESCHED) ++ return true; ++ old = cmpxchg(&ti->flags, val, val | _TIF_NEED_RESCHED); ++ if (old == val) ++ break; ++ val = old; ++ } ++ return true; ++} ++ ++#else ++static bool set_nr_and_not_polling(struct task_struct *p) ++{ ++ set_tsk_need_resched(p); ++ return true; ++} ++ ++#ifdef CONFIG_SMP ++static bool set_nr_if_polling(struct task_struct *p) ++{ ++ return false; ++} ++#endif ++#endif ++ ++#ifdef CONFIG_SMP ++#ifdef CONFIG_SMT_NICE ++static void resched_cpu_if_curr_is(int cpu, int priority) ++{ ++ struct rq *rq = cpu_rq(cpu); ++ ++ rcu_read_lock(); ++ ++ if (rcu_dereference(rq->curr)->prio != priority) ++ goto out; ++ ++ if (set_nr_if_polling(rq->idle)) { ++ trace_sched_wake_idle_without_ipi(cpu); ++ } else { ++ if (!do_raw_spin_trylock(&rq->lock)) ++ goto out; ++ spin_acquire(&rq->lock.dep_map, SINGLE_DEPTH_NESTING, 1, _RET_IP_); ++ ++ if (priority == rq->curr->prio) ++ smp_send_reschedule(cpu); ++ /* Else CPU is not idle, do nothing here */ ++ ++ spin_release(&rq->lock.dep_map, 1, _RET_IP_); ++ do_raw_spin_unlock(&rq->lock); ++ } ++ ++out: ++ rcu_read_unlock(); ++} ++#endif /* CONFIG_SMT_NICE */ ++ ++static inline bool ++__update_cpumasks_bitmap(int cpu, unsigned long *plevel, unsigned long level, ++ cpumask_t cpumasks[], unsigned long bitmap[]) ++{ ++ if (*plevel == level) ++ return false; ++ ++ cpumask_clear_cpu(cpu, cpumasks + *plevel); ++ if (cpumask_empty(cpumasks + *plevel)) ++ clear_bit(*plevel, bitmap); ++ cpumask_set_cpu(cpu, cpumasks + level); ++ set_bit(level, bitmap); ++ ++ *plevel = level; ++ ++ return true; ++} ++ ++static inline int ++task_running_policy_level(const struct task_struct *p, const struct rq *rq) ++{ ++ int prio = p->prio; ++ ++ if (NORMAL_PRIO == prio) ++ return SCHED_RQ_NORMAL_0 + task_deadline_level(p, rq); ++ ++ if (ISO_PRIO == prio) ++ return SCHED_RQ_ISO; ++ if (prio < MAX_RT_PRIO) ++ return SCHED_RQ_RT; ++ return PRIO_LIMIT - prio; ++} ++ ++static inline void update_sched_rq_queued_masks_normal(struct rq *rq) ++{ ++ struct task_struct *p = rq_first_queued_task(rq); ++ ++ if (p->prio != NORMAL_PRIO) ++ return; ++ ++ __update_cpumasks_bitmap(cpu_of(rq), &rq->queued_level, ++ task_running_policy_level(p, rq), ++ &sched_rq_queued_masks[0], ++ &sched_rq_queued_masks_bitmap[0]); ++} ++ ++#ifdef CONFIG_SMT_NICE ++static inline void update_sched_cpu_psg_mask(const int cpu) ++{ ++ cpumask_t tmp; ++ ++ cpumask_or(&tmp, &sched_rq_queued_masks[SCHED_RQ_EMPTY], ++ &sched_rq_queued_masks[SCHED_RQ_IDLE]); ++ cpumask_and(&tmp, &tmp, cpu_smt_mask(cpu)); ++ if (cpumask_equal(&tmp, cpu_smt_mask(cpu))) ++ cpumask_or(&sched_cpu_psg_mask, &sched_cpu_psg_mask, ++ cpu_smt_mask(cpu)); ++ else ++ cpumask_andnot(&sched_cpu_psg_mask, &sched_cpu_psg_mask, ++ cpu_smt_mask(cpu)); ++} ++#endif ++ ++static inline void update_sched_rq_queued_masks(struct rq *rq) ++{ ++ int cpu = cpu_of(rq); ++ struct task_struct *p = rq_first_queued_task(rq); ++ unsigned long level; ++#ifdef CONFIG_SCHED_SMT ++ unsigned long last_level = rq->queued_level; ++#endif ++ ++ level = task_running_policy_level(p, rq); ++ sched_rq_prio[cpu] = p->prio; ++ ++ if (!__update_cpumasks_bitmap(cpu, &rq->queued_level, level, ++ &sched_rq_queued_masks[0], ++ &sched_rq_queued_masks_bitmap[0])) ++ return; ++ ++#ifdef CONFIG_SCHED_SMT ++ if (cpu == per_cpu(sched_sibling_cpu, cpu)) ++ return; ++ ++ if (SCHED_RQ_EMPTY == last_level) { ++ cpumask_andnot(&sched_cpu_sg_idle_mask, &sched_cpu_sg_idle_mask, ++ cpu_smt_mask(cpu)); ++ } else if (SCHED_RQ_EMPTY == level) { ++ cpumask_t tmp; ++ ++ cpumask_and(&tmp, cpu_smt_mask(cpu), ++ &sched_rq_queued_masks[SCHED_RQ_EMPTY]); ++ if (cpumask_equal(&tmp, cpu_smt_mask(cpu))) ++ cpumask_or(&sched_cpu_sg_idle_mask, cpu_smt_mask(cpu), ++ &sched_cpu_sg_idle_mask); ++ } ++ ++#ifdef CONFIG_SMT_NICE ++ if (level <= SCHED_RQ_IDLE && last_level > SCHED_RQ_IDLE) { ++ cpumask_clear_cpu(per_cpu(sched_sibling_cpu, cpu), ++ &sched_smt_supressed_mask); ++ update_sched_cpu_psg_mask(cpu); ++ resched_cpu_if_curr_is(per_cpu(sched_sibling_cpu, cpu), PRIO_LIMIT); ++ } else if (last_level <= SCHED_RQ_IDLE && level > SCHED_RQ_IDLE) { ++ cpumask_set_cpu(per_cpu(sched_sibling_cpu, cpu), ++ &sched_smt_supressed_mask); ++ update_sched_cpu_psg_mask(cpu); ++ resched_cpu_if_curr_is(per_cpu(sched_sibling_cpu, cpu), IDLE_PRIO); ++ } ++#endif /* CONFIG_SMT_NICE */ ++#endif ++} ++ ++static inline void update_sched_rq_pending_masks(struct rq *rq) ++{ ++ unsigned long level; ++ struct task_struct *p = rq_second_queued_task(rq); ++ ++ level = task_running_policy_level(p, rq); ++ ++ __update_cpumasks_bitmap(cpu_of(rq), &rq->pending_level, level, ++ &sched_rq_pending_masks[0], ++ &sched_rq_pending_masks_bitmap[0]); ++} ++ ++#else /* CONFIG_SMP */ ++static inline void update_sched_rq_queued_masks(struct rq *rq) {} ++static inline void update_sched_rq_queued_masks_normal(struct rq *rq) {} ++static inline void update_sched_rq_pending_masks(struct rq *rq) {} ++#endif ++ ++#ifdef CONFIG_NO_HZ_FULL ++/* ++ * Tick may be needed by tasks in the runqueue depending on their policy and ++ * requirements. If tick is needed, lets send the target an IPI to kick it out ++ * of nohz mode if necessary. ++ */ ++static inline void sched_update_tick_dependency(struct rq *rq) ++{ ++ int cpu; ++ ++ if (!tick_nohz_full_enabled()) ++ return; ++ ++ cpu = cpu_of(rq); ++ ++ if (!tick_nohz_full_cpu(cpu)) ++ return; ++ ++ if (rq->nr_running < 2) ++ tick_nohz_dep_clear_cpu(cpu, TICK_DEP_BIT_SCHED); ++ else ++ tick_nohz_dep_set_cpu(cpu, TICK_DEP_BIT_SCHED); ++} ++#else /* !CONFIG_NO_HZ_FULL */ ++static inline void sched_update_tick_dependency(struct rq *rq) { } ++#endif ++ ++/* ++ * Removing from the runqueue. Deleting a task from the skip list is done ++ * via the stored node reference in the task struct and does not require a full ++ * look up. Thus it occurs in O(k) time where k is the "level" of the list the ++ * task was stored at - usually < 4, max 16. ++ * ++ * Context: rq->lock ++ */ ++static inline void dequeue_task(struct task_struct *p, struct rq *rq, int flags) ++{ ++ lockdep_assert_held(&rq->lock); ++ ++ WARN_ONCE(task_rq(p) != rq, "pds: dequeue task reside on cpu%d from cpu%d\n", ++ task_cpu(p), cpu_of(rq)); ++ if (skiplist_del_init(&rq->sl_header, &p->sl_node)) { ++ update_sched_rq_queued_masks(rq); ++ update_sched_rq_pending_masks(rq); ++ } else if (is_second_in_rq(p, rq)) ++ update_sched_rq_pending_masks(rq); ++ rq->nr_running--; ++ ++ sched_update_tick_dependency(rq); ++ psi_dequeue(p, flags & DEQUEUE_SLEEP); ++ ++ sched_info_dequeued(rq, p); ++} ++ ++/* ++ * To determine if it's safe for a task of SCHED_IDLE to actually run as ++ * an idle task, we ensure none of the following conditions are met. ++ */ ++static inline bool idleprio_suitable(struct task_struct *p) ++{ ++ return (!freezing(p) && !signal_pending(p) && ++ !(task_contributes_to_load(p)) && !(p->flags & (PF_EXITING))); ++} ++ ++/* ++ * pds_skiplist_random_level -- Returns a pseudo-random level number for skip ++ * list node which is used in PDS run queue. ++ * ++ * In current implementation, based on testing, the first 8 bits in microseconds ++ * of niffies are suitable for random level population. ++ * find_first_bit() is used to satisfy p = 0.5 between each levels, and there ++ * should be platform hardware supported instruction(known as ctz/clz) to speed ++ * up this function. ++ * The skiplist level for a task is populated when task is created and doesn't ++ * change in task's life time. When task is being inserted into run queue, this ++ * skiplist level is set to task's sl_node->level, the skiplist insert function ++ * may change it based on current level of the skip lsit. ++ */ ++static inline int pds_skiplist_random_level(const struct task_struct *p) ++{ ++ long unsigned int randseed; ++ ++ /* ++ * 1. Some architectures don't have better than microsecond resolution ++ * so mask out ~microseconds as a factor of the random seed for skiplist ++ * insertion. ++ * 2. Use address of task structure pointer as another factor of the ++ * random seed for task burst forking scenario. ++ */ ++ randseed = (task_rq(p)->clock ^ (long unsigned int)p) >> 10; ++ ++ return find_first_bit(&randseed, NUM_SKIPLIST_LEVEL - 1); ++} ++ ++/** ++ * pds_skiplist_task_search -- search function used in PDS run queue skip list ++ * node insert operation. ++ * @it: iterator pointer to the node in the skip list ++ * @node: pointer to the skiplist_node to be inserted ++ * ++ * Returns true if key of @it is less or equal to key value of @node, otherwise ++ * false. ++ */ ++static inline bool ++pds_skiplist_task_search(struct skiplist_node *it, struct skiplist_node *node) ++{ ++ return (skiplist_entry(it, struct task_struct, sl_node)->priodl <= ++ skiplist_entry(node, struct task_struct, sl_node)->priodl); ++} ++ ++/* ++ * Define the skip list insert function for PDS ++ */ ++DEFINE_SKIPLIST_INSERT_FUNC(pds_skiplist_insert, pds_skiplist_task_search); ++ ++/* ++ * Adding task to the runqueue. ++ * ++ * Context: rq->lock ++ */ ++static inline void enqueue_task(struct task_struct *p, struct rq *rq, int flags) ++{ ++ lockdep_assert_held(&rq->lock); ++ ++ WARN_ONCE(task_rq(p) != rq, "pds: enqueue task reside on cpu%d to cpu%d\n", ++ task_cpu(p), cpu_of(rq)); ++ ++ p->sl_node.level = p->sl_level; ++ if (pds_skiplist_insert(&rq->sl_header, &p->sl_node)) { ++ update_sched_rq_queued_masks(rq); ++ update_sched_rq_pending_masks(rq); ++ } else if (is_second_in_rq(p, rq)) ++ update_sched_rq_pending_masks(rq); ++ rq->nr_running++; ++ ++ sched_update_tick_dependency(rq); ++ ++ sched_info_queued(rq, p); ++ psi_enqueue(p, flags); ++ ++ /* ++ * If in_iowait is set, the code below may not trigger any cpufreq ++ * utilization updates, so do it here explicitly with the IOWAIT flag ++ * passed. ++ */ ++ if (p->in_iowait) ++ cpufreq_update_this_cpu(rq, SCHED_CPUFREQ_IOWAIT); ++} ++ ++static inline void requeue_task(struct task_struct *p, struct rq *rq) ++{ ++ bool b_first, b_second; ++ ++ lockdep_assert_held(&rq->lock); ++ ++ WARN_ONCE(task_rq(p) != rq, "pds: cpu[%d] requeue task reside on cpu%d\n", ++ cpu_of(rq), task_cpu(p)); ++ ++ b_first = skiplist_del_init(&rq->sl_header, &p->sl_node); ++ b_second = is_second_in_rq(p, rq); ++ ++ p->sl_node.level = p->sl_level; ++ if (pds_skiplist_insert(&rq->sl_header, &p->sl_node) || b_first) { ++ update_sched_rq_queued_masks(rq); ++ update_sched_rq_pending_masks(rq); ++ } else if (is_second_in_rq(p, rq) || b_second) ++ update_sched_rq_pending_masks(rq); ++} ++ ++/* ++ * resched_curr - mark rq's current task 'to be rescheduled now'. ++ * ++ * On UP this means the setting of the need_resched flag, on SMP it ++ * might also involve a cross-CPU call to trigger the scheduler on ++ * the target CPU. ++ */ ++void resched_curr(struct rq *rq) ++{ ++ struct task_struct *curr = rq->curr; ++ int cpu; ++ ++ lockdep_assert_held(&rq->lock); ++ ++ if (test_tsk_need_resched(curr)) ++ return; ++ ++ cpu = cpu_of(rq); ++ if (cpu == smp_processor_id()) { ++ set_tsk_need_resched(curr); ++ set_preempt_need_resched(); ++ return; ++ } ++ ++ if (set_nr_and_not_polling(curr)) ++ smp_send_reschedule(cpu); ++ else ++ trace_sched_wake_idle_without_ipi(cpu); ++} ++ ++static inline void check_preempt_curr(struct rq *rq, struct task_struct *p) ++{ ++ struct task_struct *curr = rq->curr; ++ ++ if (curr->prio == PRIO_LIMIT) ++ resched_curr(rq); ++ ++ if (task_running_idle(p)) ++ return; ++ ++ if (p->priodl < curr->priodl) ++ resched_curr(rq); ++} ++ ++#ifdef CONFIG_SCHED_HRTICK ++/* ++ * Use HR-timers to deliver accurate preemption points. ++ */ ++ ++static void hrtick_clear(struct rq *rq) ++{ ++ if (hrtimer_active(&rq->hrtick_timer)) ++ hrtimer_cancel(&rq->hrtick_timer); ++} ++ ++/* ++ * High-resolution timer tick. ++ * Runs from hardirq context with interrupts disabled. ++ */ ++static enum hrtimer_restart hrtick(struct hrtimer *timer) ++{ ++ struct rq *rq = container_of(timer, struct rq, hrtick_timer); ++ struct task_struct *p; ++ ++ WARN_ON_ONCE(cpu_of(rq) != smp_processor_id()); ++ ++ raw_spin_lock(&rq->lock); ++ p = rq->curr; ++ p->time_slice = 0; ++ resched_curr(rq); ++ raw_spin_unlock(&rq->lock); ++ ++ return HRTIMER_NORESTART; ++} ++ ++/* ++ * Use hrtick when: ++ * - enabled by features ++ * - hrtimer is actually high res ++ */ ++static inline int hrtick_enabled(struct rq *rq) ++{ ++ /** ++ * PDS doesn't support sched_feat yet ++ if (!sched_feat(HRTICK)) ++ return 0; ++ */ ++ if (!cpu_active(cpu_of(rq))) ++ return 0; ++ return hrtimer_is_hres_active(&rq->hrtick_timer); ++} ++ ++#ifdef CONFIG_SMP ++ ++static void __hrtick_restart(struct rq *rq) ++{ ++ struct hrtimer *timer = &rq->hrtick_timer; ++ ++ hrtimer_start_expires(timer, HRTIMER_MODE_ABS_PINNED_HARD); ++} ++ ++/* ++ * called from hardirq (IPI) context ++ */ ++static void __hrtick_start(void *arg) ++{ ++ struct rq *rq = arg; ++ ++ raw_spin_lock(&rq->lock); ++ __hrtick_restart(rq); ++ rq->hrtick_csd_pending = 0; ++ raw_spin_unlock(&rq->lock); ++} ++ ++/* ++ * Called to set the hrtick timer state. ++ * ++ * called with rq->lock held and irqs disabled ++ */ ++void hrtick_start(struct rq *rq, u64 delay) ++{ ++ struct hrtimer *timer = &rq->hrtick_timer; ++ ktime_t time; ++ s64 delta; ++ ++ /* ++ * Don't schedule slices shorter than 10000ns, that just ++ * doesn't make sense and can cause timer DoS. ++ */ ++ delta = max_t(s64, delay, 10000LL); ++ time = ktime_add_ns(timer->base->get_time(), delta); ++ ++ hrtimer_set_expires(timer, time); ++ ++ if (rq == this_rq()) { ++ __hrtick_restart(rq); ++ } else if (!rq->hrtick_csd_pending) { ++ smp_call_function_single_async(cpu_of(rq), &rq->hrtick_csd); ++ rq->hrtick_csd_pending = 1; ++ } ++} ++ ++#else ++/* ++ * Called to set the hrtick timer state. ++ * ++ * called with rq->lock held and irqs disabled ++ */ ++void hrtick_start(struct rq *rq, u64 delay) ++{ ++ /* ++ * Don't schedule slices shorter than 10000ns, that just ++ * doesn't make sense. Rely on vruntime for fairness. ++ */ ++ delay = max_t(u64, delay, 10000LL); ++ hrtimer_start(&rq->hrtick_timer, ns_to_ktime(delay), ++ HRTIMER_MODE_REL_PINNED_HARD); ++} ++#endif /* CONFIG_SMP */ ++ ++static void hrtick_rq_init(struct rq *rq) ++{ ++#ifdef CONFIG_SMP ++ rq->hrtick_csd_pending = 0; ++ ++ rq->hrtick_csd.flags = 0; ++ rq->hrtick_csd.func = __hrtick_start; ++ rq->hrtick_csd.info = rq; ++#endif ++ ++ hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD); ++ rq->hrtick_timer.function = hrtick; ++} ++ ++static inline int rq_dither(struct rq *rq) ++{ ++ if ((rq->clock - rq->last_tick > HALF_JIFFY_NS) || hrtick_enabled(rq)) ++ return 0; ++ ++ return HALF_JIFFY_NS; ++} ++ ++#else /* CONFIG_SCHED_HRTICK */ ++static inline int hrtick_enabled(struct rq *rq) ++{ ++ return 0; ++} ++ ++static inline void hrtick_clear(struct rq *rq) ++{ ++} ++ ++static inline void hrtick_rq_init(struct rq *rq) ++{ ++} ++ ++static inline int rq_dither(struct rq *rq) ++{ ++ return (rq->clock - rq->last_tick > HALF_JIFFY_NS)? 0:HALF_JIFFY_NS; ++} ++#endif /* CONFIG_SCHED_HRTICK */ ++ ++static inline int normal_prio(struct task_struct *p) ++{ ++ static const int policy_to_prio[] = { ++ NORMAL_PRIO, /* SCHED_NORMAL */ ++ 0, /* SCHED_FIFO */ ++ 0, /* SCHED_RR */ ++ IDLE_PRIO, /* SCHED_BATCH */ ++ ISO_PRIO, /* SCHED_ISO */ ++ IDLE_PRIO /* SCHED_IDLE */ ++ }; ++ ++ if (task_has_rt_policy(p)) ++ return MAX_RT_PRIO - 1 - p->rt_priority; ++ return policy_to_prio[p->policy]; ++} ++ ++/* ++ * Calculate the current priority, i.e. the priority ++ * taken into account by the scheduler. This value might ++ * be boosted by RT tasks as it will be RT if the task got ++ * RT-boosted. If not then it returns p->normal_prio. ++ */ ++static int effective_prio(struct task_struct *p) ++{ ++ p->normal_prio = normal_prio(p); ++ /* ++ * If we are RT tasks or we were boosted to RT priority, ++ * keep the priority unchanged. Otherwise, update priority ++ * to the normal priority: ++ */ ++ if (!rt_prio(p->prio)) ++ return p->normal_prio; ++ return p->prio; ++} ++ ++/* ++ * activate_task - move a task to the runqueue. ++ * ++ * Context: rq->lock ++ */ ++static void activate_task(struct task_struct *p, struct rq *rq) ++{ ++ if (task_contributes_to_load(p)) ++ rq->nr_uninterruptible--; ++ enqueue_task(p, rq, ENQUEUE_WAKEUP); ++ p->on_rq = 1; ++ cpufreq_update_this_cpu(rq, 0); ++} ++ ++/* ++ * deactivate_task - remove a task from the runqueue. ++ * ++ * Context: rq->lock ++ */ ++static inline void deactivate_task(struct task_struct *p, struct rq *rq) ++{ ++ if (task_contributes_to_load(p)) ++ rq->nr_uninterruptible++; ++ dequeue_task(p, rq, DEQUEUE_SLEEP); ++ p->on_rq = 0; ++ cpufreq_update_this_cpu(rq, 0); ++} ++ ++static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu) ++{ ++#ifdef CONFIG_SMP ++ /* ++ * After ->cpu is set up to a new value, task_access_lock(p, ...) can be ++ * successfully executed on another CPU. We must ensure that updates of ++ * per-task data have been completed by this moment. ++ */ ++ smp_wmb(); ++ ++#ifdef CONFIG_THREAD_INFO_IN_TASK ++ WRITE_ONCE(p->cpu, cpu); ++#else ++ WRITE_ONCE(task_thread_info(p)->cpu, cpu); ++#endif ++#endif ++} ++ ++#ifdef CONFIG_SMP ++void set_task_cpu(struct task_struct *p, unsigned int new_cpu) ++{ ++#ifdef CONFIG_SCHED_DEBUG ++ /* ++ * We should never call set_task_cpu() on a blocked task, ++ * ttwu() will sort out the placement. ++ */ ++ WARN_ON_ONCE(p->state != TASK_RUNNING && p->state != TASK_WAKING && ++ !p->on_rq); ++#ifdef CONFIG_LOCKDEP ++ /* ++ * The caller should hold either p->pi_lock or rq->lock, when changing ++ * a task's CPU. ->pi_lock for waking tasks, rq->lock for runnable tasks. ++ * ++ * sched_move_task() holds both and thus holding either pins the cgroup, ++ * see task_group(). ++ */ ++ WARN_ON_ONCE(debug_locks && !(lockdep_is_held(&p->pi_lock) || ++ lockdep_is_held(&task_rq(p)->lock))); ++#endif ++ /* ++ * Clearly, migrating tasks to offline CPUs is a fairly daft thing. ++ */ ++ WARN_ON_ONCE(!cpu_online(new_cpu)); ++#endif ++ if (task_cpu(p) == new_cpu) ++ return; ++ trace_sched_migrate_task(p, new_cpu); ++ rseq_migrate(p); ++ perf_event_task_migrate(p); ++ ++ __set_task_cpu(p, new_cpu); ++} ++ ++static inline bool is_per_cpu_kthread(struct task_struct *p) ++{ ++ return ((p->flags & PF_KTHREAD) && (1 == p->nr_cpus_allowed)); ++} ++ ++/* ++ * Per-CPU kthreads are allowed to run on !active && online CPUs, see ++ * __set_cpus_allowed_ptr() and select_fallback_rq(). ++ */ ++static inline bool is_cpu_allowed(struct task_struct *p, int cpu) ++{ ++ if (!cpumask_test_cpu(cpu, &p->cpus_mask)) ++ return false; ++ ++ if (is_per_cpu_kthread(p)) ++ return cpu_online(cpu); ++ ++ return cpu_active(cpu); ++} ++ ++/* ++ * This is how migration works: ++ * ++ * 1) we invoke migration_cpu_stop() on the target CPU using ++ * stop_one_cpu(). ++ * 2) stopper starts to run (implicitly forcing the migrated thread ++ * off the CPU) ++ * 3) it checks whether the migrated task is still in the wrong runqueue. ++ * 4) if it's in the wrong runqueue then the migration thread removes ++ * it and puts it into the right queue. ++ * 5) stopper completes and stop_one_cpu() returns and the migration ++ * is done. ++ */ ++ ++/* ++ * detach_task() -- detach the task for the migration specified in @target_cpu ++ */ ++static void detach_task(struct rq *rq, struct task_struct *p, int target_cpu) ++{ ++ lockdep_assert_held(&rq->lock); ++ ++ WRITE_ONCE(p->on_rq ,TASK_ON_RQ_MIGRATING); ++ if (task_contributes_to_load(p)) ++ rq->nr_uninterruptible++; ++ dequeue_task(p, rq, 0); ++ ++ set_task_cpu(p, target_cpu); ++} ++ ++/* ++ * attach_task() -- attach the task detached by detach_task() to its new rq. ++ */ ++static void attach_task(struct rq *rq, struct task_struct *p) ++{ ++ lockdep_assert_held(&rq->lock); ++ ++ BUG_ON(task_rq(p) != rq); ++ ++ if (task_contributes_to_load(p)) ++ rq->nr_uninterruptible--; ++ enqueue_task(p, rq, 0); ++ p->on_rq = TASK_ON_RQ_QUEUED; ++ cpufreq_update_this_cpu(rq, 0); ++} ++ ++/* ++ * move_queued_task - move a queued task to new rq. ++ * ++ * Returns (locked) new rq. Old rq's lock is released. ++ */ ++static struct rq *move_queued_task(struct rq *rq, struct task_struct *p, int ++ new_cpu) ++{ ++ detach_task(rq, p, new_cpu); ++ raw_spin_unlock(&rq->lock); ++ ++ rq = cpu_rq(new_cpu); ++ ++ raw_spin_lock(&rq->lock); ++ update_rq_clock(rq); ++ ++ attach_task(rq, p); ++ ++ check_preempt_curr(rq, p); ++ ++ return rq; ++} ++ ++struct migration_arg { ++ struct task_struct *task; ++ int dest_cpu; ++}; ++ ++/* ++ * Move (not current) task off this CPU, onto the destination CPU. We're doing ++ * this because either it can't run here any more (set_cpus_allowed() ++ * away from this CPU, or CPU going down), or because we're ++ * attempting to rebalance this task on exec (sched_exec). ++ * ++ * So we race with normal scheduler movements, but that's OK, as long ++ * as the task is no longer on this CPU. ++ */ ++static struct rq *__migrate_task(struct rq *rq, struct task_struct *p, int ++ dest_cpu) ++{ ++ /* Affinity changed (again). */ ++ if (!is_cpu_allowed(p, dest_cpu)) ++ return rq; ++ ++ update_rq_clock(rq); ++ return move_queued_task(rq, p, dest_cpu); ++} ++ ++/* ++ * migration_cpu_stop - this will be executed by a highprio stopper thread ++ * and performs thread migration by bumping thread off CPU then ++ * 'pushing' onto another runqueue. ++ */ ++static int migration_cpu_stop(void *data) ++{ ++ struct migration_arg *arg = data; ++ struct task_struct *p = arg->task; ++ struct rq *rq = this_rq(); ++ ++ /* ++ * The original target CPU might have gone down and we might ++ * be on another CPU but it doesn't matter. ++ */ ++ local_irq_disable(); ++ ++ raw_spin_lock(&p->pi_lock); ++ raw_spin_lock(&rq->lock); ++ /* ++ * If task_rq(p) != rq, it cannot be migrated here, because we're ++ * holding rq->lock, if p->on_rq == 0 it cannot get enqueued because ++ * we're holding p->pi_lock. ++ */ ++ if (task_rq(p) == rq) ++ if (task_on_rq_queued(p)) ++ rq = __migrate_task(rq, p, arg->dest_cpu); ++ raw_spin_unlock(&rq->lock); ++ raw_spin_unlock(&p->pi_lock); ++ ++ local_irq_enable(); ++ return 0; ++} ++ ++static inline void ++set_cpus_allowed_common(struct task_struct *p, const struct cpumask *new_mask) ++{ ++ cpumask_copy(&p->cpus_mask, new_mask); ++ p->nr_cpus_allowed = cpumask_weight(new_mask); ++} ++ ++void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask) ++{ ++ set_cpus_allowed_common(p, new_mask); ++} ++#endif ++ ++/* Enter with rq lock held. We know p is on the local CPU */ ++static inline void __set_tsk_resched(struct task_struct *p) ++{ ++ set_tsk_need_resched(p); ++ set_preempt_need_resched(); ++} ++ ++/** ++ * task_curr - is this task currently executing on a CPU? ++ * @p: the task in question. ++ * ++ * Return: 1 if the task is currently executing. 0 otherwise. ++ */ ++inline int task_curr(const struct task_struct *p) ++{ ++ return cpu_curr(task_cpu(p)) == p; ++} ++ ++#ifdef CONFIG_SMP ++/* ++ * wait_task_inactive - wait for a thread to unschedule. ++ * ++ * If @match_state is nonzero, it's the @p->state value just checked and ++ * not expected to change. If it changes, i.e. @p might have woken up, ++ * then return zero. When we succeed in waiting for @p to be off its CPU, ++ * we return a positive number (its total switch count). If a second call ++ * a short while later returns the same number, the caller can be sure that ++ * @p has remained unscheduled the whole time. ++ * ++ * The caller must ensure that the task *will* unschedule sometime soon, ++ * else this function might spin for a *long* time. This function can't ++ * be called with interrupts off, or it may introduce deadlock with ++ * smp_call_function() if an IPI is sent by the same process we are ++ * waiting to become inactive. ++ */ ++unsigned long wait_task_inactive(struct task_struct *p, long match_state) ++{ ++ unsigned long flags; ++ bool running, on_rq; ++ unsigned long ncsw; ++ struct rq *rq; ++ raw_spinlock_t *lock; ++ ++ for (;;) { ++ rq = task_rq(p); ++ ++ /* ++ * If the task is actively running on another CPU ++ * still, just relax and busy-wait without holding ++ * any locks. ++ * ++ * NOTE! Since we don't hold any locks, it's not ++ * even sure that "rq" stays as the right runqueue! ++ * But we don't care, since this will return false ++ * if the runqueue has changed and p is actually now ++ * running somewhere else! ++ */ ++ while (task_running(p) && p == rq->curr) { ++ if (match_state && unlikely(p->state != match_state)) ++ return 0; ++ cpu_relax(); ++ } ++ ++ /* ++ * Ok, time to look more closely! We need the rq ++ * lock now, to be *sure*. If we're wrong, we'll ++ * just go back and repeat. ++ */ ++ task_access_lock_irqsave(p, &lock, &flags); ++ trace_sched_wait_task(p); ++ running = task_running(p); ++ on_rq = p->on_rq; ++ ncsw = 0; ++ if (!match_state || p->state == match_state) ++ ncsw = p->nvcsw | LONG_MIN; /* sets MSB */ ++ task_access_unlock_irqrestore(p, lock, &flags); ++ ++ /* ++ * If it changed from the expected state, bail out now. ++ */ ++ if (unlikely(!ncsw)) ++ break; ++ ++ /* ++ * Was it really running after all now that we ++ * checked with the proper locks actually held? ++ * ++ * Oops. Go back and try again.. ++ */ ++ if (unlikely(running)) { ++ cpu_relax(); ++ continue; ++ } ++ ++ /* ++ * It's not enough that it's not actively running, ++ * it must be off the runqueue _entirely_, and not ++ * preempted! ++ * ++ * So if it was still runnable (but just not actively ++ * running right now), it's preempted, and we should ++ * yield - it could be a while. ++ */ ++ if (unlikely(on_rq)) { ++ ktime_t to = NSEC_PER_SEC / HZ; ++ ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ schedule_hrtimeout(&to, HRTIMER_MODE_REL); ++ continue; ++ } ++ ++ /* ++ * Ahh, all good. It wasn't running, and it wasn't ++ * runnable, which means that it will never become ++ * running in the future either. We're all done! ++ */ ++ break; ++ } ++ ++ return ncsw; ++} ++ ++/*** ++ * kick_process - kick a running thread to enter/exit the kernel ++ * @p: the to-be-kicked thread ++ * ++ * Cause a process which is running on another CPU to enter ++ * kernel-mode, without any delay. (to get signals handled.) ++ * ++ * NOTE: this function doesn't have to take the runqueue lock, ++ * because all it wants to ensure is that the remote task enters ++ * the kernel. If the IPI races and the task has been migrated ++ * to another CPU then no harm is done and the purpose has been ++ * achieved as well. ++ */ ++void kick_process(struct task_struct *p) ++{ ++ int cpu; ++ ++ preempt_disable(); ++ cpu = task_cpu(p); ++ if ((cpu != smp_processor_id()) && task_curr(p)) ++ smp_send_reschedule(cpu); ++ preempt_enable(); ++} ++EXPORT_SYMBOL_GPL(kick_process); ++ ++/* ++ * ->cpus_mask is protected by both rq->lock and p->pi_lock ++ * ++ * A few notes on cpu_active vs cpu_online: ++ * ++ * - cpu_active must be a subset of cpu_online ++ * ++ * - on CPU-up we allow per-CPU kthreads on the online && !active CPU, ++ * see __set_cpus_allowed_ptr(). At this point the newly online ++ * CPU isn't yet part of the sched domains, and balancing will not ++ * see it. ++ * ++ * - on cpu-down we clear cpu_active() to mask the sched domains and ++ * avoid the load balancer to place new tasks on the to be removed ++ * CPU. Existing tasks will remain running there and will be taken ++ * off. ++ * ++ * This means that fallback selection must not select !active CPUs. ++ * And can assume that any active CPU must be online. Conversely ++ * select_task_rq() below may allow selection of !active CPUs in order ++ * to satisfy the above rules. ++ */ ++static int select_fallback_rq(int cpu, struct task_struct *p) ++{ ++ int nid = cpu_to_node(cpu); ++ const struct cpumask *nodemask = NULL; ++ enum { cpuset, possible, fail } state = cpuset; ++ int dest_cpu; ++ ++ /* ++ * If the node that the CPU is on has been offlined, cpu_to_node() ++ * will return -1. There is no CPU on the node, and we should ++ * select the CPU on the other node. ++ */ ++ if (nid != -1) { ++ nodemask = cpumask_of_node(nid); ++ ++ /* Look for allowed, online CPU in same node. */ ++ for_each_cpu(dest_cpu, nodemask) { ++ if (!cpu_active(dest_cpu)) ++ continue; ++ if (cpumask_test_cpu(dest_cpu, &p->cpus_mask)) ++ return dest_cpu; ++ } ++ } ++ ++ for (;;) { ++ /* Any allowed, online CPU? */ ++ for_each_cpu(dest_cpu, &p->cpus_mask) { ++ if (!is_cpu_allowed(p, dest_cpu)) ++ continue; ++ goto out; ++ } ++ ++ /* No more Mr. Nice Guy. */ ++ switch (state) { ++ case cpuset: ++ if (IS_ENABLED(CONFIG_CPUSETS)) { ++ cpuset_cpus_allowed_fallback(p); ++ state = possible; ++ break; ++ } ++ /* Fall-through */ ++ case possible: ++ do_set_cpus_allowed(p, cpu_possible_mask); ++ state = fail; ++ break; ++ ++ case fail: ++ BUG(); ++ break; ++ } ++ } ++ ++out: ++ if (state != cpuset) { ++ /* ++ * Don't tell them about moving exiting tasks or ++ * kernel threads (both mm NULL), since they never ++ * leave kernel. ++ */ ++ if (p->mm && printk_ratelimit()) { ++ printk_deferred("process %d (%s) no longer affine to cpu%d\n", ++ task_pid_nr(p), p->comm, cpu); ++ } ++ } ++ ++ return dest_cpu; ++} ++ ++static inline int best_mask_cpu(int cpu, const cpumask_t *cpumask) ++{ ++ cpumask_t *mask; ++ ++ if (cpumask_test_cpu(cpu, cpumask)) ++ return cpu; ++ ++ mask = &(per_cpu(sched_cpu_affinity_chk_masks, cpu)[0]); ++ while ((cpu = cpumask_any_and(cpumask, mask)) >= nr_cpu_ids) ++ mask++; ++ ++ return cpu; ++} ++ ++/* ++ * task_preemptible_rq - return the rq which the given task can preempt on ++ * @p: task wants to preempt CPU ++ * @only_preempt_low_policy: indicate only preempt rq running low policy than @p ++ */ ++static inline int ++task_preemptible_rq_idle(struct task_struct *p, cpumask_t *chk_mask) ++{ ++ cpumask_t tmp; ++ ++#ifdef CONFIG_SCHED_SMT ++ if (cpumask_and(&tmp, chk_mask, &sched_cpu_sg_idle_mask)) ++ return best_mask_cpu(task_cpu(p), &tmp); ++#endif ++ ++#ifdef CONFIG_SMT_NICE ++ /* Only ttwu on cpu which is not smt supressed */ ++ if (cpumask_andnot(&tmp, chk_mask, &sched_smt_supressed_mask)) { ++ cpumask_t t; ++ if (cpumask_and(&t, &tmp, &sched_rq_queued_masks[SCHED_RQ_EMPTY])) ++ return best_mask_cpu(task_cpu(p), &t); ++ return best_mask_cpu(task_cpu(p), &tmp); ++ } ++#endif ++ ++ if (cpumask_and(&tmp, chk_mask, &sched_rq_queued_masks[SCHED_RQ_EMPTY])) ++ return best_mask_cpu(task_cpu(p), &tmp); ++ return best_mask_cpu(task_cpu(p), chk_mask); ++} ++ ++static inline int ++task_preemptible_rq(struct task_struct *p, cpumask_t *chk_mask, ++ int preempt_level) ++{ ++ cpumask_t tmp; ++ int level; ++ ++#ifdef CONFIG_SCHED_SMT ++#ifdef CONFIG_SMT_NICE ++ if (cpumask_and(&tmp, chk_mask, &sched_cpu_psg_mask)) ++ return best_mask_cpu(task_cpu(p), &tmp); ++#else ++ if (cpumask_and(&tmp, chk_mask, &sched_cpu_sg_idle_mask)) ++ return best_mask_cpu(task_cpu(p), &tmp); ++#endif ++#endif ++ ++ level = find_first_bit(sched_rq_queued_masks_bitmap, ++ NR_SCHED_RQ_QUEUED_LEVEL); ++ ++ while (level < preempt_level) { ++ if (cpumask_and(&tmp, chk_mask, &sched_rq_queued_masks[level])) ++ return best_mask_cpu(task_cpu(p), &tmp); ++ ++ level = find_next_bit(sched_rq_queued_masks_bitmap, ++ NR_SCHED_RQ_QUEUED_LEVEL, ++ level + 1); ++ } ++ ++ if (unlikely(SCHED_RQ_RT == level && ++ level == preempt_level && ++ cpumask_and(&tmp, chk_mask, ++ &sched_rq_queued_masks[SCHED_RQ_RT]))) { ++ unsigned int cpu; ++ ++ for_each_cpu (cpu, &tmp) ++ if (p->prio < sched_rq_prio[cpu]) ++ return cpu; ++ } ++ ++ return best_mask_cpu(task_cpu(p), chk_mask); ++} ++ ++/* ++ * wake flags ++ */ ++#define WF_SYNC 0x01 /* waker goes to sleep after wakeup */ ++#define WF_FORK 0x02 /* child wakeup after fork */ ++#define WF_MIGRATED 0x04 /* internal use, task got migrated */ ++ ++static inline int select_task_rq(struct task_struct *p) ++{ ++ cpumask_t chk_mask; ++ ++ if (unlikely(!cpumask_and(&chk_mask, &p->cpus_mask, cpu_online_mask))) ++ return select_fallback_rq(task_cpu(p), p); ++ ++ /* Check IDLE tasks suitable to run normal priority */ ++ if (idleprio_task(p)) { ++ if (idleprio_suitable(p)) { ++ p->prio = p->normal_prio; ++ update_task_priodl(p); ++ return task_preemptible_rq_idle(p, &chk_mask); ++ } ++ p->prio = NORMAL_PRIO; ++ update_task_priodl(p); ++ } ++ ++ return task_preemptible_rq(p, &chk_mask, ++ task_running_policy_level(p, this_rq())); ++} ++#else /* CONFIG_SMP */ ++static inline int select_task_rq(struct task_struct *p) ++{ ++ return 0; ++} ++#endif /* CONFIG_SMP */ ++ ++static void ++ttwu_stat(struct task_struct *p, int cpu, int wake_flags) ++{ ++ struct rq *rq; ++ ++ if (!schedstat_enabled()) ++ return; ++ ++ rq= this_rq(); ++ ++#ifdef CONFIG_SMP ++ if (cpu == rq->cpu) ++ __schedstat_inc(rq->ttwu_local); ++ else { ++ /** PDS ToDo: ++ * How to do ttwu_wake_remote ++ */ ++ } ++#endif /* CONFIG_SMP */ ++ ++ __schedstat_inc(rq->ttwu_count); ++} ++ ++/* ++ * Mark the task runnable and perform wakeup-preemption. ++ */ ++static inline void ++ttwu_do_wakeup(struct rq *rq, struct task_struct *p, int wake_flags) ++{ ++ p->state = TASK_RUNNING; ++ trace_sched_wakeup(p); ++} ++ ++static inline void ++ttwu_do_activate(struct rq *rq, struct task_struct *p, int wake_flags) ++{ ++#ifdef CONFIG_SMP ++ if (p->sched_contributes_to_load) ++ rq->nr_uninterruptible--; ++#endif ++ ++ activate_task(p, rq); ++ ttwu_do_wakeup(rq, p, 0); ++} ++ ++static int ttwu_remote(struct task_struct *p, int wake_flags) ++{ ++ struct rq *rq; ++ raw_spinlock_t *lock; ++ int ret = 0; ++ ++ rq = __task_access_lock(p, &lock); ++ if (task_on_rq_queued(p)) { ++ ttwu_do_wakeup(rq, p, wake_flags); ++ ret = 1; ++ } ++ __task_access_unlock(p, lock); ++ ++ return ret; ++} ++ ++/* ++ * Notes on Program-Order guarantees on SMP systems. ++ * ++ * MIGRATION ++ * ++ * The basic program-order guarantee on SMP systems is that when a task [t] ++ * migrates, all its activity on its old CPU [c0] happens-before any subsequent ++ * execution on its new CPU [c1]. ++ * ++ * For migration (of runnable tasks) this is provided by the following means: ++ * ++ * A) UNLOCK of the rq(c0)->lock scheduling out task t ++ * B) migration for t is required to synchronize *both* rq(c0)->lock and ++ * rq(c1)->lock (if not at the same time, then in that order). ++ * C) LOCK of the rq(c1)->lock scheduling in task ++ * ++ * Transitivity guarantees that B happens after A and C after B. ++ * Note: we only require RCpc transitivity. ++ * Note: the CPU doing B need not be c0 or c1 ++ * ++ * Example: ++ * ++ * CPU0 CPU1 CPU2 ++ * ++ * LOCK rq(0)->lock ++ * sched-out X ++ * sched-in Y ++ * UNLOCK rq(0)->lock ++ * ++ * LOCK rq(0)->lock // orders against CPU0 ++ * dequeue X ++ * UNLOCK rq(0)->lock ++ * ++ * LOCK rq(1)->lock ++ * enqueue X ++ * UNLOCK rq(1)->lock ++ * ++ * LOCK rq(1)->lock // orders against CPU2 ++ * sched-out Z ++ * sched-in X ++ * UNLOCK rq(1)->lock ++ * ++ * ++ * BLOCKING -- aka. SLEEP + WAKEUP ++ * ++ * For blocking we (obviously) need to provide the same guarantee as for ++ * migration. However the means are completely different as there is no lock ++ * chain to provide order. Instead we do: ++ * ++ * 1) smp_store_release(X->on_cpu, 0) ++ * 2) smp_cond_load_acquire(!X->on_cpu) ++ * ++ * Example: ++ * ++ * CPU0 (schedule) CPU1 (try_to_wake_up) CPU2 (schedule) ++ * ++ * LOCK rq(0)->lock LOCK X->pi_lock ++ * dequeue X ++ * sched-out X ++ * smp_store_release(X->on_cpu, 0); ++ * ++ * smp_cond_load_acquire(&X->on_cpu, !VAL); ++ * X->state = WAKING ++ * set_task_cpu(X,2) ++ * ++ * LOCK rq(2)->lock ++ * enqueue X ++ * X->state = RUNNING ++ * UNLOCK rq(2)->lock ++ * ++ * LOCK rq(2)->lock // orders against CPU1 ++ * sched-out Z ++ * sched-in X ++ * UNLOCK rq(2)->lock ++ * ++ * UNLOCK X->pi_lock ++ * UNLOCK rq(0)->lock ++ * ++ * ++ * However; for wakeups there is a second guarantee we must provide, namely we ++ * must observe the state that lead to our wakeup. That is, not only must our ++ * task observe its own prior state, it must also observe the stores prior to ++ * its wakeup. ++ * ++ * This means that any means of doing remote wakeups must order the CPU doing ++ * the wakeup against the CPU the task is going to end up running on. This, ++ * however, is already required for the regular Program-Order guarantee above, ++ * since the waking CPU is the one issueing the ACQUIRE (smp_cond_load_acquire). ++ * ++ */ ++ ++/*** ++ * try_to_wake_up - wake up a thread ++ * @p: the thread to be awakened ++ * @state: the mask of task states that can be woken ++ * @wake_flags: wake modifier flags (WF_*) ++ * ++ * Put it on the run-queue if it's not already there. The "current" ++ * thread is always on the run-queue (except when the actual ++ * re-schedule is in progress), and as such you're allowed to do ++ * the simpler "current->state = TASK_RUNNING" to mark yourself ++ * runnable without the overhead of this. ++ * ++ * Return: %true if @p was woken up, %false if it was already running. ++ * or @state didn't match @p's state. ++ */ ++static int try_to_wake_up(struct task_struct *p, unsigned int state, ++ int wake_flags) ++{ ++ unsigned long flags; ++ struct rq *rq; ++ int cpu, success = 0; ++ ++ /* ++ * If we are going to wake up a thread waiting for CONDITION we ++ * need to ensure that CONDITION=1 done by the caller can not be ++ * reordered with p->state check below. This pairs with mb() in ++ * set_current_state() the waiting thread does. ++ */ ++ raw_spin_lock_irqsave(&p->pi_lock, flags); ++ smp_mb__after_spinlock(); ++ if (!(p->state & state)) ++ goto out; ++ ++ trace_sched_waking(p); ++ ++ /* We're going to change ->state: */ ++ success = 1; ++ cpu = task_cpu(p); ++ ++ /* ++ * Ensure we load p->on_rq _after_ p->state, otherwise it would ++ * be possible to, falsely, observe p->on_rq == 0 and get stuck ++ * in smp_cond_load_acquire() below. ++ * ++ * sched_ttwu_pending() try_to_wake_up() ++ * STORE p->on_rq = 1 LOAD p->state ++ * UNLOCK rq->lock ++ * ++ * __schedule() (switch to task 'p') ++ * LOCK rq->lock smp_rmb(); ++ * smp_mb__after_spinlock(); ++ * UNLOCK rq->lock ++ * ++ * [task p] ++ * STORE p->state = UNINTERRUPTIBLE LOAD p->on_rq ++ * ++ * Pairs with the LOCK+smp_mb__after_spinlock() on rq->lock in ++ * __schedule(). See the comment for smp_mb__after_spinlock(). ++ */ ++ smp_rmb(); ++ if (p->on_rq && ttwu_remote(p, wake_flags)) ++ goto stat; ++ ++#ifdef CONFIG_SMP ++ /* ++ * Ensure we load p->on_cpu _after_ p->on_rq, otherwise it would be ++ * possible to, falsely, observe p->on_cpu == 0. ++ * ++ * One must be running (->on_cpu == 1) in order to remove oneself ++ * from the runqueue. ++ * ++ * __schedule() (switch to task 'p') try_to_wake_up() ++ * STORE p->on_cpu = 1 LOAD p->on_rq ++ * UNLOCK rq->lock ++ * ++ * __schedule() (put 'p' to sleep) ++ * LOCK rq->lock smp_rmb(); ++ * smp_mb__after_spinlock(); ++ * STORE p->on_rq = 0 LOAD p->on_cpu ++ * ++ * Pairs with the LOCK+smp_mb__after_spinlock() on rq->lock in ++ * __schedule(). See the comment for smp_mb__after_spinlock(). ++ */ ++ smp_rmb(); ++ ++ /* ++ * If the owning (remote) CPU is still in the middle of schedule() with ++ * this task as prev, wait until its done referencing the task. ++ * ++ * Pairs with the smp_store_release() in finish_task(). ++ * ++ * This ensures that tasks getting woken will be fully ordered against ++ * their previous state and preserve Program Order. ++ */ ++ smp_cond_load_acquire(&p->on_cpu, !VAL); ++ ++ p->sched_contributes_to_load = !!task_contributes_to_load(p); ++ p->state = TASK_WAKING; ++ ++ if (p->in_iowait) { ++ delayacct_blkio_end(p); ++ atomic_dec(&task_rq(p)->nr_iowait); ++ } ++ ++ if (SCHED_ISO == p->policy && ISO_PRIO != p->prio) { ++ p->prio = ISO_PRIO; ++ p->deadline = 0UL; ++ update_task_priodl(p); ++ } ++ ++ cpu = select_task_rq(p); ++ ++ if (cpu != task_cpu(p)) { ++ wake_flags |= WF_MIGRATED; ++ psi_ttwu_dequeue(p); ++ set_task_cpu(p, cpu); ++ } ++#else /* CONFIG_SMP */ ++ if (p->in_iowait) { ++ delayacct_blkio_end(p); ++ atomic_dec(&task_rq(p)->nr_iowait); ++ } ++#endif ++ ++ rq = cpu_rq(cpu); ++ raw_spin_lock(&rq->lock); ++ ++ update_rq_clock(rq); ++ ttwu_do_activate(rq, p, wake_flags); ++ check_preempt_curr(rq, p); ++ ++ raw_spin_unlock(&rq->lock); ++ ++stat: ++ ttwu_stat(p, cpu, wake_flags); ++out: ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++ ++ return success; ++} ++ ++/** ++ * wake_up_process - Wake up a specific process ++ * @p: The process to be woken up. ++ * ++ * Attempt to wake up the nominated process and move it to the set of runnable ++ * processes. ++ * ++ * Return: 1 if the process was woken up, 0 if it was already running. ++ * ++ * This function executes a full memory barrier before accessing the task state. ++ */ ++int wake_up_process(struct task_struct *p) ++{ ++ return try_to_wake_up(p, TASK_NORMAL, 0); ++} ++EXPORT_SYMBOL(wake_up_process); ++ ++int wake_up_state(struct task_struct *p, unsigned int state) ++{ ++ return try_to_wake_up(p, state, 0); ++} ++ ++/* ++ * Perform scheduler related setup for a newly forked process p. ++ * p is forked by current. ++ */ ++int sched_fork(unsigned long __maybe_unused clone_flags, struct task_struct *p) ++{ ++ unsigned long flags; ++ int cpu = get_cpu(); ++ struct rq *rq = this_rq(); ++ ++#ifdef CONFIG_PREEMPT_NOTIFIERS ++ INIT_HLIST_HEAD(&p->preempt_notifiers); ++#endif ++ /* Should be reset in fork.c but done here for ease of PDS patching */ ++ p->on_cpu = ++ p->on_rq = ++ p->utime = ++ p->stime = ++ p->sched_time = 0; ++ ++ p->sl_level = pds_skiplist_random_level(p); ++ INIT_SKIPLIST_NODE(&p->sl_node); ++ ++#ifdef CONFIG_COMPACTION ++ p->capture_control = NULL; ++#endif ++ ++ /* ++ * We mark the process as NEW here. This guarantees that ++ * nobody will actually run it, and a signal or other external ++ * event cannot wake it up and insert it on the runqueue either. ++ */ ++ p->state = TASK_NEW; ++ ++ /* ++ * Make sure we do not leak PI boosting priority to the child. ++ */ ++ p->prio = current->normal_prio; ++ ++ /* ++ * Revert to default priority/policy on fork if requested. ++ */ ++ if (unlikely(p->sched_reset_on_fork)) { ++ if (task_has_rt_policy(p)) { ++ p->policy = SCHED_NORMAL; ++ p->static_prio = NICE_TO_PRIO(0); ++ p->rt_priority = 0; ++ } else if (PRIO_TO_NICE(p->static_prio) < 0) ++ p->static_prio = NICE_TO_PRIO(0); ++ ++ p->prio = p->normal_prio = normal_prio(p); ++ ++ /* ++ * We don't need the reset flag anymore after the fork. It has ++ * fulfilled its duty: ++ */ ++ p->sched_reset_on_fork = 0; ++ } ++ ++ /* ++ * Share the timeslice between parent and child, thus the ++ * total amount of pending timeslices in the system doesn't change, ++ * resulting in more scheduling fairness. ++ */ ++ raw_spin_lock_irqsave(&rq->lock, flags); ++ rq->curr->time_slice /= 2; ++ p->time_slice = rq->curr->time_slice; ++#ifdef CONFIG_SCHED_HRTICK ++ hrtick_start(rq, US_TO_NS(rq->curr->time_slice)); ++#endif ++ ++ if (p->time_slice < RESCHED_US) { ++ update_rq_clock(rq); ++ time_slice_expired(p, rq); ++ resched_curr(rq); ++ } else ++ update_task_priodl(p); ++ raw_spin_unlock_irqrestore(&rq->lock, flags); ++ ++ /* ++ * The child is not yet in the pid-hash so no cgroup attach races, ++ * and the cgroup is pinned to this child due to cgroup_fork() ++ * is ran before sched_fork(). ++ * ++ * Silence PROVE_RCU. ++ */ ++ raw_spin_lock_irqsave(&p->pi_lock, flags); ++ /* ++ * We're setting the CPU for the first time, we don't migrate, ++ * so use __set_task_cpu(). ++ */ ++ __set_task_cpu(p, cpu); ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++ ++#ifdef CONFIG_SCHED_INFO ++ if (unlikely(sched_info_on())) ++ memset(&p->sched_info, 0, sizeof(p->sched_info)); ++#endif ++ init_task_preempt_count(p); ++ ++ put_cpu(); ++ return 0; ++} ++ ++#ifdef CONFIG_SCHEDSTATS ++ ++DEFINE_STATIC_KEY_FALSE(sched_schedstats); ++static bool __initdata __sched_schedstats = false; ++ ++static void set_schedstats(bool enabled) ++{ ++ if (enabled) ++ static_branch_enable(&sched_schedstats); ++ else ++ static_branch_disable(&sched_schedstats); ++} ++ ++void force_schedstat_enabled(void) ++{ ++ if (!schedstat_enabled()) { ++ pr_info("kernel profiling enabled schedstats, disable via kernel.sched_schedstats.\n"); ++ static_branch_enable(&sched_schedstats); ++ } ++} ++ ++static int __init setup_schedstats(char *str) ++{ ++ int ret = 0; ++ if (!str) ++ goto out; ++ ++ /* ++ * This code is called before jump labels have been set up, so we can't ++ * change the static branch directly just yet. Instead set a temporary ++ * variable so init_schedstats() can do it later. ++ */ ++ if (!strcmp(str, "enable")) { ++ __sched_schedstats = true; ++ ret = 1; ++ } else if (!strcmp(str, "disable")) { ++ __sched_schedstats = false; ++ ret = 1; ++ } ++out: ++ if (!ret) ++ pr_warn("Unable to parse schedstats=\n"); ++ ++ return ret; ++} ++__setup("schedstats=", setup_schedstats); ++ ++static void __init init_schedstats(void) ++{ ++ set_schedstats(__sched_schedstats); ++} ++ ++#ifdef CONFIG_PROC_SYSCTL ++int sysctl_schedstats(struct ctl_table *table, int write, ++ void __user *buffer, size_t *lenp, loff_t *ppos) ++{ ++ struct ctl_table t; ++ int err; ++ int state = static_branch_likely(&sched_schedstats); ++ ++ if (write && !capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ ++ t = *table; ++ t.data = &state; ++ err = proc_dointvec_minmax(&t, write, buffer, lenp, ppos); ++ if (err < 0) ++ return err; ++ if (write) ++ set_schedstats(state); ++ return err; ++} ++#endif /* CONFIG_PROC_SYSCTL */ ++#else /* !CONFIG_SCHEDSTATS */ ++static inline void init_schedstats(void) {} ++#endif /* CONFIG_SCHEDSTATS */ ++ ++/* ++ * wake_up_new_task - wake up a newly created task for the first time. ++ * ++ * This function will do some initial scheduler statistics housekeeping ++ * that must be done for every newly created context, then puts the task ++ * on the runqueue and wakes it. ++ */ ++void wake_up_new_task(struct task_struct *p) ++{ ++ unsigned long flags; ++ struct rq *rq; ++ ++ raw_spin_lock_irqsave(&p->pi_lock, flags); ++ ++ p->state = TASK_RUNNING; ++ ++ rq = cpu_rq(select_task_rq(p)); ++#ifdef CONFIG_SMP ++ /* ++ * Fork balancing, do it here and not earlier because: ++ * - cpus_mask can change in the fork path ++ * - any previously selected CPU might disappear through hotplug ++ * Use __set_task_cpu() to avoid calling sched_class::migrate_task_rq, ++ * as we're not fully set-up yet. ++ */ ++ __set_task_cpu(p, cpu_of(rq)); ++#endif ++ ++ raw_spin_lock(&rq->lock); ++ ++ update_rq_clock(rq); ++ activate_task(p, rq); ++ trace_sched_wakeup_new(p); ++ check_preempt_curr(rq, p); ++ ++ raw_spin_unlock(&rq->lock); ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++} ++ ++#ifdef CONFIG_PREEMPT_NOTIFIERS ++ ++static DEFINE_STATIC_KEY_FALSE(preempt_notifier_key); ++ ++void preempt_notifier_inc(void) ++{ ++ static_branch_inc(&preempt_notifier_key); ++} ++EXPORT_SYMBOL_GPL(preempt_notifier_inc); ++ ++void preempt_notifier_dec(void) ++{ ++ static_branch_dec(&preempt_notifier_key); ++} ++EXPORT_SYMBOL_GPL(preempt_notifier_dec); ++ ++/** ++ * preempt_notifier_register - tell me when current is being preempted & rescheduled ++ * @notifier: notifier struct to register ++ */ ++void preempt_notifier_register(struct preempt_notifier *notifier) ++{ ++ if (!static_branch_unlikely(&preempt_notifier_key)) ++ WARN(1, "registering preempt_notifier while notifiers disabled\n"); ++ ++ hlist_add_head(¬ifier->link, ¤t->preempt_notifiers); ++} ++EXPORT_SYMBOL_GPL(preempt_notifier_register); ++ ++/** ++ * preempt_notifier_unregister - no longer interested in preemption notifications ++ * @notifier: notifier struct to unregister ++ * ++ * This is *not* safe to call from within a preemption notifier. ++ */ ++void preempt_notifier_unregister(struct preempt_notifier *notifier) ++{ ++ hlist_del(¬ifier->link); ++} ++EXPORT_SYMBOL_GPL(preempt_notifier_unregister); ++ ++static void __fire_sched_in_preempt_notifiers(struct task_struct *curr) ++{ ++ struct preempt_notifier *notifier; ++ ++ hlist_for_each_entry(notifier, &curr->preempt_notifiers, link) ++ notifier->ops->sched_in(notifier, raw_smp_processor_id()); ++} ++ ++static __always_inline void fire_sched_in_preempt_notifiers(struct task_struct *curr) ++{ ++ if (static_branch_unlikely(&preempt_notifier_key)) ++ __fire_sched_in_preempt_notifiers(curr); ++} ++ ++static void ++__fire_sched_out_preempt_notifiers(struct task_struct *curr, ++ struct task_struct *next) ++{ ++ struct preempt_notifier *notifier; ++ ++ hlist_for_each_entry(notifier, &curr->preempt_notifiers, link) ++ notifier->ops->sched_out(notifier, next); ++} ++ ++static __always_inline void ++fire_sched_out_preempt_notifiers(struct task_struct *curr, ++ struct task_struct *next) ++{ ++ if (static_branch_unlikely(&preempt_notifier_key)) ++ __fire_sched_out_preempt_notifiers(curr, next); ++} ++ ++#else /* !CONFIG_PREEMPT_NOTIFIERS */ ++ ++static inline void fire_sched_in_preempt_notifiers(struct task_struct *curr) ++{ ++} ++ ++static inline void ++fire_sched_out_preempt_notifiers(struct task_struct *curr, ++ struct task_struct *next) ++{ ++} ++ ++#endif /* CONFIG_PREEMPT_NOTIFIERS */ ++ ++static inline void prepare_task(struct task_struct *next) ++{ ++ /* ++ * Claim the task as running, we do this before switching to it ++ * such that any running task will have this set. ++ */ ++ next->on_cpu = 1; ++} ++ ++static inline void finish_task(struct task_struct *prev) ++{ ++#ifdef CONFIG_SMP ++ /* ++ * After ->on_cpu is cleared, the task can be moved to a different CPU. ++ * We must ensure this doesn't happen until the switch is completely ++ * finished. ++ * ++ * In particular, the load of prev->state in finish_task_switch() must ++ * happen before this. ++ * ++ * Pairs with the smp_cond_load_acquire() in try_to_wake_up(). ++ */ ++ smp_store_release(&prev->on_cpu, 0); ++#else ++ prev->on_cpu = 0; ++#endif ++} ++ ++static inline void ++prepare_lock_switch(struct rq *rq, struct task_struct *next) ++{ ++ /* ++ * Since the runqueue lock will be released by the next ++ * task (which is an invalid locking op but in the case ++ * of the scheduler it's an obvious special-case), so we ++ * do an early lockdep release here: ++ */ ++ spin_release(&rq->lock.dep_map, 1, _THIS_IP_); ++#ifdef CONFIG_DEBUG_SPINLOCK ++ /* this is a valid case when another task releases the spinlock */ ++ rq->lock.owner = next; ++#endif ++} ++ ++static inline void finish_lock_switch(struct rq *rq) ++{ ++ /* ++ * If we are tracking spinlock dependencies then we have to ++ * fix up the runqueue lock - which gets 'carried over' from ++ * prev into current: ++ */ ++ spin_acquire(&rq->lock.dep_map, 0, 0, _THIS_IP_); ++ raw_spin_unlock_irq(&rq->lock); ++} ++ ++/** ++ * prepare_task_switch - prepare to switch tasks ++ * @rq: the runqueue preparing to switch ++ * @next: the task we are going to switch to. ++ * ++ * This is called with the rq lock held and interrupts off. It must ++ * be paired with a subsequent finish_task_switch after the context ++ * switch. ++ * ++ * prepare_task_switch sets up locking and calls architecture specific ++ * hooks. ++ */ ++static inline void ++prepare_task_switch(struct rq *rq, struct task_struct *prev, ++ struct task_struct *next) ++{ ++ kcov_prepare_switch(prev); ++ sched_info_switch(rq, prev, next); ++ perf_event_task_sched_out(prev, next); ++ rseq_preempt(prev); ++ fire_sched_out_preempt_notifiers(prev, next); ++ prepare_task(next); ++ prepare_arch_switch(next); ++} ++ ++/** ++ * finish_task_switch - clean up after a task-switch ++ * @rq: runqueue associated with task-switch ++ * @prev: the thread we just switched away from. ++ * ++ * finish_task_switch must be called after the context switch, paired ++ * with a prepare_task_switch call before the context switch. ++ * finish_task_switch will reconcile locking set up by prepare_task_switch, ++ * and do any other architecture-specific cleanup actions. ++ * ++ * Note that we may have delayed dropping an mm in context_switch(). If ++ * so, we finish that here outside of the runqueue lock. (Doing it ++ * with the lock held can cause deadlocks; see schedule() for ++ * details.) ++ * ++ * The context switch have flipped the stack from under us and restored the ++ * local variables which were saved when this task called schedule() in the ++ * past. prev == current is still correct but we need to recalculate this_rq ++ * because prev may have moved to another CPU. ++ */ ++static struct rq *finish_task_switch(struct task_struct *prev) ++ __releases(rq->lock) ++{ ++ struct rq *rq = this_rq(); ++ struct mm_struct *mm = rq->prev_mm; ++ long prev_state; ++ ++ /* ++ * The previous task will have left us with a preempt_count of 2 ++ * because it left us after: ++ * ++ * schedule() ++ * preempt_disable(); // 1 ++ * __schedule() ++ * raw_spin_lock_irq(&rq->lock) // 2 ++ * ++ * Also, see FORK_PREEMPT_COUNT. ++ */ ++ if (WARN_ONCE(preempt_count() != 2*PREEMPT_DISABLE_OFFSET, ++ "corrupted preempt_count: %s/%d/0x%x\n", ++ current->comm, current->pid, preempt_count())) ++ preempt_count_set(FORK_PREEMPT_COUNT); ++ ++ rq->prev_mm = NULL; ++ ++ /* ++ * A task struct has one reference for the use as "current". ++ * If a task dies, then it sets TASK_DEAD in tsk->state and calls ++ * schedule one last time. The schedule call will never return, and ++ * the scheduled task must drop that reference. ++ * ++ * We must observe prev->state before clearing prev->on_cpu (in ++ * finish_task), otherwise a concurrent wakeup can get prev ++ * running on another CPU and we could rave with its RUNNING -> DEAD ++ * transition, resulting in a double drop. ++ */ ++ prev_state = prev->state; ++ vtime_task_switch(prev); ++ perf_event_task_sched_in(prev, current); ++ finish_task(prev); ++ finish_lock_switch(rq); ++ finish_arch_post_lock_switch(); ++ kcov_finish_switch(current); ++ ++ fire_sched_in_preempt_notifiers(current); ++ /* ++ * When switching through a kernel thread, the loop in ++ * membarrier_{private,global}_expedited() may have observed that ++ * kernel thread and not issued an IPI. It is therefore possible to ++ * schedule between user->kernel->user threads without passing though ++ * switch_mm(). Membarrier requires a barrier after storing to ++ * rq->curr, before returning to userspace, so provide them here: ++ * ++ * - a full memory barrier for {PRIVATE,GLOBAL}_EXPEDITED, implicitly ++ * provided by mmdrop(), ++ * - a sync_core for SYNC_CORE. ++ */ ++ if (mm) { ++ membarrier_mm_sync_core_before_usermode(mm); ++ mmdrop(mm); ++ } ++ if (unlikely(prev_state == TASK_DEAD)) { ++ /* ++ * Remove function-return probe instances associated with this ++ * task and put them back on the free list. ++ */ ++ kprobe_flush_task(prev); ++ ++ /* Task is done with its stack. */ ++ put_task_stack(prev); ++ ++ put_task_struct_rcu_user(prev); ++ } ++ ++ tick_nohz_task_switch(); ++ return rq; ++} ++ ++/** ++ * schedule_tail - first thing a freshly forked thread must call. ++ * @prev: the thread we just switched away from. ++ */ ++asmlinkage __visible void schedule_tail(struct task_struct *prev) ++ __releases(rq->lock) ++{ ++ struct rq *rq; ++ ++ /* ++ * New tasks start with FORK_PREEMPT_COUNT, see there and ++ * finish_task_switch() for details. ++ * ++ * finish_task_switch() will drop rq->lock() and lower preempt_count ++ * and the preempt_enable() will end up enabling preemption (on ++ * PREEMPT_COUNT kernels). ++ */ ++ ++ rq = finish_task_switch(prev); ++ preempt_enable(); ++ ++ if (current->set_child_tid) ++ put_user(task_pid_vnr(current), current->set_child_tid); ++ ++ calculate_sigpending(); ++} ++ ++/* ++ * context_switch - switch to the new MM and the new thread's register state. ++ */ ++static __always_inline struct rq * ++context_switch(struct rq *rq, struct task_struct *prev, ++ struct task_struct *next) ++{ ++ prepare_task_switch(rq, prev, next); ++ ++ /* ++ * For paravirt, this is coupled with an exit in switch_to to ++ * combine the page table reload and the switch backend into ++ * one hypercall. ++ */ ++ arch_start_context_switch(prev); ++ ++ /* ++ * kernel -> kernel lazy + transfer active ++ * user -> kernel lazy + mmgrab() active ++ * ++ * kernel -> user switch + mmdrop() active ++ * user -> user switch ++ */ ++ if (!next->mm) { // to kernel ++ enter_lazy_tlb(prev->active_mm, next); ++ ++ next->active_mm = prev->active_mm; ++ if (prev->mm) // from user ++ mmgrab(prev->active_mm); ++ else ++ prev->active_mm = NULL; ++ } else { // to user ++ membarrier_switch_mm(rq, prev->active_mm, next->mm); ++ /* ++ * sys_membarrier() requires an smp_mb() between setting ++ * rq->curr / membarrier_switch_mm() and returning to userspace. ++ * ++ * The below provides this either through switch_mm(), or in ++ * case 'prev->active_mm == next->mm' through ++ * finish_task_switch()'s mmdrop(). ++ */ ++ switch_mm_irqs_off(prev->active_mm, next->mm, next); ++ ++ if (!prev->mm) { // from kernel ++ /* will mmdrop() in finish_task_switch(). */ ++ rq->prev_mm = prev->active_mm; ++ prev->active_mm = NULL; ++ } ++ } ++ ++ prepare_lock_switch(rq, next); ++ ++ /* Here we just switch the register state and the stack. */ ++ switch_to(prev, next, prev); ++ barrier(); ++ ++ return finish_task_switch(prev); ++} ++ ++/* ++ * nr_running, nr_uninterruptible and nr_context_switches: ++ * ++ * externally visible scheduler statistics: current number of runnable ++ * threads, total number of context switches performed since bootup. ++ */ ++unsigned long nr_running(void) ++{ ++ unsigned long i, sum = 0; ++ ++ for_each_online_cpu(i) ++ sum += cpu_rq(i)->nr_running; ++ ++ return sum; ++} ++ ++/* ++ * Check if only the current task is running on the CPU. ++ * ++ * Caution: this function does not check that the caller has disabled ++ * preemption, thus the result might have a time-of-check-to-time-of-use ++ * race. The caller is responsible to use it correctly, for example: ++ * ++ * - from a non-preemptible section (of course) ++ * ++ * - from a thread that is bound to a single CPU ++ * ++ * - in a loop with very short iterations (e.g. a polling loop) ++ */ ++bool single_task_running(void) ++{ ++ return raw_rq()->nr_running == 1; ++} ++EXPORT_SYMBOL(single_task_running); ++ ++unsigned long long nr_context_switches(void) ++{ ++ int i; ++ unsigned long long sum = 0; ++ ++ for_each_possible_cpu(i) ++ sum += cpu_rq(i)->nr_switches; ++ ++ return sum; ++} ++ ++/* ++ * Consumers of these two interfaces, like for example the cpuidle menu ++ * governor, are using nonsensical data. Preferring shallow idle state selection ++ * for a CPU that has IO-wait which might not even end up running the task when ++ * it does become runnable. ++ */ ++ ++unsigned long nr_iowait_cpu(int cpu) ++{ ++ return atomic_read(&cpu_rq(cpu)->nr_iowait); ++} ++ ++/* ++ * IO-wait accounting, and how its mostly bollocks (on SMP). ++ * ++ * The idea behind IO-wait account is to account the idle time that we could ++ * have spend running if it were not for IO. That is, if we were to improve the ++ * storage performance, we'd have a proportional reduction in IO-wait time. ++ * ++ * This all works nicely on UP, where, when a task blocks on IO, we account ++ * idle time as IO-wait, because if the storage were faster, it could've been ++ * running and we'd not be idle. ++ * ++ * This has been extended to SMP, by doing the same for each CPU. This however ++ * is broken. ++ * ++ * Imagine for instance the case where two tasks block on one CPU, only the one ++ * CPU will have IO-wait accounted, while the other has regular idle. Even ++ * though, if the storage were faster, both could've ran at the same time, ++ * utilising both CPUs. ++ * ++ * This means, that when looking globally, the current IO-wait accounting on ++ * SMP is a lower bound, by reason of under accounting. ++ * ++ * Worse, since the numbers are provided per CPU, they are sometimes ++ * interpreted per CPU, and that is nonsensical. A blocked task isn't strictly ++ * associated with any one particular CPU, it can wake to another CPU than it ++ * blocked on. This means the per CPU IO-wait number is meaningless. ++ * ++ * Task CPU affinities can make all that even more 'interesting'. ++ */ ++ ++unsigned long nr_iowait(void) ++{ ++ unsigned long i, sum = 0; ++ ++ for_each_possible_cpu(i) ++ sum += nr_iowait_cpu(i); ++ ++ return sum; ++} ++ ++DEFINE_PER_CPU(struct kernel_stat, kstat); ++DEFINE_PER_CPU(struct kernel_cpustat, kernel_cpustat); ++ ++EXPORT_PER_CPU_SYMBOL(kstat); ++EXPORT_PER_CPU_SYMBOL(kernel_cpustat); ++ ++static inline void pds_update_curr(struct rq *rq, struct task_struct *p) ++{ ++ s64 ns = rq->clock_task - p->last_ran; ++ ++ p->sched_time += ns; ++ cgroup_account_cputime(p, ns); ++ account_group_exec_runtime(p, ns); ++ ++ /* time_slice accounting is done in usecs to avoid overflow on 32bit */ ++ p->time_slice -= NS_TO_US(ns); ++ p->last_ran = rq->clock_task; ++} ++ ++/* ++ * Return accounted runtime for the task. ++ * Return separately the current's pending runtime that have not been ++ * accounted yet. ++ */ ++unsigned long long task_sched_runtime(struct task_struct *p) ++{ ++ unsigned long flags; ++ struct rq *rq; ++ raw_spinlock_t *lock; ++ u64 ns; ++ ++#if defined(CONFIG_64BIT) && defined(CONFIG_SMP) ++ /* ++ * 64-bit doesn't need locks to atomically read a 64-bit value. ++ * So we have a optimization chance when the task's delta_exec is 0. ++ * Reading ->on_cpu is racy, but this is ok. ++ * ++ * If we race with it leaving CPU, we'll take a lock. So we're correct. ++ * If we race with it entering CPU, unaccounted time is 0. This is ++ * indistinguishable from the read occurring a few cycles earlier. ++ * If we see ->on_cpu without ->on_rq, the task is leaving, and has ++ * been accounted, so we're correct here as well. ++ */ ++ if (!p->on_cpu || !task_on_rq_queued(p)) ++ return tsk_seruntime(p); ++#endif ++ ++ rq = task_access_lock_irqsave(p, &lock, &flags); ++ /* ++ * Must be ->curr _and_ ->on_rq. If dequeued, we would ++ * project cycles that may never be accounted to this ++ * thread, breaking clock_gettime(). ++ */ ++ if (p == rq->curr && task_on_rq_queued(p)) { ++ update_rq_clock(rq); ++ pds_update_curr(rq, p); ++ } ++ ns = tsk_seruntime(p); ++ task_access_unlock_irqrestore(p, lock, &flags); ++ ++ return ns; ++} ++ ++/* This manages tasks that have run out of timeslice during a scheduler_tick */ ++static inline void pds_scheduler_task_tick(struct rq *rq) ++{ ++ struct task_struct *p = rq->curr; ++ ++ if (is_idle_task(p)) ++ return; ++ ++ pds_update_curr(rq, p); ++ ++ cpufreq_update_util(rq, 0); ++ ++ /* ++ * Tasks that were scheduled in the first half of a tick are not ++ * allowed to run into the 2nd half of the next tick if they will ++ * run out of time slice in the interim. Otherwise, if they have ++ * less than RESCHED_US μs of time slice left they will be rescheduled. ++ */ ++ if (p->time_slice - rq->dither >= RESCHED_US) ++ return; ++ ++ /** ++ * p->time_slice < RESCHED_US. We will modify task_struct under ++ * rq lock as p is rq->curr ++ */ ++ __set_tsk_resched(p); ++} ++ ++#ifdef CONFIG_SMP ++ ++#ifdef CONFIG_SCHED_SMT ++static int active_load_balance_cpu_stop(void *data) ++{ ++ struct rq *rq = this_rq(); ++ struct task_struct *p = data; ++ int cpu; ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ ++ raw_spin_lock(&p->pi_lock); ++ raw_spin_lock(&rq->lock); ++ ++ rq->active_balance = 0; ++ /* ++ * _something_ may have changed the task, double check again ++ */ ++ if (task_on_rq_queued(p) && task_rq(p) == rq && ++ (cpu = cpumask_any_and(&p->cpus_mask, &sched_cpu_sg_idle_mask)) < nr_cpu_ids) ++ rq = __migrate_task(rq, p, cpu); ++ ++ raw_spin_unlock(&rq->lock); ++ raw_spin_unlock(&p->pi_lock); ++ ++ local_irq_restore(flags); ++ ++ return 0; ++} ++ ++/* pds_sg_balance_trigger - trigger slibing group balance for @cpu */ ++static void pds_sg_balance_trigger(const int cpu) ++{ ++ struct rq *rq = cpu_rq(cpu); ++ unsigned long flags; ++ struct task_struct *curr; ++ ++ if (!raw_spin_trylock_irqsave(&rq->lock, flags)) ++ return; ++ curr = rq->curr; ++ if (!is_idle_task(curr) && ++ cpumask_intersects(&curr->cpus_mask, &sched_cpu_sg_idle_mask)) { ++ int active_balance = 0; ++ ++ if (likely(!rq->active_balance)) { ++ rq->active_balance = 1; ++ active_balance = 1; ++ } ++ ++ raw_spin_unlock_irqrestore(&rq->lock, flags); ++ ++ if (likely(active_balance)) ++ stop_one_cpu_nowait(cpu, active_load_balance_cpu_stop, ++ curr, &rq->active_balance_work); ++ } else ++ raw_spin_unlock_irqrestore(&rq->lock, flags); ++} ++ ++/* ++ * pds_sg_balance_check - slibing group balance check for run queue @rq ++ */ ++static inline void pds_sg_balance_check(const struct rq *rq) ++{ ++ cpumask_t chk; ++ int i; ++ ++ /* Only online cpu will do sg balance checking */ ++ if (unlikely(!rq->online)) ++ return; ++ ++ /* Only cpu in slibing idle group will do the checking */ ++ if (!cpumask_test_cpu(cpu_of(rq), &sched_cpu_sg_idle_mask)) ++ return; ++ ++ /* Find potential cpus which can migrate the currently running task */ ++ if (!cpumask_andnot(&chk, &sched_rq_pending_masks[SCHED_RQ_EMPTY], ++ &sched_rq_queued_masks[SCHED_RQ_EMPTY])) ++ return; ++ ++ for_each_cpu(i, &chk) { ++ /* skip the cpu which has idle slibing cpu */ ++ if (cpumask_test_cpu(per_cpu(sched_sibling_cpu, i), ++ &sched_rq_queued_masks[SCHED_RQ_EMPTY])) ++ continue; ++ pds_sg_balance_trigger(i); ++ } ++} ++#endif /* CONFIG_SCHED_SMT */ ++#endif /* CONFIG_SMP */ ++ ++/* ++ * This function gets called by the timer code, with HZ frequency. ++ * We call it with interrupts disabled. ++ */ ++void scheduler_tick(void) ++{ ++ int cpu __maybe_unused = smp_processor_id(); ++ struct rq *rq = cpu_rq(cpu); ++ ++ sched_clock_tick(); ++ ++ raw_spin_lock(&rq->lock); ++ update_rq_clock(rq); ++ ++ pds_scheduler_task_tick(rq); ++ update_sched_rq_queued_masks_normal(rq); ++ calc_global_load_tick(rq); ++ psi_task_tick(rq); ++ ++ rq->last_tick = rq->clock; ++ raw_spin_unlock(&rq->lock); ++ ++ perf_event_task_tick(); ++} ++ ++#ifdef CONFIG_NO_HZ_FULL ++struct tick_work { ++ int cpu; ++ atomic_t state; ++ struct delayed_work work; ++}; ++/* Values for ->state, see diagram below. */ ++#define TICK_SCHED_REMOTE_OFFLINE 0 ++#define TICK_SCHED_REMOTE_OFFLINING 1 ++#define TICK_SCHED_REMOTE_RUNNING 2 ++ ++/* ++ * State diagram for ->state: ++ * ++ * ++ * TICK_SCHED_REMOTE_OFFLINE ++ * | ^ ++ * | | ++ * | | sched_tick_remote() ++ * | | ++ * | | ++ * +--TICK_SCHED_REMOTE_OFFLINING ++ * | ^ ++ * | | ++ * sched_tick_start() | | sched_tick_stop() ++ * | | ++ * V | ++ * TICK_SCHED_REMOTE_RUNNING ++ * ++ * ++ * Other transitions get WARN_ON_ONCE(), except that sched_tick_remote() ++ * and sched_tick_start() are happy to leave the state in RUNNING. ++ */ ++ ++static struct tick_work __percpu *tick_work_cpu; ++ ++static void sched_tick_remote(struct work_struct *work) ++{ ++ struct delayed_work *dwork = to_delayed_work(work); ++ struct tick_work *twork = container_of(dwork, struct tick_work, work); ++ int cpu = twork->cpu; ++ struct rq *rq = cpu_rq(cpu); ++ struct task_struct *curr; ++ unsigned long flags; ++ u64 delta; ++ int os; ++ ++ /* ++ * Handle the tick only if it appears the remote CPU is running in full ++ * dynticks mode. The check is racy by nature, but missing a tick or ++ * having one too much is no big deal because the scheduler tick updates ++ * statistics and checks timeslices in a time-independent way, regardless ++ * of when exactly it is running. ++ */ ++ if (idle_cpu(cpu) || !tick_nohz_tick_stopped_cpu(cpu)) ++ goto out_requeue; ++ ++ raw_spin_lock_irqsave(&rq->lock, flags); ++ curr = rq->curr; ++ ++ if (is_idle_task(curr) || cpu_is_offline(cpu)) ++ goto out_unlock; ++ ++ update_rq_clock(rq); ++ delta = rq_clock_task(rq) - curr->last_ran; ++ ++ /* ++ * Make sure the next tick runs within a reasonable ++ * amount of time. ++ */ ++ WARN_ON_ONCE(delta > (u64)NSEC_PER_SEC * 3); ++ pds_scheduler_task_tick(rq); ++ update_sched_rq_queued_masks_normal(rq); ++ ++out_unlock: ++ raw_spin_unlock_irqrestore(&rq->lock, flags); ++ ++out_requeue: ++ /* ++ * Run the remote tick once per second (1Hz). This arbitrary ++ * frequency is large enough to avoid overload but short enough ++ * to keep scheduler internal stats reasonably up to date. But ++ * first update state to reflect hotplug activity if required. ++ */ ++ os = atomic_fetch_add_unless(&twork->state, -1, TICK_SCHED_REMOTE_RUNNING); ++ WARN_ON_ONCE(os == TICK_SCHED_REMOTE_OFFLINE); ++ if (os == TICK_SCHED_REMOTE_RUNNING) ++ queue_delayed_work(system_unbound_wq, dwork, HZ); ++} ++ ++static void sched_tick_start(int cpu) ++{ ++ int os; ++ struct tick_work *twork; ++ ++ if (housekeeping_cpu(cpu, HK_FLAG_TICK)) ++ return; ++ ++ WARN_ON_ONCE(!tick_work_cpu); ++ ++ twork = per_cpu_ptr(tick_work_cpu, cpu); ++ os = atomic_xchg(&twork->state, TICK_SCHED_REMOTE_RUNNING); ++ WARN_ON_ONCE(os == TICK_SCHED_REMOTE_RUNNING); ++ if (os == TICK_SCHED_REMOTE_OFFLINE) { ++ twork->cpu = cpu; ++ INIT_DELAYED_WORK(&twork->work, sched_tick_remote); ++ queue_delayed_work(system_unbound_wq, &twork->work, HZ); ++ } ++} ++ ++#ifdef CONFIG_HOTPLUG_CPU ++static void sched_tick_stop(int cpu) ++{ ++ struct tick_work *twork; ++ ++ if (housekeeping_cpu(cpu, HK_FLAG_TICK)) ++ return; ++ ++ WARN_ON_ONCE(!tick_work_cpu); ++ ++ twork = per_cpu_ptr(tick_work_cpu, cpu); ++ cancel_delayed_work_sync(&twork->work); ++} ++#endif /* CONFIG_HOTPLUG_CPU */ ++ ++int __init sched_tick_offload_init(void) ++{ ++ tick_work_cpu = alloc_percpu(struct tick_work); ++ BUG_ON(!tick_work_cpu); ++ return 0; ++} ++ ++#else /* !CONFIG_NO_HZ_FULL */ ++static inline void sched_tick_start(int cpu) { } ++static inline void sched_tick_stop(int cpu) { } ++#endif ++ ++#if defined(CONFIG_PREEMPTION) && (defined(CONFIG_DEBUG_PREEMPT) || \ ++ defined(CONFIG_PREEMPT_TRACER)) ++/* ++ * If the value passed in is equal to the current preempt count ++ * then we just disabled preemption. Start timing the latency. ++ */ ++static inline void preempt_latency_start(int val) ++{ ++ if (preempt_count() == val) { ++ unsigned long ip = get_lock_parent_ip(); ++#ifdef CONFIG_DEBUG_PREEMPT ++ current->preempt_disable_ip = ip; ++#endif ++ trace_preempt_off(CALLER_ADDR0, ip); ++ } ++} ++ ++void preempt_count_add(int val) ++{ ++#ifdef CONFIG_DEBUG_PREEMPT ++ /* ++ * Underflow? ++ */ ++ if (DEBUG_LOCKS_WARN_ON((preempt_count() < 0))) ++ return; ++#endif ++ __preempt_count_add(val); ++#ifdef CONFIG_DEBUG_PREEMPT ++ /* ++ * Spinlock count overflowing soon? ++ */ ++ DEBUG_LOCKS_WARN_ON((preempt_count() & PREEMPT_MASK) >= ++ PREEMPT_MASK - 10); ++#endif ++ preempt_latency_start(val); ++} ++EXPORT_SYMBOL(preempt_count_add); ++NOKPROBE_SYMBOL(preempt_count_add); ++ ++/* ++ * If the value passed in equals to the current preempt count ++ * then we just enabled preemption. Stop timing the latency. ++ */ ++static inline void preempt_latency_stop(int val) ++{ ++ if (preempt_count() == val) ++ trace_preempt_on(CALLER_ADDR0, get_lock_parent_ip()); ++} ++ ++void preempt_count_sub(int val) ++{ ++#ifdef CONFIG_DEBUG_PREEMPT ++ /* ++ * Underflow? ++ */ ++ if (DEBUG_LOCKS_WARN_ON(val > preempt_count())) ++ return; ++ /* ++ * Is the spinlock portion underflowing? ++ */ ++ if (DEBUG_LOCKS_WARN_ON((val < PREEMPT_MASK) && ++ !(preempt_count() & PREEMPT_MASK))) ++ return; ++#endif ++ ++ preempt_latency_stop(val); ++ __preempt_count_sub(val); ++} ++EXPORT_SYMBOL(preempt_count_sub); ++NOKPROBE_SYMBOL(preempt_count_sub); ++ ++#else ++static inline void preempt_latency_start(int val) { } ++static inline void preempt_latency_stop(int val) { } ++#endif ++ ++/* ++ * Timeslices below RESCHED_US are considered as good as expired as there's no ++ * point rescheduling when there's so little time left. SCHED_BATCH tasks ++ * have been flagged be not latency sensitive and likely to be fully CPU ++ * bound so every time they're rescheduled they have their time_slice ++ * refilled, but get a new later deadline to have little effect on ++ * SCHED_NORMAL tasks. ++ ++ */ ++static inline void check_deadline(struct task_struct *p, struct rq *rq) ++{ ++ if (rq->idle == p) ++ return; ++ ++ pds_update_curr(rq, p); ++ ++ if (p->time_slice < RESCHED_US) { ++ time_slice_expired(p, rq); ++ if (SCHED_ISO == p->policy && ISO_PRIO == p->prio) { ++ p->prio = NORMAL_PRIO; ++ p->deadline = rq->clock + task_deadline_diff(p); ++ update_task_priodl(p); ++ } ++ if (SCHED_FIFO != p->policy && task_on_rq_queued(p)) ++ requeue_task(p, rq); ++ } ++} ++ ++#ifdef CONFIG_SMP ++ ++#define SCHED_RQ_NR_MIGRATION (32UL) ++/* ++ * Migrate pending tasks in @rq to @dest_cpu ++ * Will try to migrate mininal of half of @rq nr_running tasks and ++ * SCHED_RQ_NR_MIGRATION to @dest_cpu ++ */ ++static inline int ++migrate_pending_tasks(struct rq *rq, struct rq *dest_rq, int filter_prio) ++{ ++ struct task_struct *p; ++ int dest_cpu = cpu_of(dest_rq); ++ int nr_migrated = 0; ++ int nr_tries = min((rq->nr_running + 1) / 2, SCHED_RQ_NR_MIGRATION); ++ struct skiplist_node *node = rq->sl_header.next[0]; ++ ++ while (nr_tries && node != &rq->sl_header) { ++ p = skiplist_entry(node, struct task_struct, sl_node); ++ node = node->next[0]; ++ ++ if (task_running(p)) ++ continue; ++ if (p->prio >= filter_prio) ++ break; ++ if (cpumask_test_cpu(dest_cpu, &p->cpus_mask)) { ++ detach_task(rq, p, dest_cpu); ++ attach_task(dest_rq, p); ++ nr_migrated++; ++ } ++ nr_tries--; ++ /* make a jump */ ++ if (node == &rq->sl_header) ++ break; ++ node = node->next[0]; ++ } ++ ++ return nr_migrated; ++} ++ ++static inline int ++take_queued_task_cpumask(struct rq *rq, cpumask_t *chk_mask, int filter_prio) ++{ ++ int src_cpu; ++ ++ for_each_cpu(src_cpu, chk_mask) { ++ int nr_migrated; ++ struct rq *src_rq = cpu_rq(src_cpu); ++ ++ if (!do_raw_spin_trylock(&src_rq->lock)) { ++ if (PRIO_LIMIT == filter_prio) ++ continue; ++ return 0; ++ } ++ spin_acquire(&src_rq->lock.dep_map, SINGLE_DEPTH_NESTING, 1, _RET_IP_); ++ ++ update_rq_clock(src_rq); ++ nr_migrated = migrate_pending_tasks(src_rq, rq, filter_prio); ++ ++ spin_release(&src_rq->lock.dep_map, 1, _RET_IP_); ++ do_raw_spin_unlock(&src_rq->lock); ++ ++ if (nr_migrated || PRIO_LIMIT != filter_prio) ++ return nr_migrated; ++ } ++ return 0; ++} ++ ++static inline int take_other_rq_task(struct rq *rq, int cpu, int filter_prio) ++{ ++ struct cpumask *affinity_mask, *end; ++ struct cpumask chk; ++ ++ if (PRIO_LIMIT == filter_prio) { ++ cpumask_complement(&chk, &sched_rq_pending_masks[SCHED_RQ_EMPTY]); ++#ifdef CONFIG_SMT_NICE ++ { ++ /* also try to take IDLE priority tasks from smt supressed cpu */ ++ struct cpumask t; ++ if (cpumask_and(&t, &sched_smt_supressed_mask, ++ &sched_rq_queued_masks[SCHED_RQ_IDLE])) ++ cpumask_or(&chk, &chk, &t); ++ } ++#endif ++ } else if (NORMAL_PRIO == filter_prio) { ++ cpumask_or(&chk, &sched_rq_pending_masks[SCHED_RQ_RT], ++ &sched_rq_pending_masks[SCHED_RQ_ISO]); ++ } else if (IDLE_PRIO == filter_prio) { ++ cpumask_complement(&chk, &sched_rq_pending_masks[SCHED_RQ_EMPTY]); ++ cpumask_andnot(&chk, &chk, &sched_rq_pending_masks[SCHED_RQ_IDLE]); ++ } else ++ cpumask_copy(&chk, &sched_rq_pending_masks[SCHED_RQ_RT]); ++ ++ if (cpumask_empty(&chk)) ++ return 0; ++ ++ affinity_mask = per_cpu(sched_cpu_llc_start_mask, cpu); ++ end = per_cpu(sched_cpu_affinity_chk_end_masks, cpu); ++ do { ++ struct cpumask tmp; ++ ++ if (cpumask_and(&tmp, &chk, affinity_mask) && ++ take_queued_task_cpumask(rq, &tmp, filter_prio)) ++ return 1; ++ } while (++affinity_mask < end); ++ ++ return 0; ++} ++#endif ++ ++static inline struct task_struct * ++choose_next_task(struct rq *rq, int cpu, struct task_struct *prev) ++{ ++ struct task_struct *next = rq_first_queued_task(rq); ++ ++#ifdef CONFIG_SMT_NICE ++ if (cpumask_test_cpu(cpu, &sched_smt_supressed_mask)) { ++ if (next->prio >= IDLE_PRIO) { ++ if (rq->online && ++ take_other_rq_task(rq, cpu, IDLE_PRIO)) ++ return rq_first_queued_task(rq); ++ return rq->idle; ++ } ++ } ++#endif ++ ++#ifdef CONFIG_SMP ++ if (likely(rq->online)) ++ if (take_other_rq_task(rq, cpu, next->prio)) { ++ resched_curr(rq); ++ return rq_first_queued_task(rq); ++ } ++#endif ++ return next; ++} ++ ++static inline unsigned long get_preempt_disable_ip(struct task_struct *p) ++{ ++#ifdef CONFIG_DEBUG_PREEMPT ++ return p->preempt_disable_ip; ++#else ++ return 0; ++#endif ++} ++ ++/* ++ * Print scheduling while atomic bug: ++ */ ++static noinline void __schedule_bug(struct task_struct *prev) ++{ ++ /* Save this before calling printk(), since that will clobber it */ ++ unsigned long preempt_disable_ip = get_preempt_disable_ip(current); ++ ++ if (oops_in_progress) ++ return; ++ ++ printk(KERN_ERR "BUG: scheduling while atomic: %s/%d/0x%08x\n", ++ prev->comm, prev->pid, preempt_count()); ++ ++ debug_show_held_locks(prev); ++ print_modules(); ++ if (irqs_disabled()) ++ print_irqtrace_events(prev); ++ if (IS_ENABLED(CONFIG_DEBUG_PREEMPT) ++ && in_atomic_preempt_off()) { ++ pr_err("Preemption disabled at:"); ++ print_ip_sym(preempt_disable_ip); ++ pr_cont("\n"); ++ } ++ if (panic_on_warn) ++ panic("scheduling while atomic\n"); ++ ++ dump_stack(); ++ add_taint(TAINT_WARN, LOCKDEP_STILL_OK); ++} ++ ++/* ++ * Various schedule()-time debugging checks and statistics: ++ */ ++static inline void schedule_debug(struct task_struct *prev, bool preempt) ++{ ++#ifdef CONFIG_SCHED_STACK_END_CHECK ++ if (task_stack_end_corrupted(prev)) ++ panic("corrupted stack end detected inside scheduler\n"); ++#endif ++ ++#ifdef CONFIG_DEBUG_ATOMIC_SLEEP ++ if (!preempt && prev->state && prev->non_block_count) { ++ printk(KERN_ERR "BUG: scheduling in a non-blocking section: %s/%d/%i\n", ++ prev->comm, prev->pid, prev->non_block_count); ++ dump_stack(); ++ add_taint(TAINT_WARN, LOCKDEP_STILL_OK); ++ } ++#endif ++ ++ if (unlikely(in_atomic_preempt_off())) { ++ __schedule_bug(prev); ++ preempt_count_set(PREEMPT_DISABLED); ++ } ++ rcu_sleep_check(); ++ ++ profile_hit(SCHED_PROFILING, __builtin_return_address(0)); ++ ++ schedstat_inc(this_rq()->sched_count); ++} ++ ++static inline void set_rq_task(struct rq *rq, struct task_struct *p) ++{ ++ p->last_ran = rq->clock_task; ++ ++#ifdef CONFIG_HIGH_RES_TIMERS ++ if (p != rq->idle) ++ hrtick_start(rq, US_TO_NS(p->time_slice)); ++#endif ++ /* update rq->dither */ ++ rq->dither = rq_dither(rq); ++} ++ ++/* ++ * schedule() is the main scheduler function. ++ * ++ * The main means of driving the scheduler and thus entering this function are: ++ * ++ * 1. Explicit blocking: mutex, semaphore, waitqueue, etc. ++ * ++ * 2. TIF_NEED_RESCHED flag is checked on interrupt and userspace return ++ * paths. For example, see arch/x86/entry_64.S. ++ * ++ * To drive preemption between tasks, the scheduler sets the flag in timer ++ * interrupt handler scheduler_tick(). ++ * ++ * 3. Wakeups don't really cause entry into schedule(). They add a ++ * task to the run-queue and that's it. ++ * ++ * Now, if the new task added to the run-queue preempts the current ++ * task, then the wakeup sets TIF_NEED_RESCHED and schedule() gets ++ * called on the nearest possible occasion: ++ * ++ * - If the kernel is preemptible (CONFIG_PREEMPTION=y): ++ * ++ * - in syscall or exception context, at the next outmost ++ * preempt_enable(). (this might be as soon as the wake_up()'s ++ * spin_unlock()!) ++ * ++ * - in IRQ context, return from interrupt-handler to ++ * preemptible context ++ * ++ * - If the kernel is not preemptible (CONFIG_PREEMPT is not set) ++ * then at the next: ++ * ++ * - cond_resched() call ++ * - explicit schedule() call ++ * - return from syscall or exception to user-space ++ * - return from interrupt-handler to user-space ++ * ++ * WARNING: must be called with preemption disabled! ++ */ ++static void __sched notrace __schedule(bool preempt) ++{ ++ struct task_struct *prev, *next; ++ unsigned long *switch_count; ++ struct rq *rq; ++ int cpu; ++ ++ cpu = smp_processor_id(); ++ rq = cpu_rq(cpu); ++ prev = rq->curr; ++ ++ schedule_debug(prev, preempt); ++ ++ /* by passing sched_feat(HRTICK) checking which PDS doesn't support */ ++ hrtick_clear(rq); ++ ++ local_irq_disable(); ++ rcu_note_context_switch(preempt); ++ ++ /* ++ * Make sure that signal_pending_state()->signal_pending() below ++ * can't be reordered with __set_current_state(TASK_INTERRUPTIBLE) ++ * done by the caller to avoid the race with signal_wake_up(). ++ * ++ * The membarrier system call requires a full memory barrier ++ * after coming from user-space, before storing to rq->curr. ++ */ ++ raw_spin_lock(&rq->lock); ++ smp_mb__after_spinlock(); ++ ++ update_rq_clock(rq); ++ ++ switch_count = &prev->nivcsw; ++ if (!preempt && prev->state) { ++ if (signal_pending_state(prev->state, prev)) { ++ prev->state = TASK_RUNNING; ++ } else { ++ deactivate_task(prev, rq); ++ ++ if (prev->in_iowait) { ++ atomic_inc(&rq->nr_iowait); ++ delayacct_blkio_start(); ++ } ++ } ++ switch_count = &prev->nvcsw; ++ } ++ ++ clear_tsk_need_resched(prev); ++ clear_preempt_need_resched(); ++ ++ check_deadline(prev, rq); ++ ++ next = choose_next_task(rq, cpu, prev); ++ ++ set_rq_task(rq, next); ++ ++ if (prev != next) { ++ if (next->prio == PRIO_LIMIT) ++ schedstat_inc(rq->sched_goidle); ++ ++ /* ++ * RCU users of rcu_dereference(rq->curr) may not see ++ * changes to task_struct made by pick_next_task(). ++ */ ++ RCU_INIT_POINTER(rq->curr, next); ++ /* ++ * The membarrier system call requires each architecture ++ * to have a full memory barrier after updating ++ * rq->curr, before returning to user-space. ++ * ++ * Here are the schemes providing that barrier on the ++ * various architectures: ++ * - mm ? switch_mm() : mmdrop() for x86, s390, sparc, PowerPC. ++ * switch_mm() rely on membarrier_arch_switch_mm() on PowerPC. ++ * - finish_lock_switch() for weakly-ordered ++ * architectures where spin_unlock is a full barrier, ++ * - switch_to() for arm64 (weakly-ordered, spin_unlock ++ * is a RELEASE barrier), ++ */ ++ ++*switch_count; ++ rq->nr_switches++; ++ ++ trace_sched_switch(preempt, prev, next); ++ ++ /* Also unlocks the rq: */ ++ rq = context_switch(rq, prev, next); ++#ifdef CONFIG_SCHED_SMT ++ pds_sg_balance_check(rq); ++#endif ++ } else ++ raw_spin_unlock_irq(&rq->lock); ++} ++ ++void __noreturn do_task_dead(void) ++{ ++ /* Causes final put_task_struct in finish_task_switch(): */ ++ set_special_state(TASK_DEAD); ++ ++ /* Tell freezer to ignore us: */ ++ current->flags |= PF_NOFREEZE; ++ __schedule(false); ++ ++ BUG(); ++ ++ /* Avoid "noreturn function does return" - but don't continue if BUG() is a NOP: */ ++ for (;;) ++ cpu_relax(); ++} ++ ++static inline void sched_submit_work(struct task_struct *tsk) ++{ ++ if (!tsk->state || tsk_is_pi_blocked(tsk) || ++ signal_pending_state(tsk->state, tsk)) ++ return; ++ ++ /* ++ * If a worker went to sleep, notify and ask workqueue whether ++ * it wants to wake up a task to maintain concurrency. ++ * As this function is called inside the schedule() context, ++ * we disable preemption to avoid it calling schedule() again ++ * in the possible wakeup of a kworker. ++ */ ++ if (tsk->flags & PF_WQ_WORKER) { ++ preempt_disable(); ++ wq_worker_sleeping(tsk); ++ preempt_enable_no_resched(); ++ } ++ ++ /* ++ * If we are going to sleep and we have plugged IO queued, ++ * make sure to submit it to avoid deadlocks. ++ */ ++ if (blk_needs_flush_plug(tsk)) ++ blk_schedule_flush_plug(tsk); ++} ++ ++static void sched_update_worker(struct task_struct *tsk) ++{ ++ if (tsk->flags & PF_WQ_WORKER) ++ wq_worker_running(tsk); ++} ++ ++asmlinkage __visible void __sched schedule(void) ++{ ++ struct task_struct *tsk = current; ++ ++ sched_submit_work(tsk); ++ do { ++ preempt_disable(); ++ __schedule(false); ++ sched_preempt_enable_no_resched(); ++ } while (need_resched()); ++ sched_update_worker(tsk); ++} ++EXPORT_SYMBOL(schedule); ++ ++/* ++ * synchronize_rcu_tasks() makes sure that no task is stuck in preempted ++ * state (have scheduled out non-voluntarily) by making sure that all ++ * tasks have either left the run queue or have gone into user space. ++ * As idle tasks do not do either, they must not ever be preempted ++ * (schedule out non-voluntarily). ++ * ++ * schedule_idle() is similar to schedule_preempt_disable() except that it ++ * never enables preemption because it does not call sched_submit_work(). ++ */ ++void __sched schedule_idle(void) ++{ ++ /* ++ * As this skips calling sched_submit_work(), which the idle task does ++ * regardless because that function is a nop when the task is in a ++ * TASK_RUNNING state, make sure this isn't used someplace that the ++ * current task can be in any other state. Note, idle is always in the ++ * TASK_RUNNING state. ++ */ ++ WARN_ON_ONCE(current->state); ++ do { ++ __schedule(false); ++ } while (need_resched()); ++} ++ ++#ifdef CONFIG_CONTEXT_TRACKING ++asmlinkage __visible void __sched schedule_user(void) ++{ ++ /* ++ * If we come here after a random call to set_need_resched(), ++ * or we have been woken up remotely but the IPI has not yet arrived, ++ * we haven't yet exited the RCU idle mode. Do it here manually until ++ * we find a better solution. ++ * ++ * NB: There are buggy callers of this function. Ideally we ++ * should warn if prev_state != CONTEXT_USER, but that will trigger ++ * too frequently to make sense yet. ++ */ ++ enum ctx_state prev_state = exception_enter(); ++ schedule(); ++ exception_exit(prev_state); ++} ++#endif ++ ++/** ++ * schedule_preempt_disabled - called with preemption disabled ++ * ++ * Returns with preemption disabled. Note: preempt_count must be 1 ++ */ ++void __sched schedule_preempt_disabled(void) ++{ ++ sched_preempt_enable_no_resched(); ++ schedule(); ++ preempt_disable(); ++} ++ ++static void __sched notrace preempt_schedule_common(void) ++{ ++ do { ++ /* ++ * Because the function tracer can trace preempt_count_sub() ++ * and it also uses preempt_enable/disable_notrace(), if ++ * NEED_RESCHED is set, the preempt_enable_notrace() called ++ * by the function tracer will call this function again and ++ * cause infinite recursion. ++ * ++ * Preemption must be disabled here before the function ++ * tracer can trace. Break up preempt_disable() into two ++ * calls. One to disable preemption without fear of being ++ * traced. The other to still record the preemption latency, ++ * which can also be traced by the function tracer. ++ */ ++ preempt_disable_notrace(); ++ preempt_latency_start(1); ++ __schedule(true); ++ preempt_latency_stop(1); ++ preempt_enable_no_resched_notrace(); ++ ++ /* ++ * Check again in case we missed a preemption opportunity ++ * between schedule and now. ++ */ ++ } while (need_resched()); ++} ++ ++#ifdef CONFIG_PREEMPTION ++/* ++ * This is the entry point to schedule() from in-kernel preemption ++ * off of preempt_enable. ++ */ ++asmlinkage __visible void __sched notrace preempt_schedule(void) ++{ ++ /* ++ * If there is a non-zero preempt_count or interrupts are disabled, ++ * we do not want to preempt the current task. Just return.. ++ */ ++ if (likely(!preemptible())) ++ return; ++ ++ preempt_schedule_common(); ++} ++NOKPROBE_SYMBOL(preempt_schedule); ++EXPORT_SYMBOL(preempt_schedule); ++ ++/** ++ * preempt_schedule_notrace - preempt_schedule called by tracing ++ * ++ * The tracing infrastructure uses preempt_enable_notrace to prevent ++ * recursion and tracing preempt enabling caused by the tracing ++ * infrastructure itself. But as tracing can happen in areas coming ++ * from userspace or just about to enter userspace, a preempt enable ++ * can occur before user_exit() is called. This will cause the scheduler ++ * to be called when the system is still in usermode. ++ * ++ * To prevent this, the preempt_enable_notrace will use this function ++ * instead of preempt_schedule() to exit user context if needed before ++ * calling the scheduler. ++ */ ++asmlinkage __visible void __sched notrace preempt_schedule_notrace(void) ++{ ++ enum ctx_state prev_ctx; ++ ++ if (likely(!preemptible())) ++ return; ++ ++ do { ++ /* ++ * Because the function tracer can trace preempt_count_sub() ++ * and it also uses preempt_enable/disable_notrace(), if ++ * NEED_RESCHED is set, the preempt_enable_notrace() called ++ * by the function tracer will call this function again and ++ * cause infinite recursion. ++ * ++ * Preemption must be disabled here before the function ++ * tracer can trace. Break up preempt_disable() into two ++ * calls. One to disable preemption without fear of being ++ * traced. The other to still record the preemption latency, ++ * which can also be traced by the function tracer. ++ */ ++ preempt_disable_notrace(); ++ preempt_latency_start(1); ++ /* ++ * Needs preempt disabled in case user_exit() is traced ++ * and the tracer calls preempt_enable_notrace() causing ++ * an infinite recursion. ++ */ ++ prev_ctx = exception_enter(); ++ __schedule(true); ++ exception_exit(prev_ctx); ++ ++ preempt_latency_stop(1); ++ preempt_enable_no_resched_notrace(); ++ } while (need_resched()); ++} ++EXPORT_SYMBOL_GPL(preempt_schedule_notrace); ++ ++#endif /* CONFIG_PREEMPTION */ ++ ++/* ++ * This is the entry point to schedule() from kernel preemption ++ * off of irq context. ++ * Note, that this is called and return with irqs disabled. This will ++ * protect us against recursive calling from irq. ++ */ ++asmlinkage __visible void __sched preempt_schedule_irq(void) ++{ ++ enum ctx_state prev_state; ++ ++ /* Catch callers which need to be fixed */ ++ BUG_ON(preempt_count() || !irqs_disabled()); ++ ++ prev_state = exception_enter(); ++ ++ do { ++ preempt_disable(); ++ local_irq_enable(); ++ __schedule(true); ++ local_irq_disable(); ++ sched_preempt_enable_no_resched(); ++ } while (need_resched()); ++ ++ exception_exit(prev_state); ++} ++ ++int default_wake_function(wait_queue_entry_t *curr, unsigned mode, int wake_flags, ++ void *key) ++{ ++ return try_to_wake_up(curr->private, mode, wake_flags); ++} ++EXPORT_SYMBOL(default_wake_function); ++ ++static inline void ++check_task_changed(struct rq *rq, struct task_struct *p) ++{ ++ /* ++ * Trigger changes when task priority/deadline modified. ++ */ ++ if (task_on_rq_queued(p)) { ++ struct task_struct *first; ++ ++ requeue_task(p, rq); ++ ++ /* Resched if first queued task not running and not IDLE */ ++ if ((first = rq_first_queued_task(rq)) != rq->curr && ++ !task_running_idle(first)) ++ resched_curr(rq); ++ } ++} ++ ++#ifdef CONFIG_RT_MUTEXES ++ ++static inline int __rt_effective_prio(struct task_struct *pi_task, int prio) ++{ ++ if (pi_task) ++ prio = min(prio, pi_task->prio); ++ ++ return prio; ++} ++ ++static inline int rt_effective_prio(struct task_struct *p, int prio) ++{ ++ struct task_struct *pi_task = rt_mutex_get_top_task(p); ++ ++ return __rt_effective_prio(pi_task, prio); ++} ++ ++/* ++ * rt_mutex_setprio - set the current priority of a task ++ * @p: task to boost ++ * @pi_task: donor task ++ * ++ * This function changes the 'effective' priority of a task. It does ++ * not touch ->normal_prio like __setscheduler(). ++ * ++ * Used by the rt_mutex code to implement priority inheritance ++ * logic. Call site only calls if the priority of the task changed. ++ */ ++void rt_mutex_setprio(struct task_struct *p, struct task_struct *pi_task) ++{ ++ int prio; ++ struct rq *rq; ++ raw_spinlock_t *lock; ++ ++ /* XXX used to be waiter->prio, not waiter->task->prio */ ++ prio = __rt_effective_prio(pi_task, p->normal_prio); ++ ++ /* ++ * If nothing changed; bail early. ++ */ ++ if (p->pi_top_task == pi_task && prio == p->prio) ++ return; ++ ++ rq = __task_access_lock(p, &lock); ++ /* ++ * Set under pi_lock && rq->lock, such that the value can be used under ++ * either lock. ++ * ++ * Note that there is loads of tricky to make this pointer cache work ++ * right. rt_mutex_slowunlock()+rt_mutex_postunlock() work together to ++ * ensure a task is de-boosted (pi_task is set to NULL) before the ++ * task is allowed to run again (and can exit). This ensures the pointer ++ * points to a blocked task -- which guaratees the task is present. ++ */ ++ p->pi_top_task = pi_task; ++ ++ /* ++ * For FIFO/RR we only need to set prio, if that matches we're done. ++ */ ++ if (prio == p->prio) ++ goto out_unlock; ++ ++ /* ++ * Idle task boosting is a nono in general. There is one ++ * exception, when PREEMPT_RT and NOHZ is active: ++ * ++ * The idle task calls get_next_timer_interrupt() and holds ++ * the timer wheel base->lock on the CPU and another CPU wants ++ * to access the timer (probably to cancel it). We can safely ++ * ignore the boosting request, as the idle CPU runs this code ++ * with interrupts disabled and will complete the lock ++ * protected section without being interrupted. So there is no ++ * real need to boost. ++ */ ++ if (unlikely(p == rq->idle)) { ++ WARN_ON(p != rq->curr); ++ WARN_ON(p->pi_blocked_on); ++ goto out_unlock; ++ } ++ ++ trace_sched_pi_setprio(p, pi_task); ++ p->prio = prio; ++ update_task_priodl(p); ++ ++ check_task_changed(rq, p); ++ ++out_unlock: ++ __task_access_unlock(p, lock); ++} ++#else ++static inline int rt_effective_prio(struct task_struct *p, int prio) ++{ ++ return prio; ++} ++#endif ++ ++void set_user_nice(struct task_struct *p, long nice) ++{ ++ int new_static; ++ unsigned long flags; ++ struct rq *rq; ++ raw_spinlock_t *lock; ++ ++ if (task_nice(p) == nice || nice < MIN_NICE || nice > MAX_NICE) ++ return; ++ new_static = NICE_TO_PRIO(nice); ++ /* ++ * We have to be careful, if called from sys_setpriority(), ++ * the task might be in the middle of scheduling on another CPU. ++ */ ++ raw_spin_lock_irqsave(&p->pi_lock, flags); ++ rq = __task_access_lock(p, &lock); ++ ++ /* rq lock may not held!! */ ++ update_rq_clock(rq); ++ ++ p->static_prio = new_static; ++ /* ++ * The RT priorities are set via sched_setscheduler(), but we still ++ * allow the 'normal' nice value to be set - but as expected ++ * it wont have any effect on scheduling until the task is ++ * not SCHED_NORMAL/SCHED_BATCH: ++ */ ++ if (task_has_rt_policy(p)) ++ goto out_unlock; ++ ++ p->deadline -= task_deadline_diff(p); ++ p->deadline += static_deadline_diff(new_static); ++ p->prio = effective_prio(p); ++ update_task_priodl(p); ++ ++ check_task_changed(rq, p); ++out_unlock: ++ __task_access_unlock(p, lock); ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++} ++EXPORT_SYMBOL(set_user_nice); ++ ++/* ++ * can_nice - check if a task can reduce its nice value ++ * @p: task ++ * @nice: nice value ++ */ ++int can_nice(const struct task_struct *p, const int nice) ++{ ++ /* Convert nice value [19,-20] to rlimit style value [1,40] */ ++ int nice_rlim = nice_to_rlimit(nice); ++ ++ return (nice_rlim <= task_rlimit(p, RLIMIT_NICE) || ++ capable(CAP_SYS_NICE)); ++} ++ ++#ifdef __ARCH_WANT_SYS_NICE ++ ++/* ++ * sys_nice - change the priority of the current process. ++ * @increment: priority increment ++ * ++ * sys_setpriority is a more generic, but much slower function that ++ * does similar things. ++ */ ++SYSCALL_DEFINE1(nice, int, increment) ++{ ++ long nice, retval; ++ ++ /* ++ * Setpriority might change our priority at the same moment. ++ * We don't have to worry. Conceptually one call occurs first ++ * and we have a single winner. ++ */ ++ ++ increment = clamp(increment, -NICE_WIDTH, NICE_WIDTH); ++ nice = task_nice(current) + increment; ++ ++ nice = clamp_val(nice, MIN_NICE, MAX_NICE); ++ if (increment < 0 && !can_nice(current, nice)) ++ return -EPERM; ++ ++ retval = security_task_setnice(current, nice); ++ if (retval) ++ return retval; ++ ++ set_user_nice(current, nice); ++ return 0; ++} ++ ++#endif ++ ++/** ++ * task_prio - return the priority value of a given task. ++ * @p: the task in question. ++ * ++ * Return: The priority value as seen by users in /proc. ++ * RT tasks are offset by -100. Normal tasks are centered around 1, value goes ++ * from 0(SCHED_ISO) up to 82 (nice +19 SCHED_IDLE). ++ */ ++int task_prio(const struct task_struct *p) ++{ ++ int level, prio = p->prio - MAX_RT_PRIO; ++ static const int level_to_nice_prio[] = {39, 33, 26, 20, 14, 7, 0, 0}; ++ ++ /* rt tasks */ ++ if (prio <= 0) ++ goto out; ++ ++ preempt_disable(); ++ level = task_deadline_level(p, this_rq()); ++ preempt_enable(); ++ prio += level_to_nice_prio[level]; ++ if (idleprio_task(p)) ++ prio += NICE_WIDTH; ++out: ++ return prio; ++} ++ ++/** ++ * idle_cpu - is a given CPU idle currently? ++ * @cpu: the processor in question. ++ * ++ * Return: 1 if the CPU is currently idle. 0 otherwise. ++ */ ++int idle_cpu(int cpu) ++{ ++ return cpu_curr(cpu) == cpu_rq(cpu)->idle; ++} ++ ++/** ++ * idle_task - return the idle task for a given CPU. ++ * @cpu: the processor in question. ++ * ++ * Return: The idle task for the cpu @cpu. ++ */ ++struct task_struct *idle_task(int cpu) ++{ ++ return cpu_rq(cpu)->idle; ++} ++ ++/** ++ * find_process_by_pid - find a process with a matching PID value. ++ * @pid: the pid in question. ++ * ++ * The task of @pid, if found. %NULL otherwise. ++ */ ++static inline struct task_struct *find_process_by_pid(pid_t pid) ++{ ++ return pid ? find_task_by_vpid(pid) : current; ++} ++ ++#ifdef CONFIG_SMP ++void sched_set_stop_task(int cpu, struct task_struct *stop) ++{ ++ struct sched_param stop_param = { .sched_priority = STOP_PRIO }; ++ struct sched_param start_param = { .sched_priority = 0 }; ++ struct task_struct *old_stop = cpu_rq(cpu)->stop; ++ ++ if (stop) { ++ /* ++ * Make it appear like a SCHED_FIFO task, its something ++ * userspace knows about and won't get confused about. ++ * ++ * Also, it will make PI more or less work without too ++ * much confusion -- but then, stop work should not ++ * rely on PI working anyway. ++ */ ++ sched_setscheduler_nocheck(stop, SCHED_FIFO, &stop_param); ++ } ++ ++ cpu_rq(cpu)->stop = stop; ++ ++ if (old_stop) { ++ /* ++ * Reset it back to a normal scheduling policy so that ++ * it can die in pieces. ++ */ ++ sched_setscheduler_nocheck(old_stop, SCHED_NORMAL, &start_param); ++ } ++} ++ ++/* ++ * Change a given task's CPU affinity. Migrate the thread to a ++ * proper CPU and schedule it away if the CPU it's executing on ++ * is removed from the allowed bitmask. ++ * ++ * NOTE: the caller must have a valid reference to the task, the ++ * task must not exit() & deallocate itself prematurely. The ++ * call is not atomic; no spinlocks may be held. ++ */ ++static int __set_cpus_allowed_ptr(struct task_struct *p, ++ const struct cpumask *new_mask, bool check) ++{ ++ const struct cpumask *cpu_valid_mask = cpu_active_mask; ++ int dest_cpu; ++ unsigned long flags; ++ struct rq *rq; ++ raw_spinlock_t *lock; ++ int ret = 0; ++ ++ raw_spin_lock_irqsave(&p->pi_lock, flags); ++ rq = __task_access_lock(p, &lock); ++ ++ if (p->flags & PF_KTHREAD) { ++ /* ++ * Kernel threads are allowed on online && !active CPUs ++ */ ++ cpu_valid_mask = cpu_online_mask; ++ } ++ ++ /* ++ * Must re-check here, to close a race against __kthread_bind(), ++ * sched_setaffinity() is not guaranteed to observe the flag. ++ */ ++ if (check && (p->flags & PF_NO_SETAFFINITY)) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ if (cpumask_equal(&p->cpus_mask, new_mask)) ++ goto out; ++ ++ dest_cpu = cpumask_any_and(cpu_valid_mask, new_mask); ++ if (dest_cpu >= nr_cpu_ids) { ++ ret = -EINVAL; ++ goto out; ++ } ++ ++ do_set_cpus_allowed(p, new_mask); ++ ++ if (p->flags & PF_KTHREAD) { ++ /* ++ * For kernel threads that do indeed end up on online && ++ * !active we want to ensure they are strict per-CPU threads. ++ */ ++ WARN_ON(cpumask_intersects(new_mask, cpu_online_mask) && ++ !cpumask_intersects(new_mask, cpu_active_mask) && ++ p->nr_cpus_allowed != 1); ++ } ++ ++ /* Can the task run on the task's current CPU? If so, we're done */ ++ if (cpumask_test_cpu(task_cpu(p), new_mask)) ++ goto out; ++ ++ if (task_running(p) || p->state == TASK_WAKING) { ++ struct migration_arg arg = { p, dest_cpu }; ++ ++ /* Need help from migration thread: drop lock and wait. */ ++ __task_access_unlock(p, lock); ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++ stop_one_cpu(cpu_of(rq), migration_cpu_stop, &arg); ++ return 0; ++ } ++ if (task_on_rq_queued(p)) { ++ /* ++ * OK, since we're going to drop the lock immediately ++ * afterwards anyway. ++ */ ++ update_rq_clock(rq); ++ rq = move_queued_task(rq, p, dest_cpu); ++ lock = &rq->lock; ++ } ++ ++out: ++ __task_access_unlock(p, lock); ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++ ++ return ret; ++} ++ ++int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask) ++{ ++ return __set_cpus_allowed_ptr(p, new_mask, false); ++} ++EXPORT_SYMBOL_GPL(set_cpus_allowed_ptr); ++ ++#else ++static inline int ++__set_cpus_allowed_ptr(struct task_struct *p, ++ const struct cpumask *new_mask, bool check) ++{ ++ return set_cpus_allowed_ptr(p, new_mask); ++} ++#endif ++ ++static u64 task_init_deadline(const struct task_struct *p) ++{ ++ return task_rq(p)->clock + task_deadline_diff(p); ++} ++ ++u64 (* task_init_deadline_func_tbl[])(const struct task_struct *p) = { ++ task_init_deadline, /* SCHED_NORMAL */ ++ NULL, /* SCHED_FIFO */ ++ NULL, /* SCHED_RR */ ++ task_init_deadline, /* SCHED_BATCH */ ++ NULL, /* SCHED_ISO */ ++ task_init_deadline /* SCHED_IDLE */ ++}; ++ ++/* ++ * sched_setparam() passes in -1 for its policy, to let the functions ++ * it calls know not to change it. ++ */ ++#define SETPARAM_POLICY -1 ++ ++static void __setscheduler_params(struct task_struct *p, ++ const struct sched_attr *attr) ++{ ++ int old_policy = p->policy; ++ int policy = attr->sched_policy; ++ ++ if (policy == SETPARAM_POLICY) ++ policy = p->policy; ++ ++ p->policy = policy; ++ ++ /* ++ * allow normal nice value to be set, but will not have any ++ * effect on scheduling until the task not SCHED_NORMAL/ ++ * SCHED_BATCH ++ */ ++ p->static_prio = NICE_TO_PRIO(attr->sched_nice); ++ ++ /* ++ * __sched_setscheduler() ensures attr->sched_priority == 0 when ++ * !rt_policy. Always setting this ensures that things like ++ * getparam()/getattr() don't report silly values for !rt tasks. ++ */ ++ p->rt_priority = attr->sched_priority; ++ p->normal_prio = normal_prio(p); ++ ++ if (old_policy != policy) ++ p->deadline = (task_init_deadline_func_tbl[p->policy])? ++ task_init_deadline_func_tbl[p->policy](p):0ULL; ++} ++ ++/* Actually do priority change: must hold rq lock. */ ++static void __setscheduler(struct rq *rq, struct task_struct *p, ++ const struct sched_attr *attr, bool keep_boost) ++{ ++ __setscheduler_params(p, attr); ++ ++ /* ++ * Keep a potential priority boosting if called from ++ * sched_setscheduler(). ++ */ ++ p->prio = normal_prio(p); ++ if (keep_boost) ++ p->prio = rt_effective_prio(p, p->prio); ++ update_task_priodl(p); ++} ++ ++/* ++ * check the target process has a UID that matches the current process's ++ */ ++static bool check_same_owner(struct task_struct *p) ++{ ++ const struct cred *cred = current_cred(), *pcred; ++ bool match; ++ ++ rcu_read_lock(); ++ pcred = __task_cred(p); ++ match = (uid_eq(cred->euid, pcred->euid) || ++ uid_eq(cred->euid, pcred->uid)); ++ rcu_read_unlock(); ++ return match; ++} ++ ++static int ++__sched_setscheduler(struct task_struct *p, ++ const struct sched_attr *attr, bool user, bool pi) ++{ ++ const struct sched_attr dl_squash_attr = { ++ .size = sizeof(struct sched_attr), ++ .sched_policy = SCHED_FIFO, ++ .sched_nice = 0, ++ .sched_priority = 99, ++ }; ++ int newprio = MAX_RT_PRIO - 1 - attr->sched_priority; ++ int retval, oldpolicy = -1; ++ int policy = attr->sched_policy; ++ unsigned long flags; ++ struct rq *rq; ++ int reset_on_fork; ++ raw_spinlock_t *lock; ++ ++ /* The pi code expects interrupts enabled */ ++ BUG_ON(pi && in_interrupt()); ++ ++ /* ++ * PDS supports SCHED_DEADLINE by squash it as prio 0 SCHED_FIFO ++ */ ++ if (unlikely(SCHED_DEADLINE == policy)) { ++ attr = &dl_squash_attr; ++ policy = attr->sched_policy; ++ newprio = MAX_RT_PRIO - 1 - attr->sched_priority; ++ } ++recheck: ++ /* Double check policy once rq lock held */ ++ if (policy < 0) { ++ reset_on_fork = p->sched_reset_on_fork; ++ policy = oldpolicy = p->policy; ++ } else { ++ reset_on_fork = !!(attr->sched_flags & SCHED_RESET_ON_FORK); ++ ++ if (policy > SCHED_IDLE) ++ return -EINVAL; ++ } ++ ++ if (attr->sched_flags & ~(SCHED_FLAG_ALL)) ++ return -EINVAL; ++ ++ /* ++ * Valid priorities for SCHED_FIFO and SCHED_RR are ++ * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL and ++ * SCHED_BATCH and SCHED_IDLE is 0. ++ */ ++ if (attr->sched_priority < 0 || ++ (p->mm && attr->sched_priority > MAX_USER_RT_PRIO - 1) || ++ (!p->mm && attr->sched_priority > MAX_RT_PRIO - 1)) ++ return -EINVAL; ++ if ((SCHED_RR == policy || SCHED_FIFO == policy) != ++ (attr->sched_priority != 0)) ++ return -EINVAL; ++ ++ /* ++ * Allow unprivileged RT tasks to decrease priority: ++ */ ++ if (user && !capable(CAP_SYS_NICE)) { ++ if (SCHED_FIFO == policy || SCHED_RR == policy) { ++ unsigned long rlim_rtprio = ++ task_rlimit(p, RLIMIT_RTPRIO); ++ ++ /* Can't set/change the rt policy */ ++ if (policy != p->policy && !rlim_rtprio) ++ return -EPERM; ++ ++ /* Can't increase priority */ ++ if (attr->sched_priority > p->rt_priority && ++ attr->sched_priority > rlim_rtprio) ++ return -EPERM; ++ } ++ ++ /* Can't change other user's priorities */ ++ if (!check_same_owner(p)) ++ return -EPERM; ++ ++ /* Normal users shall not reset the sched_reset_on_fork flag */ ++ if (p->sched_reset_on_fork && !reset_on_fork) ++ return -EPERM; ++ } ++ ++ if (user) { ++ retval = security_task_setscheduler(p); ++ if (retval) ++ return retval; ++ } ++ ++ if (pi) ++ cpuset_read_lock(); ++ ++ /* ++ * Make sure no PI-waiters arrive (or leave) while we are ++ * changing the priority of the task: ++ */ ++ raw_spin_lock_irqsave(&p->pi_lock, flags); ++ ++ /* ++ * To be able to change p->policy safely, task_access_lock() ++ * must be called. ++ * IF use task_access_lock() here: ++ * For the task p which is not running, reading rq->stop is ++ * racy but acceptable as ->stop doesn't change much. ++ * An enhancemnet can be made to read rq->stop saftly. ++ */ ++ rq = __task_access_lock(p, &lock); ++ ++ /* ++ * Changing the policy of the stop threads its a very bad idea ++ */ ++ if (p == rq->stop) { ++ retval = -EINVAL; ++ goto unlock; ++ } ++ ++ /* ++ * If not changing anything there's no need to proceed further: ++ */ ++ if (unlikely(policy == p->policy)) { ++ if (rt_policy(policy) && attr->sched_priority != p->rt_priority) ++ goto change; ++ if (!rt_policy(policy) && ++ NICE_TO_PRIO(attr->sched_nice) != p->static_prio) ++ goto change; ++ ++ p->sched_reset_on_fork = reset_on_fork; ++ retval = 0; ++ goto unlock; ++ } ++change: ++ ++ /* Re-check policy now with rq lock held */ ++ if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) { ++ policy = oldpolicy = -1; ++ __task_access_unlock(p, lock); ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++ if (pi) ++ cpuset_read_unlock(); ++ goto recheck; ++ } ++ ++ p->sched_reset_on_fork = reset_on_fork; ++ ++ if (pi) { ++ /* ++ * Take priority boosted tasks into account. If the new ++ * effective priority is unchanged, we just store the new ++ * normal parameters and do not touch the scheduler class and ++ * the runqueue. This will be done when the task deboost ++ * itself. ++ */ ++ if (rt_effective_prio(p, newprio) == p->prio) { ++ __setscheduler_params(p, attr); ++ retval = 0; ++ goto unlock; ++ } ++ } ++ ++ __setscheduler(rq, p, attr, pi); ++ ++ check_task_changed(rq, p); ++ ++ /* Avoid rq from going away on us: */ ++ preempt_disable(); ++ __task_access_unlock(p, lock); ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++ ++ if (pi) { ++ cpuset_read_unlock(); ++ rt_mutex_adjust_pi(p); ++ } ++ ++ preempt_enable(); ++ ++ return 0; ++ ++unlock: ++ __task_access_unlock(p, lock); ++ raw_spin_unlock_irqrestore(&p->pi_lock, flags); ++ if (pi) ++ cpuset_read_unlock(); ++ return retval; ++} ++ ++static int _sched_setscheduler(struct task_struct *p, int policy, ++ const struct sched_param *param, bool check) ++{ ++ struct sched_attr attr = { ++ .sched_policy = policy, ++ .sched_priority = param->sched_priority, ++ .sched_nice = PRIO_TO_NICE(p->static_prio), ++ }; ++ ++ /* Fixup the legacy SCHED_RESET_ON_FORK hack. */ ++ if ((policy != SETPARAM_POLICY) && (policy & SCHED_RESET_ON_FORK)) { ++ attr.sched_flags |= SCHED_FLAG_RESET_ON_FORK; ++ policy &= ~SCHED_RESET_ON_FORK; ++ attr.sched_policy = policy; ++ } ++ ++ return __sched_setscheduler(p, &attr, check, true); ++} ++ ++/** ++ * sched_setscheduler - change the scheduling policy and/or RT priority of a thread. ++ * @p: the task in question. ++ * @policy: new policy. ++ * @param: structure containing the new RT priority. ++ * ++ * Return: 0 on success. An error code otherwise. ++ * ++ * NOTE that the task may be already dead. ++ */ ++int sched_setscheduler(struct task_struct *p, int policy, ++ const struct sched_param *param) ++{ ++ return _sched_setscheduler(p, policy, param, true); ++} ++ ++EXPORT_SYMBOL_GPL(sched_setscheduler); ++ ++int sched_setattr(struct task_struct *p, const struct sched_attr *attr) ++{ ++ return __sched_setscheduler(p, attr, true, true); ++} ++EXPORT_SYMBOL_GPL(sched_setattr); ++ ++int sched_setattr_nocheck(struct task_struct *p, const struct sched_attr *attr) ++{ ++ return __sched_setscheduler(p, attr, false, true); ++} ++ ++/** ++ * sched_setscheduler_nocheck - change the scheduling policy and/or RT priority of a thread from kernelspace. ++ * @p: the task in question. ++ * @policy: new policy. ++ * @param: structure containing the new RT priority. ++ * ++ * Just like sched_setscheduler, only don't bother checking if the ++ * current context has permission. For example, this is needed in ++ * stop_machine(): we create temporary high priority worker threads, ++ * but our caller might not have that capability. ++ * ++ * Return: 0 on success. An error code otherwise. ++ */ ++int sched_setscheduler_nocheck(struct task_struct *p, int policy, ++ const struct sched_param *param) ++{ ++ return _sched_setscheduler(p, policy, param, false); ++} ++EXPORT_SYMBOL_GPL(sched_setscheduler_nocheck); ++ ++static int ++do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param) ++{ ++ struct sched_param lparam; ++ struct task_struct *p; ++ int retval; ++ ++ if (!param || pid < 0) ++ return -EINVAL; ++ if (copy_from_user(&lparam, param, sizeof(struct sched_param))) ++ return -EFAULT; ++ ++ rcu_read_lock(); ++ retval = -ESRCH; ++ p = find_process_by_pid(pid); ++ if (likely(p)) ++ get_task_struct(p); ++ rcu_read_unlock(); ++ ++ if (likely(p)) { ++ retval = sched_setscheduler(p, policy, &lparam); ++ put_task_struct(p); ++ } ++ ++ return retval; ++} ++ ++/* ++ * Mimics kernel/events/core.c perf_copy_attr(). ++ */ ++static int sched_copy_attr(struct sched_attr __user *uattr, struct sched_attr *attr) ++{ ++ u32 size; ++ int ret; ++ ++ /* Zero the full structure, so that a short copy will be nice: */ ++ memset(attr, 0, sizeof(*attr)); ++ ++ ret = get_user(size, &uattr->size); ++ if (ret) ++ return ret; ++ ++ /* ABI compatibility quirk: */ ++ if (!size) ++ size = SCHED_ATTR_SIZE_VER0; ++ ++ if (size < SCHED_ATTR_SIZE_VER0 || size > PAGE_SIZE) ++ goto err_size; ++ ++ ret = copy_struct_from_user(attr, sizeof(*attr), uattr, size); ++ if (ret) { ++ if (ret == -E2BIG) ++ goto err_size; ++ return ret; ++ } ++ ++ /* ++ * XXX: Do we want to be lenient like existing syscalls; or do we want ++ * to be strict and return an error on out-of-bounds values? ++ */ ++ attr->sched_nice = clamp(attr->sched_nice, -20, 19); ++ ++ /* sched/core.c uses zero here but we already know ret is zero */ ++ return 0; ++ ++err_size: ++ put_user(sizeof(*attr), &uattr->size); ++ return -E2BIG; ++} ++ ++/** ++ * sys_sched_setscheduler - set/change the scheduler policy and RT priority ++ * @pid: the pid in question. ++ * @policy: new policy. ++ * ++ * Return: 0 on success. An error code otherwise. ++ * @param: structure containing the new RT priority. ++ */ ++SYSCALL_DEFINE3(sched_setscheduler, pid_t, pid, int, policy, struct sched_param __user *, param) ++{ ++ if (policy < 0) ++ return -EINVAL; ++ ++ return do_sched_setscheduler(pid, policy, param); ++} ++ ++/** ++ * sys_sched_setparam - set/change the RT priority of a thread ++ * @pid: the pid in question. ++ * @param: structure containing the new RT priority. ++ * ++ * Return: 0 on success. An error code otherwise. ++ */ ++SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param) ++{ ++ return do_sched_setscheduler(pid, SETPARAM_POLICY, param); ++} ++ ++/** ++ * sys_sched_setattr - same as above, but with extended sched_attr ++ * @pid: the pid in question. ++ * @uattr: structure containing the extended parameters. ++ */ ++SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr, ++ unsigned int, flags) ++{ ++ struct sched_attr attr; ++ struct task_struct *p; ++ int retval; ++ ++ if (!uattr || pid < 0 || flags) ++ return -EINVAL; ++ ++ retval = sched_copy_attr(uattr, &attr); ++ if (retval) ++ return retval; ++ ++ if ((int)attr.sched_policy < 0) ++ return -EINVAL; ++ ++ rcu_read_lock(); ++ retval = -ESRCH; ++ p = find_process_by_pid(pid); ++ if (p != NULL) ++ retval = sched_setattr(p, &attr); ++ rcu_read_unlock(); ++ ++ return retval; ++} ++ ++/** ++ * sys_sched_getscheduler - get the policy (scheduling class) of a thread ++ * @pid: the pid in question. ++ * ++ * Return: On success, the policy of the thread. Otherwise, a negative error ++ * code. ++ */ ++SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid) ++{ ++ struct task_struct *p; ++ int retval = -EINVAL; ++ ++ if (pid < 0) ++ goto out_nounlock; ++ ++ retval = -ESRCH; ++ rcu_read_lock(); ++ p = find_process_by_pid(pid); ++ if (p) { ++ retval = security_task_getscheduler(p); ++ if (!retval) ++ retval = p->policy; ++ } ++ rcu_read_unlock(); ++ ++out_nounlock: ++ return retval; ++} ++ ++/** ++ * sys_sched_getscheduler - get the RT priority of a thread ++ * @pid: the pid in question. ++ * @param: structure containing the RT priority. ++ * ++ * Return: On success, 0 and the RT priority is in @param. Otherwise, an error ++ * code. ++ */ ++SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param) ++{ ++ struct sched_param lp = { .sched_priority = 0 }; ++ struct task_struct *p; ++ int retval = -EINVAL; ++ ++ if (!param || pid < 0) ++ goto out_nounlock; ++ ++ rcu_read_lock(); ++ p = find_process_by_pid(pid); ++ retval = -ESRCH; ++ if (!p) ++ goto out_unlock; ++ ++ retval = security_task_getscheduler(p); ++ if (retval) ++ goto out_unlock; ++ ++ if (task_has_rt_policy(p)) ++ lp.sched_priority = p->rt_priority; ++ rcu_read_unlock(); ++ ++ /* ++ * This one might sleep, we cannot do it with a spinlock held ... ++ */ ++ retval = copy_to_user(param, &lp, sizeof(*param)) ? -EFAULT : 0; ++ ++out_nounlock: ++ return retval; ++ ++out_unlock: ++ rcu_read_unlock(); ++ return retval; ++} ++ ++/* ++ * Copy the kernel size attribute structure (which might be larger ++ * than what user-space knows about) to user-space. ++ * ++ * Note that all cases are valid: user-space buffer can be larger or ++ * smaller than the kernel-space buffer. The usual case is that both ++ * have the same size. ++ */ ++static int ++sched_attr_copy_to_user(struct sched_attr __user *uattr, ++ struct sched_attr *kattr, ++ unsigned int usize) ++{ ++ unsigned int ksize = sizeof(*kattr); ++ ++ if (!access_ok(uattr, usize)) ++ return -EFAULT; ++ ++ /* ++ * sched_getattr() ABI forwards and backwards compatibility: ++ * ++ * If usize == ksize then we just copy everything to user-space and all is good. ++ * ++ * If usize < ksize then we only copy as much as user-space has space for, ++ * this keeps ABI compatibility as well. We skip the rest. ++ * ++ * If usize > ksize then user-space is using a newer version of the ABI, ++ * which part the kernel doesn't know about. Just ignore it - tooling can ++ * detect the kernel's knowledge of attributes from the attr->size value ++ * which is set to ksize in this case. ++ */ ++ kattr->size = min(usize, ksize); ++ ++ if (copy_to_user(uattr, kattr, kattr->size)) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++/** ++ * sys_sched_getattr - similar to sched_getparam, but with sched_attr ++ * @pid: the pid in question. ++ * @uattr: structure containing the extended parameters. ++ * @usize: sizeof(attr) for fwd/bwd comp. ++ * @flags: for future extension. ++ */ ++SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr, ++ unsigned int, usize, unsigned int, flags) ++{ ++ struct sched_attr kattr = { }; ++ struct task_struct *p; ++ int retval; ++ ++ if (!uattr || pid < 0 || usize > PAGE_SIZE || ++ usize < SCHED_ATTR_SIZE_VER0 || flags) ++ return -EINVAL; ++ ++ rcu_read_lock(); ++ p = find_process_by_pid(pid); ++ retval = -ESRCH; ++ if (!p) ++ goto out_unlock; ++ ++ retval = security_task_getscheduler(p); ++ if (retval) ++ goto out_unlock; ++ ++ kattr.sched_policy = p->policy; ++ if (rt_task(p)) ++ kattr.sched_priority = p->rt_priority; ++ else ++ kattr.sched_nice = task_nice(p); ++ ++#ifdef CONFIG_UCLAMP_TASK ++ kattr.sched_util_min = p->uclamp_req[UCLAMP_MIN].value; ++ kattr.sched_util_max = p->uclamp_req[UCLAMP_MAX].value; ++#endif ++ ++ rcu_read_unlock(); ++ ++ return sched_attr_copy_to_user(uattr, &kattr, usize); ++ ++out_unlock: ++ rcu_read_unlock(); ++ return retval; ++} ++ ++long sched_setaffinity(pid_t pid, const struct cpumask *in_mask) ++{ ++ cpumask_var_t cpus_mask, new_mask; ++ struct task_struct *p; ++ int retval; ++ ++ get_online_cpus(); ++ rcu_read_lock(); ++ ++ p = find_process_by_pid(pid); ++ if (!p) { ++ rcu_read_unlock(); ++ put_online_cpus(); ++ return -ESRCH; ++ } ++ ++ /* Prevent p going away */ ++ get_task_struct(p); ++ rcu_read_unlock(); ++ ++ if (p->flags & PF_NO_SETAFFINITY) { ++ retval = -EINVAL; ++ goto out_put_task; ++ } ++ if (!alloc_cpumask_var(&cpus_mask, GFP_KERNEL)) { ++ retval = -ENOMEM; ++ goto out_put_task; ++ } ++ if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) { ++ retval = -ENOMEM; ++ goto out_free_cpus_allowed; ++ } ++ retval = -EPERM; ++ if (!check_same_owner(p)) { ++ rcu_read_lock(); ++ if (!ns_capable(__task_cred(p)->user_ns, CAP_SYS_NICE)) { ++ rcu_read_unlock(); ++ goto out_unlock; ++ } ++ rcu_read_unlock(); ++ } ++ ++ retval = security_task_setscheduler(p); ++ if (retval) ++ goto out_unlock; ++ ++ cpuset_cpus_allowed(p, cpus_mask); ++ cpumask_and(new_mask, in_mask, cpus_mask); ++again: ++ retval = __set_cpus_allowed_ptr(p, new_mask, true); ++ ++ if (!retval) { ++ cpuset_cpus_allowed(p, cpus_mask); ++ if (!cpumask_subset(new_mask, cpus_mask)) { ++ /* ++ * We must have raced with a concurrent cpuset ++ * update. Just reset the cpus_mask to the ++ * cpuset's cpus_mask ++ */ ++ cpumask_copy(new_mask, cpus_mask); ++ goto again; ++ } ++ } ++out_unlock: ++ free_cpumask_var(new_mask); ++out_free_cpus_allowed: ++ free_cpumask_var(cpus_mask); ++out_put_task: ++ put_task_struct(p); ++ put_online_cpus(); ++ return retval; ++} ++ ++static int get_user_cpu_mask(unsigned long __user *user_mask_ptr, unsigned len, ++ struct cpumask *new_mask) ++{ ++ if (len < cpumask_size()) ++ cpumask_clear(new_mask); ++ else if (len > cpumask_size()) ++ len = cpumask_size(); ++ ++ return copy_from_user(new_mask, user_mask_ptr, len) ? -EFAULT : 0; ++} ++ ++/** ++ * sys_sched_setaffinity - set the CPU affinity of a process ++ * @pid: pid of the process ++ * @len: length in bytes of the bitmask pointed to by user_mask_ptr ++ * @user_mask_ptr: user-space pointer to the new CPU mask ++ * ++ * Return: 0 on success. An error code otherwise. ++ */ ++SYSCALL_DEFINE3(sched_setaffinity, pid_t, pid, unsigned int, len, ++ unsigned long __user *, user_mask_ptr) ++{ ++ cpumask_var_t new_mask; ++ int retval; ++ ++ if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) ++ return -ENOMEM; ++ ++ retval = get_user_cpu_mask(user_mask_ptr, len, new_mask); ++ if (retval == 0) ++ retval = sched_setaffinity(pid, new_mask); ++ free_cpumask_var(new_mask); ++ return retval; ++} ++ ++long sched_getaffinity(pid_t pid, cpumask_t *mask) ++{ ++ struct task_struct *p; ++ raw_spinlock_t *lock; ++ unsigned long flags; ++ int retval; ++ ++ rcu_read_lock(); ++ ++ retval = -ESRCH; ++ p = find_process_by_pid(pid); ++ if (!p) ++ goto out_unlock; ++ ++ retval = security_task_getscheduler(p); ++ if (retval) ++ goto out_unlock; ++ ++ task_access_lock_irqsave(p, &lock, &flags); ++ cpumask_and(mask, &p->cpus_mask, cpu_active_mask); ++ task_access_unlock_irqrestore(p, lock, &flags); ++ ++out_unlock: ++ rcu_read_unlock(); ++ ++ return retval; ++} ++ ++/** ++ * sys_sched_getaffinity - get the CPU affinity of a process ++ * @pid: pid of the process ++ * @len: length in bytes of the bitmask pointed to by user_mask_ptr ++ * @user_mask_ptr: user-space pointer to hold the current CPU mask ++ * ++ * Return: size of CPU mask copied to user_mask_ptr on success. An ++ * error code otherwise. ++ */ ++SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len, ++ unsigned long __user *, user_mask_ptr) ++{ ++ int ret; ++ cpumask_var_t mask; ++ ++ if ((len * BITS_PER_BYTE) < nr_cpu_ids) ++ return -EINVAL; ++ if (len & (sizeof(unsigned long)-1)) ++ return -EINVAL; ++ ++ if (!alloc_cpumask_var(&mask, GFP_KERNEL)) ++ return -ENOMEM; ++ ++ ret = sched_getaffinity(pid, mask); ++ if (ret == 0) { ++ unsigned int retlen = min_t(size_t, len, cpumask_size()); ++ ++ if (copy_to_user(user_mask_ptr, mask, retlen)) ++ ret = -EFAULT; ++ else ++ ret = retlen; ++ } ++ free_cpumask_var(mask); ++ ++ return ret; ++} ++ ++/** ++ * sys_sched_yield - yield the current processor to other threads. ++ * ++ * This function yields the current CPU to other tasks. It does this by ++ * scheduling away the current task. If it still has the earliest deadline ++ * it will be scheduled again as the next task. ++ * ++ * Return: 0. ++ */ ++static void do_sched_yield(void) ++{ ++ struct rq *rq; ++ struct rq_flags rf; ++ ++ if (!sched_yield_type) ++ return; ++ ++ rq = this_rq_lock_irq(&rf); ++ ++ if (sched_yield_type > 1) { ++ time_slice_expired(current, rq); ++ requeue_task(current, rq); ++ } ++ schedstat_inc(rq->yld_count); ++ ++ /* ++ * Since we are going to call schedule() anyway, there's ++ * no need to preempt or enable interrupts: ++ */ ++ preempt_disable(); ++ raw_spin_unlock(&rq->lock); ++ sched_preempt_enable_no_resched(); ++ ++ schedule(); ++} ++ ++SYSCALL_DEFINE0(sched_yield) ++{ ++ do_sched_yield(); ++ return 0; ++} ++ ++#ifndef CONFIG_PREEMPTION ++int __sched _cond_resched(void) ++{ ++ if (should_resched(0)) { ++ preempt_schedule_common(); ++ return 1; ++ } ++ rcu_all_qs(); ++ return 0; ++} ++EXPORT_SYMBOL(_cond_resched); ++#endif ++ ++/* ++ * __cond_resched_lock() - if a reschedule is pending, drop the given lock, ++ * call schedule, and on return reacquire the lock. ++ * ++ * This works OK both with and without CONFIG_PREEMPTION. We do strange low-level ++ * operations here to prevent schedule() from being called twice (once via ++ * spin_unlock(), once by hand). ++ */ ++int __cond_resched_lock(spinlock_t *lock) ++{ ++ int resched = should_resched(PREEMPT_LOCK_OFFSET); ++ int ret = 0; ++ ++ lockdep_assert_held(lock); ++ ++ if (spin_needbreak(lock) || resched) { ++ spin_unlock(lock); ++ if (resched) ++ preempt_schedule_common(); ++ else ++ cpu_relax(); ++ ret = 1; ++ spin_lock(lock); ++ } ++ return ret; ++} ++EXPORT_SYMBOL(__cond_resched_lock); ++ ++/** ++ * yield - yield the current processor to other threads. ++ * ++ * Do not ever use this function, there's a 99% chance you're doing it wrong. ++ * ++ * The scheduler is at all times free to pick the calling task as the most ++ * eligible task to run, if removing the yield() call from your code breaks ++ * it, its already broken. ++ * ++ * Typical broken usage is: ++ * ++ * while (!event) ++ * yield(); ++ * ++ * where one assumes that yield() will let 'the other' process run that will ++ * make event true. If the current task is a SCHED_FIFO task that will never ++ * happen. Never use yield() as a progress guarantee!! ++ * ++ * If you want to use yield() to wait for something, use wait_event(). ++ * If you want to use yield() to be 'nice' for others, use cond_resched(). ++ * If you still want to use yield(), do not! ++ */ ++void __sched yield(void) ++{ ++ set_current_state(TASK_RUNNING); ++ do_sched_yield(); ++} ++EXPORT_SYMBOL(yield); ++ ++/** ++ * yield_to - yield the current processor to another thread in ++ * your thread group, or accelerate that thread toward the ++ * processor it's on. ++ * @p: target task ++ * @preempt: whether task preemption is allowed or not ++ * ++ * It's the caller's job to ensure that the target task struct ++ * can't go away on us before we can do any checks. ++ * ++ * In PDS, yield_to is not supported. ++ * ++ * Return: ++ * true (>0) if we indeed boosted the target task. ++ * false (0) if we failed to boost the target. ++ * -ESRCH if there's no task to yield to. ++ */ ++int __sched yield_to(struct task_struct *p, bool preempt) ++{ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(yield_to); ++ ++int io_schedule_prepare(void) ++{ ++ int old_iowait = current->in_iowait; ++ ++ current->in_iowait = 1; ++ blk_schedule_flush_plug(current); ++ ++ return old_iowait; ++} ++ ++void io_schedule_finish(int token) ++{ ++ current->in_iowait = token; ++} ++ ++/* ++ * This task is about to go to sleep on IO. Increment rq->nr_iowait so ++ * that process accounting knows that this is a task in IO wait state. ++ * ++ * But don't do that if it is a deliberate, throttling IO wait (this task ++ * has set its backing_dev_info: the queue against which it should throttle) ++ */ ++ ++long __sched io_schedule_timeout(long timeout) ++{ ++ int token; ++ long ret; ++ ++ token = io_schedule_prepare(); ++ ret = schedule_timeout(timeout); ++ io_schedule_finish(token); ++ ++ return ret; ++} ++EXPORT_SYMBOL(io_schedule_timeout); ++ ++void io_schedule(void) ++{ ++ int token; ++ ++ token = io_schedule_prepare(); ++ schedule(); ++ io_schedule_finish(token); ++} ++EXPORT_SYMBOL(io_schedule); ++ ++/** ++ * sys_sched_get_priority_max - return maximum RT priority. ++ * @policy: scheduling class. ++ * ++ * Return: On success, this syscall returns the maximum ++ * rt_priority that can be used by a given scheduling class. ++ * On failure, a negative error code is returned. ++ */ ++SYSCALL_DEFINE1(sched_get_priority_max, int, policy) ++{ ++ int ret = -EINVAL; ++ ++ switch (policy) { ++ case SCHED_FIFO: ++ case SCHED_RR: ++ ret = MAX_USER_RT_PRIO-1; ++ break; ++ case SCHED_NORMAL: ++ case SCHED_BATCH: ++ case SCHED_ISO: ++ case SCHED_IDLE: ++ ret = 0; ++ break; ++ } ++ return ret; ++} ++ ++/** ++ * sys_sched_get_priority_min - return minimum RT priority. ++ * @policy: scheduling class. ++ * ++ * Return: On success, this syscall returns the minimum ++ * rt_priority that can be used by a given scheduling class. ++ * On failure, a negative error code is returned. ++ */ ++SYSCALL_DEFINE1(sched_get_priority_min, int, policy) ++{ ++ int ret = -EINVAL; ++ ++ switch (policy) { ++ case SCHED_FIFO: ++ case SCHED_RR: ++ ret = 1; ++ break; ++ case SCHED_NORMAL: ++ case SCHED_BATCH: ++ case SCHED_ISO: ++ case SCHED_IDLE: ++ ret = 0; ++ break; ++ } ++ return ret; ++} ++ ++static int sched_rr_get_interval(pid_t pid, struct timespec64 *t) ++{ ++ struct task_struct *p; ++ int retval; ++ ++ if (pid < 0) ++ return -EINVAL; ++ ++ retval = -ESRCH; ++ rcu_read_lock(); ++ p = find_process_by_pid(pid); ++ if (!p) ++ goto out_unlock; ++ ++ retval = security_task_getscheduler(p); ++ if (retval) ++ goto out_unlock; ++ rcu_read_unlock(); ++ ++ *t = ns_to_timespec64(MS_TO_NS(rr_interval)); ++ return 0; ++ ++out_unlock: ++ rcu_read_unlock(); ++ return retval; ++} ++ ++/** ++ * sys_sched_rr_get_interval - return the default timeslice of a process. ++ * @pid: pid of the process. ++ * @interval: userspace pointer to the timeslice value. ++ * ++ * ++ * Return: On success, 0 and the timeslice is in @interval. Otherwise, ++ * an error code. ++ */ ++SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid, ++ struct __kernel_timespec __user *, interval) ++{ ++ struct timespec64 t; ++ int retval = sched_rr_get_interval(pid, &t); ++ ++ if (retval == 0) ++ retval = put_timespec64(&t, interval); ++ ++ return retval; ++} ++ ++#ifdef CONFIG_COMPAT_32BIT_TIME ++SYSCALL_DEFINE2(sched_rr_get_interval_time32, pid_t, pid, ++ struct old_timespec32 __user *, interval) ++{ ++ struct timespec64 t; ++ int retval = sched_rr_get_interval(pid, &t); ++ ++ if (retval == 0) ++ retval = put_old_timespec32(&t, interval); ++ return retval; ++} ++#endif ++ ++void sched_show_task(struct task_struct *p) ++{ ++ unsigned long free = 0; ++ int ppid; ++ ++ if (!try_get_task_stack(p)) ++ return; ++ ++ printk(KERN_INFO "%-15.15s %c", p->comm, task_state_to_char(p)); ++ ++ if (p->state == TASK_RUNNING) ++ printk(KERN_CONT " running task "); ++#ifdef CONFIG_DEBUG_STACK_USAGE ++ free = stack_not_used(p); ++#endif ++ ppid = 0; ++ rcu_read_lock(); ++ if (pid_alive(p)) ++ ppid = task_pid_nr(rcu_dereference(p->real_parent)); ++ rcu_read_unlock(); ++ printk(KERN_CONT "%5lu %5d %6d 0x%08lx\n", free, ++ task_pid_nr(p), ppid, ++ (unsigned long)task_thread_info(p)->flags); ++ ++ print_worker_info(KERN_INFO, p); ++ show_stack(p, NULL); ++ put_task_stack(p); ++} ++EXPORT_SYMBOL_GPL(sched_show_task); ++ ++static inline bool ++state_filter_match(unsigned long state_filter, struct task_struct *p) ++{ ++ /* no filter, everything matches */ ++ if (!state_filter) ++ return true; ++ ++ /* filter, but doesn't match */ ++ if (!(p->state & state_filter)) ++ return false; ++ ++ /* ++ * When looking for TASK_UNINTERRUPTIBLE skip TASK_IDLE (allows ++ * TASK_KILLABLE). ++ */ ++ if (state_filter == TASK_UNINTERRUPTIBLE && p->state == TASK_IDLE) ++ return false; ++ ++ return true; ++} ++ ++ ++void show_state_filter(unsigned long state_filter) ++{ ++ struct task_struct *g, *p; ++ ++#if BITS_PER_LONG == 32 ++ printk(KERN_INFO ++ " task PC stack pid father\n"); ++#else ++ printk(KERN_INFO ++ " task PC stack pid father\n"); ++#endif ++ rcu_read_lock(); ++ for_each_process_thread(g, p) { ++ /* ++ * reset the NMI-timeout, listing all files on a slow ++ * console might take a lot of time: ++ * Also, reset softlockup watchdogs on all CPUs, because ++ * another CPU might be blocked waiting for us to process ++ * an IPI. ++ */ ++ touch_nmi_watchdog(); ++ touch_all_softlockup_watchdogs(); ++ if (state_filter_match(state_filter, p)) ++ sched_show_task(p); ++ } ++ ++#ifdef CONFIG_SCHED_DEBUG ++ /* PDS TODO: should support this ++ if (!state_filter) ++ sysrq_sched_debug_show(); ++ */ ++#endif ++ rcu_read_unlock(); ++ /* ++ * Only show locks if all tasks are dumped: ++ */ ++ if (!state_filter) ++ debug_show_all_locks(); ++} ++ ++void dump_cpu_task(int cpu) ++{ ++ pr_info("Task dump for CPU %d:\n", cpu); ++ sched_show_task(cpu_curr(cpu)); ++} ++ ++/** ++ * init_idle - set up an idle thread for a given CPU ++ * @idle: task in question ++ * @cpu: cpu the idle task belongs to ++ * ++ * NOTE: this function does not set the idle thread's NEED_RESCHED ++ * flag, to make booting more robust. ++ */ ++void init_idle(struct task_struct *idle, int cpu) ++{ ++ struct rq *rq = cpu_rq(cpu); ++ unsigned long flags; ++ ++ raw_spin_lock_irqsave(&idle->pi_lock, flags); ++ raw_spin_lock(&rq->lock); ++ update_rq_clock(rq); ++ ++ idle->last_ran = rq->clock_task; ++ idle->state = TASK_RUNNING; ++ idle->flags |= PF_IDLE; ++ /* Setting prio to illegal value shouldn't matter when never queued */ ++ idle->prio = PRIO_LIMIT; ++ idle->deadline = rq_clock(rq) + task_deadline_diff(idle); ++ update_task_priodl(idle); ++ ++ kasan_unpoison_task_stack(idle); ++ ++#ifdef CONFIG_SMP ++ /* ++ * It's possible that init_idle() gets called multiple times on a task, ++ * in that case do_set_cpus_allowed() will not do the right thing. ++ * ++ * And since this is boot we can forgo the serialisation. ++ */ ++ set_cpus_allowed_common(idle, cpumask_of(cpu)); ++#endif ++ ++ /* Silence PROVE_RCU */ ++ rcu_read_lock(); ++ __set_task_cpu(idle, cpu); ++ rcu_read_unlock(); ++ ++ rq->idle = idle; ++ rcu_assign_pointer(rq->curr, idle); ++ idle->on_cpu = 1; ++ ++ raw_spin_unlock(&rq->lock); ++ raw_spin_unlock_irqrestore(&idle->pi_lock, flags); ++ ++ /* Set the preempt count _outside_ the spinlocks! */ ++ init_idle_preempt_count(idle, cpu); ++ ++ ftrace_graph_init_idle_task(idle, cpu); ++ vtime_init_idle(idle, cpu); ++#ifdef CONFIG_SMP ++ sprintf(idle->comm, "%s/%d", INIT_TASK_COMM, cpu); ++#endif ++} ++ ++void resched_cpu(int cpu) ++{ ++ struct rq *rq = cpu_rq(cpu); ++ unsigned long flags; ++ ++ raw_spin_lock_irqsave(&rq->lock, flags); ++ if (cpu_online(cpu) || cpu == smp_processor_id()) ++ resched_curr(cpu_rq(cpu)); ++ raw_spin_unlock_irqrestore(&rq->lock, flags); ++} ++ ++static bool __wake_q_add(struct wake_q_head *head, struct task_struct *task) ++{ ++ struct wake_q_node *node = &task->wake_q; ++ ++ /* ++ * Atomically grab the task, if ->wake_q is !nil already it means ++ * its already queued (either by us or someone else) and will get the ++ * wakeup due to that. ++ * ++ * In order to ensure that a pending wakeup will observe our pending ++ * state, even in the failed case, an explicit smp_mb() must be used. ++ */ ++ smp_mb__before_atomic(); ++ if (unlikely(cmpxchg_relaxed(&node->next, NULL, WAKE_Q_TAIL))) ++ return false; ++ ++ /* ++ * The head is context local, there can be no concurrency. ++ */ ++ *head->lastp = node; ++ head->lastp = &node->next; ++ return true; ++} ++ ++/** ++ * wake_q_add() - queue a wakeup for 'later' waking. ++ * @head: the wake_q_head to add @task to ++ * @task: the task to queue for 'later' wakeup ++ * ++ * Queue a task for later wakeup, most likely by the wake_up_q() call in the ++ * same context, _HOWEVER_ this is not guaranteed, the wakeup can come ++ * instantly. ++ * ++ * This function must be used as-if it were wake_up_process(); IOW the task ++ * must be ready to be woken at this location. ++ */ ++void wake_q_add(struct wake_q_head *head, struct task_struct *task) ++{ ++ if (__wake_q_add(head, task)) ++ get_task_struct(task); ++} ++ ++/** ++ * wake_q_add_safe() - safely queue a wakeup for 'later' waking. ++ * @head: the wake_q_head to add @task to ++ * @task: the task to queue for 'later' wakeup ++ * ++ * Queue a task for later wakeup, most likely by the wake_up_q() call in the ++ * same context, _HOWEVER_ this is not guaranteed, the wakeup can come ++ * instantly. ++ * ++ * This function must be used as-if it were wake_up_process(); IOW the task ++ * must be ready to be woken at this location. ++ * ++ * This function is essentially a task-safe equivalent to wake_q_add(). Callers ++ * that already hold reference to @task can call the 'safe' version and trust ++ * wake_q to do the right thing depending whether or not the @task is already ++ * queued for wakeup. ++ */ ++void wake_q_add_safe(struct wake_q_head *head, struct task_struct *task) ++{ ++ if (!__wake_q_add(head, task)) ++ put_task_struct(task); ++} ++ ++void wake_up_q(struct wake_q_head *head) ++{ ++ struct wake_q_node *node = head->first; ++ ++ while (node != WAKE_Q_TAIL) { ++ struct task_struct *task; ++ ++ task = container_of(node, struct task_struct, wake_q); ++ BUG_ON(!task); ++ /* task can safely be re-inserted now: */ ++ node = node->next; ++ task->wake_q.next = NULL; ++ ++ /* ++ * wake_up_process() executes a full barrier, which pairs with ++ * the queueing in wake_q_add() so as not to miss wakeups. ++ */ ++ wake_up_process(task); ++ put_task_struct(task); ++ } ++} ++ ++#ifdef CONFIG_SMP ++ ++int cpuset_cpumask_can_shrink(const struct cpumask __maybe_unused *cur, ++ const struct cpumask __maybe_unused *trial) ++{ ++ return 1; ++} ++ ++int task_can_attach(struct task_struct *p, ++ const struct cpumask *cs_cpus_allowed) ++{ ++ int ret = 0; ++ ++ /* ++ * Kthreads which disallow setaffinity shouldn't be moved ++ * to a new cpuset; we don't want to change their CPU ++ * affinity and isolating such threads by their set of ++ * allowed nodes is unnecessary. Thus, cpusets are not ++ * applicable for such threads. This prevents checking for ++ * success of set_cpus_allowed_ptr() on all attached tasks ++ * before cpus_mask may be changed. ++ */ ++ if (p->flags & PF_NO_SETAFFINITY) ++ ret = -EINVAL; ++ ++ return ret; ++} ++ ++static bool sched_smp_initialized __read_mostly; ++ ++#ifdef CONFIG_NO_HZ_COMMON ++void nohz_balance_enter_idle(int cpu) ++{ ++} ++ ++void select_nohz_load_balancer(int stop_tick) ++{ ++} ++ ++void set_cpu_sd_state_idle(void) {} ++ ++/* ++ * In the semi idle case, use the nearest busy CPU for migrating timers ++ * from an idle CPU. This is good for power-savings. ++ * ++ * We don't do similar optimization for completely idle system, as ++ * selecting an idle CPU will add more delays to the timers than intended ++ * (as that CPU's timer base may not be uptodate wrt jiffies etc). ++ */ ++int get_nohz_timer_target(void) ++{ ++ int i, cpu = smp_processor_id(); ++ struct cpumask *mask; ++ ++ if (!idle_cpu(cpu) && housekeeping_cpu(cpu, HK_FLAG_TIMER)) ++ return cpu; ++ ++ for (mask = &(per_cpu(sched_cpu_affinity_chk_masks, cpu)[0]); ++ mask < per_cpu(sched_cpu_affinity_chk_end_masks, cpu); mask++) ++ for_each_cpu(i, mask) ++ if (!idle_cpu(i) && housekeeping_cpu(i, HK_FLAG_TIMER)) ++ return i; ++ ++ if (!housekeeping_cpu(cpu, HK_FLAG_TIMER)) ++ cpu = housekeeping_any_cpu(HK_FLAG_TIMER); ++ ++ return cpu; ++} ++ ++/* ++ * When add_timer_on() enqueues a timer into the timer wheel of an ++ * idle CPU then this timer might expire before the next timer event ++ * which is scheduled to wake up that CPU. In case of a completely ++ * idle system the next event might even be infinite time into the ++ * future. wake_up_idle_cpu() ensures that the CPU is woken up and ++ * leaves the inner idle loop so the newly added timer is taken into ++ * account when the CPU goes back to idle and evaluates the timer ++ * wheel for the next timer event. ++ */ ++void wake_up_idle_cpu(int cpu) ++{ ++ if (cpu == smp_processor_id()) ++ return; ++ ++ set_tsk_need_resched(cpu_rq(cpu)->idle); ++ smp_send_reschedule(cpu); ++} ++ ++void wake_up_nohz_cpu(int cpu) ++{ ++ wake_up_idle_cpu(cpu); ++} ++#endif /* CONFIG_NO_HZ_COMMON */ ++ ++#ifdef CONFIG_HOTPLUG_CPU ++/* ++ * Ensures that the idle task is using init_mm right before its CPU goes ++ * offline. ++ */ ++void idle_task_exit(void) ++{ ++ struct mm_struct *mm = current->active_mm; ++ ++ BUG_ON(cpu_online(smp_processor_id())); ++ ++ if (mm != &init_mm) { ++ switch_mm(mm, &init_mm, current); ++ current->active_mm = &init_mm; ++ finish_arch_post_lock_switch(); ++ } ++ mmdrop(mm); ++} ++ ++/* ++ * Migrate all tasks from the rq, sleeping tasks will be migrated by ++ * try_to_wake_up()->select_task_rq(). ++ * ++ * Called with rq->lock held even though we'er in stop_machine() and ++ * there's no concurrency possible, we hold the required locks anyway ++ * because of lock validation efforts. ++ */ ++static void migrate_tasks(struct rq *dead_rq) ++{ ++ struct rq *rq = dead_rq; ++ struct task_struct *p, *stop = rq->stop; ++ struct skiplist_node *node; ++ int count = 0; ++ ++ /* ++ * Fudge the rq selection such that the below task selection loop ++ * doesn't get stuck on the currently eligible stop task. ++ * ++ * We're currently inside stop_machine() and the rq is either stuck ++ * in the stop_machine_cpu_stop() loop, or we're executing this code, ++ * either way we should never end up calling schedule() until we're ++ * done here. ++ */ ++ rq->stop = NULL; ++ ++ node = &rq->sl_header; ++ while ((node = node->next[0]) != &rq->sl_header) { ++ int dest_cpu; ++ ++ p = skiplist_entry(node, struct task_struct, sl_node); ++ ++ /* skip the running task */ ++ if (task_running(p)) ++ continue; ++ ++ /* ++ * Rules for changing task_struct::cpus_mask are holding ++ * both pi_lock and rq->lock, such that holding either ++ * stabilizes the mask. ++ * ++ * Drop rq->lock is not quite as disastrous as it usually is ++ * because !cpu_active at this point, which means load-balance ++ * will not interfere. Also, stop-machine. ++ */ ++ raw_spin_unlock(&rq->lock); ++ raw_spin_lock(&p->pi_lock); ++ raw_spin_lock(&rq->lock); ++ ++ /* ++ * Since we're inside stop-machine, _nothing_ should have ++ * changed the task, WARN if weird stuff happened, because in ++ * that case the above rq->lock drop is a fail too. ++ */ ++ if (WARN_ON(task_rq(p) != rq || !task_on_rq_queued(p))) { ++ raw_spin_unlock(&p->pi_lock); ++ continue; ++ } ++ ++ count++; ++ /* Find suitable destination for @next, with force if needed. */ ++ dest_cpu = select_fallback_rq(dead_rq->cpu, p); ++ ++ rq = __migrate_task(rq, p, dest_cpu); ++ raw_spin_unlock(&rq->lock); ++ raw_spin_unlock(&p->pi_lock); ++ ++ rq = dead_rq; ++ raw_spin_lock(&rq->lock); ++ /* Check queued task all over from the header again */ ++ node = &rq->sl_header; ++ } ++ ++ rq->stop = stop; ++} ++ ++static void set_rq_offline(struct rq *rq) ++{ ++ if (rq->online) ++ rq->online = false; ++} ++#endif /* CONFIG_HOTPLUG_CPU */ ++ ++static void set_rq_online(struct rq *rq) ++{ ++ if (!rq->online) ++ rq->online = true; ++} ++ ++#ifdef CONFIG_SCHED_DEBUG ++ ++static __read_mostly int sched_debug_enabled; ++ ++static int __init sched_debug_setup(char *str) ++{ ++ sched_debug_enabled = 1; ++ ++ return 0; ++} ++early_param("sched_debug", sched_debug_setup); ++ ++static inline bool sched_debug(void) ++{ ++ return sched_debug_enabled; ++} ++#else /* !CONFIG_SCHED_DEBUG */ ++static inline bool sched_debug(void) ++{ ++ return false; ++} ++#endif /* CONFIG_SCHED_DEBUG */ ++ ++#ifdef CONFIG_SMP ++void scheduler_ipi(void) ++{ ++ /* ++ * Fold TIF_NEED_RESCHED into the preempt_count; anybody setting ++ * TIF_NEED_RESCHED remotely (for the first time) will also send ++ * this IPI. ++ */ ++ preempt_fold_need_resched(); ++ ++ if (!idle_cpu(smp_processor_id()) || need_resched()) ++ return; ++ ++ irq_enter(); ++ irq_exit(); ++} ++ ++void wake_up_if_idle(int cpu) ++{ ++ struct rq *rq = cpu_rq(cpu); ++ unsigned long flags; ++ ++ rcu_read_lock(); ++ ++ if (!is_idle_task(rcu_dereference(rq->curr))) ++ goto out; ++ ++ if (set_nr_if_polling(rq->idle)) { ++ trace_sched_wake_idle_without_ipi(cpu); ++ } else { ++ raw_spin_lock_irqsave(&rq->lock, flags); ++ if (is_idle_task(rq->curr)) ++ smp_send_reschedule(cpu); ++ /* Else CPU is not idle, do nothing here */ ++ raw_spin_unlock_irqrestore(&rq->lock, flags); ++ } ++ ++out: ++ rcu_read_unlock(); ++} ++ ++bool cpus_share_cache(int this_cpu, int that_cpu) ++{ ++ return per_cpu(sd_llc_id, this_cpu) == per_cpu(sd_llc_id, that_cpu); ++} ++#endif /* CONFIG_SMP */ ++ ++/* ++ * Topology list, bottom-up. ++ */ ++static struct sched_domain_topology_level default_topology[] = { ++#ifdef CONFIG_SCHED_SMT ++ { cpu_smt_mask, cpu_smt_flags, SD_INIT_NAME(SMT) }, ++#endif ++#ifdef CONFIG_SCHED_MC ++ { cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) }, ++#endif ++ { cpu_cpu_mask, SD_INIT_NAME(DIE) }, ++ { NULL, }, ++}; ++ ++static struct sched_domain_topology_level *sched_domain_topology = ++ default_topology; ++ ++#define for_each_sd_topology(tl) \ ++ for (tl = sched_domain_topology; tl->mask; tl++) ++ ++void set_sched_topology(struct sched_domain_topology_level *tl) ++{ ++ if (WARN_ON_ONCE(sched_smp_initialized)) ++ return; ++ ++ sched_domain_topology = tl; ++} ++ ++/* ++ * Initializers for schedule domains ++ * Non-inlined to reduce accumulated stack pressure in build_sched_domains() ++ */ ++ ++int sched_domain_level_max; ++ ++/* ++ * Partition sched domains as specified by the 'ndoms_new' ++ * cpumasks in the array doms_new[] of cpumasks. This compares ++ * doms_new[] to the current sched domain partitioning, doms_cur[]. ++ * It destroys each deleted domain and builds each new domain. ++ * ++ * 'doms_new' is an array of cpumask_var_t's of length 'ndoms_new'. ++ * The masks don't intersect (don't overlap.) We should setup one ++ * sched domain for each mask. CPUs not in any of the cpumasks will ++ * not be load balanced. If the same cpumask appears both in the ++ * current 'doms_cur' domains and in the new 'doms_new', we can leave ++ * it as it is. ++ * ++ * The passed in 'doms_new' should be allocated using ++ * alloc_sched_domains. This routine takes ownership of it and will ++ * free_sched_domains it when done with it. If the caller failed the ++ * alloc call, then it can pass in doms_new == NULL && ndoms_new == 1, ++ * and partition_sched_domains() will fallback to the single partition ++ * 'fallback_doms', it also forces the domains to be rebuilt. ++ * ++ * If doms_new == NULL it will be replaced with cpu_online_mask. ++ * ndoms_new == 0 is a special case for destroying existing domains, ++ * and it will not create the default domain. ++ * ++ * Call with hotplug lock held ++ */ ++void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[], ++ struct sched_domain_attr *dattr_new) ++{ ++ /** ++ * PDS doesn't depend on sched domains, but just keep this api ++ */ ++} ++ ++/* ++ * used to mark begin/end of suspend/resume: ++ */ ++static int num_cpus_frozen; ++ ++#ifdef CONFIG_NUMA ++int __read_mostly node_reclaim_distance = RECLAIM_DISTANCE; ++ ++/* ++ * sched_numa_find_closest() - given the NUMA topology, find the cpu ++ * closest to @cpu from @cpumask. ++ * cpumask: cpumask to find a cpu from ++ * cpu: cpu to be close to ++ * ++ * returns: cpu, or nr_cpu_ids when nothing found. ++ */ ++int sched_numa_find_closest(const struct cpumask *cpus, int cpu) ++{ ++ return best_mask_cpu(cpu, cpus); ++} ++#endif /* CONFIG_NUMA */ ++ ++/* ++ * Update cpusets according to cpu_active mask. If cpusets are ++ * disabled, cpuset_update_active_cpus() becomes a simple wrapper ++ * around partition_sched_domains(). ++ * ++ * If we come here as part of a suspend/resume, don't touch cpusets because we ++ * want to restore it back to its original state upon resume anyway. ++ */ ++static void cpuset_cpu_active(void) ++{ ++ if (cpuhp_tasks_frozen) { ++ /* ++ * num_cpus_frozen tracks how many CPUs are involved in suspend ++ * resume sequence. As long as this is not the last online ++ * operation in the resume sequence, just build a single sched ++ * domain, ignoring cpusets. ++ */ ++ partition_sched_domains(1, NULL, NULL); ++ if (--num_cpus_frozen) ++ return; ++ /* ++ * This is the last CPU online operation. So fall through and ++ * restore the original sched domains by considering the ++ * cpuset configurations. ++ */ ++ cpuset_force_rebuild(); ++ } ++ ++ cpuset_update_active_cpus(); ++} ++ ++static int cpuset_cpu_inactive(unsigned int cpu) ++{ ++ if (!cpuhp_tasks_frozen) { ++ cpuset_update_active_cpus(); ++ } else { ++ num_cpus_frozen++; ++ partition_sched_domains(1, NULL, NULL); ++ } ++ return 0; ++} ++ ++int sched_cpu_activate(unsigned int cpu) ++{ ++ struct rq *rq = cpu_rq(cpu); ++ unsigned long flags; ++ ++#ifdef CONFIG_SCHED_SMT ++ /* ++ * When going up, increment the number of cores with SMT present. ++ */ ++ if (cpumask_weight(cpu_smt_mask(cpu)) == 2) ++ static_branch_inc_cpuslocked(&sched_smt_present); ++#endif ++ set_cpu_active(cpu, true); ++ ++ if (sched_smp_initialized) ++ cpuset_cpu_active(); ++ ++ /* ++ * Put the rq online, if not already. This happens: ++ * ++ * 1) In the early boot process, because we build the real domains ++ * after all cpus have been brought up. ++ * ++ * 2) At runtime, if cpuset_cpu_active() fails to rebuild the ++ * domains. ++ */ ++ raw_spin_lock_irqsave(&rq->lock, flags); ++ set_rq_online(rq); ++ raw_spin_unlock_irqrestore(&rq->lock, flags); ++ ++ return 0; ++} ++ ++int sched_cpu_deactivate(unsigned int cpu) ++{ ++ int ret; ++ ++ set_cpu_active(cpu, false); ++ /* ++ * We've cleared cpu_active_mask, wait for all preempt-disabled and RCU ++ * users of this state to go away such that all new such users will ++ * observe it. ++ * ++ * Do sync before park smpboot threads to take care the rcu boost case. ++ */ ++ synchronize_rcu(); ++ ++#ifdef CONFIG_SCHED_SMT ++ /* ++ * When going down, decrement the number of cores with SMT present. ++ */ ++ if (cpumask_weight(cpu_smt_mask(cpu)) == 2) ++ static_branch_dec_cpuslocked(&sched_smt_present); ++#endif ++ ++ if (!sched_smp_initialized) ++ return 0; ++ ++ ret = cpuset_cpu_inactive(cpu); ++ if (ret) { ++ set_cpu_active(cpu, true); ++ return ret; ++ } ++ return 0; ++} ++ ++static void sched_rq_cpu_starting(unsigned int cpu) ++{ ++ struct rq *rq = cpu_rq(cpu); ++ ++ rq->calc_load_update = calc_load_update; ++} ++ ++int sched_cpu_starting(unsigned int cpu) ++{ ++ sched_rq_cpu_starting(cpu); ++ sched_tick_start(cpu); ++ return 0; ++} ++ ++#ifdef CONFIG_HOTPLUG_CPU ++int sched_cpu_dying(unsigned int cpu) ++{ ++ struct rq *rq = cpu_rq(cpu); ++ unsigned long flags; ++ ++ sched_tick_stop(cpu); ++ raw_spin_lock_irqsave(&rq->lock, flags); ++ set_rq_offline(rq); ++ migrate_tasks(rq); ++ raw_spin_unlock_irqrestore(&rq->lock, flags); ++ ++ hrtick_clear(rq); ++ return 0; ++} ++#endif ++ ++#ifdef CONFIG_SMP ++static void sched_init_topology_cpumask_early(void) ++{ ++ int cpu, level; ++ cpumask_t *tmp; ++ ++ for_each_possible_cpu(cpu) { ++ for (level = 0; level < NR_CPU_AFFINITY_CHK_LEVEL; level++) { ++ tmp = &(per_cpu(sched_cpu_affinity_chk_masks, cpu)[level]); ++ cpumask_copy(tmp, cpu_possible_mask); ++ cpumask_clear_cpu(cpu, tmp); ++ } ++ per_cpu(sched_cpu_llc_start_mask, cpu) = ++ &(per_cpu(sched_cpu_affinity_chk_masks, cpu)[0]); ++ per_cpu(sched_cpu_affinity_chk_end_masks, cpu) = ++ &(per_cpu(sched_cpu_affinity_chk_masks, cpu)[1]); ++ } ++} ++ ++static void sched_init_topology_cpumask(void) ++{ ++ int cpu; ++ cpumask_t *chk; ++ ++ for_each_online_cpu(cpu) { ++ chk = &(per_cpu(sched_cpu_affinity_chk_masks, cpu)[0]); ++ ++#ifdef CONFIG_SCHED_SMT ++ cpumask_setall(chk); ++ cpumask_clear_cpu(cpu, chk); ++ if (cpumask_and(chk, chk, topology_sibling_cpumask(cpu))) { ++ per_cpu(sched_sibling_cpu, cpu) = cpumask_first(chk); ++ printk(KERN_INFO "pds: cpu #%d affinity check mask - smt 0x%08lx", ++ cpu, (chk++)->bits[0]); ++ } ++#endif ++#ifdef CONFIG_SCHED_MC ++ cpumask_setall(chk); ++ cpumask_clear_cpu(cpu, chk); ++ if (cpumask_and(chk, chk, cpu_coregroup_mask(cpu))) { ++ per_cpu(sched_cpu_llc_start_mask, cpu) = chk; ++ printk(KERN_INFO "pds: cpu #%d affinity check mask - coregroup 0x%08lx", ++ cpu, (chk++)->bits[0]); ++ } ++ cpumask_complement(chk, cpu_coregroup_mask(cpu)); ++ ++ /** ++ * Set up sd_llc_id per CPU ++ */ ++ per_cpu(sd_llc_id, cpu) = ++ cpumask_first(cpu_coregroup_mask(cpu)); ++#else ++ per_cpu(sd_llc_id, cpu) = ++ cpumask_first(topology_core_cpumask(cpu)); ++ ++ per_cpu(sched_cpu_llc_start_mask, cpu) = chk; ++ ++ cpumask_setall(chk); ++ cpumask_clear_cpu(cpu, chk); ++#endif /* NOT CONFIG_SCHED_MC */ ++ if (cpumask_and(chk, chk, topology_core_cpumask(cpu))) ++ printk(KERN_INFO "pds: cpu #%d affinity check mask - core 0x%08lx", ++ cpu, (chk++)->bits[0]); ++ cpumask_complement(chk, topology_core_cpumask(cpu)); ++ ++ if (cpumask_and(chk, chk, cpu_online_mask)) ++ printk(KERN_INFO "pds: cpu #%d affinity check mask - others 0x%08lx", ++ cpu, (chk++)->bits[0]); ++ ++ per_cpu(sched_cpu_affinity_chk_end_masks, cpu) = chk; ++ } ++} ++#endif ++ ++void __init sched_init_smp(void) ++{ ++ /* Move init over to a non-isolated CPU */ ++ if (set_cpus_allowed_ptr(current, housekeeping_cpumask(HK_FLAG_DOMAIN)) < 0) ++ BUG(); ++ ++ cpumask_copy(&sched_rq_queued_masks[SCHED_RQ_EMPTY], cpu_online_mask); ++ ++ sched_init_topology_cpumask(); ++ ++ sched_smp_initialized = true; ++} ++#else ++void __init sched_init_smp(void) ++{ ++} ++#endif /* CONFIG_SMP */ ++ ++int in_sched_functions(unsigned long addr) ++{ ++ return in_lock_functions(addr) || ++ (addr >= (unsigned long)__sched_text_start ++ && addr < (unsigned long)__sched_text_end); ++} ++ ++#ifdef CONFIG_CGROUP_SCHED ++/* task group related information */ ++struct task_group { ++ struct cgroup_subsys_state css; ++ ++ struct rcu_head rcu; ++ struct list_head list; ++ ++ struct task_group *parent; ++ struct list_head siblings; ++ struct list_head children; ++}; ++ ++/* ++ * Default task group. ++ * Every task in system belongs to this group at bootup. ++ */ ++struct task_group root_task_group; ++LIST_HEAD(task_groups); ++ ++/* Cacheline aligned slab cache for task_group */ ++static struct kmem_cache *task_group_cache __read_mostly; ++#endif /* CONFIG_CGROUP_SCHED */ ++ ++void __init sched_init(void) ++{ ++ int i; ++ struct rq *rq; ++ ++ print_scheduler_version(); ++ ++ wait_bit_init(); ++ ++#ifdef CONFIG_SMP ++ for (i = 0; i < NR_SCHED_RQ_QUEUED_LEVEL; i++) ++ cpumask_clear(&sched_rq_queued_masks[i]); ++ cpumask_setall(&sched_rq_queued_masks[SCHED_RQ_EMPTY]); ++ set_bit(SCHED_RQ_EMPTY, sched_rq_queued_masks_bitmap); ++ ++ cpumask_setall(&sched_rq_pending_masks[SCHED_RQ_EMPTY]); ++ set_bit(SCHED_RQ_EMPTY, sched_rq_pending_masks_bitmap); ++#else ++ uprq = &per_cpu(runqueues, 0); ++#endif ++ ++#ifdef CONFIG_CGROUP_SCHED ++ task_group_cache = KMEM_CACHE(task_group, 0); ++ ++ list_add(&root_task_group.list, &task_groups); ++ INIT_LIST_HEAD(&root_task_group.children); ++ INIT_LIST_HEAD(&root_task_group.siblings); ++#endif /* CONFIG_CGROUP_SCHED */ ++ for_each_possible_cpu(i) { ++ rq = cpu_rq(i); ++ FULL_INIT_SKIPLIST_NODE(&rq->sl_header); ++ raw_spin_lock_init(&rq->lock); ++ rq->dither = 0; ++ rq->nr_running = rq->nr_uninterruptible = 0; ++ rq->calc_load_active = 0; ++ rq->calc_load_update = jiffies + LOAD_FREQ; ++#ifdef CONFIG_SMP ++ rq->online = false; ++ rq->cpu = i; ++ ++ rq->queued_level = SCHED_RQ_EMPTY; ++ rq->pending_level = SCHED_RQ_EMPTY; ++#ifdef CONFIG_SCHED_SMT ++ per_cpu(sched_sibling_cpu, i) = i; ++ rq->active_balance = 0; ++#endif ++#endif ++ rq->nr_switches = 0; ++ atomic_set(&rq->nr_iowait, 0); ++ hrtick_rq_init(rq); ++ } ++#ifdef CONFIG_SMP ++ /* Set rq->online for cpu 0 */ ++ cpu_rq(0)->online = true; ++#endif ++ ++ /* ++ * The boot idle thread does lazy MMU switching as well: ++ */ ++ mmgrab(&init_mm); ++ enter_lazy_tlb(&init_mm, current); ++ ++ /* ++ * Make us the idle thread. Technically, schedule() should not be ++ * called from this thread, however somewhere below it might be, ++ * but because we are the idle thread, we just pick up running again ++ * when this runqueue becomes "idle". ++ */ ++ init_idle(current, smp_processor_id()); ++ ++ calc_load_update = jiffies + LOAD_FREQ; ++ ++#ifdef CONFIG_SMP ++ idle_thread_set_boot_cpu(); ++ ++ sched_init_topology_cpumask_early(); ++#endif /* SMP */ ++ ++ init_schedstats(); ++ ++ psi_init(); ++} ++ ++#ifdef CONFIG_DEBUG_ATOMIC_SLEEP ++static inline int preempt_count_equals(int preempt_offset) ++{ ++ int nested = preempt_count() + rcu_preempt_depth(); ++ ++ return (nested == preempt_offset); ++} ++ ++void __might_sleep(const char *file, int line, int preempt_offset) ++{ ++ /* ++ * Blocking primitives will set (and therefore destroy) current->state, ++ * since we will exit with TASK_RUNNING make sure we enter with it, ++ * otherwise we will destroy state. ++ */ ++ WARN_ONCE(current->state != TASK_RUNNING && current->task_state_change, ++ "do not call blocking ops when !TASK_RUNNING; " ++ "state=%lx set at [<%p>] %pS\n", ++ current->state, ++ (void *)current->task_state_change, ++ (void *)current->task_state_change); ++ ++ ___might_sleep(file, line, preempt_offset); ++} ++EXPORT_SYMBOL(__might_sleep); ++ ++void ___might_sleep(const char *file, int line, int preempt_offset) ++{ ++ /* Ratelimiting timestamp: */ ++ static unsigned long prev_jiffy; ++ ++ unsigned long preempt_disable_ip; ++ ++ /* WARN_ON_ONCE() by default, no rate limit required: */ ++ rcu_sleep_check(); ++ ++ if ((preempt_count_equals(preempt_offset) && !irqs_disabled() && ++ !is_idle_task(current) && !current->non_block_count) || ++ system_state == SYSTEM_BOOTING || system_state > SYSTEM_RUNNING || ++ oops_in_progress) ++ return; ++ if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy) ++ return; ++ prev_jiffy = jiffies; ++ ++ /* Save this before calling printk(), since that will clobber it: */ ++ preempt_disable_ip = get_preempt_disable_ip(current); ++ ++ printk(KERN_ERR ++ "BUG: sleeping function called from invalid context at %s:%d\n", ++ file, line); ++ printk(KERN_ERR ++ "in_atomic(): %d, irqs_disabled(): %d, non_block: %d, pid: %d, name: %s\n", ++ in_atomic(), irqs_disabled(), current->non_block_count, ++ current->pid, current->comm); ++ ++ if (task_stack_end_corrupted(current)) ++ printk(KERN_EMERG "Thread overran stack, or stack corrupted\n"); ++ ++ debug_show_held_locks(current); ++ if (irqs_disabled()) ++ print_irqtrace_events(current); ++#ifdef CONFIG_DEBUG_PREEMPT ++ if (!preempt_count_equals(preempt_offset)) { ++ pr_err("Preemption disabled at:"); ++ print_ip_sym(preempt_disable_ip); ++ pr_cont("\n"); ++ } ++#endif ++ dump_stack(); ++ add_taint(TAINT_WARN, LOCKDEP_STILL_OK); ++} ++EXPORT_SYMBOL(___might_sleep); ++ ++void __cant_sleep(const char *file, int line, int preempt_offset) ++{ ++ static unsigned long prev_jiffy; ++ ++ if (irqs_disabled()) ++ return; ++ ++ if (!IS_ENABLED(CONFIG_PREEMPT_COUNT)) ++ return; ++ ++ if (preempt_count() > preempt_offset) ++ return; ++ ++ if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy) ++ return; ++ prev_jiffy = jiffies; ++ ++ printk(KERN_ERR "BUG: assuming atomic context at %s:%d\n", file, line); ++ printk(KERN_ERR "in_atomic(): %d, irqs_disabled(): %d, pid: %d, name: %s\n", ++ in_atomic(), irqs_disabled(), ++ current->pid, current->comm); ++ ++ debug_show_held_locks(current); ++ dump_stack(); ++ add_taint(TAINT_WARN, LOCKDEP_STILL_OK); ++} ++EXPORT_SYMBOL_GPL(__cant_sleep); ++#endif ++ ++#ifdef CONFIG_MAGIC_SYSRQ ++void normalize_rt_tasks(void) ++{ ++ struct task_struct *g, *p; ++ struct sched_attr attr = { ++ .sched_policy = SCHED_NORMAL, ++ }; ++ ++ read_lock(&tasklist_lock); ++ for_each_process_thread(g, p) { ++ /* ++ * Only normalize user tasks: ++ */ ++ if (p->flags & PF_KTHREAD) ++ continue; ++ ++ if (!rt_task(p)) { ++ /* ++ * Renice negative nice level userspace ++ * tasks back to 0: ++ */ ++ if (task_nice(p) < 0) ++ set_user_nice(p, 0); ++ continue; ++ } ++ ++ __sched_setscheduler(p, &attr, false, false); ++ } ++ read_unlock(&tasklist_lock); ++} ++#endif /* CONFIG_MAGIC_SYSRQ */ ++ ++#if defined(CONFIG_IA64) || defined(CONFIG_KGDB_KDB) ++/* ++ * These functions are only useful for the IA64 MCA handling, or kdb. ++ * ++ * They can only be called when the whole system has been ++ * stopped - every CPU needs to be quiescent, and no scheduling ++ * activity can take place. Using them for anything else would ++ * be a serious bug, and as a result, they aren't even visible ++ * under any other configuration. ++ */ ++ ++/** ++ * curr_task - return the current task for a given CPU. ++ * @cpu: the processor in question. ++ * ++ * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED! ++ * ++ * Return: The current task for @cpu. ++ */ ++struct task_struct *curr_task(int cpu) ++{ ++ return cpu_curr(cpu); ++} ++ ++#endif /* defined(CONFIG_IA64) || defined(CONFIG_KGDB_KDB) */ ++ ++#ifdef CONFIG_IA64 ++/** ++ * ia64_set_curr_task - set the current task for a given CPU. ++ * @cpu: the processor in question. ++ * @p: the task pointer to set. ++ * ++ * Description: This function must only be used when non-maskable interrupts ++ * are serviced on a separate stack. It allows the architecture to switch the ++ * notion of the current task on a CPU in a non-blocking manner. This function ++ * must be called with all CPU's synchronised, and interrupts disabled, the ++ * and caller must save the original value of the current task (see ++ * curr_task() above) and restore that value before reenabling interrupts and ++ * re-starting the system. ++ * ++ * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED! ++ */ ++void ia64_set_curr_task(int cpu, struct task_struct *p) ++{ ++ cpu_curr(cpu) = p; ++} ++ ++#endif ++ ++#ifdef CONFIG_SCHED_DEBUG ++void proc_sched_show_task(struct task_struct *p, struct pid_namespace *ns, ++ struct seq_file *m) ++{} ++ ++void proc_sched_set_task(struct task_struct *p) ++{} ++#endif ++ ++#ifdef CONFIG_CGROUP_SCHED ++static void sched_free_group(struct task_group *tg) ++{ ++ kmem_cache_free(task_group_cache, tg); ++} ++ ++/* allocate runqueue etc for a new task group */ ++struct task_group *sched_create_group(struct task_group *parent) ++{ ++ struct task_group *tg; ++ ++ tg = kmem_cache_alloc(task_group_cache, GFP_KERNEL | __GFP_ZERO); ++ if (!tg) ++ return ERR_PTR(-ENOMEM); ++ ++ return tg; ++} ++ ++void sched_online_group(struct task_group *tg, struct task_group *parent) ++{ ++} ++ ++/* rcu callback to free various structures associated with a task group */ ++static void sched_free_group_rcu(struct rcu_head *rhp) ++{ ++ /* Now it should be safe to free those cfs_rqs */ ++ sched_free_group(container_of(rhp, struct task_group, rcu)); ++} ++ ++void sched_destroy_group(struct task_group *tg) ++{ ++ /* Wait for possible concurrent references to cfs_rqs complete */ ++ call_rcu(&tg->rcu, sched_free_group_rcu); ++} ++ ++void sched_offline_group(struct task_group *tg) ++{ ++} ++ ++static inline struct task_group *css_tg(struct cgroup_subsys_state *css) ++{ ++ return css ? container_of(css, struct task_group, css) : NULL; ++} ++ ++static struct cgroup_subsys_state * ++cpu_cgroup_css_alloc(struct cgroup_subsys_state *parent_css) ++{ ++ struct task_group *parent = css_tg(parent_css); ++ struct task_group *tg; ++ ++ if (!parent) { ++ /* This is early initialization for the top cgroup */ ++ return &root_task_group.css; ++ } ++ ++ tg = sched_create_group(parent); ++ if (IS_ERR(tg)) ++ return ERR_PTR(-ENOMEM); ++ return &tg->css; ++} ++ ++/* Expose task group only after completing cgroup initialization */ ++static int cpu_cgroup_css_online(struct cgroup_subsys_state *css) ++{ ++ struct task_group *tg = css_tg(css); ++ struct task_group *parent = css_tg(css->parent); ++ ++ if (parent) ++ sched_online_group(tg, parent); ++ return 0; ++} ++ ++static void cpu_cgroup_css_released(struct cgroup_subsys_state *css) ++{ ++ struct task_group *tg = css_tg(css); ++ ++ sched_offline_group(tg); ++} ++ ++static void cpu_cgroup_css_free(struct cgroup_subsys_state *css) ++{ ++ struct task_group *tg = css_tg(css); ++ ++ /* ++ * Relies on the RCU grace period between css_released() and this. ++ */ ++ sched_free_group(tg); ++} ++ ++static void cpu_cgroup_fork(struct task_struct *task) ++{ ++} ++ ++static int cpu_cgroup_can_attach(struct cgroup_taskset *tset) ++{ ++ return 0; ++} ++ ++static void cpu_cgroup_attach(struct cgroup_taskset *tset) ++{ ++} ++ ++static struct cftype cpu_legacy_files[] = { ++ { } /* Terminate */ ++}; ++ ++static struct cftype cpu_files[] = { ++ { } /* terminate */ ++}; ++ ++static int cpu_extra_stat_show(struct seq_file *sf, ++ struct cgroup_subsys_state *css) ++{ ++ return 0; ++} ++ ++struct cgroup_subsys cpu_cgrp_subsys = { ++ .css_alloc = cpu_cgroup_css_alloc, ++ .css_online = cpu_cgroup_css_online, ++ .css_released = cpu_cgroup_css_released, ++ .css_free = cpu_cgroup_css_free, ++ .css_extra_stat_show = cpu_extra_stat_show, ++ .fork = cpu_cgroup_fork, ++ .can_attach = cpu_cgroup_can_attach, ++ .attach = cpu_cgroup_attach, ++ .legacy_cftypes = cpu_files, ++ .legacy_cftypes = cpu_legacy_files, ++ .dfl_cftypes = cpu_files, ++ .early_init = true, ++ .threaded = true, ++}; ++#endif /* CONFIG_CGROUP_SCHED */ ++ ++#undef CREATE_TRACE_POINTS +--- /dev/null ++++ b/kernel/sched/pds_sched.h +@@ -0,0 +1,475 @@ ++#ifndef PDS_SCHED_H ++#define PDS_SCHED_H ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#ifdef CONFIG_PARAVIRT ++# include ++#endif ++ ++#include "cpupri.h" ++ ++/* task_struct::on_rq states: */ ++#define TASK_ON_RQ_QUEUED 1 ++#define TASK_ON_RQ_MIGRATING 2 ++ ++static inline int task_on_rq_queued(struct task_struct *p) ++{ ++ return p->on_rq == TASK_ON_RQ_QUEUED; ++} ++ ++static inline int task_on_rq_migrating(struct task_struct *p) ++{ ++ return READ_ONCE(p->on_rq) == TASK_ON_RQ_MIGRATING; ++} ++ ++/* ++ * This is the main, per-CPU runqueue data structure. ++ * This data should only be modified by the local cpu. ++ */ ++struct rq { ++ /* runqueue lock: */ ++ raw_spinlock_t lock; ++ ++ struct task_struct *curr, *idle, *stop; ++ struct mm_struct *prev_mm; ++ ++ struct skiplist_node sl_header; ++ ++ /* switch count */ ++ u64 nr_switches; ++ ++ atomic_t nr_iowait; ++ ++#ifdef CONFIG_MEMBARRIER ++ int membarrier_state; ++#endif ++ ++#ifdef CONFIG_SMP ++ int cpu; /* cpu of this runqueue */ ++ bool online; ++ ++#ifdef CONFIG_HAVE_SCHED_AVG_IRQ ++ struct sched_avg avg_irq; ++#endif ++ ++ unsigned long queued_level; ++ unsigned long pending_level; ++ ++#ifdef CONFIG_SCHED_SMT ++ int active_balance; ++ struct cpu_stop_work active_balance_work; ++#endif ++#endif /* CONFIG_SMP */ ++#ifdef CONFIG_IRQ_TIME_ACCOUNTING ++ u64 prev_irq_time; ++#endif /* CONFIG_IRQ_TIME_ACCOUNTING */ ++#ifdef CONFIG_PARAVIRT ++ u64 prev_steal_time; ++#endif /* CONFIG_PARAVIRT */ ++#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING ++ u64 prev_steal_time_rq; ++#endif /* CONFIG_PARAVIRT_TIME_ACCOUNTING */ ++ ++ /* calc_load related fields */ ++ unsigned long calc_load_update; ++ long calc_load_active; ++ ++ u64 clock, last_tick; ++ u64 clock_task; ++ int dither; ++ ++ unsigned long nr_running; ++ unsigned long nr_uninterruptible; ++ ++#ifdef CONFIG_SCHED_HRTICK ++#ifdef CONFIG_SMP ++ int hrtick_csd_pending; ++ call_single_data_t hrtick_csd; ++#endif ++ struct hrtimer hrtick_timer; ++#endif ++ ++#ifdef CONFIG_SCHEDSTATS ++ ++ /* latency stats */ ++ struct sched_info rq_sched_info; ++ unsigned long long rq_cpu_time; ++ /* could above be rq->cfs_rq.exec_clock + rq->rt_rq.rt_runtime ? */ ++ ++ /* sys_sched_yield() stats */ ++ unsigned int yld_count; ++ ++ /* schedule() stats */ ++ unsigned int sched_switch; ++ unsigned int sched_count; ++ unsigned int sched_goidle; ++ ++ /* try_to_wake_up() stats */ ++ unsigned int ttwu_count; ++ unsigned int ttwu_local; ++#endif /* CONFIG_SCHEDSTATS */ ++#ifdef CONFIG_CPU_IDLE ++ /* Must be inspected within a rcu lock section */ ++ struct cpuidle_state *idle_state; ++#endif ++}; ++ ++extern unsigned long calc_load_update; ++extern atomic_long_t calc_load_tasks; ++ ++extern void calc_global_load_tick(struct rq *this_rq); ++extern long calc_load_fold_active(struct rq *this_rq, long adjust); ++ ++#ifndef CONFIG_SMP ++extern struct rq *uprq; ++#define cpu_rq(cpu) (uprq) ++#define this_rq() (uprq) ++#define raw_rq() (uprq) ++#define task_rq(p) (uprq) ++#define cpu_curr(cpu) ((uprq)->curr) ++#else /* CONFIG_SMP */ ++DECLARE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues); ++#define cpu_rq(cpu) (&per_cpu(runqueues, (cpu))) ++#define this_rq() this_cpu_ptr(&runqueues) ++#define raw_rq() raw_cpu_ptr(&runqueues) ++#define task_rq(p) cpu_rq(task_cpu(p)) ++#define cpu_curr(cpu) (cpu_rq(cpu)->curr) ++ ++#if defined(CONFIG_SCHED_DEBUG) && defined(CONFIG_SYSCTL) ++void register_sched_domain_sysctl(void); ++void unregister_sched_domain_sysctl(void); ++#else ++static inline void register_sched_domain_sysctl(void) ++{ ++} ++static inline void unregister_sched_domain_sysctl(void) ++{ ++} ++#endif ++ ++#endif /* CONFIG_SMP */ ++ ++#ifndef arch_scale_freq_capacity ++static __always_inline ++unsigned long arch_scale_freq_capacity(int cpu) ++{ ++ return SCHED_CAPACITY_SCALE; ++} ++#endif ++ ++static inline u64 __rq_clock_broken(struct rq *rq) ++{ ++ return READ_ONCE(rq->clock); ++} ++ ++static inline u64 rq_clock(struct rq *rq) ++{ ++ /* ++ * Relax lockdep_assert_held() checking as in VRQ, call to ++ * sched_info_xxxx() may not held rq->lock ++ * lockdep_assert_held(&rq->lock); ++ */ ++ return rq->clock; ++} ++ ++static inline u64 rq_clock_task(struct rq *rq) ++{ ++ /* ++ * Relax lockdep_assert_held() checking as in VRQ, call to ++ * sched_info_xxxx() may not held rq->lock ++ * lockdep_assert_held(&rq->lock); ++ */ ++ return rq->clock_task; ++} ++ ++/* ++ * {de,en}queue flags: ++ * ++ * DEQUEUE_SLEEP - task is no longer runnable ++ * ENQUEUE_WAKEUP - task just became runnable ++ * ++ */ ++ ++#define DEQUEUE_SLEEP 0x01 ++ ++#define ENQUEUE_WAKEUP 0x01 ++ ++ ++/* ++ * Below are scheduler API which using in other kernel code ++ * It use the dummy rq_flags ++ * ToDo : PDS need to support these APIs for compatibility with mainline ++ * scheduler code. ++ */ ++struct rq_flags { ++ unsigned long flags; ++}; ++ ++struct rq *__task_rq_lock(struct task_struct *p, struct rq_flags *rf) ++ __acquires(rq->lock); ++ ++struct rq *task_rq_lock(struct task_struct *p, struct rq_flags *rf) ++ __acquires(p->pi_lock) ++ __acquires(rq->lock); ++ ++static inline void __task_rq_unlock(struct rq *rq, struct rq_flags *rf) ++ __releases(rq->lock) ++{ ++ raw_spin_unlock(&rq->lock); ++} ++ ++static inline void ++task_rq_unlock(struct rq *rq, struct task_struct *p, struct rq_flags *rf) ++ __releases(rq->lock) ++ __releases(p->pi_lock) ++{ ++ raw_spin_unlock(&rq->lock); ++ raw_spin_unlock_irqrestore(&p->pi_lock, rf->flags); ++} ++ ++static inline void ++rq_unlock_irq(struct rq *rq, struct rq_flags *rf) ++ __releases(rq->lock) ++{ ++ raw_spin_unlock_irq(&rq->lock); ++} ++ ++static inline struct rq * ++this_rq_lock_irq(struct rq_flags *rf) ++ __acquires(rq->lock) ++{ ++ struct rq *rq; ++ ++ local_irq_disable(); ++ rq = this_rq(); ++ raw_spin_lock(&rq->lock); ++ ++ return rq; ++} ++ ++static inline bool task_running(struct task_struct *p) ++{ ++ return p->on_cpu; ++} ++ ++extern struct static_key_false sched_schedstats; ++ ++static inline void sched_ttwu_pending(void) { } ++ ++#ifdef CONFIG_CPU_IDLE ++static inline void idle_set_state(struct rq *rq, ++ struct cpuidle_state *idle_state) ++{ ++ rq->idle_state = idle_state; ++} ++ ++static inline struct cpuidle_state *idle_get_state(struct rq *rq) ++{ ++ WARN_ON(!rcu_read_lock_held()); ++ return rq->idle_state; ++} ++#else ++static inline void idle_set_state(struct rq *rq, ++ struct cpuidle_state *idle_state) ++{ ++} ++ ++static inline struct cpuidle_state *idle_get_state(struct rq *rq) ++{ ++ return NULL; ++} ++#endif ++ ++static inline int cpu_of(const struct rq *rq) ++{ ++#ifdef CONFIG_SMP ++ return rq->cpu; ++#else ++ return 0; ++#endif ++} ++ ++#include "stats.h" ++ ++#ifdef CONFIG_IRQ_TIME_ACCOUNTING ++struct irqtime { ++ u64 total; ++ u64 tick_delta; ++ u64 irq_start_time; ++ struct u64_stats_sync sync; ++}; ++ ++DECLARE_PER_CPU(struct irqtime, cpu_irqtime); ++ ++/* ++ * Returns the irqtime minus the softirq time computed by ksoftirqd. ++ * Otherwise ksoftirqd's sum_exec_runtime is substracted its own runtime ++ * and never move forward. ++ */ ++static inline u64 irq_time_read(int cpu) ++{ ++ struct irqtime *irqtime = &per_cpu(cpu_irqtime, cpu); ++ unsigned int seq; ++ u64 total; ++ ++ do { ++ seq = __u64_stats_fetch_begin(&irqtime->sync); ++ total = irqtime->total; ++ } while (__u64_stats_fetch_retry(&irqtime->sync, seq)); ++ ++ return total; ++} ++#endif /* CONFIG_IRQ_TIME_ACCOUNTING */ ++ ++#ifdef CONFIG_CPU_FREQ ++DECLARE_PER_CPU(struct update_util_data __rcu *, cpufreq_update_util_data); ++ ++/** ++ * cpufreq_update_util - Take a note about CPU utilization changes. ++ * @rq: Runqueue to carry out the update for. ++ * @flags: Update reason flags. ++ * ++ * This function is called by the scheduler on the CPU whose utilization is ++ * being updated. ++ * ++ * It can only be called from RCU-sched read-side critical sections. ++ * ++ * The way cpufreq is currently arranged requires it to evaluate the CPU ++ * performance state (frequency/voltage) on a regular basis to prevent it from ++ * being stuck in a completely inadequate performance level for too long. ++ * That is not guaranteed to happen if the updates are only triggered from CFS ++ * and DL, though, because they may not be coming in if only RT tasks are ++ * active all the time (or there are RT tasks only). ++ * ++ * As a workaround for that issue, this function is called periodically by the ++ * RT sched class to trigger extra cpufreq updates to prevent it from stalling, ++ * but that really is a band-aid. Going forward it should be replaced with ++ * solutions targeted more specifically at RT tasks. ++ */ ++static inline void cpufreq_update_util(struct rq *rq, unsigned int flags) ++{ ++ struct update_util_data *data; ++ ++ data = rcu_dereference_sched(*per_cpu_ptr(&cpufreq_update_util_data, ++ cpu_of(rq))); ++ if (data) ++ data->func(data, rq_clock(rq), flags); ++} ++ ++static inline void cpufreq_update_this_cpu(struct rq *rq, unsigned int flags) ++{ ++ if (cpu_of(rq) == smp_processor_id()) ++ cpufreq_update_util(rq, flags); ++} ++#else ++static inline void cpufreq_update_util(struct rq *rq, unsigned int flags) {} ++static inline void cpufreq_update_this_cpu(struct rq *rq, unsigned int flags) {} ++#endif /* CONFIG_CPU_FREQ */ ++ ++#ifdef CONFIG_NO_HZ_FULL ++extern int __init sched_tick_offload_init(void); ++#else ++static inline int sched_tick_offload_init(void) { return 0; } ++#endif ++ ++#ifdef arch_scale_freq_capacity ++#ifndef arch_scale_freq_invariant ++#define arch_scale_freq_invariant() (true) ++#endif ++#else /* arch_scale_freq_capacity */ ++#define arch_scale_freq_invariant() (false) ++#endif ++ ++extern void schedule_idle(void); ++ ++/* ++ * !! For sched_setattr_nocheck() (kernel) only !! ++ * ++ * This is actually gross. :( ++ * ++ * It is used to make schedutil kworker(s) higher priority than SCHED_DEADLINE ++ * tasks, but still be able to sleep. We need this on platforms that cannot ++ * atomically change clock frequency. Remove once fast switching will be ++ * available on such platforms. ++ * ++ * SUGOV stands for SchedUtil GOVernor. ++ */ ++#define SCHED_FLAG_SUGOV 0x10000000 ++ ++#ifdef CONFIG_MEMBARRIER ++/* ++ * The scheduler provides memory barriers required by membarrier between: ++ * - prior user-space memory accesses and store to rq->membarrier_state, ++ * - store to rq->membarrier_state and following user-space memory accesses. ++ * In the same way it provides those guarantees around store to rq->curr. ++ */ ++static inline void membarrier_switch_mm(struct rq *rq, ++ struct mm_struct *prev_mm, ++ struct mm_struct *next_mm) ++{ ++ int membarrier_state; ++ ++ if (prev_mm == next_mm) ++ return; ++ ++ membarrier_state = atomic_read(&next_mm->membarrier_state); ++ if (READ_ONCE(rq->membarrier_state) == membarrier_state) ++ return; ++ ++ WRITE_ONCE(rq->membarrier_state, membarrier_state); ++} ++#else ++static inline void membarrier_switch_mm(struct rq *rq, ++ struct mm_struct *prev_mm, ++ struct mm_struct *next_mm) ++{ ++} ++#endif ++ ++#ifdef CONFIG_NUMA ++extern int sched_numa_find_closest(const struct cpumask *cpus, int cpu); ++#else ++static inline int sched_numa_find_closest(const struct cpumask *cpus, int cpu) ++{ ++ return nr_cpu_ids; ++} ++#endif ++#endif /* PDS_SCHED_H */ +--- a/kernel/sched/pelt.c ++++ b/kernel/sched/pelt.c +@@ -236,6 +236,7 @@ ___update_load_avg(struct sched_avg *sa, + WRITE_ONCE(sa->util_avg, sa->util_sum / divider); + } + ++#ifndef CONFIG_SCHED_PDS + /* + * sched_entity: + * +@@ -352,6 +353,7 @@ int update_dl_rq_load_avg(u64 now, struc + + return 0; + } ++#endif + + #ifdef CONFIG_HAVE_SCHED_AVG_IRQ + /* +--- a/kernel/sched/pelt.h ++++ b/kernel/sched/pelt.h +@@ -1,11 +1,13 @@ + #ifdef CONFIG_SMP + #include "sched-pelt.h" + ++#ifndef CONFIG_SCHED_PDS + int __update_load_avg_blocked_se(u64 now, struct sched_entity *se); + int __update_load_avg_se(u64 now, struct cfs_rq *cfs_rq, struct sched_entity *se); + int __update_load_avg_cfs_rq(u64 now, struct cfs_rq *cfs_rq); + int update_rt_rq_load_avg(u64 now, struct rq *rq, int running); + int update_dl_rq_load_avg(u64 now, struct rq *rq, int running); ++#endif + + #ifdef CONFIG_HAVE_SCHED_AVG_IRQ + int update_irq_load_avg(struct rq *rq, u64 running); +@@ -17,6 +19,7 @@ update_irq_load_avg(struct rq *rq, u64 r + } + #endif + ++#ifndef CONFIG_SCHED_PDS + /* + * When a task is dequeued, its estimated utilization should not be update if + * its util_avg has not been updated at least once. +@@ -137,9 +140,11 @@ static inline u64 cfs_rq_clock_pelt(stru + return rq_clock_pelt(rq_of(cfs_rq)); + } + #endif ++#endif /* CONFIG_SCHED_PDS */ + + #else + ++#ifndef CONFIG_SCHED_PDS + static inline int + update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq) + { +@@ -157,6 +162,7 @@ update_dl_rq_load_avg(u64 now, struct rq + { + return 0; + } ++#endif + + static inline int + update_irq_load_avg(struct rq *rq, u64 running) +--- a/kernel/sched/sched.h ++++ b/kernel/sched/sched.h +@@ -2,6 +2,10 @@ + /* + * Scheduler internal types and methods: + */ ++#ifdef CONFIG_SCHED_PDS ++#include "pds_sched.h" ++#else ++ + #include + + #include +@@ -2551,3 +2555,4 @@ static inline void membarrier_switch_mm( + { + } + #endif ++#endif /* !CONFIG_SCHED_PDS */ +--- a/kernel/sched/stats.c ++++ b/kernel/sched/stats.c +@@ -22,9 +22,11 @@ static int show_schedstat(struct seq_fil + } else { + struct rq *rq; + #ifdef CONFIG_SMP ++#ifndef CONFIG_SCHED_PDS + struct sched_domain *sd; + int dcount = 0; + #endif ++#endif + cpu = (unsigned long)(v - 2); + rq = cpu_rq(cpu); + +@@ -40,6 +42,7 @@ static int show_schedstat(struct seq_fil + seq_printf(seq, "\n"); + + #ifdef CONFIG_SMP ++#ifndef CONFIG_SCHED_PDS + /* domain-specific stats */ + rcu_read_lock(); + for_each_domain(cpu, sd) { +@@ -69,6 +72,7 @@ static int show_schedstat(struct seq_fil + } + rcu_read_unlock(); + #endif ++#endif + } + return 0; + } +--- a/kernel/sysctl.c ++++ b/kernel/sysctl.c +@@ -130,8 +130,12 @@ static int __maybe_unused four = 4; + static unsigned long zero_ul; + static unsigned long one_ul = 1; + static unsigned long long_max = LONG_MAX; +-static int one_hundred = 100; +-static int one_thousand = 1000; ++static int __read_mostly one_hundred = 100; ++static int __read_mostly one_thousand = 1000; ++#ifdef CONFIG_SCHED_PDS ++extern int rr_interval; ++extern int sched_yield_type; ++#endif + #ifdef CONFIG_PRINTK + static int ten_thousand = 10000; + #endif +@@ -300,7 +304,7 @@ static struct ctl_table sysctl_base_tabl + { } + }; + +-#ifdef CONFIG_SCHED_DEBUG ++#if defined(CONFIG_SCHED_DEBUG) && !defined(CONFIG_SCHED_PDS) + static int min_sched_granularity_ns = 100000; /* 100 usecs */ + static int max_sched_granularity_ns = NSEC_PER_SEC; /* 1 second */ + static int min_wakeup_granularity_ns; /* 0 usecs */ +@@ -317,6 +321,7 @@ static int max_extfrag_threshold = 1000; + #endif + + static struct ctl_table kern_table[] = { ++#ifndef CONFIG_SCHED_PDS + { + .procname = "sched_child_runs_first", + .data = &sysctl_sched_child_runs_first, +@@ -498,6 +503,7 @@ static struct ctl_table kern_table[] = { + .extra2 = SYSCTL_ONE, + }, + #endif ++#endif /* !CONFIG_SCHED_PDS */ + #ifdef CONFIG_PROVE_LOCKING + { + .procname = "prove_locking", +@@ -1070,6 +1076,26 @@ static struct ctl_table kern_table[] = { + .proc_handler = proc_dointvec, + }, + #endif ++#ifdef CONFIG_SCHED_PDS ++ { ++ .procname = "rr_interval", ++ .data = &rr_interval, ++ .maxlen = sizeof (int), ++ .mode = 0644, ++ .proc_handler = &proc_dointvec_minmax, ++ .extra1 = SYSCTL_ONE, ++ .extra2 = &one_thousand, ++ }, ++ { ++ .procname = "yield_type", ++ .data = &sched_yield_type, ++ .maxlen = sizeof (int), ++ .mode = 0644, ++ .proc_handler = &proc_dointvec_minmax, ++ .extra1 = SYSCTL_ZERO, ++ .extra2 = &two, ++ }, ++#endif + #if defined(CONFIG_S390) && defined(CONFIG_SMP) + { + .procname = "spin_retry", +--- a/kernel/time/posix-cpu-timers.c ++++ b/kernel/time/posix-cpu-timers.c +@@ -226,7 +226,7 @@ static void task_sample_cputime(struct t + u64 stime, utime; + + task_cputime(p, &utime, &stime); +- store_samples(samples, stime, utime, p->se.sum_exec_runtime); ++ store_samples(samples, stime, utime, tsk_seruntime(p)); + } + + static void proc_sample_cputime_atomic(struct task_cputime_atomic *at, +@@ -796,6 +796,7 @@ static void collect_posix_cputimers(stru + } + } + ++#ifndef CONFIG_SCHED_PDS + static inline void check_dl_overrun(struct task_struct *tsk) + { + if (tsk->dl.dl_overrun) { +@@ -803,6 +804,7 @@ static inline void check_dl_overrun(stru + __group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk); + } + } ++#endif + + static bool check_rlimit(u64 time, u64 limit, int signo, bool rt, bool hard) + { +@@ -830,8 +832,10 @@ static void check_thread_timers(struct t + u64 samples[CPUCLOCK_MAX]; + unsigned long soft; + ++#ifndef CONFIG_SCHED_PDS + if (dl_task(tsk)) + check_dl_overrun(tsk); ++#endif + + if (expiry_cache_is_inactive(pct)) + return; +@@ -845,7 +849,7 @@ static void check_thread_timers(struct t + soft = task_rlimit(tsk, RLIMIT_RTTIME); + if (soft != RLIM_INFINITY) { + /* Task RT timeout is accounted in jiffies. RTTIME is usec */ +- unsigned long rttime = tsk->rt.timeout * (USEC_PER_SEC / HZ); ++ unsigned long rttime = tsk_rttimeout(tsk) * (USEC_PER_SEC / HZ); + unsigned long hard = task_rlimit_max(tsk, RLIMIT_RTTIME); + + /* At the hard limit, send SIGKILL. No further action. */ +@@ -1099,8 +1103,10 @@ static inline bool fastpath_timer_check( + return true; + } + ++#ifndef CONFIG_SCHED_PDS + if (dl_task(tsk) && tsk->dl.dl_overrun) + return true; ++#endif + + return false; + } +--- a/kernel/trace/trace_selftest.c ++++ b/kernel/trace/trace_selftest.c +@@ -1053,10 +1053,15 @@ static int trace_wakeup_test_thread(void + { + /* Make this a -deadline thread */ + static const struct sched_attr attr = { ++#ifdef CONFIG_SCHED_PDS ++ /* No deadline on BFS, use RR */ ++ .sched_policy = SCHED_RR, ++#else + .sched_policy = SCHED_DEADLINE, + .sched_runtime = 100000ULL, + .sched_deadline = 10000000ULL, + .sched_period = 10000000ULL ++#endif + }; + struct wakeup_test_data *x = data; + +--- a/scripts/headers_install.sh ++++ b/scripts/headers_install.sh +@@ -94,6 +94,7 @@ include/uapi/linux/eventpoll.h:CONFIG_PM + include/uapi/linux/hw_breakpoint.h:CONFIG_HAVE_MIXED_BREAKPOINTS_REGS + include/uapi/linux/pktcdvd.h:CONFIG_CDROM_PKTCDVD_WCACHE + include/uapi/linux/raw.h:CONFIG_MAX_RAW_DEVS ++include/uapi/linux/sched.h:CONFIG_SCHED_PDS + " + + for c in $configs + +--- a/kernel/sched/pds.c 2021-11-27 13:16:17.290258000 +0800 ++++ b/kernel/sched/pds.c 2021-11-27 13:20:16.627647000 +0800 +@@ -876,14 +876,6 @@ + + sched_info_queued(rq, p); + psi_enqueue(p, flags); +- +- /* +- * If in_iowait is set, the code below may not trigger any cpufreq +- * utilization updates, so do it here explicitly with the IOWAIT flag +- * passed. +- */ +- if (p->in_iowait) +- cpufreq_update_this_cpu(rq, SCHED_CPUFREQ_IOWAIT); + } + + static inline void requeue_task(struct task_struct *p, struct rq *rq) +@@ -2800,7 +2792,12 @@ + + pds_update_curr(rq, p); + +- cpufreq_update_util(rq, 0); ++ /* ++ * If in_iowait is set, the code below may not trigger any cpufreq ++ * utilization updates, so do it here explicitly with the IOWAIT flag ++ * passed. ++ */ ++ cpufreq_update_util(rq, SCHED_CPUFREQ_IOWAIT * p->in_iowait); + + /* + * Tasks that were scheduled in the first half of a tick are not + +--- a/kernel/sched/cpufreq_schedutil.c 2021-11-27 13:16:17.290258000 +0800 ++++ b/kernel/sched/cpufreq_schedutil.c 2021-11-27 13:20:16.627647000 +0800 +@@ -56,6 +56,13 @@ + unsigned long bw_dl; + unsigned long max; + ++#ifdef CONFIG_SCHED_PDS ++ /* For genenal cpu load util */ ++ s32 load_history; ++ u64 load_block; ++ u64 load_stamp; ++#endif ++ + /* The field below is for single-CPU policies only: */ + #ifdef CONFIG_NO_HZ_COMMON + unsigned long saved_idle_calls; +@@ -301,16 +308,54 @@ + + return schedutil_cpu_util(sg_cpu->cpu, util, max, FREQUENCY_UTIL, NULL); + } ++ + #else /* CONFIG_SCHED_PDS */ ++ ++#define SG_CPU_LOAD_HISTORY_BITS (sizeof(s32) * 8ULL) ++#define SG_CPU_UTIL_SHIFT (8) ++#define SG_CPU_LOAD_HISTORY_SHIFT (SG_CPU_LOAD_HISTORY_BITS - 1 - SG_CPU_UTIL_SHIFT) ++#define SG_CPU_LOAD_HISTORY_TO_UTIL(l) (((l) >> SG_CPU_LOAD_HISTORY_SHIFT) & 0xff) ++ ++#define LOAD_BLOCK(t) ((t) >> 17) ++#define LOAD_HALF_BLOCK(t) ((t) >> 16) ++#define BLOCK_MASK(t) ((t) & ((0x01 << 18) - 1)) ++#define LOAD_BLOCK_BIT(b) (1UL << (SG_CPU_LOAD_HISTORY_BITS - 1 - (b))) ++#define CURRENT_LOAD_BIT LOAD_BLOCK_BIT(0) ++ + static unsigned long sugov_get_util(struct sugov_cpu *sg_cpu) + { + unsigned long max = arch_scale_cpu_capacity(sg_cpu->cpu); + sg_cpu->max = max; + sg_cpu->bw_dl = 0; +- return cpu_rq(sg_cpu->cpu)->nr_running ? max:0UL; ++ return SG_CPU_LOAD_HISTORY_TO_UTIL(sg_cpu->load_history) * ++ (max >> SG_CPU_UTIL_SHIFT); ++} ++ ++static inline void sugov_cpu_load_update(struct sugov_cpu *sg_cpu, u64 time) ++{ ++ u64 delta = min(LOAD_BLOCK(time) - LOAD_BLOCK(sg_cpu->load_stamp), ++ SG_CPU_LOAD_HISTORY_BITS - 1); ++ u64 prev = !!(sg_cpu->load_history & CURRENT_LOAD_BIT); ++ u64 curr = !!cpu_rq(sg_cpu->cpu)->nr_running; + ++ if (delta) { ++ sg_cpu->load_history = sg_cpu->load_history >> delta; ++ ++ if (delta <= SG_CPU_UTIL_SHIFT) { ++ sg_cpu->load_block += (~BLOCK_MASK(sg_cpu->load_stamp)) * prev; ++ if (!!LOAD_HALF_BLOCK(sg_cpu->load_block) ^ curr) ++ sg_cpu->load_history ^= LOAD_BLOCK_BIT(delta); ++ } ++ ++ sg_cpu->load_block = BLOCK_MASK(time) * prev; ++ } else { ++ sg_cpu->load_block += (time - sg_cpu->load_stamp) * prev; ++ } ++ if (prev ^ curr) ++ sg_cpu->load_history ^= CURRENT_LOAD_BIT; ++ sg_cpu->load_stamp = time; + } +-#endif ++#endif /* CONFIG_SCHED_PDS */ + + /** + * sugov_iowait_reset() - Reset the IO boost status of a CPU. +@@ -469,6 +514,10 @@ + unsigned int next_f; + bool busy; + ++#ifdef CONFIG_SCHED_PDS ++ sugov_cpu_load_update(sg_cpu, time); ++#endif /* CONFIG_SCHED_PDS */ ++ + sugov_iowait_boost(sg_cpu, time, flags); + sg_cpu->last_update = time; + +@@ -542,6 +591,10 @@ + + raw_spin_lock(&sg_policy->update_lock); + ++#ifdef CONFIG_SCHED_PDS ++ sugov_cpu_load_update(sg_cpu, time); ++#endif /* CONFIG_SCHED_PDS */ ++ + sugov_iowait_boost(sg_cpu, time, flags); + sg_cpu->last_update = time; + \ No newline at end of file diff --git a/README.md b/README.md index d0d8079b5..186c54436 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ - O3 编译,CFLAG优化 - 插件包含:SSRP,PassWall,OpenClash,AdguardHome,微信推送,网易云解锁,SQM,DNSProxy,网络唤醒,DDNS,迅雷快鸟,UPNP,FullCone(防火墙中开启,默认开启),流量分载,irq优化,京东签到,Zerotier,FRPC,FRPS,无线打印,流量监控,过滤军刀,R2S-OLED - ss协议在armv8上实现了aes硬件加速(请仅使用aead加密的连接方式) -- 集成并默认启用了BBRv2,LRNG,以及BMQ Scheduler +- 集成并默认启用了BBRv2,LRNG,以及PDS Scheduler - 如有任何问题,请先尝试ssh进入后台,输入fuck后回车,等待机器重启后确认问题是否已经解决 ### 下载 diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 234f77cc3..8355e638a 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -42,9 +42,9 @@ wget -qO - https://github.com/openwrt/openwrt/commit/cfaf039.patch | patch -p1 #cp -f ../PATCH/MuQSS/0002-MuQSS-Fix-build-error-on-config-leak.patch ./target/linux/generic/hack-5.4/694-0002-MuQSS-Fix-build-error-on-config-leak.patch #cp -f ../PATCH/MuQSS/0003-Work-around-x86-only-llc-stuff.patch ./target/linux/generic/hack-5.4/694-0003-Work-around-x86-only-llc-stuff.patch # BMQ -cp -f ../PATCH/BMQ/01-bmq_v5.4-r2.patch ./target/linux/generic/hack-5.4/694-01-bmq_v5.4-r2.patch +#cp -f ../PATCH/BMQ/01-bmq_v5.4-r2.patch ./target/linux/generic/hack-5.4/694-01-bmq_v5.4-r2.patch # PDS -#wget https://github.com/Frogging-Family/linux-tkg/raw/master/linux-tkg-patches/5.4/0005-v5.4_undead-pds099o.patch -O ./target/linux/generic/hack-5.4/694-0005-01-v5.4_undead-pds099o.patch +cp -f ../PATCH/PDS/v5.4_undead-pds099o.patch ./target/linux/generic/hack-5.4/694-v5.4_undead-pds099o.patch #wget https://github.com/Frogging-Family/linux-tkg/raw/master/linux-tkg-patches/5.4/0005-glitched-pds.patch -O ./target/linux/generic/hack-5.4/694-0005-02-glitched-pds.patch # UKSM #cp -f ../PATCH/UKSM/695-uksm-5.4.patch ./target/linux/generic/hack-5.4/695-uksm-5.4.patch From bd5015e3da76d667e699f4e8d2f62a66cb45554d Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sat, 27 Nov 2021 14:25:54 +0800 Subject: [PATCH 211/244] BMQ: set 'Time slice' to 6 --- PATCH/BMQ/01-bmq_v5.4-r2.patch | 4 ++-- README.md | 2 +- SCRIPTS/02_prepare_package.sh | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/PATCH/BMQ/01-bmq_v5.4-r2.patch b/PATCH/BMQ/01-bmq_v5.4-r2.patch index 79ca052cb..b28e97e71 100644 --- a/PATCH/BMQ/01-bmq_v5.4-r2.patch +++ b/PATCH/BMQ/01-bmq_v5.4-r2.patch @@ -413,8 +413,8 @@ index b4daad2bac23..f9faeb82f677 100644 + depends on SCHED_BMQ + help + Time slice in ms for BMQ CPU scheduler, default 4 ms. -+ default 2 if PREEMPT -+ default 4 if !PREEMPT ++ default 6 if PREEMPT ++ default 6 if !PREEMPT + config UCLAMP_TASK bool "Enable utilization clamping for RT/FAIR tasks" diff --git a/README.md b/README.md index 186c54436..d0d8079b5 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ - O3 编译,CFLAG优化 - 插件包含:SSRP,PassWall,OpenClash,AdguardHome,微信推送,网易云解锁,SQM,DNSProxy,网络唤醒,DDNS,迅雷快鸟,UPNP,FullCone(防火墙中开启,默认开启),流量分载,irq优化,京东签到,Zerotier,FRPC,FRPS,无线打印,流量监控,过滤军刀,R2S-OLED - ss协议在armv8上实现了aes硬件加速(请仅使用aead加密的连接方式) -- 集成并默认启用了BBRv2,LRNG,以及PDS Scheduler +- 集成并默认启用了BBRv2,LRNG,以及BMQ Scheduler - 如有任何问题,请先尝试ssh进入后台,输入fuck后回车,等待机器重启后确认问题是否已经解决 ### 下载 diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 8355e638a..440fa0a91 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -42,9 +42,9 @@ wget -qO - https://github.com/openwrt/openwrt/commit/cfaf039.patch | patch -p1 #cp -f ../PATCH/MuQSS/0002-MuQSS-Fix-build-error-on-config-leak.patch ./target/linux/generic/hack-5.4/694-0002-MuQSS-Fix-build-error-on-config-leak.patch #cp -f ../PATCH/MuQSS/0003-Work-around-x86-only-llc-stuff.patch ./target/linux/generic/hack-5.4/694-0003-Work-around-x86-only-llc-stuff.patch # BMQ -#cp -f ../PATCH/BMQ/01-bmq_v5.4-r2.patch ./target/linux/generic/hack-5.4/694-01-bmq_v5.4-r2.patch +cp -f ../PATCH/BMQ/01-bmq_v5.4-r2.patch ./target/linux/generic/hack-5.4/694-01-bmq_v5.4-r2.patch # PDS -cp -f ../PATCH/PDS/v5.4_undead-pds099o.patch ./target/linux/generic/hack-5.4/694-v5.4_undead-pds099o.patch +#cp -f ../PATCH/PDS/v5.4_undead-pds099o.patch ./target/linux/generic/hack-5.4/694-v5.4_undead-pds099o.patch #wget https://github.com/Frogging-Family/linux-tkg/raw/master/linux-tkg-patches/5.4/0005-glitched-pds.patch -O ./target/linux/generic/hack-5.4/694-0005-02-glitched-pds.patch # UKSM #cp -f ../PATCH/UKSM/695-uksm-5.4.patch ./target/linux/generic/hack-5.4/695-uksm-5.4.patch From 4edccf6987c853610bce3a6d2c46fa143869efc7 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sat, 27 Nov 2021 15:26:00 +0800 Subject: [PATCH 212/244] Stick with CFS orz --- README.md | 2 +- SCRIPTS/02_prepare_package.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d0d8079b5..08696d3bd 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ - O3 编译,CFLAG优化 - 插件包含:SSRP,PassWall,OpenClash,AdguardHome,微信推送,网易云解锁,SQM,DNSProxy,网络唤醒,DDNS,迅雷快鸟,UPNP,FullCone(防火墙中开启,默认开启),流量分载,irq优化,京东签到,Zerotier,FRPC,FRPS,无线打印,流量监控,过滤军刀,R2S-OLED - ss协议在armv8上实现了aes硬件加速(请仅使用aead加密的连接方式) -- 集成并默认启用了BBRv2,LRNG,以及BMQ Scheduler +- 集成并默认启用了BBRv2,LRNG - 如有任何问题,请先尝试ssh进入后台,输入fuck后回车,等待机器重启后确认问题是否已经解决 ### 下载 diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 440fa0a91..cfc4ef3f8 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -42,7 +42,7 @@ wget -qO - https://github.com/openwrt/openwrt/commit/cfaf039.patch | patch -p1 #cp -f ../PATCH/MuQSS/0002-MuQSS-Fix-build-error-on-config-leak.patch ./target/linux/generic/hack-5.4/694-0002-MuQSS-Fix-build-error-on-config-leak.patch #cp -f ../PATCH/MuQSS/0003-Work-around-x86-only-llc-stuff.patch ./target/linux/generic/hack-5.4/694-0003-Work-around-x86-only-llc-stuff.patch # BMQ -cp -f ../PATCH/BMQ/01-bmq_v5.4-r2.patch ./target/linux/generic/hack-5.4/694-01-bmq_v5.4-r2.patch +#cp -f ../PATCH/BMQ/01-bmq_v5.4-r2.patch ./target/linux/generic/hack-5.4/694-01-bmq_v5.4-r2.patch # PDS #cp -f ../PATCH/PDS/v5.4_undead-pds099o.patch ./target/linux/generic/hack-5.4/694-v5.4_undead-pds099o.patch #wget https://github.com/Frogging-Family/linux-tkg/raw/master/linux-tkg-patches/5.4/0005-glitched-pds.patch -O ./target/linux/generic/hack-5.4/694-0005-02-glitched-pds.patch From e54f0b245718a29cbd11ec0ac7710b802ae1529b Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 29 Nov 2021 16:35:03 +0800 Subject: [PATCH 213/244] Update 02_target_only.sh --- SCRIPTS/R2S/02_target_only.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index ba6025577..cf6f653b2 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -9,6 +9,9 @@ cp -f ../PATCH/mbedtls/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.p wget -P target/linux/rockchip/armv8/base-files/etc/init.d/ https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3328/base-files/etc/init.d/fa-rk3328-pwmfan wget -P target/linux/rockchip/armv8/base-files/usr/bin/ https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3328/base-files/usr/bin/start-rk3328-pwm-fan.sh +# BMQ +cp -f ../PATCH/BMQ/01-bmq_v5.4-r2.patch ./target/linux/generic/hack-5.4/694-01-bmq_v5.4-r2.patch + # CacULE #sed -i '/CONFIG_NR_CPUS/d' ./target/linux/rockchip/armv8/config-5.4 #echo ' From c46338461c58f814164192e96a22d88e30eaf1d9 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 29 Nov 2021 16:35:19 +0800 Subject: [PATCH 214/244] Update 02_target_only.sh --- SCRIPTS/X86/02_target_only.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SCRIPTS/X86/02_target_only.sh b/SCRIPTS/X86/02_target_only.sh index 94d89235d..9f106d32d 100644 --- a/SCRIPTS/X86/02_target_only.sh +++ b/SCRIPTS/X86/02_target_only.sh @@ -12,6 +12,9 @@ echo ' CONFIG_CRYPTO_AES_NI_INTEL=y ' >>./target/linux/x86/64/config-5.4 +# BMQ +cp -f ../PATCH/BMQ/01-bmq_v5.4-r2.patch ./target/linux/generic/hack-5.4/694-01-bmq_v5.4-r2.patch + # UKSM #echo ' #CONFIG_KSM=y From f1a820b0d13c3636b26934b788708a29a7a12b84 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 29 Nov 2021 16:35:03 +0800 Subject: [PATCH 215/244] R2S/X86: Use BMQ Scheduler --- README.md | 2 +- SCRIPTS/R2S/02_target_only.sh | 3 +++ SCRIPTS/X86/02_target_only.sh | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 08696d3bd..50165ca79 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ - O3 编译,CFLAG优化 - 插件包含:SSRP,PassWall,OpenClash,AdguardHome,微信推送,网易云解锁,SQM,DNSProxy,网络唤醒,DDNS,迅雷快鸟,UPNP,FullCone(防火墙中开启,默认开启),流量分载,irq优化,京东签到,Zerotier,FRPC,FRPS,无线打印,流量监控,过滤军刀,R2S-OLED - ss协议在armv8上实现了aes硬件加速(请仅使用aead加密的连接方式) -- 集成并默认启用了BBRv2,LRNG +- 集成并默认启用了BBRv2,LRNG,R2S/X86使用BMQ Scheduler - 如有任何问题,请先尝试ssh进入后台,输入fuck后回车,等待机器重启后确认问题是否已经解决 ### 下载 diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index ba6025577..cf6f653b2 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -9,6 +9,9 @@ cp -f ../PATCH/mbedtls/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.p wget -P target/linux/rockchip/armv8/base-files/etc/init.d/ https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3328/base-files/etc/init.d/fa-rk3328-pwmfan wget -P target/linux/rockchip/armv8/base-files/usr/bin/ https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3328/base-files/usr/bin/start-rk3328-pwm-fan.sh +# BMQ +cp -f ../PATCH/BMQ/01-bmq_v5.4-r2.patch ./target/linux/generic/hack-5.4/694-01-bmq_v5.4-r2.patch + # CacULE #sed -i '/CONFIG_NR_CPUS/d' ./target/linux/rockchip/armv8/config-5.4 #echo ' diff --git a/SCRIPTS/X86/02_target_only.sh b/SCRIPTS/X86/02_target_only.sh index 94d89235d..9f106d32d 100644 --- a/SCRIPTS/X86/02_target_only.sh +++ b/SCRIPTS/X86/02_target_only.sh @@ -12,6 +12,9 @@ echo ' CONFIG_CRYPTO_AES_NI_INTEL=y ' >>./target/linux/x86/64/config-5.4 +# BMQ +cp -f ../PATCH/BMQ/01-bmq_v5.4-r2.patch ./target/linux/generic/hack-5.4/694-01-bmq_v5.4-r2.patch + # UKSM #echo ' #CONFIG_KSM=y From 4993e5000de33680e371d278643a00209835060b Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 29 Nov 2021 16:42:43 +0800 Subject: [PATCH 216/244] Revert "R2S/X86: Use BMQ Scheduler" This reverts commit f1a820b0d13c3636b26934b788708a29a7a12b84. --- README.md | 2 +- SCRIPTS/R2S/02_target_only.sh | 3 --- SCRIPTS/X86/02_target_only.sh | 3 --- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/README.md b/README.md index 50165ca79..08696d3bd 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ - O3 编译,CFLAG优化 - 插件包含:SSRP,PassWall,OpenClash,AdguardHome,微信推送,网易云解锁,SQM,DNSProxy,网络唤醒,DDNS,迅雷快鸟,UPNP,FullCone(防火墙中开启,默认开启),流量分载,irq优化,京东签到,Zerotier,FRPC,FRPS,无线打印,流量监控,过滤军刀,R2S-OLED - ss协议在armv8上实现了aes硬件加速(请仅使用aead加密的连接方式) -- 集成并默认启用了BBRv2,LRNG,R2S/X86使用BMQ Scheduler +- 集成并默认启用了BBRv2,LRNG - 如有任何问题,请先尝试ssh进入后台,输入fuck后回车,等待机器重启后确认问题是否已经解决 ### 下载 diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index cf6f653b2..ba6025577 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -9,9 +9,6 @@ cp -f ../PATCH/mbedtls/100-Implements-AES-and-GCM-with-ARMv8-Crypto-Extensions.p wget -P target/linux/rockchip/armv8/base-files/etc/init.d/ https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3328/base-files/etc/init.d/fa-rk3328-pwmfan wget -P target/linux/rockchip/armv8/base-files/usr/bin/ https://github.com/friendlyarm/friendlywrt/raw/master-v19.07.1/target/linux/rockchip-rk3328/base-files/usr/bin/start-rk3328-pwm-fan.sh -# BMQ -cp -f ../PATCH/BMQ/01-bmq_v5.4-r2.patch ./target/linux/generic/hack-5.4/694-01-bmq_v5.4-r2.patch - # CacULE #sed -i '/CONFIG_NR_CPUS/d' ./target/linux/rockchip/armv8/config-5.4 #echo ' diff --git a/SCRIPTS/X86/02_target_only.sh b/SCRIPTS/X86/02_target_only.sh index 9f106d32d..94d89235d 100644 --- a/SCRIPTS/X86/02_target_only.sh +++ b/SCRIPTS/X86/02_target_only.sh @@ -12,9 +12,6 @@ echo ' CONFIG_CRYPTO_AES_NI_INTEL=y ' >>./target/linux/x86/64/config-5.4 -# BMQ -cp -f ../PATCH/BMQ/01-bmq_v5.4-r2.patch ./target/linux/generic/hack-5.4/694-01-bmq_v5.4-r2.patch - # UKSM #echo ' #CONFIG_KSM=y From 6faed6f5e1854531a850786dd01bc679000b156c Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 29 Nov 2021 20:26:54 +0800 Subject: [PATCH 217/244] tcp: TCP performance optimizations backport from linux/net-next --- PATCH/backport/695-tcp-optimizations.patch | 682 +++++++++++++++++++++ SCRIPTS/02_prepare_package.sh | 2 + 2 files changed, 684 insertions(+) create mode 100644 PATCH/backport/695-tcp-optimizations.patch diff --git a/PATCH/backport/695-tcp-optimizations.patch b/PATCH/backport/695-tcp-optimizations.patch new file mode 100644 index 000000000..f77d1bcff --- /dev/null +++ b/PATCH/backport/695-tcp-optimizations.patch @@ -0,0 +1,682 @@ +From d519f350967a60b85a574ad8aeac43f2b4384746 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Mon, 15 Nov 2021 11:02:30 -0800 +Subject: tcp: optimizations for linux-5.17 + +Mostly small improvements in this series. + +The notable change is in "defer skb freeing after +socket lock is released" in recvmsg() (and RX zerocopy) + +The idea is to try to let skb freeing to BH handler, +whenever possible, or at least perform the freeing +outside of the socket lock section, for much improved +performance. This idea can probably be extended +to other protocols. + + Tests on a 100Gbit NIC + Max throughput for one TCP_STREAM flow, over 10 runs. + + MTU : 1500 (1428 bytes of TCP payload per MSS) + Before: 55 Gbit + After: 66 Gbit + + MTU : 4096+ (4096 bytes of TCP payload, plus TCP/IPv6 headers) + Before: 82 Gbit + After: 95 Gbit +==================== + +Acked-by: Soheil Hassas Yeganeh +Signed-off-by: David S. Miller + +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller + +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -36,6 +36,7 @@ + #include + #include + #include ++#include + #include + #if IS_ENABLED(CONFIG_NF_CONNTRACK) + #include +@@ -700,6 +701,7 @@ struct sk_buff { + }; + struct rb_node rbnode; /* used in netem, ip4 defrag, and tcp stack */ + struct list_head list; ++ struct llist_node ll_node; + }; + + union { +--- a/include/net/ip6_checksum.h ++++ b/include/net/ip6_checksum.h +@@ -65,15 +65,9 @@ static inline void __tcp_v6_send_check(s + { + struct tcphdr *th = tcp_hdr(skb); + +- if (skb->ip_summed == CHECKSUM_PARTIAL) { + th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0); + skb->csum_start = skb_transport_header(skb) - skb->head; + skb->csum_offset = offsetof(struct tcphdr, check); +- } else { +- th->check = tcp_v6_check(skb->len, saddr, daddr, +- csum_partial(th, th->doff << 2, +- skb->csum)); +- } + } + + #if IS_ENABLED(CONFIG_IPV6) +--- a/include/net/ipv6.h ++++ b/include/net/ipv6.h +@@ -344,9 +344,9 @@ struct ipcm6_cookie { + struct sockcm_cookie sockc; + __s16 hlimit; + __s16 tclass; ++ __u16 gso_size; + __s8 dontfrag; + struct ipv6_txoptions *opt; +- __u16 gso_size; + }; + + static inline void ipcm6_init(struct ipcm6_cookie *ipc6) +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -62,6 +62,8 @@ + + #include + #include ++#include ++#include + #include + #include + #include +@@ -265,7 +266,7 @@ struct bpf_sk_storage; + * @sk_no_check_tx: %SO_NO_CHECK setting, set checksum in TX packets + * @sk_no_check_rx: allow zero checksum in RX packets + * @sk_route_caps: route capabilities (e.g. %NETIF_F_TSO) +- * @sk_route_nocaps: forbidden route capabilities (e.g NETIF_F_GSO_MASK) ++ * @sk_gso_disabled: if set, NETIF_F_GSO_MASK is forbidden. + * @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4) + * @sk_gso_max_size: Maximum GSO segment size to build + * @sk_gso_max_segs: Maximum number of GSO segments +@@ -361,6 +362,8 @@ struct sock { + #define sk_flags __sk_common.skc_flags + #define sk_rxhash __sk_common.skc_rxhash + ++ /* early demux fields */ ++ + socket_lock_t sk_lock; + atomic_t sk_drops; + int sk_rcvlowat; +@@ -381,6 +384,8 @@ struct sock { + struct sk_buff *head; + struct sk_buff *tail; + } sk_backlog; ++ struct llist_head defer_list; ++ + #define sk_rmem_alloc sk_backlog.rmem_alloc + + int sk_forward_alloc; +@@ -426,8 +431,6 @@ struct sock { + unsigned long sk_max_pacing_rate; + struct page_frag sk_frag; + netdev_features_t sk_route_caps; +- netdev_features_t sk_route_nocaps; +- netdev_features_t sk_route_forced_caps; + int sk_gso_type; + unsigned int sk_gso_max_size; + gfp_t sk_allocation; +@@ -452,7 +455,7 @@ struct sock { + #define SK_FL_TYPE_MASK 0xffff0000 + #endif + +- unsigned int sk_padding : 1, ++ unsigned int sk_gso_disabled : 1, + sk_kern_sock : 1, + sk_no_check_tx : 1, + sk_no_check_rx : 1, +@@ -953,12 +956,18 @@ static inline __must_check int sk_add_ba + + int __sk_backlog_rcv(struct sock *sk, struct sk_buff *skb); + ++INDIRECT_CALLABLE_DECLARE(int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)); ++INDIRECT_CALLABLE_DECLARE(int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)); ++ + static inline int sk_backlog_rcv(struct sock *sk, struct sk_buff *skb) + { + if (sk_memalloc_socks() && skb_pfmemalloc(skb)) + return __sk_backlog_rcv(sk, skb); + +- return sk->sk_backlog_rcv(sk, skb); ++ return INDIRECT_CALL_INET(sk->sk_backlog_rcv, ++ tcp_v6_do_rcv, ++ tcp_v4_do_rcv, ++ sk, skb); + } + + static inline void sk_incoming_cpu_update(struct sock *sk) +@@ -1978,10 +1987,10 @@ static inline bool sk_can_gso(const stru + + void sk_setup_caps(struct sock *sk, struct dst_entry *dst); + +-static inline void sk_nocaps_add(struct sock *sk, netdev_features_t flags) ++static inline void sk_gso_disable(struct sock *sk) + { +- sk->sk_route_nocaps |= flags; +- sk->sk_route_caps &= ~flags; ++ sk->sk_gso_disabled = 1; ++ sk->sk_route_caps &= ~NETIF_F_GSO_MASK; + } + + static inline int skb_do_copy_data_nocache(struct sock *sk, struct sk_buff *skb, +@@ -2468,6 +2477,11 @@ static inline void skb_setup_tx_timestam + &skb_shinfo(skb)->tskey); + } + ++static inline bool sk_is_tcp(const struct sock *sk) ++{ ++ return sk->sk_type == SOCK_STREAM && sk->sk_protocol == IPPROTO_TCP; ++} ++ + /** + * sk_eat_skb - Release a skb if it is no longer needed + * @sk: socket to eat this skb from +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -1377,6 +1377,16 @@ static inline bool tcp_checksum_complete + } + + bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb); ++ ++void __sk_defer_free_flush(struct sock *sk); ++ ++static inline void sk_defer_free_flush(struct sock *sk) ++{ ++ if (llist_empty(&sk->defer_list)) ++ return; ++ __sk_defer_free_flush(sk); ++} ++ + int tcp_filter(struct sock *sk, struct sk_buff *skb); + void tcp_set_state(struct sock *sk, int state); + void tcp_done(struct sock *sk); +@@ -2150,9 +2160,13 @@ static inline void tcp_segs_in(struct tc + u16 segs_in; + + segs_in = max_t(u16, 1, skb_shinfo(skb)->gso_segs); +- tp->segs_in += segs_in; ++ ++ /* We update these fields while other threads might ++ * read them from tcp_get_info() ++ */ ++ WRITE_ONCE(tp->segs_in, tp->segs_in + segs_in); + if (skb->len > tcp_hdrlen(skb)) +- tp->data_segs_in += segs_in; ++ WRITE_ONCE(tp->data_segs_in, tp->data_segs_in + segs_in); + } + + /* +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -4549,8 +4549,7 @@ static void __skb_complete_tx_timestamp( + serr->header.h4.iif = skb->dev ? skb->dev->ifindex : 0; + if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) { + serr->ee.ee_data = skb_shinfo(skb)->tskey; +- if (sk->sk_protocol == IPPROTO_TCP && +- sk->sk_type == SOCK_STREAM) ++ if (sk_is_tcp(sk)) + serr->ee.ee_data -= sk->sk_tskey; + } + +@@ -4618,8 +4617,7 @@ void __skb_tstamp_tx(struct sk_buff *ori + if (tsonly) { + #ifdef CONFIG_INET + if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_STATS) && +- sk->sk_protocol == IPPROTO_TCP && +- sk->sk_type == SOCK_STREAM) { ++ sk_is_tcp(sk)) { + skb = tcp_get_timestamping_opt_stats(sk); + opt_stats = true; + } else +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -323,7 +323,10 @@ int __sk_backlog_rcv(struct sock *sk, st + BUG_ON(!sock_flag(sk, SOCK_MEMALLOC)); + + noreclaim_flag = memalloc_noreclaim_save(); +- ret = sk->sk_backlog_rcv(sk, skb); ++ ret = INDIRECT_CALL_INET(sk->sk_backlog_rcv, ++ tcp_v6_do_rcv, ++ tcp_v4_do_rcv, ++ sk, skb); + memalloc_noreclaim_restore(noreclaim_flag); + + return ret; +@@ -935,8 +938,7 @@ set_rcvbuf: + + if (val & SOF_TIMESTAMPING_OPT_ID && + !(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID)) { +- if (sk->sk_protocol == IPPROTO_TCP && +- sk->sk_type == SOCK_STREAM) { ++ if (sk_is_tcp(sk)) { + if ((1 << sk->sk_state) & + (TCPF_CLOSE | TCPF_LISTEN)) { + ret = -EINVAL; +@@ -1132,8 +1134,7 @@ set_rcvbuf: + + case SO_ZEROCOPY: + if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6) { +- if (!((sk->sk_type == SOCK_STREAM && +- sk->sk_protocol == IPPROTO_TCP) || ++ if (!(sk_is_tcp(sk) || + (sk->sk_type == SOCK_DGRAM && + sk->sk_protocol == IPPROTO_UDP))) + ret = -ENOTSUPP; +@@ -1939,10 +1940,13 @@ void sk_setup_caps(struct sock *sk, stru + u32 max_segs = 1; + + sk_dst_set(sk, dst); +- sk->sk_route_caps = dst->dev->features | sk->sk_route_forced_caps; ++ sk->sk_route_caps = dst->dev->features; ++ if (sk_is_tcp(sk)) ++ sk->sk_route_caps |= NETIF_F_GSO; + if (sk->sk_route_caps & NETIF_F_GSO) + sk->sk_route_caps |= NETIF_F_GSO_SOFTWARE; +- sk->sk_route_caps &= ~sk->sk_route_nocaps; ++ if (unlikely(sk->sk_gso_disabled)) ++ sk->sk_route_caps &= ~NETIF_F_GSO_MASK; + if (sk_can_gso(sk)) { + if (dst->header_len && !xfrm_dst_offload_ok(dst)) { + sk->sk_route_caps &= ~NETIF_F_GSO_MASK; +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -285,7 +285,7 @@ EXPORT_SYMBOL_GPL(tcp_orphan_count); + long sysctl_tcp_mem[3] __read_mostly; + EXPORT_SYMBOL(sysctl_tcp_mem); + +-atomic_long_t tcp_memory_allocated; /* Current allocated memory. */ ++atomic_long_t tcp_memory_allocated ____cacheline_aligned_in_smp; /* Current allocated memory. */ + EXPORT_SYMBOL(tcp_memory_allocated); + + #if IS_ENABLED(CONFIG_SMC) +@@ -296,7 +296,7 @@ EXPORT_SYMBOL(tcp_have_smc); + /* + * Current number of TCP sockets. + */ +-struct percpu_counter tcp_sockets_allocated; ++struct percpu_counter tcp_sockets_allocated ____cacheline_aligned_in_smp; + EXPORT_SYMBOL(tcp_sockets_allocated); + + /* +@@ -454,7 +454,6 @@ void tcp_init_sock(struct sock *sk) + WRITE_ONCE(sk->sk_rcvbuf, sock_net(sk)->ipv4.sysctl_tcp_rmem[1]); + + sk_sockets_allocated_inc(sk); +- sk->sk_route_forced_caps = NETIF_F_GSO; + } + EXPORT_SYMBOL(tcp_init_sock); + +@@ -555,10 +554,11 @@ __poll_t tcp_poll(struct file *file, str + if (state != TCP_SYN_SENT && + (state != TCP_SYN_RECV || rcu_access_pointer(tp->fastopen_rsk))) { + int target = sock_rcvlowat(sk, 0, INT_MAX); ++ u16 urg_data = READ_ONCE(tp->urg_data); + +- if (READ_ONCE(tp->urg_seq) == READ_ONCE(tp->copied_seq) && +- !sock_flag(sk, SOCK_URGINLINE) && +- tp->urg_data) ++ if (unlikely(urg_data) && ++ READ_ONCE(tp->urg_seq) == READ_ONCE(tp->copied_seq) && ++ !sock_flag(sk, SOCK_URGINLINE)) + target++; + + if (tcp_stream_is_readable(tp, target, sk)) +@@ -583,7 +583,7 @@ __poll_t tcp_poll(struct file *file, str + } else + mask |= EPOLLOUT | EPOLLWRNORM; + +- if (tp->urg_data & TCP_URG_VALID) ++ if (urg_data & TCP_URG_VALID) + mask |= EPOLLPRI; + } else if (state == TCP_SYN_SENT && inet_sk(sk)->defer_connect) { + /* Active TCP fastopen socket with defer_connect +@@ -617,7 +617,7 @@ int tcp_ioctl(struct sock *sk, int cmd, + unlock_sock_fast(sk, slow); + break; + case SIOCATMARK: +- answ = tp->urg_data && ++ answ = READ_ONCE(tp->urg_data) && + READ_ONCE(tp->urg_seq) == READ_ONCE(tp->copied_seq); + break; + case SIOCOUTQ: +@@ -1471,7 +1471,7 @@ static int tcp_recv_urg(struct sock *sk, + char c = tp->urg_data; + + if (!(flags & MSG_PEEK)) +- tp->urg_data = TCP_URG_READ; ++ WRITE_ONCE(tp->urg_data, TCP_URG_READ); + + /* Read urgent data. */ + msg->msg_flags |= MSG_OOB; +@@ -1587,6 +1587,36 @@ static void tcp_cleanup_rbuf(struct sock + tcp_send_ack(sk); + } + ++void __sk_defer_free_flush(struct sock *sk) ++{ ++ struct llist_node *head; ++ struct sk_buff *skb, *n; ++ ++ head = llist_del_all(&sk->defer_list); ++ llist_for_each_entry_safe(skb, n, head, ll_node) { ++ prefetch(n); ++ skb_mark_not_on_list(skb); ++ __kfree_skb(skb); ++ } ++} ++EXPORT_SYMBOL(__sk_defer_free_flush); ++ ++static void tcp_eat_recv_skb(struct sock *sk, struct sk_buff *skb) ++{ ++ __skb_unlink(skb, &sk->sk_receive_queue); ++ if (likely(skb->destructor == sock_rfree)) { ++ sock_rfree(skb); ++ skb->destructor = NULL; ++ skb->sk = NULL; ++ if (!skb_queue_empty(&sk->sk_receive_queue) || ++ !llist_empty(&sk->defer_list)) { ++ llist_add(&skb->ll_node, &sk->defer_list); ++ return; ++ } ++ } ++ __kfree_skb(skb); ++} ++ + static struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off) + { + struct sk_buff *skb; +@@ -1606,7 +1636,7 @@ static struct sk_buff *tcp_recv_skb(stru + * splitted a fat GRO packet, while we released socket lock + * in skb_splice_bits() + */ +- sk_eat_skb(sk, skb); ++ tcp_eat_recv_skb(sk, skb); + } + return NULL; + } +@@ -1640,7 +1670,7 @@ int tcp_read_sock(struct sock *sk, read_ + + len = skb->len - offset; + /* Stop reading if we hit a patch of urgent data */ +- if (tp->urg_data) { ++ if (unlikely(tp->urg_data)) { + u32 urg_offset = tp->urg_seq - seq; + if (urg_offset < len) + len = urg_offset; +@@ -1672,11 +1702,11 @@ int tcp_read_sock(struct sock *sk, read_ + continue; + } + if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) { +- sk_eat_skb(sk, skb); ++ tcp_eat_recv_skb(sk, skb); + ++seq; + break; + } +- sk_eat_skb(sk, skb); ++ tcp_eat_recv_skb(sk, skb); + if (!desc->count) + break; + WRITE_ONCE(tp->copied_seq, seq); +@@ -2017,7 +2047,7 @@ int tcp_recvmsg(struct sock *sk, struct + u32 offset; + + /* Are we at urgent data? Stop if we have read anything or have SIGURG pending. */ +- if (tp->urg_data && tp->urg_seq == *seq) { ++ if (unlikely(tp->urg_data) && tp->urg_seq == *seq) { + if (copied) + break; + if (signal_pending(current)) { +@@ -2060,10 +2090,10 @@ int tcp_recvmsg(struct sock *sk, struct + break; + + if (copied) { +- if (sk->sk_err || ++ if (!timeo || ++ sk->sk_err || + sk->sk_state == TCP_CLOSE || + (sk->sk_shutdown & RCV_SHUTDOWN) || +- !timeo || + signal_pending(current)) + break; + } else { +@@ -2097,13 +2127,12 @@ int tcp_recvmsg(struct sock *sk, struct + } + } + +- tcp_cleanup_rbuf(sk, copied); +- + if (copied >= target) { + /* Do not sleep, just process backlog. */ +- release_sock(sk); +- lock_sock(sk); ++ __sk_flush_backlog(sk); + } else { ++ tcp_cleanup_rbuf(sk, copied); ++ sk_defer_free_flush(sk); + sk_wait_data(sk, &timeo, last); + } + +@@ -2123,7 +2152,7 @@ found_ok_skb: + used = len; + + /* Do we have urgent data here? */ +- if (tp->urg_data) { ++ if (unlikely(tp->urg_data)) { + u32 urg_offset = tp->urg_seq - *seq; + if (urg_offset < used) { + if (!urg_offset) { +@@ -2157,8 +2186,8 @@ found_ok_skb: + tcp_rcv_space_adjust(sk); + + skip_copy: +- if (tp->urg_data && after(tp->copied_seq, tp->urg_seq)) { +- tp->urg_data = 0; ++ if (unlikely(tp->urg_data) && after(tp->copied_seq, tp->urg_seq)) { ++ WRITE_ONCE(tp->urg_data, 0); + tcp_fast_path_check(sk); + } + +@@ -2173,14 +2202,14 @@ skip_copy: + if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) + goto found_fin_ok; + if (!(flags & MSG_PEEK)) +- sk_eat_skb(sk, skb); ++ tcp_eat_recv_skb(sk, skb); + continue; + + found_fin_ok: + /* Process the FIN. */ + WRITE_ONCE(*seq, *seq + 1); + if (!(flags & MSG_PEEK)) +- sk_eat_skb(sk, skb); ++ tcp_eat_recv_skb(sk, skb); + break; + } while (len > 0); + +@@ -2192,6 +2221,7 @@ found_fin_ok: + tcp_cleanup_rbuf(sk, copied); + + release_sock(sk); ++ sk_defer_free_flush(sk); + + if (cmsg_flags) { + if (cmsg_flags & 2) +@@ -2603,7 +2633,7 @@ int tcp_disconnect(struct sock *sk, int + sk->sk_rx_skb_cache = NULL; + } + WRITE_ONCE(tp->copied_seq, tp->rcv_nxt); +- tp->urg_data = 0; ++ WRITE_ONCE(tp->urg_data, 0); + tcp_write_queue_purge(sk); + tcp_fastopen_active_disable_ofo_check(sk); + skb_rbtree_purge(&tp->out_of_order_queue); +@@ -3315,10 +3345,12 @@ void tcp_get_info(struct sock *sk, struc + tcp_get_info_chrono_stats(tp, info); + + info->tcpi_segs_out = tp->segs_out; +- info->tcpi_segs_in = tp->segs_in; ++ ++ /* segs_in and data_segs_in can be updated from tcp_segs_in() from BH */ ++ info->tcpi_segs_in = READ_ONCE(tp->segs_in); ++ info->tcpi_data_segs_in = READ_ONCE(tp->data_segs_in); + + info->tcpi_min_rtt = tcp_min_rtt(tp); +- info->tcpi_data_segs_in = tp->data_segs_in; + info->tcpi_data_segs_out = tp->data_segs_out; + + info->tcpi_delivery_rate_app_limited = tp->rate_app_limited ? 1 : 0; +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -5409,7 +5409,7 @@ static void tcp_check_urg(struct sock *s + } + } + +- tp->urg_data = TCP_URG_NOTYET; ++ WRITE_ONCE(tp->urg_data, TCP_URG_NOTYET); + WRITE_ONCE(tp->urg_seq, ptr); + + /* Disable header prediction. */ +@@ -5422,11 +5422,11 @@ static void tcp_urg(struct sock *sk, str + struct tcp_sock *tp = tcp_sk(sk); + + /* Check if we get a new urgent pointer - normally not. */ +- if (th->urg) ++ if (unlikely(th->urg)) + tcp_check_urg(sk, th); + + /* Do we wait for any urgent data? - normally not... */ +- if (tp->urg_data == TCP_URG_NOTYET) { ++ if (unlikely(tp->urg_data == TCP_URG_NOTYET)) { + u32 ptr = tp->urg_seq - ntohl(th->seq) + (th->doff * 4) - + th->syn; + +@@ -5435,7 +5435,7 @@ static void tcp_urg(struct sock *sk, str + u8 tmp; + if (skb_copy_bits(skb, ptr, &tmp, 1)) + BUG(); +- tp->urg_data = TCP_URG_VALID | tmp; ++ WRITE_ONCE(tp->urg_data, TCP_URG_VALID | tmp); + if (!sock_flag(sk, SOCK_DEAD)) + sk->sk_data_ready(sk); + } +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -1099,7 +1099,7 @@ int tcp_md5_do_add(struct sock *sk, cons + if (!md5sig) + return -ENOMEM; + +- sk_nocaps_add(sk, NETIF_F_GSO_MASK); ++ sk_gso_disable(sk); + INIT_HLIST_HEAD(&md5sig->head); + rcu_assign_pointer(tp->md5sig_info, md5sig); + } +@@ -1490,7 +1490,7 @@ struct sock *tcp_v4_syn_recv_sock(const + */ + tcp_md5_do_add(newsk, (union tcp_md5_addr *)&newinet->inet_daddr, + AF_INET, 32, key->key, key->keylen, GFP_ATOMIC); +- sk_nocaps_add(newsk, NETIF_F_GSO_MASK); ++ sk_gso_disable(newsk); + } + #endif + +@@ -1656,8 +1656,7 @@ int tcp_v4_early_demux(struct sk_buff *s + + bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb) + { +- u32 limit = READ_ONCE(sk->sk_rcvbuf) + READ_ONCE(sk->sk_sndbuf); +- u32 tail_gso_size, tail_gso_segs; ++ u32 limit, tail_gso_size, tail_gso_segs; + struct skb_shared_info *shinfo; + const struct tcphdr *th; + struct tcphdr *thtail; +@@ -1764,7 +1763,7 @@ no_coalesce: + * to reduce memory overhead, so add a little headroom here. + * Few sockets backlog are possibly concurrently non empty. + */ +- limit += 64*1024; ++ limit = READ_ONCE(sk->sk_rcvbuf) + READ_ONCE(sk->sk_sndbuf) + 64*1024; + + if (unlikely(sk_add_backlog(sk, skb, limit))) { + bh_unlock_sock(sk); +@@ -1946,6 +1945,7 @@ process: + + sk_incoming_cpu_update(sk); + ++ sk_defer_free_flush(sk); + bh_lock_sock_nested(sk); + tcp_segs_in(tcp_sk(sk), skb); + ret = 0; +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -1141,7 +1141,7 @@ static int __tcp_transmit_skb(struct soc + #ifdef CONFIG_TCP_MD5SIG + /* Calculate the MD5 hash, as we have all we need now */ + if (md5) { +- sk_nocaps_add(sk, NETIF_F_GSO_MASK); ++ sk_gso_disable(sk); + tp->af_specific->calc_md5_hash(opts.hash_location, + md5, sk, skb); + } +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -119,7 +119,7 @@ EXPORT_SYMBOL(udp_table); + long sysctl_udp_mem[3] __read_mostly; + EXPORT_SYMBOL(sysctl_udp_mem); + +-atomic_long_t udp_memory_allocated; ++atomic_long_t udp_memory_allocated ____cacheline_aligned_in_smp; + EXPORT_SYMBOL(udp_memory_allocated); + + #define MAX_UDP_PORTS 65536 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -999,7 +999,7 @@ slow_path: + + fail_toobig: + if (skb->sk && dst_allfrag(skb_dst(skb))) +- sk_nocaps_add(skb->sk, NETIF_F_GSO_MASK); ++ sk_gso_disable(skb->sk); + + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); + err = -EMSGSIZE; +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -72,7 +72,7 @@ static void tcp_v6_send_reset(const stru + static void tcp_v6_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb, + struct request_sock *req); + +-static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); ++INDIRECT_CALLABLE_SCOPE int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); + + static const struct inet_connection_sock_af_ops ipv6_mapped; + static const struct inet_connection_sock_af_ops ipv6_specific; +@@ -1344,7 +1344,8 @@ out: + * This is because we cannot sleep with the original spinlock + * held. + */ +-static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) ++INDIRECT_CALLABLE_SCOPE ++int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) + { + struct ipv6_pinfo *np = tcp_inet6_sk(sk); + struct sk_buff *opt_skb = NULL; +@@ -1621,6 +1622,7 @@ process: + + sk_incoming_cpu_update(sk); + ++ sk_defer_free_flush(sk); + bh_lock_sock_nested(sk); + tcp_segs_in(tcp_sk(sk), skb); + ret = 0; \ No newline at end of file diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index cfc4ef3f8..ef1c99957 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -22,6 +22,8 @@ sed -i '/mirror02/d' scripts/download.pl echo "net.netfilter.nf_conntrack_helper = 1" >>./package/kernel/linux/files/sysctl-nf-conntrack.conf ### 必要的 Patches ### +# TCP performance optimizations backport from linux/net-next +cp -f ../PATCH/backport/695-tcp-optimizations.patch ./target/linux/generic/backport-5.4/695-tcp-optimizations.patch # Patch arm64 型号名称 wget -P target/linux/generic/hack-5.4/ https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/target/linux/generic/hack-5.4/312-arm64-cpuinfo-Add-model-name-in-proc-cpuinfo-for-64bit-ta.patch # Patch jsonc From 8886d85752028faeb3f35c7511bdf8abeee96bfd Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 29 Nov 2021 22:18:01 +0800 Subject: [PATCH 218/244] introduce "le9" Linux kernel patches --- PATCH/backport/695-le9i.patch | 284 ++++++++++++++++++++++++++++++++++ SCRIPTS/02_prepare_package.sh | 2 + 2 files changed, 286 insertions(+) create mode 100644 PATCH/backport/695-le9i.patch diff --git a/PATCH/backport/695-le9i.patch b/PATCH/backport/695-le9i.patch new file mode 100644 index 000000000..e1160c89e --- /dev/null +++ b/PATCH/backport/695-le9i.patch @@ -0,0 +1,284 @@ +le9i.patch +revision 4 from le9h.patch: removed CONFIG_IKCONFIG_PROC because I remembered that IKCONFIG_PROC was initially used by le9e.patch as a personal preference(so I'd know whether CONFIG_LE9D_PATCH was part of the kernel ie. was patch applied to the running kernel?), but for everyone else it's not needed because the presence of the sysctl values gives away that the patch was applied or not! + +le9i.patch +trying to keep inactive ones above threshold too, to see if no freezes with memtest3 +these freezes seem to be caused by writing dmesg/journald, but in fact are possibly caused by both! +a better patch would be keeping executable data unevictable - so todo: see memlockd + +le9h.patch +revision 2: fixed 1 compilation warning +warning: there's a regression that is fixed by reverting commit aa56a292ce623734ddd30f52d73f527d1f3529b5 which is required to use this patch successfully(even tho this regression happens without this patch too!) see https://bugzilla.kernel.org/show_bug.cgi?id=203317#c4 + +this is licensed under all/any of: +Apache License, Version 2.0 +MIT license +0BSD +CC0 +UNLICENSE + +Interesting, a phoronix user here https://www.phoronix.com/forums/forum/phoronix/general-discussion/1118164-yes-linux-does-bad-in-low-ram-memory-pressure-situations-on-the-desktop/page17#post1120291 linked to two older patches(that I was completely unaware of) which are supposedly doing this same thing (9yrs ago for the first, Oct 23, 2018 or earlier for the second): +https://lore.kernel.org/patchwork/patch/222042/ +https://gitlab.freedesktop.org/seanpaul/dpu-staging/commit/0b992f2dbb044896c3584e10bd5b97cf41e2ec6d + +they seem way more complicated though, at first glance. +but hey, they were at least aware of the issue and how to fix it! + +see also: https://gitlab.freedesktop.org/hadess/low-memory-monitor/ +earlyoom +etc. + + +diff --git a/Documentation/admin-guide/sysctl/vm.rst b/Documentation/admin-guide/sysctl/vm.rst +index 64aeee1009ca..d30f0a967375 100644 +--- a/Documentation/admin-guide/sysctl/vm.rst ++++ b/Documentation/admin-guide/sysctl/vm.rst +@@ -68,6 +68,8 @@ Currently, these files are in /proc/sys/vm: + - numa_stat + - swappiness + - unprivileged_userfaultfd ++- unevictable_activefile_kbytes ++- unevictable_inactivefile_kbytes + - user_reserve_kbytes + - vfs_cache_pressure + - watermark_boost_factor +@@ -848,6 +850,75 @@ privileged users (with SYS_CAP_PTRACE capability). + The default value is 1. + + ++unevictable_activefile_kbytes ++============================= ++ ++How many kilobytes of `Active(file)` to never evict during high-pressure ++low-memory situations. ie. never evict active file pages if under this value. ++This will help prevent disk thrashing caused by Active(file) being close to zero ++in such situations, especially when no swap is used. ++ ++As 'nivedita' (phoronix user) put it: ++"Executables and shared libraries are paged into memory, and can be paged out ++even with no swap. [...] The kernel is dumping those pages and [...] immediately ++reading them back in when execution continues." ++^ and that's what's causing the disk thrashing during memory pressure. ++ ++unevictable_activefile_kbytes=X will prevent X kbytes of those most used pages ++from being evicted. ++ ++The default value is 65536. That's 64 MiB. ++ ++Set it to 0 to keep the default behaviour, as if this option was never ++implemented, so you can see the disk thrashing as usual. ++ ++To get an idea what value to use here for your workload(eg. xfce4 with idle ++terminals) to not disk thrash at all, run this:: ++ ++ $ echo 1 | sudo tee /proc/sys/vm/drop_caches; grep -F 'Active(file)' /proc/meminfo ++ 1 ++ Active(file): 203444 kB ++ ++so, using vm.unevictable_activefile_kbytes=203444 would be a good idea here. ++(you can even add a `sleep` before the grep to get a slightly increased value, ++which might be useful if something is compiling in the background and you want ++to account for that too) ++ ++But you can probably go with the default value of just 65536 (aka 64 MiB) ++as this will eliminate most disk thrashing anyway, unless you're not using ++an SSD, in which case it might still be noticeable (I'm guessing?). ++ ++Note that `echo 1 | sudo tee /proc/sys/vm/drop_caches` can still cause ++Active(file) to go a under the vm.unevictable_activefile_kbytes value. ++It's not an issue and this is how you know how much the value for ++vm.unevictable_activefile_kbytes should be, at the time/workload when you ran it. ++ ++The value of `Active(file)` can be gotten in two ways:: ++ ++ $ grep -F 'Active(file)' /proc/meminfo ++ Active(file): 2712004 kB ++ ++and:: ++ ++ $ grep nr_active_file /proc/vmstat ++ nr_active_file 678001 ++ ++and multiply that with MAX_NR_ZONES (which is 4), ie. `nr_active_file * MAX_NR_ZONES` ++so 678001*4=2712004 kB ++ ++MAX_NR_ZONES is 4 as per: ++`include/generated/bounds.h:10:#define MAX_NR_ZONES 4 /* __MAX_NR_ZONES */` ++and is unlikely the change in the future. ++ ++The hub of disk thrashing tests/explanations is here: ++https://gist.github.com/constantoverride/84eba764f487049ed642eb2111a20830 ++ ++unevictable_inactivefile_kbytes ++=============================== ++ ++same thing as vm.unevictable_activefile_kbytes but for `Inactive(file):` ++ ++ + user_reserve_kbytes + =================== + +diff --git a/kernel/sysctl.c b/kernel/sysctl.c +index 078950d9605b..57a379b89d4c 100644 +--- a/kernel/sysctl.c ++++ b/kernel/sysctl.c +@@ -110,6 +110,24 @@ extern int core_uses_pid; + extern char core_pattern[]; + extern unsigned int core_pipe_limit; + #endif ++#if defined(CONFIG_RESERVE_ACTIVEFILE_TO_PREVENT_DISK_THRASHING) ++unsigned long sysctl_unevictable_activefile_kbytes __read_mostly = ++#if CONFIG_RESERVE_ACTIVEFILE_KBYTES < 0 ++#error "CONFIG_RESERVE_ACTIVEFILE_KBYTES should be >= 0" ++#else ++ CONFIG_RESERVE_ACTIVEFILE_KBYTES ++#endif ++; ++#endif ++#if defined(CONFIG_RESERVE_INACTIVEFILE_TO_PREVENT_DISK_THRASHING) ++unsigned long sysctl_unevictable_inactivefile_kbytes __read_mostly = ++#if CONFIG_RESERVE_INACTIVEFILE_KBYTES < 0 ++#error "CONFIG_RESERVE_INACTIVEFILE_KBYTES should be >= 0" ++#else ++ CONFIG_RESERVE_INACTIVEFILE_KBYTES ++#endif ++; ++#endif + extern int pid_max; + extern int pid_max_min, pid_max_max; + extern int percpu_pagelist_fraction; +@@ -1691,6 +1710,24 @@ static struct ctl_table vm_table[] = { + .extra1 = SYSCTL_ZERO, + .extra2 = SYSCTL_ONE, + }, ++#endif ++#if defined(CONFIG_RESERVE_ACTIVEFILE_TO_PREVENT_DISK_THRASHING) ++ { ++ .procname = "unevictable_activefile_kbytes", ++ .data = &sysctl_unevictable_activefile_kbytes, ++ .maxlen = sizeof(sysctl_unevictable_activefile_kbytes), ++ .mode = 0644, ++ .proc_handler = proc_doulongvec_minmax, ++ }, ++#endif ++#if defined(CONFIG_RESERVE_INACTIVEFILE_TO_PREVENT_DISK_THRASHING) ++ { ++ .procname = "unevictable_inactivefile_kbytes", ++ .data = &sysctl_unevictable_inactivefile_kbytes, ++ .maxlen = sizeof(sysctl_unevictable_inactivefile_kbytes), ++ .mode = 0644, ++ .proc_handler = proc_doulongvec_minmax, ++ }, + #endif + { + .procname = "user_reserve_kbytes", +diff --git a/mm/Kconfig b/mm/Kconfig +index 56cec636a1fc..6d5c34b11990 100644 +--- a/mm/Kconfig ++++ b/mm/Kconfig +@@ -63,6 +63,74 @@ config SPARSEMEM_MANUAL + + endchoice + ++config RESERVE_ACTIVEFILE_TO_PREVENT_DISK_THRASHING ++ bool "Reserve some `Active(file)` to prevent disk thrashing" ++ depends on SYSCTL ++ def_bool y ++ help ++ Keep `Active(file)`(/proc/meminfo) pages in RAM so as to avoid system freeze ++ due to the disk thrashing(disk reading only) that occurrs because the running ++ executables's code is being evicted during low-mem conditions which is ++ why it also prevents oom-killer from triggering until 10s of minutes later ++ on some systems. ++ ++ Please see the value of CONFIG_RESERVE_ACTIVEFILE_KBYTES to set how many ++ KiloBytes of Active(file) to keep by default in the sysctl setting ++ vm.unevictable_activefile_kbytes ++ see Documentation/admin-guide/sysctl/vm.rst for more info ++ ++config RESERVE_ACTIVEFILE_KBYTES ++ int "Set default value for vm.unevictable_activefile_kbytes" ++ depends on RESERVE_ACTIVEFILE_TO_PREVENT_DISK_THRASHING ++ default "65536" ++ help ++ This is the default value(in KiB) that vm.unevictable_activefile_kbytes gets. ++ A value of at least 65536 or at most 262144 is recommended for users ++ of xfce4 to avoid disk thrashing on low-memory/memory-pressure conditions, ++ ie. mouse freeze with constant disk activity (but you can still sysrq+f to ++ trigger oom-killer though, even without this mitigation) ++ ++ You can still sysctl set vm.unevictable_activefile_kbytes to a value of 0 ++ to disable this whole feature at runtime. ++ ++ see Documentation/admin-guide/sysctl/vm.rst for more info ++ see also CONFIG_RESERVE_ACTIVEFILE_TO_PREVENT_DISK_THRASHING ++ ++config RESERVE_INACTIVEFILE_TO_PREVENT_DISK_THRASHING ++ bool "Reserve some `Inactive(file)` to prevent disk thrashing" ++ depends on SYSCTL ++ def_bool y ++ help ++ Keep `Inactive(file)`(/proc/meminfo) pages in RAM so as to avoid system freeze ++ due to the disk thrashing(disk reading only) that occurrs because the running ++ executables's code is being evicted during low-mem conditions which is ++ why it also prevents oom-killer from triggering until 10s of minutes later ++ on some systems. ++ ++ This happens with memfreeze3 script ++ ++ Please see the value of CONFIG_RESERVE_INACTIVEFILE_KBYTES to set how many ++ KiloBytes of Inactive(file) to keep by default in the sysctl setting ++ vm.unevictable_inactivefile_kbytes ++ see Documentation/admin-guide/sysctl/vm.rst for more info ++ ++config RESERVE_INACTIVEFILE_KBYTES ++ int "Set default value for vm.unevictable_inactivefile_kbytes" ++ depends on RESERVE_INACTIVEFILE_TO_PREVENT_DISK_THRASHING ++ default "65536" ++ help ++ This is the default value(in KiB) that vm.unevictable_inactivefile_kbytes gets. ++ A value of at least 65536 or at most 262144 is recommended for users ++ of xfce4 to avoid disk thrashing on low-memory/memory-pressure conditions, ++ ie. mouse freeze with constant disk activity (but you can still sysrq+f to ++ trigger oom-killer though, even without this mitigation) ++ ++ You can still sysctl set vm.unevictable_inactivefile_kbytes to a value of 0 ++ to disable this whole feature at runtime. ++ ++ see Documentation/admin-guide/sysctl/vm.rst for more info ++ see also CONFIG_RESERVE_INACTIVEFILE_TO_PREVENT_DISK_THRASHING ++ + config DISCONTIGMEM + def_bool y + depends on (!SELECT_MEMORY_MODEL && ARCH_DISCONTIGMEM_ENABLE) || DISCONTIGMEM_MANUAL +diff --git a/mm/vmscan.c b/mm/vmscan.c +index dbdc46a84f63..c177225bd4cd 100644 +--- a/mm/vmscan.c ++++ b/mm/vmscan.c +@@ -2552,6 +2552,26 @@ + BUG(); + } + ++#if defined(CONFIG_RESERVE_ACTIVEFILE_TO_PREVENT_DISK_THRASHING) ++ extern unsigned int sysctl_unevictable_activefile_kbytes; //FIXME: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] //this just needs to be moved earlier in this same function (too lazy to, atm) ++ if (LRU_ACTIVE_FILE == lru) { //doneFIXME: warning: comparison between ‘enum node_stat_item’ and ‘enum lru_list’ [-Wenum-compare] //fixed: replaced NR_ACTIVE_FILE with LRU_ACTIVE_FILE (they are both == 3 ) ++ long long kib_active_file_now=global_node_page_state(NR_ACTIVE_FILE) * MAX_NR_ZONES; ++ if (kib_active_file_now <= sysctl_unevictable_activefile_kbytes) { ++ nr[lru] = 0; //ie. don't reclaim any Active(file) (see /proc/meminfo) if they are under sysctl_unevictable_activefile_kbytes see Documentation/admin-guide/sysctl/vm.rst and CONFIG_RESERVE_ACTIVEFILE_TO_PREVENT_DISK_THRASHING and CONFIG_RESERVE_ACTIVEFILE_KBYTES ++ continue; ++ } ++ } ++#endif ++#if defined(CONFIG_RESERVE_INACTIVEFILE_TO_PREVENT_DISK_THRASHING) ++ extern unsigned int sysctl_unevictable_inactivefile_kbytes; //FIXME: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] //this just needs to be moved earlier in this same function (too lazy to, atm) ++ if (LRU_INACTIVE_FILE == lru) { ++ long long kib_inactive_file_now=global_node_page_state(NR_INACTIVE_FILE) * MAX_NR_ZONES; ++ if (kib_inactive_file_now <= sysctl_unevictable_inactivefile_kbytes) { ++ nr[lru] = 0; //ie. don't reclaim any Inactive(file) (see /proc/meminfo) if they are under sysctl_unevictable_inactivefile_kbytes see Documentation/admin-guide/sysctl/vm.rst and CONFIG_RESERVE_INACTIVEFILE_TO_PREVENT_DISK_THRASHING and CONFIG_RESERVE_INACTIVEFILE_KBYTES ++ continue; ++ } ++ } ++#endif + *lru_pages += lruvec_size; + nr[lru] = scan; + } \ No newline at end of file diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index ef1c99957..4f3d7e1f9 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -24,6 +24,8 @@ echo "net.netfilter.nf_conntrack_helper = 1" >>./package/kernel/linux/files/sysc ### 必要的 Patches ### # TCP performance optimizations backport from linux/net-next cp -f ../PATCH/backport/695-tcp-optimizations.patch ./target/linux/generic/backport-5.4/695-tcp-optimizations.patch +# introduce "le9" Linux kernel patches +cp -f ../PATCH/backport/695-le9i.patch ./target/linux/generic/hack-5.4/695-le9i.patch # Patch arm64 型号名称 wget -P target/linux/generic/hack-5.4/ https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/target/linux/generic/hack-5.4/312-arm64-cpuinfo-Add-model-name-in-proc-cpuinfo-for-64bit-ta.patch # Patch jsonc From 19f6b9ff76ae7ab25aef4e1fc4a094d8cf8e457f Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 29 Nov 2021 23:03:12 +0800 Subject: [PATCH 219/244] sync seed --- .github/workflows/X86-OpenWrt.yml | 2 +- SEED/R2C/config.seed | 20 +++++--------------- SEED/R2S/config.seed | 20 +++++--------------- SEED/R4S/config.seed | 20 ++++---------------- 4 files changed, 15 insertions(+), 47 deletions(-) diff --git a/.github/workflows/X86-OpenWrt.yml b/.github/workflows/X86-OpenWrt.yml index aed1361b0..5cce701b2 100644 --- a/.github/workflows/X86-OpenWrt.yml +++ b/.github/workflows/X86-OpenWrt.yml @@ -113,7 +113,7 @@ jobs: run: | rm -rf ./artifact/ mkdir -p ./artifact/ - mv openwrt/bin/targets/x86/64/*combined.img* ./artifact/ + mv openwrt/bin/targets/x86/64/*combined-efi.img* ./artifact/ cd ./artifact/ ls -Ahl gzip -d *.gz && exit 0 diff --git a/SEED/R2C/config.seed b/SEED/R2C/config.seed index c934df712..703cb4454 100644 --- a/SEED/R2C/config.seed +++ b/SEED/R2C/config.seed @@ -162,9 +162,13 @@ CONFIG_LIBCURL_OPENSSL=y # CONFIG_LIBCURL_GNUTLS is not set # CONFIG_LIBCURL_NOSSL is not set +### Video Support ### +CONFIG_PACKAGE_kmod-drm-rockchip=y +CONFIG_PACKAGE_kmod-drm-lima=y +CONFIG_PACKAGE_kmod-multimedia-input=y -### DOCKER ###(实验性,有需要的删掉下面的注释) +### DOCKER ###(实验性,有需要的删掉下面的注释) #CONFIG_PACKAGE_luci-app-dockerman=y #CONFIG_DOCKER_KERNEL_OPTIONS=y #CONFIG_DOCKER_NET_ENCRYPT=y @@ -175,17 +179,3 @@ CONFIG_LIBCURL_OPENSSL=y #CONFIG_DOCKER_SECCOMP=y #CONFIG_DOCKER_STO_BTRFS=y #CONFIG_DOCKER_STO_EXT4=y - -### Video Support ### (实验性,有需要的删掉下面的注释) -#CONFIG_PACKAGE_kmod-backlight=y -#CONFIG_PACKAGE_kmod-drm=y -#CONFIG_PACKAGE_kmod-drm-kms-helper=y -#CONFIG_PACKAGE_kmod-drm-rockchip=y -#CONFIG_PACKAGE_kmod-fb=y -#CONFIG_PACKAGE_kmod-fb-cfb-copyarea=y -#CONFIG_PACKAGE_kmod-fb-cfb-fillrect=y -#CONFIG_PACKAGE_kmod-fb-cfb-imgblt=y -#CONFIG_PACKAGE_kmod-fb-sys-fops=y -#CONFIG_PACKAGE_kmod-fb-sys-ram=y -#CONFIG_PACKAGE_kmod-gpu-lima=y -#CONFIG_PACKAGE_kmod-multimedia-input=y diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 7313b3f5f..6693b8fc9 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -162,9 +162,13 @@ CONFIG_LIBCURL_OPENSSL=y # CONFIG_LIBCURL_GNUTLS is not set # CONFIG_LIBCURL_NOSSL is not set +### Video Support ### +CONFIG_PACKAGE_kmod-drm-rockchip=y +CONFIG_PACKAGE_kmod-drm-lima=y +CONFIG_PACKAGE_kmod-multimedia-input=y -### DOCKER ###(实验性,有需要的删掉下面的注释) +### DOCKER ###(实验性,有需要的删掉下面的注释) #CONFIG_PACKAGE_luci-app-dockerman=y #CONFIG_DOCKER_KERNEL_OPTIONS=y #CONFIG_DOCKER_NET_ENCRYPT=y @@ -175,17 +179,3 @@ CONFIG_LIBCURL_OPENSSL=y #CONFIG_DOCKER_SECCOMP=y #CONFIG_DOCKER_STO_BTRFS=y #CONFIG_DOCKER_STO_EXT4=y - -### Video Support ### (实验性,有需要的删掉下面的注释) -#CONFIG_PACKAGE_kmod-backlight=y -#CONFIG_PACKAGE_kmod-drm=y -#CONFIG_PACKAGE_kmod-drm-kms-helper=y -#CONFIG_PACKAGE_kmod-drm-rockchip=y -#CONFIG_PACKAGE_kmod-fb=y -#CONFIG_PACKAGE_kmod-fb-cfb-copyarea=y -#CONFIG_PACKAGE_kmod-fb-cfb-fillrect=y -#CONFIG_PACKAGE_kmod-fb-cfb-imgblt=y -#CONFIG_PACKAGE_kmod-fb-sys-fops=y -#CONFIG_PACKAGE_kmod-fb-sys-ram=y -#CONFIG_PACKAGE_kmod-gpu-lima=y -#CONFIG_PACKAGE_kmod-multimedia-input=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index b8d756fc1..75fd1556c 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -162,10 +162,13 @@ CONFIG_LIBCURL_OPENSSL=y # CONFIG_LIBCURL_GNUTLS is not set # CONFIG_LIBCURL_NOSSL is not set +### Video Support ### +CONFIG_PACKAGE_kmod-drm-rockchip=y +CONFIG_PACKAGE_kmod-drm-panfrost=y +CONFIG_PACKAGE_kmod-multimedia-input=y ### DOCKER ###(实验性,有需要的删掉下面的注释) - #CONFIG_PACKAGE_luci-app-dockerman=y #CONFIG_DOCKER_KERNEL_OPTIONS=y #CONFIG_DOCKER_NET_ENCRYPT=y @@ -176,18 +179,3 @@ CONFIG_LIBCURL_OPENSSL=y #CONFIG_DOCKER_SECCOMP=y #CONFIG_DOCKER_STO_BTRFS=y #CONFIG_DOCKER_STO_EXT4=y - -### Video Support ### (实验性,有需要的删掉下面的注释) -#CONFIG_PACKAGE_kmod-backlight=y -#CONFIG_PACKAGE_kmod-drm=y -#CONFIG_PACKAGE_kmod-drm-kms-helper=y -#CONFIG_PACKAGE_kmod-drm-rockchip=y -#CONFIG_PACKAGE_kmod-fb=y -#CONFIG_PACKAGE_kmod-fb-cfb-copyarea=y -#CONFIG_PACKAGE_kmod-fb-cfb-fillrect=y -#CONFIG_PACKAGE_kmod-fb-cfb-imgblt=y -#CONFIG_PACKAGE_kmod-fb-sys-fops=y -#CONFIG_PACKAGE_kmod-fb-sys-ram=y -#CONFIG_PACKAGE_kmod-gpu-lima=y -#CONFIG_PACKAGE_kmod-multimedia-input=y - From 2fe13fa94691f57af600e1d146e7a46804322801 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 1 Dec 2021 16:07:04 +0800 Subject: [PATCH 220/244] CFS: Tweaks --- PATCH/CFS/695-01-cfs-xanmod-tweaks.patch | 253 +++++++++++++++++++++++ PATCH/CFS/695-02-cfs-zen-tweaks.patch | 53 +++++ 2 files changed, 306 insertions(+) create mode 100644 PATCH/CFS/695-01-cfs-xanmod-tweaks.patch create mode 100644 PATCH/CFS/695-02-cfs-zen-tweaks.patch diff --git a/PATCH/CFS/695-01-cfs-xanmod-tweaks.patch b/PATCH/CFS/695-01-cfs-xanmod-tweaks.patch new file mode 100644 index 000000000..525baef2a --- /dev/null +++ b/PATCH/CFS/695-01-cfs-xanmod-tweaks.patch @@ -0,0 +1,253 @@ +--- ./kernel/sched/fair.c 2021-07-12 17:43:46.345459700 -0700 ++++ ./kernel/sched/fair.c 2021-07-12 17:43:33.857280610 -0700 +@@ -6270,231 +6270,6 @@ + } + + /* +- * Predicts what cpu_util(@cpu) would return if @p was migrated (and enqueued) +- * to @dst_cpu. +- */ +-static unsigned long cpu_util_next(int cpu, struct task_struct *p, int dst_cpu) +-{ +- struct cfs_rq *cfs_rq = &cpu_rq(cpu)->cfs; +- unsigned long util_est, util = READ_ONCE(cfs_rq->avg.util_avg); +- +- /* +- * If @p migrates from @cpu to another, remove its contribution. Or, +- * if @p migrates from another CPU to @cpu, add its contribution. In +- * the other cases, @cpu is not impacted by the migration, so the +- * util_avg should already be correct. +- */ +- if (task_cpu(p) == cpu && dst_cpu != cpu) +- sub_positive(&util, task_util(p)); +- else if (task_cpu(p) != cpu && dst_cpu == cpu) +- util += task_util(p); +- +- if (sched_feat(UTIL_EST)) { +- util_est = READ_ONCE(cfs_rq->avg.util_est.enqueued); +- +- /* +- * During wake-up, the task isn't enqueued yet and doesn't +- * appear in the cfs_rq->avg.util_est.enqueued of any rq, +- * so just add it (if needed) to "simulate" what will be +- * cpu_util() after the task has been enqueued. +- */ +- if (dst_cpu == cpu) +- util_est += _task_util_est(p); +- +- util = max(util, util_est); +- } +- +- return min(util, capacity_orig_of(cpu)); +-} +- +-/* +- * compute_energy(): Estimates the energy that @pd would consume if @p was +- * migrated to @dst_cpu. compute_energy() predicts what will be the utilization +- * landscape of @pd's CPUs after the task migration, and uses the Energy Model +- * to compute what would be the energy if we decided to actually migrate that +- * task. +- */ +-static long +-compute_energy(struct task_struct *p, int dst_cpu, struct perf_domain *pd) +-{ +- struct cpumask *pd_mask = perf_domain_span(pd); +- unsigned long cpu_cap = arch_scale_cpu_capacity(cpumask_first(pd_mask)); +- unsigned long max_util = 0, sum_util = 0; +- int cpu; +- +- /* +- * The capacity state of CPUs of the current rd can be driven by CPUs +- * of another rd if they belong to the same pd. So, account for the +- * utilization of these CPUs too by masking pd with cpu_online_mask +- * instead of the rd span. +- * +- * If an entire pd is outside of the current rd, it will not appear in +- * its pd list and will not be accounted by compute_energy(). +- */ +- for_each_cpu_and(cpu, pd_mask, cpu_online_mask) { +- unsigned long cpu_util, util_cfs = cpu_util_next(cpu, p, dst_cpu); +- struct task_struct *tsk = cpu == dst_cpu ? p : NULL; +- +- /* +- * Busy time computation: utilization clamping is not +- * required since the ratio (sum_util / cpu_capacity) +- * is already enough to scale the EM reported power +- * consumption at the (eventually clamped) cpu_capacity. +- */ +- sum_util += schedutil_cpu_util(cpu, util_cfs, cpu_cap, +- ENERGY_UTIL, NULL); +- +- /* +- * Performance domain frequency: utilization clamping +- * must be considered since it affects the selection +- * of the performance domain frequency. +- * NOTE: in case RT tasks are running, by default the +- * FREQUENCY_UTIL's utilization can be max OPP. +- */ +- cpu_util = schedutil_cpu_util(cpu, util_cfs, cpu_cap, +- FREQUENCY_UTIL, tsk); +- max_util = max(max_util, cpu_util); +- } +- +- return em_pd_energy(pd->em_pd, max_util, sum_util); +-} +- +-/* +- * find_energy_efficient_cpu(): Find most energy-efficient target CPU for the +- * waking task. find_energy_efficient_cpu() looks for the CPU with maximum +- * spare capacity in each performance domain and uses it as a potential +- * candidate to execute the task. Then, it uses the Energy Model to figure +- * out which of the CPU candidates is the most energy-efficient. +- * +- * The rationale for this heuristic is as follows. In a performance domain, +- * all the most energy efficient CPU candidates (according to the Energy +- * Model) are those for which we'll request a low frequency. When there are +- * several CPUs for which the frequency request will be the same, we don't +- * have enough data to break the tie between them, because the Energy Model +- * only includes active power costs. With this model, if we assume that +- * frequency requests follow utilization (e.g. using schedutil), the CPU with +- * the maximum spare capacity in a performance domain is guaranteed to be among +- * the best candidates of the performance domain. +- * +- * In practice, it could be preferable from an energy standpoint to pack +- * small tasks on a CPU in order to let other CPUs go in deeper idle states, +- * but that could also hurt our chances to go cluster idle, and we have no +- * ways to tell with the current Energy Model if this is actually a good +- * idea or not. So, find_energy_efficient_cpu() basically favors +- * cluster-packing, and spreading inside a cluster. That should at least be +- * a good thing for latency, and this is consistent with the idea that most +- * of the energy savings of EAS come from the asymmetry of the system, and +- * not so much from breaking the tie between identical CPUs. That's also the +- * reason why EAS is enabled in the topology code only for systems where +- * SD_ASYM_CPUCAPACITY is set. +- * +- * NOTE: Forkees are not accepted in the energy-aware wake-up path because +- * they don't have any useful utilization data yet and it's not possible to +- * forecast their impact on energy consumption. Consequently, they will be +- * placed by find_idlest_cpu() on the least loaded CPU, which might turn out +- * to be energy-inefficient in some use-cases. The alternative would be to +- * bias new tasks towards specific types of CPUs first, or to try to infer +- * their util_avg from the parent task, but those heuristics could hurt +- * other use-cases too. So, until someone finds a better way to solve this, +- * let's keep things simple by re-using the existing slow path. +- */ +-static int find_energy_efficient_cpu(struct task_struct *p, int prev_cpu) +-{ +- unsigned long prev_delta = ULONG_MAX, best_delta = ULONG_MAX; +- struct root_domain *rd = cpu_rq(smp_processor_id())->rd; +- unsigned long cpu_cap, util, base_energy = 0; +- int cpu, best_energy_cpu = prev_cpu; +- struct sched_domain *sd; +- struct perf_domain *pd; +- +- rcu_read_lock(); +- pd = rcu_dereference(rd->pd); +- if (!pd || READ_ONCE(rd->overutilized)) +- goto fail; +- +- /* +- * Energy-aware wake-up happens on the lowest sched_domain starting +- * from sd_asym_cpucapacity spanning over this_cpu and prev_cpu. +- */ +- sd = rcu_dereference(*this_cpu_ptr(&sd_asym_cpucapacity)); +- while (sd && !cpumask_test_cpu(prev_cpu, sched_domain_span(sd))) +- sd = sd->parent; +- if (!sd) +- goto fail; +- +- sync_entity_load_avg(&p->se); +- if (!task_util_est(p)) +- goto unlock; +- +- for (; pd; pd = pd->next) { +- unsigned long cur_delta, spare_cap, max_spare_cap = 0; +- unsigned long base_energy_pd; +- int max_spare_cap_cpu = -1; +- +- /* Compute the 'base' energy of the pd, without @p */ +- base_energy_pd = compute_energy(p, -1, pd); +- base_energy += base_energy_pd; +- +- for_each_cpu_and(cpu, perf_domain_span(pd), sched_domain_span(sd)) { +- if (!cpumask_test_cpu(cpu, p->cpus_ptr)) +- continue; +- +- /* Skip CPUs that will be overutilized. */ +- util = cpu_util_next(cpu, p, cpu); +- cpu_cap = capacity_of(cpu); +- if (!fits_capacity(util, cpu_cap)) +- continue; +- +- /* Always use prev_cpu as a candidate. */ +- if (cpu == prev_cpu) { +- prev_delta = compute_energy(p, prev_cpu, pd); +- prev_delta -= base_energy_pd; +- best_delta = min(best_delta, prev_delta); +- } +- +- /* +- * Find the CPU with the maximum spare capacity in +- * the performance domain +- */ +- spare_cap = cpu_cap - util; +- if (spare_cap > max_spare_cap) { +- max_spare_cap = spare_cap; +- max_spare_cap_cpu = cpu; +- } +- } +- +- /* Evaluate the energy impact of using this CPU. */ +- if (max_spare_cap_cpu >= 0 && max_spare_cap_cpu != prev_cpu) { +- cur_delta = compute_energy(p, max_spare_cap_cpu, pd); +- cur_delta -= base_energy_pd; +- if (cur_delta < best_delta) { +- best_delta = cur_delta; +- best_energy_cpu = max_spare_cap_cpu; +- } +- } +- } +-unlock: +- rcu_read_unlock(); +- +- /* +- * Pick the best CPU if prev_cpu cannot be used, or if it saves at +- * least 6% of the energy used by prev_cpu. +- */ +- if (prev_delta == ULONG_MAX) +- return best_energy_cpu; +- +- if ((prev_delta - best_delta) > ((prev_delta + base_energy) >> 4)) +- return best_energy_cpu; +- +- return prev_cpu; +- +-fail: +- rcu_read_unlock(); +- +- return -1; +-} +- +-/* + * select_task_rq_fair: Select target runqueue for the waking task in domains + * that have the 'sd_flag' flag set. In practice, this is SD_BALANCE_WAKE, + * SD_BALANCE_FORK, or SD_BALANCE_EXEC. +@@ -6518,13 +6293,6 @@ + if (sd_flag & SD_BALANCE_WAKE) { + record_wakee(p); + +- if (sched_energy_enabled()) { +- new_cpu = find_energy_efficient_cpu(p, prev_cpu); +- if (new_cpu >= 0) +- return new_cpu; +- new_cpu = prev_cpu; +- } +- + want_affine = !wake_wide(p) && !wake_cap(p, cpu, prev_cpu) && + cpumask_test_cpu(cpu, p->cpus_ptr); + } +@@ -10700,3 +10468,4 @@ + #endif + } + EXPORT_SYMBOL_GPL(sched_trace_rd_span); ++ \ No newline at end of file diff --git a/PATCH/CFS/695-02-cfs-zen-tweaks.patch b/PATCH/CFS/695-02-cfs-zen-tweaks.patch new file mode 100644 index 000000000..d54307dff --- /dev/null +++ b/PATCH/CFS/695-02-cfs-zen-tweaks.patch @@ -0,0 +1,53 @@ +--- ./kernel/sched/fair.c 2021-07-07 05:24:58.000000000 -0700 ++++ ./kernel/sched/fair.c 2021-07-09 20:19:31.297847368 -0700 +@@ -35,8 +35,8 @@ + * + * (default: 6ms * (1 + ilog(ncpus)), units: nanoseconds) + */ +-unsigned int sysctl_sched_latency = 6000000ULL; +-static unsigned int normalized_sysctl_sched_latency = 6000000ULL; ++unsigned int sysctl_sched_latency = 4000000ULL; ++static unsigned int normalized_sysctl_sched_latency = 4000000ULL; + + /* + * The initial- and re-scaling of tunables is configurable +@@ -56,13 +56,13 @@ + * + * (default: 0.75 msec * (1 + ilog(ncpus)), units: nanoseconds) + */ +-unsigned int sysctl_sched_min_granularity = 750000ULL; +-static unsigned int normalized_sysctl_sched_min_granularity = 750000ULL; ++unsigned int sysctl_sched_min_granularity = 400000ULL; ++static unsigned int normalized_sysctl_sched_min_granularity = 400000ULL; + + /* + * This value is kept at sysctl_sched_latency/sysctl_sched_min_granularity + */ +-static unsigned int sched_nr_latency = 8; ++static unsigned int sched_nr_latency = 10; + + /* + * After fork, child runs first. If set to 0 (default) then +@@ -79,10 +79,10 @@ + * + * (default: 1 msec * (1 + ilog(ncpus)), units: nanoseconds) + */ +-unsigned int sysctl_sched_wakeup_granularity = 1000000UL; +-static unsigned int normalized_sysctl_sched_wakeup_granularity = 1000000UL; ++unsigned int sysctl_sched_wakeup_granularity = 500000UL; ++static unsigned int normalized_sysctl_sched_wakeup_granularity = 500000UL; + +-const_debug unsigned int sysctl_sched_migration_cost = 500000UL; ++const_debug unsigned int sysctl_sched_migration_cost = 250000UL; + + int sched_thermal_decay_shift; + static int __init setup_sched_thermal_decay_shift(char *str) +@@ -133,7 +133,7 @@ + * + * (default: 5 msec, units: microseconds) + */ +-unsigned int sysctl_sched_cfs_bandwidth_slice = 5000UL; ++unsigned int sysctl_sched_cfs_bandwidth_slice = 3000UL; + #endif + + static inline void update_load_add(struct load_weight *lw, unsigned long inc) \ No newline at end of file From ea665d140ab0634cf2744f42e759612b95901373 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 1 Dec 2021 16:10:55 +0800 Subject: [PATCH 221/244] trojan-plus: link symbol to trojan --- SCRIPTS/02_prepare_package.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 4f3d7e1f9..62f434553 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -253,7 +253,7 @@ svn co https://github.com/Lienol/openwrt-packages/trunk/net/https-dns-proxy feed svn co https://github.com/xiaorouji/openwrt-passwall/trunk/tcping package/new/tcping svn co https://github.com/xiaorouji/openwrt-passwall/trunk/trojan-go package/new/trojan-go svn co https://github.com/xiaorouji/openwrt-passwall/trunk/brook package/new/brook -svn co https://github.com/xiaorouji/openwrt-passwall/trunk/trojan-plus package/new/trojan-plus +svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/trojan-plus package/new/trojan-plus svn co https://github.com/xiaorouji/openwrt-passwall/trunk/ssocks package/new/ssocks svn co https://github.com/xiaorouji/openwrt-passwall/trunk/hysteria package/new/hysteria # qBittorrent 下载 @@ -284,7 +284,6 @@ svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/dns2socks package svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/redsocks2 package/lean/redsocks2 svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/ipt2socks package/lean/ipt2socks svn co https://github.com/coolsnowwolf/packages/trunk/net/shadowsocks-libev package/lean/shadowsocks-libev -svn co https://github.com/fw876/helloworld/trunk/trojan package/lean/trojan svn co https://github.com/fw876/helloworld/trunk/simple-obfs package/lean/simple-obfs svn co https://github.com/fw876/helloworld/trunk/naiveproxy package/lean/naiveproxy svn co https://github.com/fw876/helloworld/trunk/v2ray-core package/lean/v2ray-core From ea1c6c7f0c9c40114a4e7620d4b2360ebf5e001d Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sat, 4 Dec 2021 14:49:23 +0800 Subject: [PATCH 222/244] Docker: enable docker support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit with udp workaround. ps. 都有docker了还要个毛线jd签到luci --- .github/workflows/R2C-OpenWrt.yml | 4 ++-- .github/workflows/R2S-OpenWrt.yml | 4 ++-- .github/workflows/R4S-OpenWrt.yml | 4 ++-- .github/workflows/X86-OpenWrt.yml | 4 ++-- README.md | 1 + SCRIPTS/02_prepare_package.sh | 6 ++++++ SEED/R2C/config.seed | 27 ++++++++++++++------------- SEED/R2S/config.seed | 27 ++++++++++++++------------- SEED/R4S/config.seed | 27 ++++++++++++++------------- SEED/X86/config.seed | 27 ++++++++++++++------------- 10 files changed, 71 insertions(+), 60 deletions(-) diff --git a/.github/workflows/R2C-OpenWrt.yml b/.github/workflows/R2C-OpenWrt.yml index 5d27b768c..2deefb539 100644 --- a/.github/workflows/R2C-OpenWrt.yml +++ b/.github/workflows/R2C-OpenWrt.yml @@ -120,8 +120,8 @@ jobs: gzip --best *.img ls -Ahl sha256sum openwrt*r2c* | tee R2C-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}.sha256sum - zip R2C-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}-ext4.zip *r2c*ext4* - zip R2C-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}-sfs.zip *r2c*squashfs* + zip R2C-GC404-Docker-$(date +%Y-%m-%d)-${{ env.latest_release }}-ext4.zip *r2c*ext4* + zip R2C-GC404-Docker-$(date +%Y-%m-%d)-${{ env.latest_release }}-sfs.zip *r2c*squashfs* ls -Ahl - name: Upload artifact uses: actions/upload-artifact@main diff --git a/.github/workflows/R2S-OpenWrt.yml b/.github/workflows/R2S-OpenWrt.yml index eb06007df..da8906c5d 100644 --- a/.github/workflows/R2S-OpenWrt.yml +++ b/.github/workflows/R2S-OpenWrt.yml @@ -120,8 +120,8 @@ jobs: gzip --best *.img ls -Ahl sha256sum openwrt*r2s* | tee R2S-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}.sha256sum - zip R2S-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}-ext4.zip *r2s*ext4* - zip R2S-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}-sfs.zip *r2s*squashfs* + zip R2S-GC404-Docker-$(date +%Y-%m-%d)-${{ env.latest_release }}-ext4.zip *r2s*ext4* + zip R2S-GC404-Docker-$(date +%Y-%m-%d)-${{ env.latest_release }}-sfs.zip *r2s*squashfs* ls -Ahl - name: Upload artifact uses: actions/upload-artifact@main diff --git a/.github/workflows/R4S-OpenWrt.yml b/.github/workflows/R4S-OpenWrt.yml index d1c637fe5..d596510e2 100644 --- a/.github/workflows/R4S-OpenWrt.yml +++ b/.github/workflows/R4S-OpenWrt.yml @@ -120,8 +120,8 @@ jobs: gzip --best *.img ls -Ahl sha256sum openwrt*r4s* | tee R4S-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}.sha256sum - zip R4S-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}-ext4.zip *r4s*ext4* - zip R4S-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}-sfs.zip *r4s*squashfs* + zip R4S-GC404-Docker-$(date +%Y-%m-%d)-${{ env.latest_release }}-ext4.zip *r4s*ext4* + zip R4S-GC404-Docker-$(date +%Y-%m-%d)-${{ env.latest_release }}-sfs.zip *r4s*squashfs* ls -Ahl - name: Upload artifact uses: actions/upload-artifact@main diff --git a/.github/workflows/X86-OpenWrt.yml b/.github/workflows/X86-OpenWrt.yml index 5cce701b2..64057a976 100644 --- a/.github/workflows/X86-OpenWrt.yml +++ b/.github/workflows/X86-OpenWrt.yml @@ -120,8 +120,8 @@ jobs: gzip --best *.img ls -Ahl sha256sum openwrt*x86* | tee X86-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}.sha256sum - zip X86-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}-ext4.zip *ext4-combined* - zip X86-GC404-$(date +%Y-%m-%d)-${{ env.latest_release }}-sfs.zip *squashfs-combined* + zip X86-GC404-Docker-$(date +%Y-%m-%d)-${{ env.latest_release }}-ext4.zip *ext4-combined* + zip X86-GC404-Docker-$(date +%Y-%m-%d)-${{ env.latest_release }}-sfs.zip *squashfs-combined* ls -Ahl - name: Upload artifact uses: actions/upload-artifact@main diff --git a/README.md b/README.md index 08696d3bd..e21816681 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ - 插件包含:SSRP,PassWall,OpenClash,AdguardHome,微信推送,网易云解锁,SQM,DNSProxy,网络唤醒,DDNS,迅雷快鸟,UPNP,FullCone(防火墙中开启,默认开启),流量分载,irq优化,京东签到,Zerotier,FRPC,FRPS,无线打印,流量监控,过滤军刀,R2S-OLED - ss协议在armv8上实现了aes硬件加速(请仅使用aead加密的连接方式) - 集成并默认启用了BBRv2,LRNG +- 集成了Docker,并针对特殊问题做了一些workaround(关于如何挂载剩余空间到 /opt/docker 的姿势请自行研究) ,从非Docker版本升级至Docker版本请执行恢复出厂设置,并手动重新配置路由器;请勿在Docker版上恢复非Docker版的备份配置 - 如有任何问题,请先尝试ssh进入后台,输入fuck后回车,等待机器重启后确认问题是否已经解决 ### 下载 diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 62f434553..95ca9d392 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -187,6 +187,12 @@ svn co https://github.com/kenzok8/openwrt-packages/trunk/luci-app-aliddns feeds/ ln -sf ../../../feeds/luci/applications/luci-app-aliddns ./package/feeds/luci/luci-app-aliddns # Docker 容器(会导致 OpenWrt 出现 UDP 转发问题,慎用) sed -i 's/+docker/+docker \\\n\t+dockerd/g' ./feeds/luci/applications/luci-app-dockerman/Makefile +sed -i '/sysctl.d/d' feeds/packages/utils/dockerd/Makefile +# DiskMan +mkdir -p package/new/luci-app-diskman && \ +wget https://raw.githubusercontent.com/lisaac/luci-app-diskman/master/applications/luci-app-diskman/Makefile -O package/new/luci-app-diskman/Makefile +mkdir -p package/new/parted && \ +wget https://raw.githubusercontent.com/lisaac/luci-app-diskman/master/Parted.Makefile -O package/new/parted/Makefile # Dnsfilter git clone --depth 1 https://github.com/kiddin9/luci-app-dnsfilter.git package/new/luci-app-dnsfilter # Dnsproxy diff --git a/SEED/R2C/config.seed b/SEED/R2C/config.seed index 703cb4454..b1177ad06 100644 --- a/SEED/R2C/config.seed +++ b/SEED/R2C/config.seed @@ -106,7 +106,7 @@ CONFIG_PACKAGE_luci-app-frpc=y CONFIG_PACKAGE_frpc=y CONFIG_PACKAGE_luci-app-frps=y CONFIG_PACKAGE_frps=y -CONFIG_PACKAGE_luci-app-jd-dailybonus=y +#CONFIG_PACKAGE_luci-app-jd-dailybonus=y #CONFIG_PACKAGE_luci-app-oled=y CONFIG_PACKAGE_luci-app-openclash=y CONFIG_PACKAGE_luci-app-opkg=y @@ -167,15 +167,16 @@ CONFIG_PACKAGE_kmod-drm-rockchip=y CONFIG_PACKAGE_kmod-drm-lima=y CONFIG_PACKAGE_kmod-multimedia-input=y - -### DOCKER ###(实验性,有需要的删掉下面的注释) -#CONFIG_PACKAGE_luci-app-dockerman=y -#CONFIG_DOCKER_KERNEL_OPTIONS=y -#CONFIG_DOCKER_NET_ENCRYPT=y -#CONFIG_DOCKER_NET_MACVLAN=y -#CONFIG_DOCKER_NET_OVERLAY=y -#CONFIG_DOCKER_NET_TFTP=y -#CONFIG_DOCKER_RES_SHAPE=y -#CONFIG_DOCKER_SECCOMP=y -#CONFIG_DOCKER_STO_BTRFS=y -#CONFIG_DOCKER_STO_EXT4=y +### DOCKER ### +CONFIG_PACKAGE_luci-app-dockerman=y +CONFIG_PACKAGE_luci-app-diskman=y +CONFIG_PACKAGE_block-mount=y +CONFIG_DOCKER_KERNEL_OPTIONS=y +CONFIG_DOCKER_NET_ENCRYPT=y +CONFIG_DOCKER_NET_MACVLAN=y +CONFIG_DOCKER_NET_OVERLAY=y +CONFIG_DOCKER_NET_TFTP=y +CONFIG_DOCKER_RES_SHAPE=y +CONFIG_DOCKER_SECCOMP=y +CONFIG_DOCKER_STO_BTRFS=y +CONFIG_DOCKER_STO_EXT4=y diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 6693b8fc9..b44e3f817 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -106,7 +106,7 @@ CONFIG_PACKAGE_luci-app-frpc=y CONFIG_PACKAGE_frpc=y CONFIG_PACKAGE_luci-app-frps=y CONFIG_PACKAGE_frps=y -CONFIG_PACKAGE_luci-app-jd-dailybonus=y +#CONFIG_PACKAGE_luci-app-jd-dailybonus=y CONFIG_PACKAGE_luci-app-oled=y CONFIG_PACKAGE_luci-app-openclash=y CONFIG_PACKAGE_luci-app-opkg=y @@ -167,15 +167,16 @@ CONFIG_PACKAGE_kmod-drm-rockchip=y CONFIG_PACKAGE_kmod-drm-lima=y CONFIG_PACKAGE_kmod-multimedia-input=y - -### DOCKER ###(实验性,有需要的删掉下面的注释) -#CONFIG_PACKAGE_luci-app-dockerman=y -#CONFIG_DOCKER_KERNEL_OPTIONS=y -#CONFIG_DOCKER_NET_ENCRYPT=y -#CONFIG_DOCKER_NET_MACVLAN=y -#CONFIG_DOCKER_NET_OVERLAY=y -#CONFIG_DOCKER_NET_TFTP=y -#CONFIG_DOCKER_RES_SHAPE=y -#CONFIG_DOCKER_SECCOMP=y -#CONFIG_DOCKER_STO_BTRFS=y -#CONFIG_DOCKER_STO_EXT4=y +### DOCKER ### +CONFIG_PACKAGE_luci-app-dockerman=y +CONFIG_PACKAGE_luci-app-diskman=y +CONFIG_PACKAGE_block-mount=y +CONFIG_DOCKER_KERNEL_OPTIONS=y +CONFIG_DOCKER_NET_ENCRYPT=y +CONFIG_DOCKER_NET_MACVLAN=y +CONFIG_DOCKER_NET_OVERLAY=y +CONFIG_DOCKER_NET_TFTP=y +CONFIG_DOCKER_RES_SHAPE=y +CONFIG_DOCKER_SECCOMP=y +CONFIG_DOCKER_STO_BTRFS=y +CONFIG_DOCKER_STO_EXT4=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index 75fd1556c..bce56fa7b 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -107,7 +107,7 @@ CONFIG_PACKAGE_luci-app-frpc=y CONFIG_PACKAGE_frpc=y CONFIG_PACKAGE_luci-app-frps=y CONFIG_PACKAGE_frps=y -CONFIG_PACKAGE_luci-app-jd-dailybonus=y +#CONFIG_PACKAGE_luci-app-jd-dailybonus=y CONFIG_PACKAGE_luci-app-openclash=y CONFIG_PACKAGE_luci-app-opkg=y #CONFIG_PACKAGE_luci-app-qbittorrent=y @@ -167,15 +167,16 @@ CONFIG_PACKAGE_kmod-drm-rockchip=y CONFIG_PACKAGE_kmod-drm-panfrost=y CONFIG_PACKAGE_kmod-multimedia-input=y - -### DOCKER ###(实验性,有需要的删掉下面的注释) -#CONFIG_PACKAGE_luci-app-dockerman=y -#CONFIG_DOCKER_KERNEL_OPTIONS=y -#CONFIG_DOCKER_NET_ENCRYPT=y -#CONFIG_DOCKER_NET_MACVLAN=y -#CONFIG_DOCKER_NET_OVERLAY=y -#CONFIG_DOCKER_NET_TFTP=y -#CONFIG_DOCKER_RES_SHAPE=y -#CONFIG_DOCKER_SECCOMP=y -#CONFIG_DOCKER_STO_BTRFS=y -#CONFIG_DOCKER_STO_EXT4=y +### DOCKER ### +CONFIG_PACKAGE_luci-app-dockerman=y +CONFIG_PACKAGE_luci-app-diskman=y +CONFIG_PACKAGE_block-mount=y +CONFIG_DOCKER_KERNEL_OPTIONS=y +CONFIG_DOCKER_NET_ENCRYPT=y +CONFIG_DOCKER_NET_MACVLAN=y +CONFIG_DOCKER_NET_OVERLAY=y +CONFIG_DOCKER_NET_TFTP=y +CONFIG_DOCKER_RES_SHAPE=y +CONFIG_DOCKER_SECCOMP=y +CONFIG_DOCKER_STO_BTRFS=y +CONFIG_DOCKER_STO_EXT4=y diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index 0548aca2f..2adf69560 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -107,7 +107,7 @@ CONFIG_PACKAGE_luci-app-frpc=y CONFIG_PACKAGE_frpc=y CONFIG_PACKAGE_luci-app-frps=y CONFIG_PACKAGE_frps=y -CONFIG_PACKAGE_luci-app-jd-dailybonus=y +#CONFIG_PACKAGE_luci-app-jd-dailybonus=y CONFIG_PACKAGE_luci-app-openclash=y CONFIG_PACKAGE_luci-app-opkg=y #CONFIG_PACKAGE_luci-app-qbittorrent=y @@ -159,15 +159,16 @@ CONFIG_LIBCURL_OPENSSL=y # CONFIG_LIBCURL_GNUTLS is not set # CONFIG_LIBCURL_NOSSL is not set -### DOCKER ###(实验性,有需要的删掉下面的注释) - -#CONFIG_PACKAGE_luci-app-dockerman=y -#CONFIG_DOCKER_KERNEL_OPTIONS=y -#CONFIG_DOCKER_NET_ENCRYPT=y -#CONFIG_DOCKER_NET_MACVLAN=y -#CONFIG_DOCKER_NET_OVERLAY=y -#CONFIG_DOCKER_NET_TFTP=y -#CONFIG_DOCKER_RES_SHAPE=y -#CONFIG_DOCKER_SECCOMP=y -#CONFIG_DOCKER_STO_BTRFS=y -#CONFIG_DOCKER_STO_EXT4=y +### DOCKER ### +CONFIG_PACKAGE_luci-app-dockerman=y +CONFIG_PACKAGE_luci-app-diskman=y +CONFIG_PACKAGE_block-mount=y +CONFIG_DOCKER_KERNEL_OPTIONS=y +CONFIG_DOCKER_NET_ENCRYPT=y +CONFIG_DOCKER_NET_MACVLAN=y +CONFIG_DOCKER_NET_OVERLAY=y +CONFIG_DOCKER_NET_TFTP=y +CONFIG_DOCKER_RES_SHAPE=y +CONFIG_DOCKER_SECCOMP=y +CONFIG_DOCKER_STO_BTRFS=y +CONFIG_DOCKER_STO_EXT4=y From eefcf296753002287abf11883828f6a7b75efa3c Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 9 Dec 2021 12:44:41 +0800 Subject: [PATCH 223/244] DPDK: initial support --- .github/workflows/R2C-OpenWrt.yml | 1 + .github/workflows/R2S-OpenWrt.yml | 1 + .github/workflows/R4S-OpenWrt.yml | 1 + .github/workflows/X86-OpenWrt.yml | 1 + SCRIPTS/02_prepare_package.sh | 2 ++ 5 files changed, 6 insertions(+) diff --git a/.github/workflows/R2C-OpenWrt.yml b/.github/workflows/R2C-OpenWrt.yml index 2deefb539..6c80f976d 100644 --- a/.github/workflows/R2C-OpenWrt.yml +++ b/.github/workflows/R2C-OpenWrt.yml @@ -44,6 +44,7 @@ jobs: sudo -E apt-get update -y sudo -E apt-get install -y build-essential rsync asciidoc binutils bzip2 gawk gettext git libncurses5-dev libz-dev patch unzip zlib1g-dev lib32gcc1 libc6-dev-i386 subversion flex uglifyjs git-core p7zip p7zip-full msmtp libssl-dev texinfo libreadline-dev libglib2.0-dev xmlto qemu-utils upx libelf-dev autoconf automake libtool autopoint ccache curl wget vim nano python3 python3-pip python3-ply haveged lrzsz device-tree-compiler scons wget -qO - https://raw.githubusercontent.com/friendlyarm/build-env-on-ubuntu-bionic/master/install.sh | sed 's/python-/python3-/g' | /bin/bash + pip3 install pyelftools sudo -E apt-get clean -y git config --global user.name 'GitHub Actions' && git config --global user.email 'noreply@github.com' df -h diff --git a/.github/workflows/R2S-OpenWrt.yml b/.github/workflows/R2S-OpenWrt.yml index da8906c5d..9633bd296 100644 --- a/.github/workflows/R2S-OpenWrt.yml +++ b/.github/workflows/R2S-OpenWrt.yml @@ -44,6 +44,7 @@ jobs: sudo -E apt-get update -y sudo -E apt-get install -y build-essential rsync asciidoc binutils bzip2 gawk gettext git libncurses5-dev libz-dev patch unzip zlib1g-dev lib32gcc1 libc6-dev-i386 subversion flex uglifyjs git-core p7zip p7zip-full msmtp libssl-dev texinfo libreadline-dev libglib2.0-dev xmlto qemu-utils upx libelf-dev autoconf automake libtool autopoint ccache curl wget vim nano python3 python3-pip python3-ply haveged lrzsz device-tree-compiler scons wget -qO - https://raw.githubusercontent.com/friendlyarm/build-env-on-ubuntu-bionic/master/install.sh | sed 's/python-/python3-/g' | /bin/bash + pip3 install pyelftools sudo -E apt-get clean -y git config --global user.name 'GitHub Actions' && git config --global user.email 'noreply@github.com' df -h diff --git a/.github/workflows/R4S-OpenWrt.yml b/.github/workflows/R4S-OpenWrt.yml index d596510e2..1424453f3 100644 --- a/.github/workflows/R4S-OpenWrt.yml +++ b/.github/workflows/R4S-OpenWrt.yml @@ -44,6 +44,7 @@ jobs: sudo -E apt-get update -y sudo -E apt-get install -y build-essential rsync asciidoc binutils bzip2 gawk gettext git libncurses5-dev libz-dev patch unzip zlib1g-dev lib32gcc1 libc6-dev-i386 subversion flex uglifyjs git-core p7zip p7zip-full msmtp libssl-dev texinfo libreadline-dev libglib2.0-dev xmlto qemu-utils upx libelf-dev autoconf automake libtool autopoint ccache curl wget vim nano python3 python3-pip python3-ply haveged lrzsz device-tree-compiler scons wget -qO - https://raw.githubusercontent.com/friendlyarm/build-env-on-ubuntu-bionic/master/install.sh | sed 's/python-/python3-/g' | /bin/bash + pip3 install pyelftools sudo -E apt-get clean -y git config --global user.name 'GitHub Actions' && git config --global user.email 'noreply@github.com' df -h diff --git a/.github/workflows/X86-OpenWrt.yml b/.github/workflows/X86-OpenWrt.yml index 64057a976..2c0fb54e6 100644 --- a/.github/workflows/X86-OpenWrt.yml +++ b/.github/workflows/X86-OpenWrt.yml @@ -44,6 +44,7 @@ jobs: sudo -E apt-get update -y sudo -E apt-get install -y build-essential rsync asciidoc binutils bzip2 gawk gettext git libncurses5-dev libz-dev patch unzip zlib1g-dev lib32gcc1 libc6-dev-i386 subversion flex uglifyjs git-core p7zip p7zip-full msmtp libssl-dev texinfo libreadline-dev libglib2.0-dev xmlto qemu-utils upx libelf-dev autoconf automake libtool autopoint ccache curl wget vim nano python3 python3-pip python3-ply haveged lrzsz device-tree-compiler scons wget -qO - https://raw.githubusercontent.com/friendlyarm/build-env-on-ubuntu-bionic/master/install.sh | sed 's/python-/python3-/g' | /bin/bash + pip3 install pyelftools sudo -E apt-get clean -y git config --global user.name 'GitHub Actions' && git config --global user.email 'noreply@github.com' df -h diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 95ca9d392..a903d6675 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -109,6 +109,8 @@ sed -i 's,noinitrd,noinitrd mitigations=off,g' target/linux/x86/image/grub-pc.cf svn co https://github.com/immortalwrt/immortalwrt/branches/openwrt-21.02/package/emortal/autocore package/lean/autocore rm -rf ./feeds/packages/utils/coremark svn co https://github.com/immortalwrt/packages/trunk/utils/coremark feeds/packages/utils/coremark +# DPDK +svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/dpdk package/new/dpdk # 更换 Nodejs 版本 rm -rf ./feeds/packages/lang/node svn co https://github.com/nxhack/openwrt-node-packages/trunk/node feeds/packages/lang/node From 1dc13ce70273dced4a4f7ace120eddb63e05a449 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 15 Dec 2021 14:24:59 +0800 Subject: [PATCH 224/244] fixes IPv6 packet drop when using software flow offload --- SCRIPTS/02_prepare_package.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index a903d6675..728565379 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -22,6 +22,8 @@ sed -i '/mirror02/d' scripts/download.pl echo "net.netfilter.nf_conntrack_helper = 1" >>./package/kernel/linux/files/sysctl-nf-conntrack.conf ### 必要的 Patches ### +# offload bug fix +wget -qO - https://github.com/openwrt/openwrt/pull/4849.patch | patch -p1 # TCP performance optimizations backport from linux/net-next cp -f ../PATCH/backport/695-tcp-optimizations.patch ./target/linux/generic/backport-5.4/695-tcp-optimizations.patch # introduce "le9" Linux kernel patches From c1bc1bc227a5157f9cf927a0fa7d83967460ba47 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 16 Dec 2021 21:27:50 +0800 Subject: [PATCH 225/244] Some fixes (#332) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Docker: Fix container create on dockerman luci * luci-app-dockerman 使用oci引擎标准运行容器 * 添加 cgroups 内核支持,满足 filesystem bundle 预期创建以及容器资源控制 --- SCRIPTS/02_prepare_package.sh | 6 +++++- SEED/R2C/config.seed | 3 ++- SEED/R2S/config.seed | 3 ++- SEED/R4S/config.seed | 3 ++- SEED/X86/config.seed | 3 ++- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 728565379..484baeaa3 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -158,6 +158,8 @@ sed -i '/\t)/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DI sed -i '/init/d' feeds/packages/net/adguardhome/Makefile # Argon 主题 git clone https://github.com/jerrykuku/luci-theme-argon.git package/new/luci-theme-argon +wget -P package/new/luci-theme-argon/htdocs/luci-static/argon/background/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/5808303.jpg +rm -rf ./package/new/luci-theme-argon/htdocs/luci-static/argon/background/README.md #pushd package/new/luci-theme-argon #git checkout 3b15d06 #popd @@ -170,7 +172,7 @@ svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-autorebo # Boost 通用即插即用 svn co https://github.com/QiuSimons/slim-wrt/branches/main/slimapps/application/luci-app-boostupnp package/new/luci-app-boostupnp rm -rf ./feeds/packages/net/miniupnpd -svn co https://github.com/openwrt/packages/trunk/net/miniupnpd feeds/packages/net/miniupnpd +svn co https://github.com/coolsnowwolf/packages/trunk/net/miniupnpd feeds/packages/net/miniupnpd # ChinaDNS git clone -b luci --depth 1 https://github.com/QiuSimons/openwrt-chinadns-ng.git package/new/luci-app-chinadns-ng svn co https://github.com/xiaorouji/openwrt-passwall/trunk/chinadns-ng package/new/chinadns-ng @@ -371,6 +373,8 @@ pushd feeds/luci/applications/luci-app-zerotier bash move_2_services.sh popd ln -sf ../../../feeds/luci/applications/luci-app-zerotier ./package/feeds/luci/luci-app-zerotier +rm -rf ./feeds/packages/net/zerotier +svn co https://github.com/openwrt/packages/trunk/net/zerotier feeds/packages/net/zerotier rm -rf ./feeds/packages/net/zerotier/files/etc/init.d/zerotier sed -i '/Default,one/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $(PKG_BUILD_DIR)/zerotier-one' feeds/packages/net/zerotier/Makefile # 翻译及部分功能优化 diff --git a/SEED/R2C/config.seed b/SEED/R2C/config.seed index b1177ad06..51514ebfb 100644 --- a/SEED/R2C/config.seed +++ b/SEED/R2C/config.seed @@ -93,7 +93,7 @@ CONFIG_PACKAGE_luci-app-socat=y CONFIG_PACKAGE_luci-app-argon-config=y CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y -CONFIG_PACKAGE_luci-app-boostupnp=y +#CONFIG_PACKAGE_luci-app-boostupnp=y CONFIG_PACKAGE_luci-app-mosdns=y CONFIG_PACKAGE_luci-app-oaf=y CONFIG_PACKAGE_luci-app-cpufreq=y @@ -171,6 +171,7 @@ CONFIG_PACKAGE_kmod-multimedia-input=y CONFIG_PACKAGE_luci-app-dockerman=y CONFIG_PACKAGE_luci-app-diskman=y CONFIG_PACKAGE_block-mount=y +CONFIG_DOCKER_CGROUP_OPTIONS=y CONFIG_DOCKER_KERNEL_OPTIONS=y CONFIG_DOCKER_NET_ENCRYPT=y CONFIG_DOCKER_NET_MACVLAN=y diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index b44e3f817..e31310d2e 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -93,7 +93,7 @@ CONFIG_PACKAGE_luci-app-socat=y CONFIG_PACKAGE_luci-app-argon-config=y CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y -CONFIG_PACKAGE_luci-app-boostupnp=y +#CONFIG_PACKAGE_luci-app-boostupnp=y CONFIG_PACKAGE_luci-app-mosdns=y CONFIG_PACKAGE_luci-app-oaf=y CONFIG_PACKAGE_luci-app-cpufreq=y @@ -171,6 +171,7 @@ CONFIG_PACKAGE_kmod-multimedia-input=y CONFIG_PACKAGE_luci-app-dockerman=y CONFIG_PACKAGE_luci-app-diskman=y CONFIG_PACKAGE_block-mount=y +CONFIG_DOCKER_CGROUP_OPTIONS=y CONFIG_DOCKER_KERNEL_OPTIONS=y CONFIG_DOCKER_NET_ENCRYPT=y CONFIG_DOCKER_NET_MACVLAN=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index bce56fa7b..1477fceb8 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -94,7 +94,7 @@ CONFIG_PACKAGE_luci-app-socat=y CONFIG_PACKAGE_luci-app-argon-config=y CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y -CONFIG_PACKAGE_luci-app-boostupnp=y +#CONFIG_PACKAGE_luci-app-boostupnp=y CONFIG_PACKAGE_luci-app-mosdns=y CONFIG_PACKAGE_luci-app-oaf=y CONFIG_PACKAGE_luci-app-cpufreq=y @@ -171,6 +171,7 @@ CONFIG_PACKAGE_kmod-multimedia-input=y CONFIG_PACKAGE_luci-app-dockerman=y CONFIG_PACKAGE_luci-app-diskman=y CONFIG_PACKAGE_block-mount=y +CONFIG_DOCKER_CGROUP_OPTIONS=y CONFIG_DOCKER_KERNEL_OPTIONS=y CONFIG_DOCKER_NET_ENCRYPT=y CONFIG_DOCKER_NET_MACVLAN=y diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index 2adf69560..e0ca7bd27 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -94,7 +94,7 @@ CONFIG_PACKAGE_luci-app-socat=y CONFIG_PACKAGE_luci-app-argon-config=y CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y -CONFIG_PACKAGE_luci-app-boostupnp=y +#CONFIG_PACKAGE_luci-app-boostupnp=y CONFIG_PACKAGE_luci-app-mosdns=y CONFIG_PACKAGE_luci-app-oaf=y CONFIG_PACKAGE_luci-app-cpufreq=y @@ -163,6 +163,7 @@ CONFIG_LIBCURL_OPENSSL=y CONFIG_PACKAGE_luci-app-dockerman=y CONFIG_PACKAGE_luci-app-diskman=y CONFIG_PACKAGE_block-mount=y +CONFIG_DOCKER_CGROUP_OPTIONS=y CONFIG_DOCKER_KERNEL_OPTIONS=y CONFIG_DOCKER_NET_ENCRYPT=y CONFIG_DOCKER_NET_MACVLAN=y From 3d7328d55bda739d6d5b5a6409e69cbfb610a70e Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 20 Dec 2021 14:34:42 +0800 Subject: [PATCH 226/244] Update white.list --- PATCH/files/etc/ssrplus/white.list | 1 + 1 file changed, 1 insertion(+) diff --git a/PATCH/files/etc/ssrplus/white.list b/PATCH/files/etc/ssrplus/white.list index 0f7abfd0e..74174a274 100644 --- a/PATCH/files/etc/ssrplus/white.list +++ b/PATCH/files/etc/ssrplus/white.list @@ -8,3 +8,4 @@ checkip.dyndns.org teamviewer.com bing.com api.ipify.org +epicgames.com From e77463206eca0eee8d1386c6b20961a207461df6 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 20 Dec 2021 16:31:03 +0800 Subject: [PATCH 227/244] use 404delivr --- SCRIPTS/02_prepare_package.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 484baeaa3..c26e0266b 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -319,9 +319,9 @@ pushd package/lean/luci-app-ssr-plus sed -i 's,default n,default y,g' Makefile sed -i '/Plugin:/d' Makefile sed -i '/result.encrypt_method/a\result.fast_open = "1"' root/usr/share/shadowsocksr/subscribe.lua -sed -i 's,ispip.clang.cn/all_cn,cdn.jsdelivr.net/gh/QiuSimons/Chnroute@master/dist/chnroute/chnroute,' root/etc/init.d/shadowsocksr +sed -i 's,ispip.clang.cn/all_cn,gh.404delivr.workers.dev/https://github.com/QiuSimons/Chnroute/raw/master/dist/chnroute/chnroute,' root/etc/init.d/shadowsocksr sed -i 's,YW5vbnltb3Vz/domain-list-community/release/gfwlist.txt,Loyalsoldier/v2ray-rules-dat/release/gfw.txt,' root/etc/init.d/shadowsocksr -sed -i '/Clang.CN.CIDR/a\o:value("https://cdn.jsdelivr.net/gh/QiuSimons/Chnroute@master/dist/chnroute/chnroute.txt", translate("QiuSimons/Chnroute"))' luasrc/model/cbi/shadowsocksr/advanced.lua +sed -i '/Clang.CN.CIDR/a\o:value("https://gh.404delivr.workers.dev/https://github.com/QiuSimons/Chnroute/raw/master/dist/chnroute/chnroute.txt", translate("QiuSimons/Chnroute"))' luasrc/model/cbi/shadowsocksr/advanced.lua popd # socat svn co https://github.com/Lienol/openwrt-package/trunk/luci-app-socat package/new/luci-app-socat From 7fef46422da564527e26dcf2b904693461ddba31 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 23 Dec 2021 14:06:22 +0800 Subject: [PATCH 228/244] Some fixes --- README.md | 2 +- SCRIPTS/02_prepare_package.sh | 1 + SCRIPTS/R2S/02_target_only.sh | 7 +++---- SCRIPTS/R4S/02_target_only.sh | 3 +-- SEED/R2C/config.seed | 1 + SEED/R2S/config.seed | 1 + SEED/R4S/config.seed | 1 + 7 files changed, 9 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index e21816681..b881135b2 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ - 可无脑 opkg kmod - R2C/R2S核心频率1.6(交换了LAN WAN),R4S核心频率2.2/1.8(建议使用5v4a电源,死机大多数情况下,都是因为你用的电源过于垃圾,另外,你也可以选择使用自带的app限制最大频率,茄子🍆) - O3 编译,CFLAG优化 -- 插件包含:SSRP,PassWall,OpenClash,AdguardHome,微信推送,网易云解锁,SQM,DNSProxy,网络唤醒,DDNS,迅雷快鸟,UPNP,FullCone(防火墙中开启,默认开启),流量分载,irq优化,京东签到,Zerotier,FRPC,FRPS,无线打印,流量监控,过滤军刀,R2S-OLED +- 插件包含:SSRP,PassWall,OpenClash,微信推送,网易云解锁,SQM,DNSProxy,网络唤醒,DDNS,迅雷快鸟,UPNP,FullCone(防火墙中开启,默认开启),流量分载,irq优化,京东签到,Zerotier,FRPC,FRPS,无线打印,流量监控,过滤军刀,R2S-OLED - ss协议在armv8上实现了aes硬件加速(请仅使用aead加密的连接方式) - 集成并默认启用了BBRv2,LRNG - 集成了Docker,并针对特殊问题做了一些workaround(关于如何挂载剩余空间到 /opt/docker 的姿势请自行研究) ,从非Docker版本升级至Docker版本请执行恢复出厂设置,并手动重新配置路由器;请勿在Docker版上恢复非Docker版的备份配置 diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index c26e0266b..a41dd14ba 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -137,6 +137,7 @@ git clone -b master --depth 1 https://github.com/BROBIRD/openwrt-r8168.git packa patch -p1 <../PATCH/r8168/r8168-fix_LAN_led-for_r4s-from_TL.patch # R8152驱动 svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/kernel/r8152 package/new/r8152 +sed -i 's,kmod-usb-net-rtl8152,kmod-usb-net-rtl8152-vendor,g' target/linux/rockchip/image/armv8.mk # UPX 可执行软件压缩 sed -i '/patchelf pkgconf/i\tools-y += ucl upx' ./tools/Makefile sed -i '\/autoconf\/compile :=/i\$(curdir)/upx/compile := $(curdir)/ucl/compile' ./tools/Makefile diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index ba6025577..573b0f04a 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -22,10 +22,9 @@ wget -P target/linux/rockchip/armv8/base-files/usr/bin/ https://github.com/frien #' >>./target/linux/rockchip/armv8/config-5.4 # 配置 IRQ 并默认关闭 eth0 offloading rx/rx -sed -i '/set_interface_core 4 "eth1"/a\set_interface_core 8 "ff160000" "ff160000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity -sed -i '/set_interface_core 4 "eth1"/a\set_interface_core 1 "ff150000" "ff150000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity -sed -i '/;;/i\ethtool -K eth0 rx off tx off && logger -t disable-offloading "disabed rk3328 ethernet tcp/udp offloading tx/rx"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity - +sed -i '/set_interface_core 4 "eth1"/a\\tset_interface_core 1 "ff150000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity +sed -i '/ff150000.i2c/a\\tset_interface_core 8 "ff160000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity +wget -P target/linux/rockchip/armv8/base-files/etc/hotplug.d/iface/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/12-disable-rk3328-eth-offloading # 交换 LAN/WAN 口 sed -i 's,"eth1" "eth0","eth0" "eth1",g' target/linux/rockchip/armv8/base-files/etc/board.d/02_network sed -i "s,'eth1' 'eth0','eth0' 'eth1',g" target/linux/rockchip/armv8/base-files/etc/board.d/02_network diff --git a/SCRIPTS/R4S/02_target_only.sh b/SCRIPTS/R4S/02_target_only.sh index f5c1d66be..fbb4956a2 100644 --- a/SCRIPTS/R4S/02_target_only.sh +++ b/SCRIPTS/R4S/02_target_only.sh @@ -23,8 +23,7 @@ wget -P target/linux/rockchip/armv8/base-files/usr/bin/ https://github.com/frien #' >>./target/linux/rockchip/armv8/config-5.4 # IRQ 调优 -sed -i '/set_interface_core 20 "eth1"/a\set_interface_core 8 "ff3c0000" "ff3c0000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity -sed -i '/set_interface_core 20 "eth1"/a\ethtool -C eth0 rx-usecs 1000 rx-frames 25 tx-usecs 100 tx-frames 25' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity +sed -i '/set_interface_core 20 "eth1"/a\\tset_interface_core 2 "ff3c0000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity #Vermagic latest_version="$(curl -s https://github.com/openwrt/openwrt/tags | grep -Eo "v[0-9\.]+\-*r*c*[0-9]*.tar.gz" | sed -n '/[2-9][0-9]/p' | sed -n 1p | sed 's/v//g' | sed 's/.tar.gz//g')" diff --git a/SEED/R2C/config.seed b/SEED/R2C/config.seed index 51514ebfb..d87249bcc 100644 --- a/SEED/R2C/config.seed +++ b/SEED/R2C/config.seed @@ -16,6 +16,7 @@ CONFIG_TOOLCHAINOPTS=y CONFIG_GCC_USE_VERSION_8=y ### BASIC ### +CONFIG_PACKAGE_kmod-hwmon-pwmfan=y CONFIG_PACKAGE_r8169-firmware=y CONFIG_PACKAGE_addition-trans-zh=y CONFIG_PACKAGE_arm-trusted-firmware-rockchip=y diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index e31310d2e..3ec3d7b5a 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -16,6 +16,7 @@ CONFIG_TOOLCHAINOPTS=y CONFIG_GCC_USE_VERSION_8=y ### BASIC ### +CONFIG_PACKAGE_kmod-hwmon-pwmfan=y CONFIG_PACKAGE_r8169-firmware=y CONFIG_PACKAGE_addition-trans-zh=y CONFIG_PACKAGE_arm-trusted-firmware-rockchip=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index 1477fceb8..3bfba903e 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -16,6 +16,7 @@ CONFIG_TOOLCHAINOPTS=y CONFIG_GCC_USE_VERSION_8=y ### BASIC ### +CONFIG_PACKAGE_kmod-hwmon-pwmfan=y CONFIG_PACKAGE_r8169-firmware=y CONFIG_PACKAGE_addition-trans-zh=y CONFIG_PACKAGE_arm-trusted-firmware-rockchip=y From 221be3a908f7bddc85198dd40ae8696f40a9fba1 Mon Sep 17 00:00:00 2001 From: Bard Date: Tue, 4 Jan 2022 13:57:13 +0800 Subject: [PATCH 229/244] busybox: Enable LOG_INFO level syslog messages (#345) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 允许 busybox 以 LOG_INFO & LOG_ERR 级别打印日志,使 “系统 - 系统 - Cron 日志级别” 功能生效 启用 LOG_INFO level 前,定时任务执行无论成功与否,系统日志均以 cron.err crond 打印; 启用 LOG_INFO level 后,可根据 “系统 - 系统 - Cron 日志级别” 按需打印,而不是统一以 LOG_ERR 记录 --- SEED/R2C/config.seed | 4 ++++ SEED/R2S/config.seed | 4 ++++ SEED/R4S/config.seed | 4 ++++ SEED/X86/config.seed | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/SEED/R2C/config.seed b/SEED/R2C/config.seed index d87249bcc..64f0a43ec 100644 --- a/SEED/R2C/config.seed +++ b/SEED/R2C/config.seed @@ -63,6 +63,10 @@ CONFIG_PACKAGE_lua=y # CONFIG_PACKAGE_miniupnpd is not set CONFIG_PACKAGE_miniupnpd-igdv1=y +### BUSYBOX ### +CONFIG_BUSYBOX_CUSTOM=y +CONFIG_BUSYBOX_CONFIG_FEATURE_SYSLOG_INFO=y + ### LUCI ### CONFIG_LUCI_LANG_zh_Hans=y CONFIG_LUCI_LANG_en=y diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 3ec3d7b5a..23489a865 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -63,6 +63,10 @@ CONFIG_PACKAGE_lua=y # CONFIG_PACKAGE_miniupnpd is not set CONFIG_PACKAGE_miniupnpd-igdv1=y +### BUSYBOX ### +CONFIG_BUSYBOX_CUSTOM=y +CONFIG_BUSYBOX_CONFIG_FEATURE_SYSLOG_INFO=y + ### LUCI ### CONFIG_LUCI_LANG_zh_Hans=y CONFIG_LUCI_LANG_en=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index 3bfba903e..459c1ad29 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -64,6 +64,10 @@ CONFIG_PACKAGE_lua=y # CONFIG_PACKAGE_miniupnpd is not set CONFIG_PACKAGE_miniupnpd-igdv1=y +### BUSYBOX ### +CONFIG_BUSYBOX_CUSTOM=y +CONFIG_BUSYBOX_CONFIG_FEATURE_SYSLOG_INFO=y + ### LUCI ### CONFIG_LUCI_LANG_zh_Hans=y CONFIG_LUCI_LANG_en=y diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index e0ca7bd27..517c7a7e6 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -63,6 +63,10 @@ CONFIG_PACKAGE_irqbalance=y # CONFIG_PACKAGE_miniupnpd is not set CONFIG_PACKAGE_miniupnpd-igdv1=y +### BUSYBOX ### +CONFIG_BUSYBOX_CUSTOM=y +CONFIG_BUSYBOX_CONFIG_FEATURE_SYSLOG_INFO=y + ### LUCI ### CONFIG_LUCI_LANG_zh_Hans=y CONFIG_LUCI_LANG_en=y From f257d5e250e24b9b4252bcab074dbb42cee31e63 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 4 Jan 2022 14:28:29 +0800 Subject: [PATCH 230/244] change package source --- PATCH/firewall/fullcone6.patch | 57 ++++++++++++++++++++++++++++++++++ SCRIPTS/02_prepare_package.sh | 13 ++++++-- 2 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 PATCH/firewall/fullcone6.patch diff --git a/PATCH/firewall/fullcone6.patch b/PATCH/firewall/fullcone6.patch new file mode 100644 index 000000000..8afba9ba5 --- /dev/null +++ b/PATCH/firewall/fullcone6.patch @@ -0,0 +1,57 @@ +From 55b35ef7c5c9f9f4f377fa8074f1fccce4453c8f Mon Sep 17 00:00:00 2001 +From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> +Date: Sat, 22 Jan 2022 09:32:20 +0800 +Subject: [PATCH] fullcone6 + +--- + openwrt-fullconenat/Makefile | 15 +++++++++++++++ + openwrt-fullconenat/files/Makefile | 5 +++++ + 2 files changed, 20 insertions(+) + +diff --git a/openwrt-fullconenat/Makefile b/openwrt-fullconenat/Makefile +index b04afda..b4b1d44 100644 +--- a/openwrt-fullconenat/Makefile ++++ b/openwrt-fullconenat/Makefile +@@ -36,6 +36,20 @@ define Package/iptables-mod-fullconenat/install + $(INSTALL_BIN) $(PKG_BUILD_DIR)/libipt_FULLCONENAT.so $(1)/usr/lib/iptables + endef + ++define Package/ip6tables-mod-fullconenat ++ SUBMENU:=Firewall ++ SECTION:=net ++ CATEGORY:=Network ++ TITLE:=FULLCONENAT ip6tables extension ++ DEPENDS:=ip6tables +kmod-nf-nat6 +kmod-ipt-fullconenat ++ MAINTAINER:=Chion Tang ++endef ++ ++define Package/ip6tables-mod-fullconenat/install ++ $(INSTALL_DIR) $(1)/usr/lib/iptables ++ $(INSTALL_BIN) $(PKG_BUILD_DIR)/libip6t_FULLCONENAT.so $(1)/usr/lib/iptables ++endef ++ + define KernelPackage/ipt-fullconenat + SUBMENU:=Netfilter Extensions + TITLE:=FULLCONENAT netfilter module +@@ -63,4 +77,5 @@ define Build/Compile + endef + + $(eval $(call BuildPackage,iptables-mod-fullconenat)) ++$(eval $(call BuildPackage,ip6tables-mod-fullconenat)) + $(eval $(call KernelPackage,ipt-fullconenat)) +diff --git a/openwrt-fullconenat/files/Makefile b/openwrt-fullconenat/files/Makefile +index b2f88db..467ad17 100644 +--- a/openwrt-fullconenat/files/Makefile ++++ b/openwrt-fullconenat/files/Makefile +@@ -1,6 +1,11 @@ ++all: libipt_FULLCONENAT.so libip6t_FULLCONENAT.so + libipt_FULLCONENAT.so: libipt_FULLCONENAT.o + $(CC) -shared -lxtables -o $@ $^; + libipt_FULLCONENAT.o: libipt_FULLCONENAT.c + $(CC) ${CFLAGS} -fPIC -D_INIT=$*_init -c -o $@ $<; ++libip6t_FULLCONENAT.so: libip6t_FULLCONENAT.o ++ $(CC) -shared -lxtables -o $@ $^; ++libip6t_FULLCONENAT.o: libip6t_FULLCONENAT.c ++ $(CC) ${CFLAGS} -fPIC -D_INIT=$*_init -c -o $@ $<; + + obj-m += xt_FULLCONENAT.o diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index a41dd14ba..8fbb9f50d 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -76,7 +76,7 @@ wget -P package/libs/openssl/patches/ https://github.com/openssl/openssl/pull/16 ### Fullcone-NAT 部分 ### # Patch Kernel 以解决 FullCone 冲突 pushd target/linux/generic/hack-5.4 -wget https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/target/linux/generic/hack-5.4/952-net-conntrack-events-support-multiple-registrant.patch +wget https://github.com/coolsnowwolf/lede/raw/master/target/linux/generic/hack-5.4/952-net-conntrack-events-support-multiple-registrant.patch popd # Patch FireWall 以增添 FullCone 功能 mkdir package/network/config/firewall/patches @@ -85,7 +85,10 @@ wget -qO- https://github.com/msylgj/R2S-R4S-OpenWrt/raw/21.02/PATCHES/001-fix-fi # Patch LuCI 以增添 FullCone 开关 patch -p1 <../PATCH/firewall/luci-app-firewall_add_fullcone.patch # FullCone 相关组件 -svn co https://github.com/Lienol/openwrt/trunk/package/network/fullconenat package/network/fullconenat +svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/openwrt-fullconenat package/lean/openwrt-fullconenat +pushd package/lean/openwrt-fullconenat +patch -p1 <../../../../PATCH/firewall/fullcone6.patch +popd ### 获取额外的基础软件包 ### # 更换为 ImmortalWrt Uboot 以及 Target @@ -193,7 +196,11 @@ svn co https://github.com/QiuSimons/OpenWrt_luci-app/trunk/luci-app-tencentddns svn co https://github.com/kenzok8/openwrt-packages/trunk/luci-app-aliddns feeds/luci/applications/luci-app-aliddns ln -sf ../../../feeds/luci/applications/luci-app-aliddns ./package/feeds/luci/luci-app-aliddns # Docker 容器(会导致 OpenWrt 出现 UDP 转发问题,慎用) -sed -i 's/+docker/+docker \\\n\t+dockerd/g' ./feeds/luci/applications/luci-app-dockerman/Makefile +rm -rf ./feeds/luci/applications/luci-app-dockerman +svn co https://github.com/lisaac/luci-app-dockerman/trunk/applications/luci-app-dockerman feeds/luci/applications/luci-app-dockerman +rm -rf ./feeds/luci/collections/luci-lib-docker +svn co https://github.com/lisaac/luci-lib-docker/trunk/collections/luci-lib-docker feeds/luci/collections/luci-lib-docker +#sed -i 's/+docker/+docker \\\n\t+dockerd/g' ./feeds/luci/applications/luci-app-dockerman/Makefile sed -i '/sysctl.d/d' feeds/packages/utils/dockerd/Makefile # DiskMan mkdir -p package/new/luci-app-diskman && \ From 112f8be97929f8614c50342f3ab632db5db8971c Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sat, 22 Jan 2022 10:56:03 +0800 Subject: [PATCH 231/244] 2022 update --- SCRIPTS/02_prepare_package.sh | 39 ++++++++++++++++++++++++++--------- SCRIPTS/X86/02_target_only.sh | 7 ------- SEED/R2C/config.seed | 1 + SEED/R2S/config.seed | 1 + SEED/R4S/config.seed | 1 + SEED/X86/config.seed | 1 + 6 files changed, 33 insertions(+), 17 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 8fbb9f50d..4dadc14df 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -87,7 +87,7 @@ patch -p1 <../PATCH/firewall/luci-app-firewall_add_fullcone.patch # FullCone 相关组件 svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/openwrt-fullconenat package/lean/openwrt-fullconenat pushd package/lean/openwrt-fullconenat -patch -p1 <../../../../PATCH/firewall/fullcone6.patch +patch -p2 <../../../../PATCH/firewall/fullcone6.patch popd ### 获取额外的基础软件包 ### @@ -259,10 +259,16 @@ svn co https://github.com/teasiu/dragino2/trunk/devices/common/diy/package/teasi svn co https://github.com/QiuSimons/dragino2-teasiu/trunk/package/teasiu/luci-app-oray package/new/luci-app-oray # Passwall svn co https://github.com/xiaorouji/openwrt-passwall/trunk/luci-app-passwall package/new/luci-app-passwall -sed -i 's,default n,default y,g' package/new/luci-app-passwall/Makefile -sed -i '/Trojan_GO:/d' package/new/luci-app-passwall/Makefile -sed -i '/V2ray:/d' package/new/luci-app-passwall/Makefile -sed -i '/Plugin:/d' package/new/luci-app-passwall/Makefile +pushd package/new/luci-app-passwall +sed -i 's,default n,default y,g' Makefile +sed -i '/trojan-go/d' Makefile +sed -i '/v2ray-core/d' Makefile +sed -i '/v2ray-plugin/d' Makefile +sed -i '/xray-plugin/d' Makefile +sed -i '/shadowsocks-libev-ss-redir/d' Makefile +sed -i '/shadowsocks-libev-ss-server/d' Makefile +sed -i '/shadowsocks-libev-ss-local/d' Makefile +popd wget -P package/new/luci-app-passwall/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/move_2_services.sh chmod -R 755 ./package/new/luci-app-passwall/move_2_services.sh pushd package/new/luci-app-passwall @@ -310,7 +316,8 @@ svn co https://github.com/fw876/helloworld/trunk/v2ray-core package/lean/v2ray-c svn co https://github.com/fw876/helloworld/trunk/xray-core package/lean/xray-core svn co https://github.com/fw876/helloworld/trunk/v2ray-plugin package/lean/v2ray-plugin svn co https://github.com/fw876/helloworld/trunk/xray-plugin package/lean/xray-plugin -svn co https://github.com/immortalwrt/packages/trunk/net/shadowsocks-rust feeds/packages/net/shadowsocks-rust +svn co https://github.com/xiaorouji/openwrt-passwall/trunk/shadowsocks-rust feeds/packages/net/shadowsocks-rust +#svn co https://github.com/immortalwrt/packages/trunk/net/shadowsocks-rust feeds/packages/net/shadowsocks-rust sed -i '/Build\/Compile/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $$(PKG_BUILD_DIR)/$(component)' feeds/packages/net/shadowsocks-rust/Makefile ln -sf ../../../feeds/packages/net/shadowsocks-rust ./package/feeds/packages/shadowsocks-rust svn co https://github.com/immortalwrt/packages/trunk/net/kcptun feeds/packages/net/kcptun @@ -325,7 +332,13 @@ wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/323fbf0.patch | popd pushd package/lean/luci-app-ssr-plus sed -i 's,default n,default y,g' Makefile -sed -i '/Plugin:/d' Makefile +sed -i '/trojan-go/d' Makefile +sed -i '/v2ray-core/d' Makefile +sed -i '/v2ray-plugin/d' Makefile +sed -i '/xray-plugin/d' Makefile +sed -i '/shadowsocks-libev-ss-redir/d' Makefile +sed -i '/shadowsocks-libev-ss-server/d' Makefile +sed -i '/shadowsocks-libev-ss-local/d' Makefile sed -i '/result.encrypt_method/a\result.fast_open = "1"' root/usr/share/shadowsocksr/subscribe.lua sed -i 's,ispip.clang.cn/all_cn,gh.404delivr.workers.dev/https://github.com/QiuSimons/Chnroute/raw/master/dist/chnroute/chnroute,' root/etc/init.d/shadowsocksr sed -i 's,YW5vbnltb3Vz/domain-list-community/release/gfwlist.txt,Loyalsoldier/v2ray-rules-dat/release/gfw.txt,' root/etc/init.d/shadowsocksr @@ -360,9 +373,15 @@ svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/vlmcsd package/le # VSSR git clone -b master --depth 1 https://github.com/jerrykuku/luci-app-vssr.git package/lean/luci-app-vssr git clone -b master --depth 1 https://github.com/jerrykuku/lua-maxminddb.git package/lean/lua-maxminddb -sed -i 's,default n,default y,g' package/lean/luci-app-vssr/Makefile -sed -i '/plugin:/d' package/lean/luci-app-vssr/Makefile -#sed -i '/plugin:v2ray/d' package/lean/luci-app-vssr/Makefile +pushd package/lean/luci-app-vssr +sed -i 's,default n,default y,g' Makefile +sed -i '/trojan-go/d' Makefile +sed -i '/v2ray-core/d' Makefile +sed -i '/v2ray-plugin/d' Makefile +sed -i '/xray-plugin/d' Makefile +sed -i 's,+shadowsocks-libev-ss-local ,,g' Makefile +sed -i 's,+shadowsocks-libev-ss-redir ,,g' Makefile +popd sed -i '/result.encrypt_method/a\result.fast_open = "1"' package/lean/luci-app-vssr/root/usr/share/vssr/subscribe.lua sed -i 's,ispip.clang.cn/all_cn.txt,raw.sevencdn.com/QiuSimons/Chnroute/master/dist/chnroute/chnroute.txt,g' package/lean/luci-app-vssr/luasrc/controller/vssr.lua sed -i 's,ispip.clang.cn/all_cn.txt,raw.sevencdn.com/QiuSimons/Chnroute/master/dist/chnroute/chnroute.txt,g' package/lean/luci-app-vssr/root/usr/share/vssr/update.lua diff --git a/SCRIPTS/X86/02_target_only.sh b/SCRIPTS/X86/02_target_only.sh index 94d89235d..9ffad6c30 100644 --- a/SCRIPTS/X86/02_target_only.sh +++ b/SCRIPTS/X86/02_target_only.sh @@ -1,12 +1,5 @@ #!/bin/bash -# 在 X86 架构下移除 Shadowsocks-rust -sed -i '/Rust_Client:/d' package/lean/luci-app-ssr-plus/Makefile -sed -i '/Rust_Server:/d' package/lean/luci-app-ssr-plus/Makefile -sed -i '/Rust_Client:/d' package/new/luci-app-passwall/Makefile -sed -i '/Rust_Server:/d' package/new/luci-app-passwall/Makefile -#sed -i '/Rust:/d' package/lean/luci-app-vssr/Makefile - # 内核加解密组件 echo ' CONFIG_CRYPTO_AES_NI_INTEL=y diff --git a/SEED/R2C/config.seed b/SEED/R2C/config.seed index 64f0a43ec..eda6f6b92 100644 --- a/SEED/R2C/config.seed +++ b/SEED/R2C/config.seed @@ -104,6 +104,7 @@ CONFIG_PACKAGE_luci-app-oaf=y CONFIG_PACKAGE_luci-app-cpufreq=y CONFIG_PACKAGE_luci-app-cpulimit=y CONFIG_PACKAGE_luci-app-ddns=y +CONFIG_PACKAGE_bind-host=y CONFIG_PACKAGE_ddns-scripts-cloudflare=y CONFIG_PACKAGE_ddns-scripts-dnspod=y CONFIG_PACKAGE_ddns-scripts-aliyun=y diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 23489a865..94f8537aa 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -104,6 +104,7 @@ CONFIG_PACKAGE_luci-app-oaf=y CONFIG_PACKAGE_luci-app-cpufreq=y CONFIG_PACKAGE_luci-app-cpulimit=y CONFIG_PACKAGE_luci-app-ddns=y +CONFIG_PACKAGE_bind-host=y CONFIG_PACKAGE_ddns-scripts-cloudflare=y CONFIG_PACKAGE_ddns-scripts-dnspod=y CONFIG_PACKAGE_ddns-scripts-aliyun=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index 459c1ad29..80f893e39 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -105,6 +105,7 @@ CONFIG_PACKAGE_luci-app-oaf=y CONFIG_PACKAGE_luci-app-cpufreq=y CONFIG_PACKAGE_luci-app-cpulimit=y CONFIG_PACKAGE_luci-app-ddns=y +CONFIG_PACKAGE_bind-host=y CONFIG_PACKAGE_ddns-scripts-cloudflare=y CONFIG_PACKAGE_ddns-scripts-dnspod=y CONFIG_PACKAGE_ddns-scripts-aliyun=y diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index 517c7a7e6..d12155c41 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -104,6 +104,7 @@ CONFIG_PACKAGE_luci-app-oaf=y CONFIG_PACKAGE_luci-app-cpufreq=y CONFIG_PACKAGE_luci-app-cpulimit=y CONFIG_PACKAGE_luci-app-ddns=y +CONFIG_PACKAGE_bind-host=y CONFIG_PACKAGE_ddns-scripts-cloudflare=y CONFIG_PACKAGE_ddns-scripts-dnspod=y CONFIG_PACKAGE_ddns-scripts-aliyun=y From d5702181d20f8b0b79d9a9ed05f969f3de16e57f Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Tue, 1 Feb 2022 16:10:16 +0800 Subject: [PATCH 232/244] fix #350 --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 4dadc14df..bd68a8f9c 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -190,6 +190,7 @@ svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/luci-app-cpulimit package/ svn co https://github.com/immortalwrt/packages/trunk/utils/cpulimit feeds/packages/utils/cpulimit ln -sf ../../../feeds/packages/utils/cpulimit ./package/feeds/packages/cpulimit # 动态DNS +sed -i '/boot()/,+2d' feeds/packages/net/ddns-scripts/files/etc/init.d/ddns svn co https://github.com/kiddin9/openwrt-packages/trunk/ddns-scripts-aliyun package/lean/ddns-scripts_dnspod svn co https://github.com/kiddin9/openwrt-packages/trunk/ddns-scripts-dnspod package/lean/ddns-scripts_aliyun svn co https://github.com/QiuSimons/OpenWrt_luci-app/trunk/luci-app-tencentddns package/lean/luci-app-tencentddns @@ -380,7 +381,6 @@ sed -i '/v2ray-core/d' Makefile sed -i '/v2ray-plugin/d' Makefile sed -i '/xray-plugin/d' Makefile sed -i 's,+shadowsocks-libev-ss-local ,,g' Makefile -sed -i 's,+shadowsocks-libev-ss-redir ,,g' Makefile popd sed -i '/result.encrypt_method/a\result.fast_open = "1"' package/lean/luci-app-vssr/root/usr/share/vssr/subscribe.lua sed -i 's,ispip.clang.cn/all_cn.txt,raw.sevencdn.com/QiuSimons/Chnroute/master/dist/chnroute/chnroute.txt,g' package/lean/luci-app-vssr/luasrc/controller/vssr.lua From 2a24d32798810adb8cbf21a773ef8bdd97895ee4 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 9 Feb 2022 13:44:13 +0800 Subject: [PATCH 233/244] Adapt to upstream change --- SCRIPTS/02_prepare_package.sh | 69 ++++++++++++++++++------------- SCRIPTS/03_convert_translation.sh | 7 ++++ 2 files changed, 47 insertions(+), 29 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index bd68a8f9c..3864ea1d5 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -135,6 +135,8 @@ svn co https://github.com/nxhack/openwrt-node-packages/trunk/node-serialport-bin rm -rf ./feeds/packages/lang/node-yarn svn co https://github.com/nxhack/openwrt-node-packages/trunk/node-yarn feeds/packages/lang/node-yarn ln -sf ../../../feeds/packages/lang/node-yarn ./package/feeds/packages/node-yarn +svn co https://github.com/nxhack/openwrt-node-packages/trunk/node-serialport-bindings-cpp feeds/packages/lang/node-serialport-bindings-cpp +ln -sf ../../../feeds/packages/lang/node-serialport-bindings-cpp ./package/feeds/packages/node-serialport-bindings-cpp # R8168驱动 git clone -b master --depth 1 https://github.com/BROBIRD/openwrt-r8168.git package/new/r8168 patch -p1 <../PATCH/r8168/r8168-fix_LAN_led-for_r4s-from_TL.patch @@ -149,13 +151,14 @@ svn co https://github.com/immortalwrt/immortalwrt/branches/master/tools/ucl tool ### 获取额外的 LuCI 应用、主题和依赖 ### # 访问控制 -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-accesscontrol package/lean/luci-app-accesscontrol +svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-accesscontrol package/lean/luci-app-accesscontrol svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/luci-app-control-weburl package/new/luci-app-control-weburl # 广告过滤 Adbyby -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-adbyby-plus package/lean/luci-app-adbyby-plus +svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-adbyby-plus package/lean/luci-app-adbyby-plus svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/adbyby package/lean/adbyby # 广告过滤 AdGuard -svn co https://github.com/Lienol/openwrt/trunk/package/diy/luci-app-adguardhome package/new/luci-app-adguardhome +#svn co https://github.com/Lienol/openwrt/trunk/package/diy/luci-app-adguardhome package/new/luci-app-adguardhome +git clone https://github.com/rufengsuixing/luci-app-adguardhome.git package/new/luci-app-adguardhome rm -rf ./feeds/packages/net/adguardhome svn co https://github.com/openwrt/packages/trunk/net/adguardhome feeds/packages/net/adguardhome sed -i '/\t)/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/AdGuardHome' ./feeds/packages/net/adguardhome/Makefile @@ -172,7 +175,7 @@ git clone -b master --depth 1 https://github.com/jerrykuku/luci-app-argon-config svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-arpbind feeds/luci/applications/luci-app-arpbind ln -sf ../../../feeds/luci/applications/luci-app-arpbind ./package/feeds/luci/luci-app-arpbind # 定时重启 -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-autoreboot package/lean/luci-app-autoreboot +svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-autoreboot package/lean/luci-app-autoreboot # Boost 通用即插即用 svn co https://github.com/QiuSimons/slim-wrt/branches/main/slimapps/application/luci-app-boostupnp package/new/luci-app-boostupnp rm -rf ./feeds/packages/net/miniupnpd @@ -222,11 +225,11 @@ rm -rf ./feeds/luci/applications/luci-app-frps rm -rf ./feeds/luci/applications/luci-app-frpc rm -rf ./feeds/packages/net/frp rm -f ./package/feeds/packages/frp -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-frps package/lean/luci-app-frps -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-frpc package/lean/luci-app-frpc -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/frp package/lean/frp +svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-frps package/lean/luci-app-frps +svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-frpc package/lean/luci-app-frpc +svn co https://github.com/coolsnowwolf/packages/trunk/net/frp package/lean/frp # IPSec -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-ipsec-vpnd package/lean/luci-app-ipsec-vpnd +svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-ipsec-vpnd package/lean/luci-app-ipsec-vpnd # IPv6 兼容助手 svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/ipv6-helper package/lean/ipv6-helper # 京东签到 By Jerrykuku @@ -242,8 +245,9 @@ git clone --depth 1 https://github.com/KyleRicardo/MentoHUST-OpenWrt-ipk package #sed -i '/mosdns-init-openwrt/d' feeds/packages/net/mosdns/Makefile svn co https://github.com/QiuSimons/openwrt-mos/trunk/mosdns package/new/mosdns svn co https://github.com/QiuSimons/openwrt-mos/trunk/luci-app-mosdns package/new/luci-app-mosdns +svn co https://github.com/QiuSimons/openwrt-mos/trunk/v2ray-geodata package/new/v2ray-geodata # 流量监管 -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-netdata package/lean/luci-app-netdata +svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-netdata package/lean/luci-app-netdata # 上网 APP 过滤 git clone -b master --depth 1 https://github.com/destan19/OpenAppFilter.git package/new/OpenAppFilter pushd package/new/OpenAppFilter @@ -284,14 +288,14 @@ svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/trojan-plus package/new/tr svn co https://github.com/xiaorouji/openwrt-passwall/trunk/ssocks package/new/ssocks svn co https://github.com/xiaorouji/openwrt-passwall/trunk/hysteria package/new/hysteria # qBittorrent 下载 -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-qbittorrent package/lean/luci-app-qbittorrent -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/qBittorrent-static package/lean/qBittorrent-static -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/qBittorrent package/lean/qBittorrent -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/rblibtorrent package/lean/rblibtorrent -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/qtbase package/lean/qtbase -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/qttools package/lean/qttools +svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-qbittorrent package/lean/luci-app-qbittorrent +svn co https://github.com/coolsnowwolf/packages/trunk/net/qBittorrent-static package/lean/qBittorrent-static +svn co https://github.com/coolsnowwolf/packages/trunk/net/qBittorrent package/lean/qBittorrent +svn co https://github.com/coolsnowwolf/packages/trunk/libs/qtbase package/lean/qtbase +svn co https://github.com/coolsnowwolf/packages/trunk/libs/qttools package/lean/qttools +svn co https://github.com/coolsnowwolf/packages/trunk/libs/rblibtorrent package/lean/rblibtorrent # 清理内存 -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-ramfree package/lean/luci-app-ramfree +svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-ramfree package/lean/luci-app-ramfree # ServerChan 微信推送 git clone -b master --depth 1 https://github.com/tty228/luci-app-serverchan.git package/new/luci-app-serverchan # SmartDNS @@ -303,14 +307,17 @@ svn co https://github.com/immortalwrt/luci/branches/openwrt-18.06/applications/l rm -rf ./feeds/packages/net/kcptun rm -rf ./feeds/packages/net/shadowsocks-libev rm -rf ./feeds/packages/net/xray-core -svn co https://github.com/fw876/helloworld/trunk/shadowsocksr-libev package/lean/shadowsocksr-libev -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/pdnsd-alt package/lean/pdnsd -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/srelay package/lean/srelay -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/microsocks package/lean/microsocks -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/dns2socks package/lean/dns2socks -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/redsocks2 package/lean/redsocks2 -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/ipt2socks package/lean/ipt2socks svn co https://github.com/coolsnowwolf/packages/trunk/net/shadowsocks-libev package/lean/shadowsocks-libev +svn co https://github.com/xiaorouji/openwrt-passwall/trunk/shadowsocksr-libev package/lean/shadowsocksr-libev +svn co https://github.com/xiaorouji/openwrt-passwall/trunk/pdnsd-alt package/lean/pdnsd +svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/srelay package/lean/srelay +svn co https://github.com/xiaorouji/openwrt-passwall/trunk/microsocks package/lean/microsocks +svn co https://github.com/xiaorouji/openwrt-passwall/trunk/dns2socks package/lean/dns2socks +svn co https://github.com/coolsnowwolf/packages/trunk/net/redsocks2 package/lean/redsocks2 +svn co https://github.com/xiaorouji/openwrt-passwall/trunk/ipt2socks package/lean/ipt2socks +svn co https://github.com/xiaorouji/openwrt-passwall/trunk/trojan package/lean/trojan +svn co https://github.com/xiaorouji/openwrt-passwall/trunk/tcping package/lean/tcping +svn co https://github.com/xiaorouji/openwrt-passwall/trunk/trojan-go package/lean/trojan-go svn co https://github.com/fw876/helloworld/trunk/simple-obfs package/lean/simple-obfs svn co https://github.com/fw876/helloworld/trunk/naiveproxy package/lean/naiveproxy svn co https://github.com/fw876/helloworld/trunk/v2ray-core package/lean/v2ray-core @@ -345,6 +352,10 @@ sed -i 's,ispip.clang.cn/all_cn,gh.404delivr.workers.dev/https://github.com/QiuS sed -i 's,YW5vbnltb3Vz/domain-list-community/release/gfwlist.txt,Loyalsoldier/v2ray-rules-dat/release/gfw.txt,' root/etc/init.d/shadowsocksr sed -i '/Clang.CN.CIDR/a\o:value("https://gh.404delivr.workers.dev/https://github.com/QiuSimons/Chnroute/raw/master/dist/chnroute/chnroute.txt", translate("QiuSimons/Chnroute"))' luasrc/model/cbi/shadowsocksr/advanced.lua popd +# v2raya +git clone --depth 1 https://github.com/zxlhhyccc/luci-app-v2raya.git package/new/luci-app-v2raya +svn co https://github.com/openwrt/packages/trunk/net/v2raya feeds/packages/net/v2raya +ln -sf ../../../feeds/packages/net/v2raya ./package/feeds/packages/v2raya # socat svn co https://github.com/Lienol/openwrt-package/trunk/luci-app-socat package/new/luci-app-socat # 订阅转换 @@ -364,13 +375,13 @@ ln -sf ../../../feeds/packages/libs/toml11 ./package/feeds/packages/toml11 # 网易云音乐解锁 git clone --depth 1 https://github.com/immortalwrt/luci-app-unblockneteasemusic.git package/new/UnblockNeteaseMusic # USB 打印机 -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-usb-printer package/lean/luci-app-usb-printer +svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-usb-printer package/lean/luci-app-usb-printer # UU加速器 -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-uugamebooster package/lean/luci-app-uugamebooster -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/uugamebooster package/lean/uugamebooster +svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-uugamebooster package/lean/luci-app-uugamebooster +svn co https://github.com/coolsnowwolf/packages/trunk/net/uugamebooster package/lean/uugamebooster # KMS 激活助手 -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/luci-app-vlmcsd package/lean/luci-app-vlmcsd -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/vlmcsd package/lean/vlmcsd +svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-vlmcsd package/lean/luci-app-vlmcsd +svn co https://github.com/coolsnowwolf/packages/trunk/net/vlmcsd package/lean/vlmcsd # VSSR git clone -b master --depth 1 https://github.com/jerrykuku/luci-app-vssr.git package/lean/luci-app-vssr git clone -b master --depth 1 https://github.com/jerrykuku/lua-maxminddb.git package/lean/lua-maxminddb @@ -386,7 +397,7 @@ sed -i '/result.encrypt_method/a\result.fast_open = "1"' package/lean/luci-app-v sed -i 's,ispip.clang.cn/all_cn.txt,raw.sevencdn.com/QiuSimons/Chnroute/master/dist/chnroute/chnroute.txt,g' package/lean/luci-app-vssr/luasrc/controller/vssr.lua sed -i 's,ispip.clang.cn/all_cn.txt,raw.sevencdn.com/QiuSimons/Chnroute/master/dist/chnroute/chnroute.txt,g' package/lean/luci-app-vssr/root/usr/share/vssr/update.lua # 网络唤醒 -svn co https://github.com/sundaqiang/openwrt-packages/trunk/luci-app-services-wolplus package/new/luci-app-services-wolplus +svn co https://github.com/zxlhhyccc/bf-package-master/trunk/zxlhhyccc/luci-app-services-wolplus package/new/luci-app-services-wolplus # 流量监视 git clone -b master --depth 1 https://github.com/brvphoenix/wrtbwmon.git package/new/wrtbwmon git clone -b master --depth 1 https://github.com/brvphoenix/luci-app-wrtbwmon.git package/new/luci-app-wrtbwmon diff --git a/SCRIPTS/03_convert_translation.sh b/SCRIPTS/03_convert_translation.sh index b301fd872..98dbdd871 100644 --- a/SCRIPTS/03_convert_translation.sh +++ b/SCRIPTS/03_convert_translation.sh @@ -42,4 +42,11 @@ for f in ${makefile_file}; do [ -n "$(grep "zh-cn" "$f")" ] && sed -i "s/zh-cn/zh_Hans/g" "$f" [ -n "$(grep "zh_Hans.lmo" "$f")" ] && sed -i "s/zh_Hans.lmo/zh-cn.lmo/g" "$f" done + +makefile_file="$({ find package | grep Makefile | sed "/Makefile./d"; } 2>"/dev/null")" +for g in ${makefile_file}; do + [ -n "$(grep "golang-package.mk" "$g")" ] && sed -i "s,\../..,\$(TOPDIR)/feeds/packages,g" "$g" + [ -n "$(grep "luci.mk" "$g")" ] && sed -i "s,\../..,\$(TOPDIR)/feeds/luci,g" "$g" +done + exit 0 From adfa8636888a748a2c870ee537031397c097d92b Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 9 Mar 2022 15:13:49 +0800 Subject: [PATCH 234/244] fix #388 --- SCRIPTS/R2S/02_target_only.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/SCRIPTS/R2S/02_target_only.sh b/SCRIPTS/R2S/02_target_only.sh index 573b0f04a..1dfe8ac0f 100644 --- a/SCRIPTS/R2S/02_target_only.sh +++ b/SCRIPTS/R2S/02_target_only.sh @@ -25,6 +25,7 @@ wget -P target/linux/rockchip/armv8/base-files/usr/bin/ https://github.com/frien sed -i '/set_interface_core 4 "eth1"/a\\tset_interface_core 1 "ff150000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity sed -i '/ff150000.i2c/a\\tset_interface_core 8 "ff160000.i2c"' target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity wget -P target/linux/rockchip/armv8/base-files/etc/hotplug.d/iface/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/12-disable-rk3328-eth-offloading +sed -i 's,eth0,eth1,g' target/linux/rockchip/armv8/base-files/etc/hotplug.d/iface/12-disable-rk3328-eth-offloading # 交换 LAN/WAN 口 sed -i 's,"eth1" "eth0","eth0" "eth1",g' target/linux/rockchip/armv8/base-files/etc/board.d/02_network sed -i "s,'eth1' 'eth0','eth0' 'eth1',g" target/linux/rockchip/armv8/base-files/etc/board.d/02_network From 5955e221c135009e05a60cdb1a74a26fb446ff93 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 9 Mar 2022 15:19:58 +0800 Subject: [PATCH 235/244] Adapt to upstream change --- SCRIPTS/02_prepare_package.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 3864ea1d5..7cdd14c80 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -263,7 +263,8 @@ svn co https://github.com/teasiu/dragino2/trunk/devices/common/diy/package/teasi svn co https://github.com/teasiu/dragino2/trunk/devices/common/diy/package/teasiu/phtunnel package/new/phtunnel svn co https://github.com/QiuSimons/dragino2-teasiu/trunk/package/teasiu/luci-app-oray package/new/luci-app-oray # Passwall -svn co https://github.com/xiaorouji/openwrt-passwall/trunk/luci-app-passwall package/new/luci-app-passwall +svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-passwall package/new/luci-app-passwall +#svn co https://github.com/xiaorouji/openwrt-passwall/trunk/luci-app-passwall package/new/luci-app-passwall pushd package/new/luci-app-passwall sed -i 's,default n,default y,g' Makefile sed -i '/trojan-go/d' Makefile From c9306b5c13bb5daf8058bf18d2a986a2051800ef Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Thu, 17 Mar 2022 11:59:25 +0800 Subject: [PATCH 236/244] use 'svn export' instead of 'svn co' --- SCRIPTS/02_prepare_package.sh | 228 +++++++++++++++++----------------- 1 file changed, 114 insertions(+), 114 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 7cdd14c80..9f85d9177 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -64,7 +64,7 @@ CONFIG_LRNG_JENT=y wget -qO - https://github.com/QiuSimons/openwrt-NoTengoBattery/commit/afed16a.patch | patch -p1 # Haproxy rm -rf ./feeds/packages/net/haproxy -svn co https://github.com/openwrt/packages/trunk/net/haproxy feeds/packages/net/haproxy +svn export https://github.com/openwrt/packages/trunk/net/haproxy feeds/packages/net/haproxy pushd feeds/packages wget -qO - https://github.com/QiuSimons/packages/commit/7ffbfbe.patch | patch -p1 popd @@ -85,7 +85,7 @@ wget -qO- https://github.com/msylgj/R2S-R4S-OpenWrt/raw/21.02/PATCHES/001-fix-fi # Patch LuCI 以增添 FullCone 开关 patch -p1 <../PATCH/firewall/luci-app-firewall_add_fullcone.patch # FullCone 相关组件 -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/openwrt-fullconenat package/lean/openwrt-fullconenat +svn export https://github.com/coolsnowwolf/lede/trunk/package/lean/openwrt-fullconenat package/lean/openwrt-fullconenat pushd package/lean/openwrt-fullconenat patch -p2 <../../../../PATCH/firewall/fullcone6.patch popd @@ -93,10 +93,10 @@ popd ### 获取额外的基础软件包 ### # 更换为 ImmortalWrt Uboot 以及 Target rm -rf ./target/linux/rockchip -svn co https://github.com/immortalwrt/immortalwrt/branches/openwrt-21.02/target/linux/rockchip target/linux/rockchip +svn export https://github.com/immortalwrt/immortalwrt/branches/openwrt-21.02/target/linux/rockchip target/linux/rockchip rm -rf ./package/boot/uboot-rockchip -svn co https://github.com/immortalwrt/immortalwrt/branches/openwrt-21.02/package/boot/uboot-rockchip package/boot/uboot-rockchip -svn co https://github.com/immortalwrt/immortalwrt/branches/openwrt-21.02/package/boot/arm-trusted-firmware-rockchip-vendor package/boot/arm-trusted-firmware-rockchip-vendor +svn export https://github.com/immortalwrt/immortalwrt/branches/openwrt-21.02/package/boot/uboot-rockchip package/boot/uboot-rockchip +svn export https://github.com/immortalwrt/immortalwrt/branches/openwrt-21.02/package/boot/arm-trusted-firmware-rockchip-vendor package/boot/arm-trusted-firmware-rockchip-vendor rm -rf ./package/kernel/linux/modules/video.mk wget -P package/kernel/linux/modules/ https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/package/kernel/linux/modules/video.mk # R4S超频到 2.2/1.8 GHz @@ -111,56 +111,56 @@ sed -i 's,noinitrd,noinitrd mitigations=off,g' target/linux/x86/image/grub-efi.c sed -i 's,noinitrd,noinitrd mitigations=off,g' target/linux/x86/image/grub-iso.cfg sed -i 's,noinitrd,noinitrd mitigations=off,g' target/linux/x86/image/grub-pc.cfg # AutoCore -svn co https://github.com/immortalwrt/immortalwrt/branches/openwrt-21.02/package/emortal/autocore package/lean/autocore +svn export https://github.com/immortalwrt/immortalwrt/branches/openwrt-21.02/package/emortal/autocore package/lean/autocore rm -rf ./feeds/packages/utils/coremark -svn co https://github.com/immortalwrt/packages/trunk/utils/coremark feeds/packages/utils/coremark +svn export https://github.com/immortalwrt/packages/trunk/utils/coremark feeds/packages/utils/coremark # DPDK -svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/dpdk package/new/dpdk +svn export https://github.com/QiuSimons/OpenWrt-Add/trunk/dpdk package/new/dpdk # 更换 Nodejs 版本 rm -rf ./feeds/packages/lang/node -svn co https://github.com/nxhack/openwrt-node-packages/trunk/node feeds/packages/lang/node +svn export https://github.com/nxhack/openwrt-node-packages/trunk/node feeds/packages/lang/node sed -i '\/bin\/node/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $(1)/usr/bin/node' feeds/packages/lang/node/Makefile rm -rf ./feeds/packages/lang/node-arduino-firmata -svn co https://github.com/nxhack/openwrt-node-packages/trunk/node-arduino-firmata feeds/packages/lang/node-arduino-firmata +svn export https://github.com/nxhack/openwrt-node-packages/trunk/node-arduino-firmata feeds/packages/lang/node-arduino-firmata rm -rf ./feeds/packages/lang/node-cylon -svn co https://github.com/nxhack/openwrt-node-packages/trunk/node-cylon feeds/packages/lang/node-cylon +svn export https://github.com/nxhack/openwrt-node-packages/trunk/node-cylon feeds/packages/lang/node-cylon rm -rf ./feeds/packages/lang/node-hid -svn co https://github.com/nxhack/openwrt-node-packages/trunk/node-hid feeds/packages/lang/node-hid +svn export https://github.com/nxhack/openwrt-node-packages/trunk/node-hid feeds/packages/lang/node-hid rm -rf ./feeds/packages/lang/node-homebridge -svn co https://github.com/nxhack/openwrt-node-packages/trunk/node-homebridge feeds/packages/lang/node-homebridge +svn export https://github.com/nxhack/openwrt-node-packages/trunk/node-homebridge feeds/packages/lang/node-homebridge rm -rf ./feeds/packages/lang/node-serialport -svn co https://github.com/nxhack/openwrt-node-packages/trunk/node-serialport feeds/packages/lang/node-serialport +svn export https://github.com/nxhack/openwrt-node-packages/trunk/node-serialport feeds/packages/lang/node-serialport rm -rf ./feeds/packages/lang/node-serialport-bindings -svn co https://github.com/nxhack/openwrt-node-packages/trunk/node-serialport-bindings feeds/packages/lang/node-serialport-bindings +svn export https://github.com/nxhack/openwrt-node-packages/trunk/node-serialport-bindings feeds/packages/lang/node-serialport-bindings rm -rf ./feeds/packages/lang/node-yarn -svn co https://github.com/nxhack/openwrt-node-packages/trunk/node-yarn feeds/packages/lang/node-yarn +svn export https://github.com/nxhack/openwrt-node-packages/trunk/node-yarn feeds/packages/lang/node-yarn ln -sf ../../../feeds/packages/lang/node-yarn ./package/feeds/packages/node-yarn -svn co https://github.com/nxhack/openwrt-node-packages/trunk/node-serialport-bindings-cpp feeds/packages/lang/node-serialport-bindings-cpp +svn export https://github.com/nxhack/openwrt-node-packages/trunk/node-serialport-bindings-cpp feeds/packages/lang/node-serialport-bindings-cpp ln -sf ../../../feeds/packages/lang/node-serialport-bindings-cpp ./package/feeds/packages/node-serialport-bindings-cpp # R8168驱动 git clone -b master --depth 1 https://github.com/BROBIRD/openwrt-r8168.git package/new/r8168 patch -p1 <../PATCH/r8168/r8168-fix_LAN_led-for_r4s-from_TL.patch # R8152驱动 -svn co https://github.com/immortalwrt/immortalwrt/branches/master/package/kernel/r8152 package/new/r8152 +svn export https://github.com/immortalwrt/immortalwrt/branches/master/package/kernel/r8152 package/new/r8152 sed -i 's,kmod-usb-net-rtl8152,kmod-usb-net-rtl8152-vendor,g' target/linux/rockchip/image/armv8.mk # UPX 可执行软件压缩 sed -i '/patchelf pkgconf/i\tools-y += ucl upx' ./tools/Makefile sed -i '\/autoconf\/compile :=/i\$(curdir)/upx/compile := $(curdir)/ucl/compile' ./tools/Makefile -svn co https://github.com/immortalwrt/immortalwrt/branches/master/tools/upx tools/upx -svn co https://github.com/immortalwrt/immortalwrt/branches/master/tools/ucl tools/ucl +svn export https://github.com/immortalwrt/immortalwrt/branches/master/tools/upx tools/upx +svn export https://github.com/immortalwrt/immortalwrt/branches/master/tools/ucl tools/ucl ### 获取额外的 LuCI 应用、主题和依赖 ### # 访问控制 -svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-accesscontrol package/lean/luci-app-accesscontrol -svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/luci-app-control-weburl package/new/luci-app-control-weburl +svn export https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-accesscontrol package/lean/luci-app-accesscontrol +svn export https://github.com/QiuSimons/OpenWrt-Add/trunk/luci-app-control-weburl package/new/luci-app-control-weburl # 广告过滤 Adbyby -svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-adbyby-plus package/lean/luci-app-adbyby-plus -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/adbyby package/lean/adbyby +svn export https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-adbyby-plus package/lean/luci-app-adbyby-plus +svn export https://github.com/coolsnowwolf/lede/trunk/package/lean/adbyby package/lean/adbyby # 广告过滤 AdGuard -#svn co https://github.com/Lienol/openwrt/trunk/package/diy/luci-app-adguardhome package/new/luci-app-adguardhome +#svn export https://github.com/Lienol/openwrt/trunk/package/diy/luci-app-adguardhome package/new/luci-app-adguardhome git clone https://github.com/rufengsuixing/luci-app-adguardhome.git package/new/luci-app-adguardhome rm -rf ./feeds/packages/net/adguardhome -svn co https://github.com/openwrt/packages/trunk/net/adguardhome feeds/packages/net/adguardhome +svn export https://github.com/openwrt/packages/trunk/net/adguardhome feeds/packages/net/adguardhome sed -i '/\t)/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $(GO_PKG_BUILD_BIN_DIR)/AdGuardHome' ./feeds/packages/net/adguardhome/Makefile sed -i '/init/d' feeds/packages/net/adguardhome/Makefile # Argon 主题 @@ -172,38 +172,38 @@ rm -rf ./package/new/luci-theme-argon/htdocs/luci-static/argon/background/README #popd git clone -b master --depth 1 https://github.com/jerrykuku/luci-app-argon-config.git package/new/luci-app-argon-config # MAC 地址与 IP 绑定 -svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-arpbind feeds/luci/applications/luci-app-arpbind +svn export https://github.com/immortalwrt/luci/trunk/applications/luci-app-arpbind feeds/luci/applications/luci-app-arpbind ln -sf ../../../feeds/luci/applications/luci-app-arpbind ./package/feeds/luci/luci-app-arpbind # 定时重启 -svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-autoreboot package/lean/luci-app-autoreboot +svn export https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-autoreboot package/lean/luci-app-autoreboot # Boost 通用即插即用 -svn co https://github.com/QiuSimons/slim-wrt/branches/main/slimapps/application/luci-app-boostupnp package/new/luci-app-boostupnp +svn export https://github.com/QiuSimons/slim-wrt/branches/main/slimapps/application/luci-app-boostupnp package/new/luci-app-boostupnp rm -rf ./feeds/packages/net/miniupnpd -svn co https://github.com/coolsnowwolf/packages/trunk/net/miniupnpd feeds/packages/net/miniupnpd +svn export https://github.com/coolsnowwolf/packages/trunk/net/miniupnpd feeds/packages/net/miniupnpd # ChinaDNS git clone -b luci --depth 1 https://github.com/QiuSimons/openwrt-chinadns-ng.git package/new/luci-app-chinadns-ng -svn co https://github.com/xiaorouji/openwrt-passwall/trunk/chinadns-ng package/new/chinadns-ng +svn export https://github.com/xiaorouji/openwrt-passwall/trunk/chinadns-ng package/new/chinadns-ng # CPU 控制相关 -svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-cpufreq feeds/luci/applications/luci-app-cpufreq +svn export https://github.com/immortalwrt/luci/trunk/applications/luci-app-cpufreq feeds/luci/applications/luci-app-cpufreq ln -sf ../../../feeds/luci/applications/luci-app-cpufreq ./package/feeds/luci/luci-app-cpufreq sed -i 's,1608,1800,g' feeds/luci/applications/luci-app-cpufreq/root/etc/uci-defaults/cpufreq sed -i 's,2016,2208,g' feeds/luci/applications/luci-app-cpufreq/root/etc/uci-defaults/cpufreq sed -i 's,1512,1608,g' feeds/luci/applications/luci-app-cpufreq/root/etc/uci-defaults/cpufreq -svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/luci-app-cpulimit package/lean/luci-app-cpulimit -svn co https://github.com/immortalwrt/packages/trunk/utils/cpulimit feeds/packages/utils/cpulimit +svn export https://github.com/QiuSimons/OpenWrt-Add/trunk/luci-app-cpulimit package/lean/luci-app-cpulimit +svn export https://github.com/immortalwrt/packages/trunk/utils/cpulimit feeds/packages/utils/cpulimit ln -sf ../../../feeds/packages/utils/cpulimit ./package/feeds/packages/cpulimit # 动态DNS sed -i '/boot()/,+2d' feeds/packages/net/ddns-scripts/files/etc/init.d/ddns -svn co https://github.com/kiddin9/openwrt-packages/trunk/ddns-scripts-aliyun package/lean/ddns-scripts_dnspod -svn co https://github.com/kiddin9/openwrt-packages/trunk/ddns-scripts-dnspod package/lean/ddns-scripts_aliyun -svn co https://github.com/QiuSimons/OpenWrt_luci-app/trunk/luci-app-tencentddns package/lean/luci-app-tencentddns -svn co https://github.com/kenzok8/openwrt-packages/trunk/luci-app-aliddns feeds/luci/applications/luci-app-aliddns +svn export https://github.com/kiddin9/openwrt-packages/trunk/ddns-scripts-aliyun package/lean/ddns-scripts_dnspod +svn export https://github.com/kiddin9/openwrt-packages/trunk/ddns-scripts-dnspod package/lean/ddns-scripts_aliyun +svn export https://github.com/QiuSimons/OpenWrt_luci-app/trunk/luci-app-tencentddns package/lean/luci-app-tencentddns +svn export https://github.com/kenzok8/openwrt-packages/trunk/luci-app-aliddns feeds/luci/applications/luci-app-aliddns ln -sf ../../../feeds/luci/applications/luci-app-aliddns ./package/feeds/luci/luci-app-aliddns # Docker 容器(会导致 OpenWrt 出现 UDP 转发问题,慎用) rm -rf ./feeds/luci/applications/luci-app-dockerman -svn co https://github.com/lisaac/luci-app-dockerman/trunk/applications/luci-app-dockerman feeds/luci/applications/luci-app-dockerman +svn export https://github.com/lisaac/luci-app-dockerman/trunk/applications/luci-app-dockerman feeds/luci/applications/luci-app-dockerman rm -rf ./feeds/luci/collections/luci-lib-docker -svn co https://github.com/lisaac/luci-lib-docker/trunk/collections/luci-lib-docker feeds/luci/collections/luci-lib-docker +svn export https://github.com/lisaac/luci-lib-docker/trunk/collections/luci-lib-docker feeds/luci/collections/luci-lib-docker #sed -i 's/+docker/+docker \\\n\t+dockerd/g' ./feeds/luci/applications/luci-app-dockerman/Makefile sed -i '/sysctl.d/d' feeds/packages/utils/dockerd/Makefile # DiskMan @@ -214,10 +214,10 @@ wget https://raw.githubusercontent.com/lisaac/luci-app-diskman/master/Parted.Mak # Dnsfilter git clone --depth 1 https://github.com/kiddin9/luci-app-dnsfilter.git package/new/luci-app-dnsfilter # Dnsproxy -svn co https://github.com/immortalwrt/packages/trunk/net/dnsproxy feeds/packages/net/dnsproxy +svn export https://github.com/immortalwrt/packages/trunk/net/dnsproxy feeds/packages/net/dnsproxy ln -sf ../../../feeds/packages/net/dnsproxy ./package/feeds/packages/dnsproxy sed -i '/CURDIR/d' feeds/packages/net/dnsproxy/Makefile -svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/luci-app-dnsproxy package/new/luci-app-dnsproxy +svn export https://github.com/QiuSimons/OpenWrt-Add/trunk/luci-app-dnsproxy package/new/luci-app-dnsproxy # Edge 主题 git clone -b master --depth 1 https://github.com/kiddin9/luci-theme-edge.git package/new/luci-theme-edge # FRP 内网穿透 @@ -225,13 +225,13 @@ rm -rf ./feeds/luci/applications/luci-app-frps rm -rf ./feeds/luci/applications/luci-app-frpc rm -rf ./feeds/packages/net/frp rm -f ./package/feeds/packages/frp -svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-frps package/lean/luci-app-frps -svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-frpc package/lean/luci-app-frpc -svn co https://github.com/coolsnowwolf/packages/trunk/net/frp package/lean/frp +svn export https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-frps package/lean/luci-app-frps +svn export https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-frpc package/lean/luci-app-frpc +svn export https://github.com/coolsnowwolf/packages/trunk/net/frp package/lean/frp # IPSec -svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-ipsec-vpnd package/lean/luci-app-ipsec-vpnd +svn export https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-ipsec-vpnd package/lean/luci-app-ipsec-vpnd # IPv6 兼容助手 -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/ipv6-helper package/lean/ipv6-helper +svn export https://github.com/coolsnowwolf/lede/trunk/package/lean/ipv6-helper package/lean/ipv6-helper # 京东签到 By Jerrykuku git clone --depth 1 https://github.com/jerrykuku/node-request.git package/new/node-request git clone --depth 1 https://github.com/jerrykuku/luci-app-jd-dailybonus.git package/new/luci-app-jd-dailybonus @@ -239,15 +239,15 @@ git clone --depth 1 https://github.com/jerrykuku/luci-app-jd-dailybonus.git pack git clone --depth 1 https://github.com/BoringCat/luci-app-mentohust package/new/luci-app-mentohust git clone --depth 1 https://github.com/KyleRicardo/MentoHUST-OpenWrt-ipk package/new/MentoHUST # Mosdns -#svn co https://github.com/immortalwrt/packages/trunk/net/mosdns feeds/packages/net/mosdns +#svn export https://github.com/immortalwrt/packages/trunk/net/mosdns feeds/packages/net/mosdns #ln -sf ../../../feeds/packages/net/mosdns ./package/feeds/packages/mosdns #sed -i '/config.yaml/d' feeds/packages/net/mosdns/Makefile #sed -i '/mosdns-init-openwrt/d' feeds/packages/net/mosdns/Makefile -svn co https://github.com/QiuSimons/openwrt-mos/trunk/mosdns package/new/mosdns -svn co https://github.com/QiuSimons/openwrt-mos/trunk/luci-app-mosdns package/new/luci-app-mosdns -svn co https://github.com/QiuSimons/openwrt-mos/trunk/v2ray-geodata package/new/v2ray-geodata +svn export https://github.com/QiuSimons/openwrt-mos/trunk/mosdns package/new/mosdns +svn export https://github.com/QiuSimons/openwrt-mos/trunk/luci-app-mosdns package/new/luci-app-mosdns +svn export https://github.com/QiuSimons/openwrt-mos/trunk/v2ray-geodata package/new/v2ray-geodata # 流量监管 -svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-netdata package/lean/luci-app-netdata +svn export https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-netdata package/lean/luci-app-netdata # 上网 APP 过滤 git clone -b master --depth 1 https://github.com/destan19/OpenAppFilter.git package/new/OpenAppFilter pushd package/new/OpenAppFilter @@ -259,12 +259,12 @@ git clone -b master --depth 1 https://github.com/NateLol/luci-app-oled.git packa # OpenClash git clone --single-branch --depth 1 -b dev https://github.com/vernesong/OpenClash.git package/new/luci-app-openclash # 花生壳内网穿透 -svn co https://github.com/teasiu/dragino2/trunk/devices/common/diy/package/teasiu/luci-app-phtunnel package/new/luci-app-phtunnel -svn co https://github.com/teasiu/dragino2/trunk/devices/common/diy/package/teasiu/phtunnel package/new/phtunnel -svn co https://github.com/QiuSimons/dragino2-teasiu/trunk/package/teasiu/luci-app-oray package/new/luci-app-oray +svn export https://github.com/teasiu/dragino2/trunk/devices/common/diy/package/teasiu/luci-app-phtunnel package/new/luci-app-phtunnel +svn export https://github.com/teasiu/dragino2/trunk/devices/common/diy/package/teasiu/phtunnel package/new/phtunnel +svn export https://github.com/QiuSimons/dragino2-teasiu/trunk/package/teasiu/luci-app-oray package/new/luci-app-oray # Passwall -svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-passwall package/new/luci-app-passwall -#svn co https://github.com/xiaorouji/openwrt-passwall/trunk/luci-app-passwall package/new/luci-app-passwall +svn export https://github.com/immortalwrt/luci/trunk/applications/luci-app-passwall package/new/luci-app-passwall +#svn export https://github.com/xiaorouji/openwrt-passwall/trunk/luci-app-passwall package/new/luci-app-passwall pushd package/new/luci-app-passwall sed -i 's,default n,default y,g' Makefile sed -i '/trojan-go/d' Makefile @@ -281,58 +281,58 @@ pushd package/new/luci-app-passwall bash move_2_services.sh popd rm -rf ./feeds/packages/net/https-dns-proxy -svn co https://github.com/Lienol/openwrt-packages/trunk/net/https-dns-proxy feeds/packages/net/https-dns-proxy -svn co https://github.com/xiaorouji/openwrt-passwall/trunk/tcping package/new/tcping -svn co https://github.com/xiaorouji/openwrt-passwall/trunk/trojan-go package/new/trojan-go -svn co https://github.com/xiaorouji/openwrt-passwall/trunk/brook package/new/brook -svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/trojan-plus package/new/trojan-plus -svn co https://github.com/xiaorouji/openwrt-passwall/trunk/ssocks package/new/ssocks -svn co https://github.com/xiaorouji/openwrt-passwall/trunk/hysteria package/new/hysteria +svn export https://github.com/Lienol/openwrt-packages/trunk/net/https-dns-proxy feeds/packages/net/https-dns-proxy +svn export https://github.com/xiaorouji/openwrt-passwall/trunk/tcping package/new/tcping +svn export https://github.com/xiaorouji/openwrt-passwall/trunk/trojan-go package/new/trojan-go +svn export https://github.com/xiaorouji/openwrt-passwall/trunk/brook package/new/brook +svn export https://github.com/QiuSimons/OpenWrt-Add/trunk/trojan-plus package/new/trojan-plus +svn export https://github.com/xiaorouji/openwrt-passwall/trunk/ssocks package/new/ssocks +svn export https://github.com/xiaorouji/openwrt-passwall/trunk/hysteria package/new/hysteria # qBittorrent 下载 -svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-qbittorrent package/lean/luci-app-qbittorrent -svn co https://github.com/coolsnowwolf/packages/trunk/net/qBittorrent-static package/lean/qBittorrent-static -svn co https://github.com/coolsnowwolf/packages/trunk/net/qBittorrent package/lean/qBittorrent -svn co https://github.com/coolsnowwolf/packages/trunk/libs/qtbase package/lean/qtbase -svn co https://github.com/coolsnowwolf/packages/trunk/libs/qttools package/lean/qttools -svn co https://github.com/coolsnowwolf/packages/trunk/libs/rblibtorrent package/lean/rblibtorrent +svn export https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-qbittorrent package/lean/luci-app-qbittorrent +svn export https://github.com/coolsnowwolf/packages/trunk/net/qBittorrent-static package/lean/qBittorrent-static +svn export https://github.com/coolsnowwolf/packages/trunk/net/qBittorrent package/lean/qBittorrent +svn export https://github.com/coolsnowwolf/packages/trunk/libs/qtbase package/lean/qtbase +svn export https://github.com/coolsnowwolf/packages/trunk/libs/qttools package/lean/qttools +svn export https://github.com/coolsnowwolf/packages/trunk/libs/rblibtorrent package/lean/rblibtorrent # 清理内存 -svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-ramfree package/lean/luci-app-ramfree +svn export https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-ramfree package/lean/luci-app-ramfree # ServerChan 微信推送 git clone -b master --depth 1 https://github.com/tty228/luci-app-serverchan.git package/new/luci-app-serverchan # SmartDNS rm -rf ./feeds/packages/net/smartdns -svn co https://github.com/Lienol/openwrt-packages/trunk/net/smartdns feeds/packages/net/smartdns +svn export https://github.com/Lienol/openwrt-packages/trunk/net/smartdns feeds/packages/net/smartdns rm -rf ./feeds/luci/applications/luci-app-smartdns -svn co https://github.com/immortalwrt/luci/branches/openwrt-18.06/applications/luci-app-smartdns feeds/luci/applications/luci-app-smartdns +svn export https://github.com/immortalwrt/luci/branches/openwrt-18.06/applications/luci-app-smartdns feeds/luci/applications/luci-app-smartdns # ShadowsocksR Plus+ 依赖 rm -rf ./feeds/packages/net/kcptun rm -rf ./feeds/packages/net/shadowsocks-libev rm -rf ./feeds/packages/net/xray-core -svn co https://github.com/coolsnowwolf/packages/trunk/net/shadowsocks-libev package/lean/shadowsocks-libev -svn co https://github.com/xiaorouji/openwrt-passwall/trunk/shadowsocksr-libev package/lean/shadowsocksr-libev -svn co https://github.com/xiaorouji/openwrt-passwall/trunk/pdnsd-alt package/lean/pdnsd -svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/srelay package/lean/srelay -svn co https://github.com/xiaorouji/openwrt-passwall/trunk/microsocks package/lean/microsocks -svn co https://github.com/xiaorouji/openwrt-passwall/trunk/dns2socks package/lean/dns2socks -svn co https://github.com/coolsnowwolf/packages/trunk/net/redsocks2 package/lean/redsocks2 -svn co https://github.com/xiaorouji/openwrt-passwall/trunk/ipt2socks package/lean/ipt2socks -svn co https://github.com/xiaorouji/openwrt-passwall/trunk/trojan package/lean/trojan -svn co https://github.com/xiaorouji/openwrt-passwall/trunk/tcping package/lean/tcping -svn co https://github.com/xiaorouji/openwrt-passwall/trunk/trojan-go package/lean/trojan-go -svn co https://github.com/fw876/helloworld/trunk/simple-obfs package/lean/simple-obfs -svn co https://github.com/fw876/helloworld/trunk/naiveproxy package/lean/naiveproxy -svn co https://github.com/fw876/helloworld/trunk/v2ray-core package/lean/v2ray-core -svn co https://github.com/fw876/helloworld/trunk/xray-core package/lean/xray-core -svn co https://github.com/fw876/helloworld/trunk/v2ray-plugin package/lean/v2ray-plugin -svn co https://github.com/fw876/helloworld/trunk/xray-plugin package/lean/xray-plugin -svn co https://github.com/xiaorouji/openwrt-passwall/trunk/shadowsocks-rust feeds/packages/net/shadowsocks-rust -#svn co https://github.com/immortalwrt/packages/trunk/net/shadowsocks-rust feeds/packages/net/shadowsocks-rust +svn export https://github.com/coolsnowwolf/packages/trunk/net/shadowsocks-libev package/lean/shadowsocks-libev +svn export https://github.com/xiaorouji/openwrt-passwall/trunk/shadowsocksr-libev package/lean/shadowsocksr-libev +svn export https://github.com/xiaorouji/openwrt-passwall/trunk/pdnsd-alt package/lean/pdnsd +svn export https://github.com/coolsnowwolf/lede/trunk/package/lean/srelay package/lean/srelay +svn export https://github.com/xiaorouji/openwrt-passwall/trunk/microsocks package/lean/microsocks +svn export https://github.com/xiaorouji/openwrt-passwall/trunk/dns2socks package/lean/dns2socks +svn export https://github.com/coolsnowwolf/packages/trunk/net/redsocks2 package/lean/redsocks2 +svn export https://github.com/xiaorouji/openwrt-passwall/trunk/ipt2socks package/lean/ipt2socks +svn export https://github.com/xiaorouji/openwrt-passwall/trunk/trojan package/lean/trojan +svn export https://github.com/xiaorouji/openwrt-passwall/trunk/tcping package/lean/tcping +svn export https://github.com/xiaorouji/openwrt-passwall/trunk/trojan-go package/lean/trojan-go +svn export https://github.com/fw876/helloworld/trunk/simple-obfs package/lean/simple-obfs +svn export https://github.com/fw876/helloworld/trunk/naiveproxy package/lean/naiveproxy +svn export https://github.com/fw876/helloworld/trunk/v2ray-core package/lean/v2ray-core +svn export https://github.com/fw876/helloworld/trunk/xray-core package/lean/xray-core +svn export https://github.com/fw876/helloworld/trunk/v2ray-plugin package/lean/v2ray-plugin +svn export https://github.com/fw876/helloworld/trunk/xray-plugin package/lean/xray-plugin +svn export https://github.com/xiaorouji/openwrt-passwall/trunk/shadowsocks-rust feeds/packages/net/shadowsocks-rust +#svn export https://github.com/immortalwrt/packages/trunk/net/shadowsocks-rust feeds/packages/net/shadowsocks-rust sed -i '/Build\/Compile/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $$(PKG_BUILD_DIR)/$(component)' feeds/packages/net/shadowsocks-rust/Makefile ln -sf ../../../feeds/packages/net/shadowsocks-rust ./package/feeds/packages/shadowsocks-rust -svn co https://github.com/immortalwrt/packages/trunk/net/kcptun feeds/packages/net/kcptun +svn export https://github.com/immortalwrt/packages/trunk/net/kcptun feeds/packages/net/kcptun ln -sf ../../../feeds/packages/net/kcptun ./package/feeds/packages/kcptun # ShadowsocksR Plus+ -svn co https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/lean/luci-app-ssr-plus +svn export https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/lean/luci-app-ssr-plus rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans pushd package/lean #wget -qO - https://github.com/fw876/helloworld/pull/656.patch | patch -p1 @@ -355,34 +355,34 @@ sed -i '/Clang.CN.CIDR/a\o:value("https://gh.404delivr.workers.dev/https://githu popd # v2raya git clone --depth 1 https://github.com/zxlhhyccc/luci-app-v2raya.git package/new/luci-app-v2raya -svn co https://github.com/openwrt/packages/trunk/net/v2raya feeds/packages/net/v2raya +svn export https://github.com/openwrt/packages/trunk/net/v2raya feeds/packages/net/v2raya ln -sf ../../../feeds/packages/net/v2raya ./package/feeds/packages/v2raya # socat -svn co https://github.com/Lienol/openwrt-package/trunk/luci-app-socat package/new/luci-app-socat +svn export https://github.com/Lienol/openwrt-package/trunk/luci-app-socat package/new/luci-app-socat # 订阅转换 -svn co https://github.com/immortalwrt/packages/trunk/net/subconverter feeds/packages/net/subconverter +svn export https://github.com/immortalwrt/packages/trunk/net/subconverter feeds/packages/net/subconverter sed -i '\/bin\/subconverter/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $(1)/usr/bin/subconverter' feeds/packages/net/subconverter/Makefile ln -sf ../../../feeds/packages/net/subconverter ./package/feeds/packages/subconverter -svn co https://github.com/immortalwrt/packages/trunk/libs/jpcre2 feeds/packages/libs/jpcre2 +svn export https://github.com/immortalwrt/packages/trunk/libs/jpcre2 feeds/packages/libs/jpcre2 ln -sf ../../../feeds/packages/libs/jpcre2 ./package/feeds/packages/jpcre2 -svn co https://github.com/immortalwrt/packages/trunk/libs/rapidjson feeds/packages/libs/rapidjson +svn export https://github.com/immortalwrt/packages/trunk/libs/rapidjson feeds/packages/libs/rapidjson ln -sf ../../../feeds/packages/libs/rapidjson ./package/feeds/packages/rapidjson -svn co https://github.com/immortalwrt/packages/trunk/libs/libcron feeds/packages/libs/libcron +svn export https://github.com/immortalwrt/packages/trunk/libs/libcron feeds/packages/libs/libcron ln -sf ../../../feeds/packages/libs/libcron ./package/feeds/packages/libcron -svn co https://github.com/immortalwrt/packages/trunk/libs/quickjspp feeds/packages/libs/quickjspp +svn export https://github.com/immortalwrt/packages/trunk/libs/quickjspp feeds/packages/libs/quickjspp ln -sf ../../../feeds/packages/libs/quickjspp ./package/feeds/packages/quickjspp -svn co https://github.com/immortalwrt/packages/trunk/libs/toml11 feeds/packages/libs/toml11 +svn export https://github.com/immortalwrt/packages/trunk/libs/toml11 feeds/packages/libs/toml11 ln -sf ../../../feeds/packages/libs/toml11 ./package/feeds/packages/toml11 # 网易云音乐解锁 git clone --depth 1 https://github.com/immortalwrt/luci-app-unblockneteasemusic.git package/new/UnblockNeteaseMusic # USB 打印机 -svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-usb-printer package/lean/luci-app-usb-printer +svn export https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-usb-printer package/lean/luci-app-usb-printer # UU加速器 -svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-uugamebooster package/lean/luci-app-uugamebooster -svn co https://github.com/coolsnowwolf/packages/trunk/net/uugamebooster package/lean/uugamebooster +svn export https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-uugamebooster package/lean/luci-app-uugamebooster +svn export https://github.com/coolsnowwolf/packages/trunk/net/uugamebooster package/lean/uugamebooster # KMS 激活助手 -svn co https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-vlmcsd package/lean/luci-app-vlmcsd -svn co https://github.com/coolsnowwolf/packages/trunk/net/vlmcsd package/lean/vlmcsd +svn export https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-vlmcsd package/lean/luci-app-vlmcsd +svn export https://github.com/coolsnowwolf/packages/trunk/net/vlmcsd package/lean/vlmcsd # VSSR git clone -b master --depth 1 https://github.com/jerrykuku/luci-app-vssr.git package/lean/luci-app-vssr git clone -b master --depth 1 https://github.com/jerrykuku/lua-maxminddb.git package/lean/lua-maxminddb @@ -398,14 +398,14 @@ sed -i '/result.encrypt_method/a\result.fast_open = "1"' package/lean/luci-app-v sed -i 's,ispip.clang.cn/all_cn.txt,raw.sevencdn.com/QiuSimons/Chnroute/master/dist/chnroute/chnroute.txt,g' package/lean/luci-app-vssr/luasrc/controller/vssr.lua sed -i 's,ispip.clang.cn/all_cn.txt,raw.sevencdn.com/QiuSimons/Chnroute/master/dist/chnroute/chnroute.txt,g' package/lean/luci-app-vssr/root/usr/share/vssr/update.lua # 网络唤醒 -svn co https://github.com/zxlhhyccc/bf-package-master/trunk/zxlhhyccc/luci-app-services-wolplus package/new/luci-app-services-wolplus +svn export https://github.com/zxlhhyccc/bf-package-master/trunk/zxlhhyccc/luci-app-services-wolplus package/new/luci-app-services-wolplus # 流量监视 git clone -b master --depth 1 https://github.com/brvphoenix/wrtbwmon.git package/new/wrtbwmon git clone -b master --depth 1 https://github.com/brvphoenix/luci-app-wrtbwmon.git package/new/luci-app-wrtbwmon # 迅雷快鸟宽带加速 git clone --depth 1 https://github.com/kiddin9/luci-app-xlnetacc.git package/lean/luci-app-xlnetacc # Zerotier -svn co https://github.com/immortalwrt/luci/trunk/applications/luci-app-zerotier feeds/luci/applications/luci-app-zerotier +svn export https://github.com/immortalwrt/luci/trunk/applications/luci-app-zerotier feeds/luci/applications/luci-app-zerotier wget -P feeds/luci/applications/luci-app-zerotier/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/move_2_services.sh chmod -R 755 ./feeds/luci/applications/luci-app-zerotier/move_2_services.sh pushd feeds/luci/applications/luci-app-zerotier @@ -413,11 +413,11 @@ bash move_2_services.sh popd ln -sf ../../../feeds/luci/applications/luci-app-zerotier ./package/feeds/luci/luci-app-zerotier rm -rf ./feeds/packages/net/zerotier -svn co https://github.com/openwrt/packages/trunk/net/zerotier feeds/packages/net/zerotier +svn export https://github.com/openwrt/packages/trunk/net/zerotier feeds/packages/net/zerotier rm -rf ./feeds/packages/net/zerotier/files/etc/init.d/zerotier sed -i '/Default,one/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $(PKG_BUILD_DIR)/zerotier-one' feeds/packages/net/zerotier/Makefile # 翻译及部分功能优化 -svn co https://github.com/QiuSimons/OpenWrt-Add/trunk/addition-trans-zh package/lean/lean-translate +svn export https://github.com/QiuSimons/OpenWrt-Add/trunk/addition-trans-zh package/lean/lean-translate ### 最后的收尾工作 ### # Lets Fuck @@ -436,12 +436,12 @@ rm -rf .config # Patch LuCI 以增添 Shortcut-FE 开关 #patch -p1 < ../PATCH/firewall/luci-app-firewall_add_sfe_switch.patch # Shortcut-FE 相关组件 -#svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/shortcut-fe package/lean/shortcut-fe -#svn co https://github.com/coolsnowwolf/lede/trunk/package/lean/fast-classifier package/lean/fast-classifier +#svn export https://github.com/coolsnowwolf/lede/trunk/package/lean/shortcut-fe package/lean/shortcut-fe +#svn export https://github.com/coolsnowwolf/lede/trunk/package/lean/fast-classifier package/lean/fast-classifier #wget -P package/base-files/files/etc/init.d/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/shortcut-fe # 回滚通用即插即用 #rm -rf ./feeds/packages/net/miniupnpd -#svn co https://github.com/coolsnowwolf/packages/trunk/net/miniupnpd feeds/packages/net/miniupnpd +#svn export https://github.com/coolsnowwolf/packages/trunk/net/miniupnpd feeds/packages/net/miniupnpd #exit 0 From b7a2da1b016eaa3499b709b682a94b0658b96dba Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 21 Mar 2022 16:20:02 +0800 Subject: [PATCH 237/244] ImmortalWrt Uboot TMP Fix --- SCRIPTS/02_prepare_package.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 9f85d9177..486e3d263 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -99,6 +99,8 @@ svn export https://github.com/immortalwrt/immortalwrt/branches/openwrt-21.02/pac svn export https://github.com/immortalwrt/immortalwrt/branches/openwrt-21.02/package/boot/arm-trusted-firmware-rockchip-vendor package/boot/arm-trusted-firmware-rockchip-vendor rm -rf ./package/kernel/linux/modules/video.mk wget -P package/kernel/linux/modules/ https://github.com/immortalwrt/immortalwrt/raw/openwrt-21.02/package/kernel/linux/modules/video.mk +# ImmortalWrt Uboot TMP Fix +wget -qO- https://github.com/immortalwrt/immortalwrt/commit/433c93e.patch | patch -REp1 # R4S超频到 2.2/1.8 GHz #rm -rf ./target/linux/rockchip/patches-5.4/992-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch #cp -f ../PATCH/target_r4s/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch ./target/linux/rockchip/patches-5.4/991-rockchip-rk3399-overclock-to-2.2-1.8-GHz-for-NanoPi4.patch From 266e78e255a6565995f6f5ae42589ede9685603c Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Mon, 21 Mar 2022 17:16:09 +0800 Subject: [PATCH 238/244] Adapt to upstream change --- SCRIPTS/02_prepare_package.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 486e3d263..f6cfbfb96 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -259,6 +259,7 @@ popd # OLED 驱动程序 git clone -b master --depth 1 https://github.com/NateLol/luci-app-oled.git package/new/luci-app-oled # OpenClash +wget -qO - https://github.com/openwrt/openwrt/commit/efc8aff.patch | patch -p1 git clone --single-branch --depth 1 -b dev https://github.com/vernesong/OpenClash.git package/new/luci-app-openclash # 花生壳内网穿透 svn export https://github.com/teasiu/dragino2/trunk/devices/common/diy/package/teasiu/luci-app-phtunnel package/new/luci-app-phtunnel @@ -363,6 +364,9 @@ ln -sf ../../../feeds/packages/net/v2raya ./package/feeds/packages/v2raya svn export https://github.com/Lienol/openwrt-package/trunk/luci-app-socat package/new/luci-app-socat # 订阅转换 svn export https://github.com/immortalwrt/packages/trunk/net/subconverter feeds/packages/net/subconverter +wget https://github.com/immortalwrt/packages/raw/b7b4499/net/subconverter/Makefile -O feeds/packages/net/subconverter/Makefile +mkdir -p ./feeds/packages/net/subconverter/patches +wget https://github.com/immortalwrt/packages/raw/b7b4499/net/subconverter/patches/100-stdcxxfs.patch -O feeds/packages/net/subconverter/patches/100-stdcxxfs.patch sed -i '\/bin\/subconverter/a\\t$(STAGING_DIR_HOST)/bin/upx --lzma --best $(1)/usr/bin/subconverter' feeds/packages/net/subconverter/Makefile ln -sf ../../../feeds/packages/net/subconverter ./package/feeds/packages/subconverter svn export https://github.com/immortalwrt/packages/trunk/libs/jpcre2 feeds/packages/libs/jpcre2 @@ -370,8 +374,10 @@ ln -sf ../../../feeds/packages/libs/jpcre2 ./package/feeds/packages/jpcre2 svn export https://github.com/immortalwrt/packages/trunk/libs/rapidjson feeds/packages/libs/rapidjson ln -sf ../../../feeds/packages/libs/rapidjson ./package/feeds/packages/rapidjson svn export https://github.com/immortalwrt/packages/trunk/libs/libcron feeds/packages/libs/libcron +wget https://github.com/immortalwrt/packages/raw/b7b4499/libs/libcron/Makefile -O feeds/packages/libs/libcron/Makefile ln -sf ../../../feeds/packages/libs/libcron ./package/feeds/packages/libcron svn export https://github.com/immortalwrt/packages/trunk/libs/quickjspp feeds/packages/libs/quickjspp +wget https://github.com/immortalwrt/packages/raw/b7b4499/libs/quickjspp/Makefile -O feeds/packages/libs/quickjspp/Makefile ln -sf ../../../feeds/packages/libs/quickjspp ./package/feeds/packages/quickjspp svn export https://github.com/immortalwrt/packages/trunk/libs/toml11 feeds/packages/libs/toml11 ln -sf ../../../feeds/packages/libs/toml11 ./package/feeds/packages/toml11 From 32d8a605f7538da81968c6417dca7c4e83cf80a1 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 23 Mar 2022 12:55:45 +0800 Subject: [PATCH 239/244] Add passwall2 --- SCRIPTS/02_prepare_package.sh | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index f6cfbfb96..7a2bdc1b5 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -291,6 +291,21 @@ svn export https://github.com/xiaorouji/openwrt-passwall/trunk/brook package/new svn export https://github.com/QiuSimons/OpenWrt-Add/trunk/trojan-plus package/new/trojan-plus svn export https://github.com/xiaorouji/openwrt-passwall/trunk/ssocks package/new/ssocks svn export https://github.com/xiaorouji/openwrt-passwall/trunk/hysteria package/new/hysteria +# passwall2 +svn export https://github.com/xiaorouji/openwrt-passwall2/trunk/luci-app-passwall2 package/new/luci-app-passwall2 +wget -P package/new/luci-app-passwall2/ https://github.com/QiuSimons/OpenWrt-Add/raw/master/move_2_services.sh +chmod -R 755 ./package/new/luci-app-passwall2/move_2_services.sh +pushd package/new/luci-app-passwall2 +bash move_2_services.sh +popd +pushd package/new/luci-app-passwall2 +sed -i 's,default n,default y,g' Makefile +sed -i 's,+v2ray-core ,,g' Makefile +sed -i '/v2ray-plugin/d' Makefile +sed -i '/shadowsocks-libev-ss-redir/d' Makefile +sed -i '/shadowsocks-libev-ss-server/d' Makefile +sed -i '/shadowsocks-libev-ss-local/d' Makefile +popd # qBittorrent 下载 svn export https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-qbittorrent package/lean/luci-app-qbittorrent svn export https://github.com/coolsnowwolf/packages/trunk/net/qBittorrent-static package/lean/qBittorrent-static From 8cf5e17d82fc3aaa2af3ee0d2ba5fc49a66a4769 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 23 Mar 2022 14:15:55 +0800 Subject: [PATCH 240/244] disable oaf --- SEED/R2C/config.seed | 2 +- SEED/R2S/config.seed | 2 +- SEED/R4S/config.seed | 2 +- SEED/X86/config.seed | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/SEED/R2C/config.seed b/SEED/R2C/config.seed index eda6f6b92..216721972 100644 --- a/SEED/R2C/config.seed +++ b/SEED/R2C/config.seed @@ -100,7 +100,7 @@ CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y #CONFIG_PACKAGE_luci-app-boostupnp=y CONFIG_PACKAGE_luci-app-mosdns=y -CONFIG_PACKAGE_luci-app-oaf=y +#CONFIG_PACKAGE_luci-app-oaf=y CONFIG_PACKAGE_luci-app-cpufreq=y CONFIG_PACKAGE_luci-app-cpulimit=y CONFIG_PACKAGE_luci-app-ddns=y diff --git a/SEED/R2S/config.seed b/SEED/R2S/config.seed index 94f8537aa..a99856682 100644 --- a/SEED/R2S/config.seed +++ b/SEED/R2S/config.seed @@ -100,7 +100,7 @@ CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y #CONFIG_PACKAGE_luci-app-boostupnp=y CONFIG_PACKAGE_luci-app-mosdns=y -CONFIG_PACKAGE_luci-app-oaf=y +#CONFIG_PACKAGE_luci-app-oaf=y CONFIG_PACKAGE_luci-app-cpufreq=y CONFIG_PACKAGE_luci-app-cpulimit=y CONFIG_PACKAGE_luci-app-ddns=y diff --git a/SEED/R4S/config.seed b/SEED/R4S/config.seed index 80f893e39..957b21a98 100644 --- a/SEED/R4S/config.seed +++ b/SEED/R4S/config.seed @@ -101,7 +101,7 @@ CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y #CONFIG_PACKAGE_luci-app-boostupnp=y CONFIG_PACKAGE_luci-app-mosdns=y -CONFIG_PACKAGE_luci-app-oaf=y +#CONFIG_PACKAGE_luci-app-oaf=y CONFIG_PACKAGE_luci-app-cpufreq=y CONFIG_PACKAGE_luci-app-cpulimit=y CONFIG_PACKAGE_luci-app-ddns=y diff --git a/SEED/X86/config.seed b/SEED/X86/config.seed index d12155c41..c97b0d516 100644 --- a/SEED/X86/config.seed +++ b/SEED/X86/config.seed @@ -100,7 +100,7 @@ CONFIG_PACKAGE_luci-app-arpbind=y CONFIG_PACKAGE_luci-app-autoreboot=y #CONFIG_PACKAGE_luci-app-boostupnp=y CONFIG_PACKAGE_luci-app-mosdns=y -CONFIG_PACKAGE_luci-app-oaf=y +#CONFIG_PACKAGE_luci-app-oaf=y CONFIG_PACKAGE_luci-app-cpufreq=y CONFIG_PACKAGE_luci-app-cpulimit=y CONFIG_PACKAGE_luci-app-ddns=y From 81a994f79a1ccdfc871f9bd2fb7ea4b3a61f2c52 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 23 Mar 2022 15:53:40 +0800 Subject: [PATCH 241/244] add ucode --- SCRIPTS/02_prepare_package.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 7a2bdc1b5..a1791fd51 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -398,6 +398,8 @@ svn export https://github.com/immortalwrt/packages/trunk/libs/toml11 feeds/packa ln -sf ../../../feeds/packages/libs/toml11 ./package/feeds/packages/toml11 # 网易云音乐解锁 git clone --depth 1 https://github.com/immortalwrt/luci-app-unblockneteasemusic.git package/new/UnblockNeteaseMusic +# ucode +svn export https://github.com/openwrt/openwrt/trunk/package/utils/ucode package/utils/ucode # USB 打印机 svn export https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-usb-printer package/lean/luci-app-usb-printer # UU加速器 From 7beb0c7f04ee58bf25775afaa86d0b2826f7462f Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Wed, 30 Mar 2022 22:25:02 +0800 Subject: [PATCH 242/244] Grant access to autocore --- SCRIPTS/02_prepare_package.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index a1791fd51..d986aa290 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -114,6 +114,7 @@ sed -i 's,noinitrd,noinitrd mitigations=off,g' target/linux/x86/image/grub-iso.c sed -i 's,noinitrd,noinitrd mitigations=off,g' target/linux/x86/image/grub-pc.cfg # AutoCore svn export https://github.com/immortalwrt/immortalwrt/branches/openwrt-21.02/package/emortal/autocore package/lean/autocore +sed -i 's/"getTempInfo" /"getTempInfo", "getCPUBench", "getCPUUsage" /g' package/lean/autocore/files/generic/luci-mod-status-autocore.json rm -rf ./feeds/packages/utils/coremark svn export https://github.com/immortalwrt/packages/trunk/utils/coremark feeds/packages/utils/coremark # DPDK From 66b4a83222a1f84ca46fef1c6a10e74b3596d0cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=90=81=E6=B5=85=E8=A2=AB=E6=B3=A8=E5=86=8C=E4=BA=86?= Date: Thu, 7 Apr 2022 00:36:44 +0800 Subject: [PATCH 243/244] Add luci-app-ipsec-server support --- SCRIPTS/02_prepare_package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index d986aa290..33ccc00ac 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -232,7 +232,7 @@ svn export https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-frps svn export https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-frpc package/lean/luci-app-frpc svn export https://github.com/coolsnowwolf/packages/trunk/net/frp package/lean/frp # IPSec -svn export https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-ipsec-vpnd package/lean/luci-app-ipsec-vpnd +svn export https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-ipsec-server package/lean/luci-app-ipsec-server # IPv6 兼容助手 svn export https://github.com/coolsnowwolf/lede/trunk/package/lean/ipv6-helper package/lean/ipv6-helper # 京东签到 By Jerrykuku From a0f3e3b99e3f070dc17b3cc9d09e8cce46757ec9 Mon Sep 17 00:00:00 2001 From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> Date: Sat, 2 Apr 2022 15:59:21 +0800 Subject: [PATCH 244/244] Adapt to upstream change --- SCRIPTS/02_prepare_package.sh | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/SCRIPTS/02_prepare_package.sh b/SCRIPTS/02_prepare_package.sh index 33ccc00ac..4c55cd933 100644 --- a/SCRIPTS/02_prepare_package.sh +++ b/SCRIPTS/02_prepare_package.sh @@ -149,10 +149,13 @@ sed -i 's,kmod-usb-net-rtl8152,kmod-usb-net-rtl8152-vendor,g' target/linux/rockc # UPX 可执行软件压缩 sed -i '/patchelf pkgconf/i\tools-y += ucl upx' ./tools/Makefile sed -i '\/autoconf\/compile :=/i\$(curdir)/upx/compile := $(curdir)/ucl/compile' ./tools/Makefile -svn export https://github.com/immortalwrt/immortalwrt/branches/master/tools/upx tools/upx -svn export https://github.com/immortalwrt/immortalwrt/branches/master/tools/ucl tools/ucl +svn export https://github.com/coolsnowwolf/openwrt/branches/lede-17.01/tools/ucl tools/ucl +svn export https://github.com/coolsnowwolf/openwrt/branches/lede-17.01/tools/upx tools/upx ### 获取额外的 LuCI 应用、主题和依赖 ### +# 更换 golang 版本 +rm -rf ./feeds/packages/lang/golang +svn export https://github.com/openwrt/packages/trunk/lang/golang feeds/packages/lang/golang # 访问控制 svn export https://github.com/coolsnowwolf/luci/trunk/applications/luci-app-accesscontrol package/lean/luci-app-accesscontrol svn export https://github.com/QiuSimons/OpenWrt-Add/trunk/luci-app-control-weburl package/new/luci-app-control-weburl @@ -267,8 +270,8 @@ svn export https://github.com/teasiu/dragino2/trunk/devices/common/diy/package/t svn export https://github.com/teasiu/dragino2/trunk/devices/common/diy/package/teasiu/phtunnel package/new/phtunnel svn export https://github.com/QiuSimons/dragino2-teasiu/trunk/package/teasiu/luci-app-oray package/new/luci-app-oray # Passwall -svn export https://github.com/immortalwrt/luci/trunk/applications/luci-app-passwall package/new/luci-app-passwall -#svn export https://github.com/xiaorouji/openwrt-passwall/trunk/luci-app-passwall package/new/luci-app-passwall +#svn export https://github.com/immortalwrt/luci/trunk/applications/luci-app-passwall package/new/luci-app-passwall +svn export https://github.com/xiaorouji/openwrt-passwall/branches/luci/luci-app-passwall package/new/luci-app-passwall pushd package/new/luci-app-passwall sed -i 's,default n,default y,g' Makefile sed -i '/trojan-go/d' Makefile @@ -355,8 +358,8 @@ svn export https://github.com/fw876/helloworld/trunk/luci-app-ssr-plus package/l rm -rf ./package/lean/luci-app-ssr-plus/po/zh_Hans pushd package/lean #wget -qO - https://github.com/fw876/helloworld/pull/656.patch | patch -p1 -wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/5bbf6e7.patch | patch -p1 -wget -qO - https://github.com/QiuSimons/helloworld-fw876/commit/323fbf0.patch | patch -p1 +wget -qO - https://github.com/fw876/helloworld/commit/5bbf6e7.patch | patch -p1 +wget -qO - https://github.com/fw876/helloworld/commit/ea3b4bd.patch | patch -p1 popd pushd package/lean/luci-app-ssr-plus sed -i 's,default n,default y,g' Makefile