diff --git a/SIG-policy.md b/SIG-policy.md
index d69fa84ff7f4a370a273436452c85af8940aed00..cc8116ea7bc7739e923b03925b180c0943442074 100644
--- a/SIG-policy.md
+++ b/SIG-policy.md
@@ -1,92 +1,94 @@
-# SIG政策指南
-## SIG运行和管理
+# SIG流程指南
+ SIG运行和管理
* 各SIG实行自治管理,按照多数票原则投票决策。
-* 各SIG每个半年向技术委员会做运行总结报告,TC给出相应的指导和帮助。
+* 各SIG每隔半年向技术委员会做运行总结报告,TC给出相应的指导和帮助。
* 其他合并等变更有SIG 维护者向技术委员会提交申请,并获批后变更。
-## 申请新SIG流程
-### 1.使用模板创建新SIG
-将 gitee.com/anolis/community/sig/sig-template Fork到你的Gitee下。并在sig目录下创建你的sig文件夹,以及把SIG申请模板文件拷贝到该文件夹下。
-SIG目录里定义了SIG元信息,这些信息作为社区基础设施和SIG同步程序的输入,以保证社区的自动化运作,所以在填写的时候需要遵守以下规范填写SIG信息:
-
-* README.md 文件要求
-README内容按模板项自定义填写,会作为SIG主页同步到社区官网对应的SIG主页,文档内容不能为空。
-注意:README.md文件必须有,同步程序才能检验通过
-
-* content 目录要求
-content 目录主要存放SIG相关文档,文件格式暂时只支持.md文档。目录下的文件夹与文档会跟SIG文档目录映射起来;同步程序会自动检测变更并同步到官网SIG文档,社区只支持三级目录。
-
-* sig-info.yaml 文件要求
-name: SIG中文名称,必填。
-en_name: SIG英文名称,必填。
-home_page:官网SIG主页的URL,必填且不能和现有重复。格式:https://openanolis.cn/sig/+英文后缀 (如:https://openanolis.cn/sig/t-one)。
-description:SIG中文具体描述信息,必填。
-en_description:SIG英文具体描述信息。
-mailing_list:SIG的邮件列表。
-meeting_url SIG的固定会议纪要信息,一般是etherpad 的url。
-maintainers对应SIG的maintainers
-openanolis_id:社区账户名称
-gitee_id:gitee帐户id
-contributors对应SIG的contributors。
-openanolis_id:社区账户名称
-gitee_id:gitee帐户id
-repositories SIG相关的仓库信息。
-仓库的填写格式:{group_name}/{repo_name},如 anolis/community
-注意:sig-info.yaml文件必须有,同步程序才能检验通过
-
-* assets 目录
-该目录用来存放资源文件,同步程序会默认跳过。
-
-注意:md 文件中图片的使用规范
-* 图片是一个地址:该地址必须为在官网 SIG 目录下上传图片后得到的图片地址,不支持其他图床上的地址。
-* 图片以相对路径的方式存放在本仓库下:需要在 md 文件的同级目录下创建一个名为 assets 的文件夹存放图片资源,并在 md 文件中使用语法引入图片。
-
-
-### 2.提交PR
-将以上修改提交到Gitee上,并在Gitee上创建一个Pull Request。同步程序会自动检查内容是否符合规范,如不符合规范请修改后重新提交,并且在评论区回复“/check”指令重新检查。直到同步程序回复可以同步为止。
-
-### 3.向TC发送邮件申请
-发送邮件到技术委员会tc@lists.openanolis.org提交创建申请,并进入TC委员会讨论议题。
-
-### 4.TC评审
-社区技术委员会将在社区会议上对SIG申请进行审批,对SIG申请PR进行合并或拒绝。
+## 1 申请新SIG流程
+### 1.1 使用模板填写信息
+* 第一步:将 gitee.com/anolis/community/sig/sig-template Fork到你的Gitee下
+* 第二步:将sig-template复制一份并重新命名(目录名称以后都不允许修改,否则会导致数据同步失败,请谨慎命名)
+* 第三步:修改“重新命名目录”下的文件内容(SIG目录里定义了SIG元信息,这些信息作为社区基础设施和SIG同步程序的输入,以保证社区的自动化运作,所以在填写的时候需要遵守以下规范填写SIG信息)
+
+ * sig-info.yaml 文件要求
+ name:SIG中文名称,*必填。
+ en_name:SIG英文名称,*必填。
+ home_page:SIG主页的URL,*必填且不能和现有重复,格式:https://openanolis.cn/sig/+英文后缀, 后缀只允许包含字母、数字、下划线(_)、中划线(-)、英文句号(.),必须以字母开头,且长度为2~191个字符 (如:https://openanolis.cn/sig/t-one)。
+ description:SIG中文简介,*必填。
+ en_description:SIG英文简介。
+ mailing_list:SIG的邮件列表。
+ meeting_url:SIG的固定会议纪要信息,一般是etherpad 的url。
+
+ maintainers:(对应SIG的maintainers)
+ openanolis_id:社区账户名称。
+ gitee_id:gitee帐户id。
+
+ contributors:(对应SIG的contributors)
+ openanolis_id:社区账户名称。
+ gitee_id:gitee帐户id。
+
+ repositories:(SIG相关的仓库信息)
+ 仓库的填写格式:{group_name}/{repo_name},如 anolis/community,多个仓库请填写多行。
+
+ * README.md 文件要求
+ SIG中文介绍,内容不能为空可自定义填写,会作为SIG主页同步到社区官网对应的SIG主页(请不要将SIG maintainers、contributors填写在这里,以免跟sig-info.yaml中重复)
+
+ * README.en.md 文件要求
+ SIG英文文介绍,填写规则与中文介绍相同。
+
+ * content 文件夹
+ content文件夹用来存放SIG文档,content下的文件夹与文档,会在社区映射成目录用来访问。暂时只支持三级,超出层级内容不会被同步。文档格式暂时只支持(.md)文档,文档内图片请存放在assets文件夹下,以相对路径的方式引用。不支持其他图床上的地址。
+
+
+ * assets 文件夹
+ 资源类文件请存放在该文件夹下,同步程序会默认跳过。
+
+### 1.2 提交PR
+将以上修改提交到Gitee上,并在Gitee上创建一个Pull Request。同步程序会自动检查内容是否符合规范,如不符合规范请按提示修改。修改后可在Pull Request评论区,回复“/retest”指令重新检查,直到同步程序回复可以同步为止。如回复指令后评论区未看到提示,请刷新页面后再查看。
+
+### 1.3 向TC发送邮件申请
+发送邮件到技术委员会tc@lists.openanolis.org提交创建申请,并附带Pull Request地址,并进入TC委员会讨论。
+
+### 1.4 TC评审
+技术委员会将在社区会议上对SIG申请进行审批,审批后对PR进行合并或拒绝操作。
技术委员会指派一位委员帮助SIG的建立,包括协助相关资源,指导SIG的建立和初期运转。
-### 5.TC评审通过
+### 1.5 TC评审通过
* 申请访问Buildsystem来构建rpms软件包
* 申请访问QA测试系统来测试软件包
* 申请SIG的Bugs管理权限
-
-
-## 变更SIG流程
-### 1.更新sig-info.yaml
-在sig文件夹的sig-info.yaml内更新相关信息,规则请参考“sig-info.yaml 文件要求 ”
+## 2 变更SIG流程
+### 2.1 更新sig-info.yaml
+更新sig文件夹下sig-info.yaml文件,规则请参考:“1.1 使用模板创建,第三步sig-info.yaml文件要求“,home_page字段请不要修改。
-### 2.更新README.md
-根据修改内容请同步更新README内容
+### 2.2 更新README.md
+根据修改内容请同步更新README内容,规则请参考:“1.1 使用模板创建,第三步README.md文件要求“
-### 3.提交PR
-将以上修改提交到Gitee上,并在Gitee上创建一个Pull Request。
+### 2.3 更新README.en.md
+根据修改内容请同步更新README.en内容,规则请参考:“1.1 使用模板创建,第三步README.en.md文件要求“
-注意:sig目录名称和sig-info里的home_page不允许修改,否则同步会失败!
+### 2.4 提交PR
+将以上修改提交到Gitee上,并在Gitee上创建一个Pull Request,规则请参考:“1.2 提交PR”。
-## 变更SIG文档
-### 1 修改content目录下文件
-支持新增、修改、删除现有文件,但目录层级最大只支持3级,否则同步官网后不展示
+### 2.5 注意事项
+存放sig文件夹名称请不要修改,否则会导致异常数据问题。
+sig-info.yaml里的home_page,做为sig社区访问唯一路径,也不允许修改,否则同步会失败。
-### 2.提交PR
-将以上修改提交到Gitee上,并在Gitee上创建一个Pull Request。
+## 3 变更SIG文档
+### 3.1 修改content目录下文件
+支持新增、修改、删除现有文件。目录层级最多只支持三级。规则请参考:“1.1 使用模板创建,第三步content文件夹”。
-## SIG退出机制
-
-TC委员会可依据以下原则,由技术委员提出并提交TC委员会会议决议SIG的撤销:
+### 3.2 提交PR
+将以上修改提交到Gitee上,并在Gitee上创建一个Pull Request,规则请参考:“1.2 提交PR”。
+## 4 SIG退出机制
+TC委员会可依据以下原则,由技术委员提出并提交TC委员会会议,决议SIG的撤销:
* SIG的工作内容无法满足社区发行版或者社区技术发展方向。
-
* SIG长期没有活跃度,或者无成果产出。
-## FAQ
-###
\ No newline at end of file
+## 5 FAQ
+### 1 回复指令后未看到结果
+目录文件缺失
\ No newline at end of file
diff --git a/TC_Project.yml b/TC_Project.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1a84a59225c668e96df02e274b275ea5cfcd92b2
--- /dev/null
+++ b/TC_Project.yml
@@ -0,0 +1,146 @@
+projects:
+ - project_id: TC2024120201 # 项目id
+ repos:
+ - repo_name: anolis/cloud-kernel # 仓库
+ dir_or_files: # 仓库内文件或文件夹, 为空时表示所有目录
+ -
+ - repo_name: src-anolis-sig/cloud-kernel
+ dir_or_files:
+ -
+ - project_id: TC2024080201 # 知识库文档共建,项目 Sponsor:林生(阿里云),徐国振(浪潮信息)
+ repos:
+ - repo_name: https://gitee.com/anolis/anolis-kb # 仓库
+
+ - project_id: TC2024080203 # 虚拟化组件的社区维护
+ repos:
+ - repo_name: https://gitee.com/anolis/qemu-kvm # qemu 仓库
+ - repo_name: https://gitee.com/src-anolis-os/libvirt # libvirt 仓库
+ - repo_name: anolis/cloud-kernel # kernel 仓库
+ dir_or_files:
+ - virt
+ - arch/arm64/kvm
+ - arch/x86/kvm
+ - arch/sw_64/kvm
+ - arch/loongarch/kvm
+
+ - project_id: TC2024080205 # 龙蜥社区 AI 容器镜像商业参考实现建设,项目 Sponsor:宋凯(浪潮信息),王洪虎(龙芯),徐春梅(阿里云)
+ repos:
+ - repo_name: anolis/anolis-container
+
+ - project_id: TC2024080206 # 龙蜥社区 AI 容器组件 Pyhon Whl 软件仓建设,项目 Sponsor:宋凯(浪潮信息),王洪虎(龙芯),徐春梅(阿里云)
+ repos:
+ - repo_name: src-anolis-whl
+
+ - project_id: TC2024080202 # Anolis OS 7 YUM 源维护项目,项目 Sponsor:崔湛(统信),庞训磊(阿里云)
+ repos:
+ - repo_name: https://gitee.com/anolis/anolis7.9els # 仓库
+
+ - project_id: TC2024080204 # [安全漏洞机制共建] 共建安全漏洞管理机制,项目 Sponsor:张世乐(阿里云),徐国振(浪潮信息),谈虎(中兴通讯),崔湛(统信软件),贺春妮(中科方德),段廷银(中科曙光),史建才(北京红旗),安全委员会,Distro SIG,Cloud Kernel SIG
+ repos:
+ - repo_name: https://gitee.com/src-anolis-os # group组下所有仓库
+
+ - repo_name: https://gitee.com/src-anolis-sig
+
+ - repo_name: https://gitee.com/openanolis-copy/docs
+
+ - project_id: TC2024110201 # [龙芯架构支持] 发行版龙芯处理器支持,项目 Sponsor:王洪虎(龙芯中科),高畅(阿里云),LoongArch SIG,Distro SIG,Cloud Kernel SIG
+ repos:
+ - repo_name: https://gitee.com/src-anolis-os # group组
+
+ - repo_name: https://gitee.com/src-anolis-sig
+
+ - project_id: TC2024110202 # [申威架构支持] 发行版申威处理器支持,项目 Sponsor:崔巍(电科申泰),韩笑(阿里云),申威架构 SIG,Distro SIG,Cloud Kernel SIG
+ repos:
+ - repo_name: https://gitee.com/src-anolis-os # group组
+
+ - repo_name: https://gitee.com/src-anolis-sig
+
+ - project_id: TC2024110203 # [GNR架构支持] 发行版 Intel 处理器支持,项目 Sponsor:李崇(英特尔),尚旭春(阿里云),Xuchun(SIG 管理员)Intel Arch SIG,Distro SIG,Cloud Kernel SIG
+ repos:
+ - repo_name: https://gitee.com/src-anolis-os # group组
+
+ - repo_name: https://gitee.com/src-anolis-sig
+
+ - project_id: TC2024120201 # [海光四号架构支持] 发行版海光处理器支持,项目 Sponsor:李伟(海光信息),易兴睿(阿里云),Hygon Arch SIG,Distro SIG,Cloud Kernel SIG
+ repos:
+ - repo_name: https://gitee.com/src-anolis-os # group组
+
+ - repo_name: https://gitee.com/src-anolis-sig
+
+ - project_id: TC2024120001
+ repos:
+ - repo_name: https://gitee.com/openanolis-copy/docs
+ dir_or_files:
+ - DEVELOPER_DOCS
+ - CESHI_ZHUANYONG/CI及代码门禁/日志文件
+
+ - project_id: TC2024120302
+ repos:
+ - repo_name: https://gitee.com/openanolis-copy/docs.git
+ dir_or_files:
+ - DEVELOPER_DOCS
+ - CESHI_ZHUANYONG/CI及代码门禁/日志文件
+ - CESHI_ZHUANYONG/CI及代码门禁/龙蜥目录1/装机.md
+ - INFRA_DOCS
+ - repo_name: https://gitee.com/suli01/docs.git
+ dir_or_files:
+ - DEVELOPER_DOCS
+ - CESHI_ZHUANYONG/CI及代码门禁/日志文件
+ - project_id: TC2024120303
+ repos:
+ - repo_name: https://gitee.com/openanolis-copy/docs.git
+ dir_or_files:
+ - DEVELOPER_DOCS
+ - CESHI_ZHUANYONG/CI及代码门禁/日志文件
+ - CESHI_ZHUANYONG/CI及代码门禁/龙蜥目录1
+ - INFRA_DOCS
+ - repo_name: https://gitee.com/suli01/docs.git
+ dir_or_files:
+ - DEVELOPER_DOCS
+ - CESHI_ZHUANYONG/CI及代码门禁/日志文件
+
+ - project_id: TC2025120302
+ repos:
+ - repo_name: https://gitee.com/openanolis-copy/docs.git
+ dir_or_files:
+ - DEVELOPER_DOCS
+ - CESHI_ZHUANYONG/CI及代码门禁/日志文件
+ - repo_name: https://gitee.com/anolis/anolis-docs.git
+ dir_or_files:
+ - INFRA_DOCS
+ - project_id: TC2025120502
+ repos:
+ - repo_name: https://gitee.com/openanolis-copy/docs.git
+ dir_or_files:
+ - INFRA_DOCS
+ - project_id: TC2024080403
+ repos:
+ - repo_name: openanolis-copy
+
+ - project_id: TC2024080404
+ repos:
+ - repo_name: https://gitee.com/openanolis-copy
+ - project_id: TC2024121101
+ repos:
+ - repo_name: https://gitee.com/openanolis-copy/docs.git
+
+ - project_id: TC2025040201 # [RISC-V 架构支持] 发行版 RISC-V 处理器支持,项目 Sponsor:宋卓(阿里云),王云龙(达摩院),谈虎(中兴通讯),RISC-V Arch SIG,Distro SIG,Cloud Kernel SIG
+ repos:
+ - repo_name: https://gitee.com/anolis/cloud-kernel
+ - repo_name: https://gitee.com/src-anolis-os # group组
+ - repo_name: https://gitee.com/src-anolis-sig
+ - repo_name: https://gitee.com/anolis/qemu-kvm
+ - repo_name: https://gitee.com/openanolis-copy/docs.git
+
+ - project_id: TC2024120502
+ repos:
+ - repo_name: https://gitee.com/openanolis-copy/docs.git
+ - project_id: TC2024080201
+ repos:
+ - repo_name: https://gitee.com/openanolis-copy/community.git
+ - project_id: TC2024121001
+ repos:
+ - repo_name: https://gitee.com/openanolis-copy/docs.git
+ - project_id: TC2024121821
+ repos:
+ - repo_name: https://gitee.com/openanolis-copy/docs.git
\ No newline at end of file
diff --git a/news/2-Dockerfile b/news/2-Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..cd4e488e1245cb7dadb833cb60fffb9793da4bab
--- /dev/null
+++ b/news/2-Dockerfile
@@ -0,0 +1,49 @@
+FROM openanolis/anolisos:8.6
+
+LABEL maintainer="OpenAnolis Cloud Native SIG"
+
+RUN yum -y update \
+ && yum -y install postgresql-server wget \
+ && yum clean all
+
+ENV PGDATA /var/lib/pgsql/data
+
+ENV PG_MAJOR 10
+
+ENV PG_VERSION 10.21-2.0.1
+
+ARG TARGETARCH
+
+ENV GOSU_VERSION 1.14
+
+RUN set -eux; \
+ wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$TARGETARCH"; \
+ wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$TARGETARCH.asc"; \
+ export GNUPGHOME="$(mktemp -d)"; \
+ gpg --batch --keyserver pgp.mit.edu --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \
+ gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \
+ gpgconf --kill all; \
+ rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \
+ chmod +x /usr/local/bin/gosu; \
+ gosu --version; \
+ gosu nobody true
+
+RUN mkdir /docker-entrypoint-initdb.d
+
+ENV PGDATA /var/lib/pgsql/data
+
+RUN chmod 2777 /var/run/postgresql && chmod 777 "$PGDATA"
+
+VOLUME /var/lib/pgsql/data
+
+COPY docker-entrypoint.sh /usr/local/bin/
+
+RUN ln -s usr/local/bin/docker-entrypoint.sh / # backwards compat
+
+ENTRYPOINT ["docker-entrypoint.sh"]
+
+STOPSIGNAL SIGINT
+
+EXPOSE 5432
+
+CMD ["postgres"]
\ No newline at end of file
diff --git a/news/3-Dockerfile b/news/3-Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..fae7e8ed6df3c29326954ed5286c3d4acb4ac420
--- /dev/null
+++ b/news/3-Dockerfile
@@ -0,0 +1,12 @@
+# Dockerfile
+
+#######################################################
+##docker base image selection part:
+# select AnolisOS tag
+# The available selection: 8.6-x86_64/8.6-aarch64/7.9-x86_64/7.9-aarch64
+# sample:FROM registry.hub.docker.com/openanolis/anolisos:8.6-x86_64
+FROM registry.hub.docker.com/openanolis/anolisos:8.6-x86_64
+# FROM centos
+#####################################################
+
+ENV container docker
\ No newline at end of file
diff --git a/news/Dockerfile b/news/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..4d286757519cb44482bd1085553592943a30f6ed
--- /dev/null
+++ b/news/Dockerfile
@@ -0,0 +1,31 @@
+# Dockerfile
+
+#######################################################
+##docker base image selection part:
+# select AnolisOS tag
+# The available selection: 8.6-x86_64/8.6-aarch64/7.9-x86_64/7.9-aarch64
+# sample:FROM registry.hub.docker.com/openanolis/anolisos:8.6-x86_64
+FROM registry.hub.docker.com/openanolis/anolisos:8.6-x86_64
+# FROM centos
+#####################################################
+
+ENV container docker
+COPY ./cla.md ./
+
+# 安装openssh-server和sudo软件包,并且将sshd的UsePAM参数设置成no
+RUN yum install -y openssh-server sudo
+RUN sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config
+
+# 添加测试用户admin,密码admin,并且将此用户添加到sudoers里
+RUN useradd admin
+RUN echo "admin:admin" | chpasswd
+RUN echo "admin ALL=(ALL) ALL" >> /etc/sudoers
+
+# 下面这两句比较特殊,在centos6上必须要有,否则创建出来的容器sshd不能登录
+RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
+RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
+
+# 启动sshd服务并且暴露22端口
+RUN mkdir /var/run/sshd
+EXPOSE 22
+CMD ["/usr/sbin/sshd", "-D"]
\ No newline at end of file
diff --git a/news/cla.md b/news/cla.md
new file mode 100644
index 0000000000000000000000000000000000000000..9233c1a47d531a76b514363c615dab9a92ece9bc
--- /dev/null
+++ b/news/cla.md
@@ -0,0 +1 @@
+dd
\ No newline at end of file
diff --git a/sig/AI/README.md b/sig/AI/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..5fa2d494c29d1a0add3f5245a14ba1b767be3d9d
--- /dev/null
+++ b/sig/AI/README.md
@@ -0,0 +1,46 @@
+## SIG主页
+
+https://openanolis.cn/sig/AI_SIG
+
+## SIG目标
+AI SIG致力于构建Anolis OS上AI软件栈,包括流行AI框架TensorFlow/PyTorch等,AI加速库,和相应软件方案。
+
+
+## 使用教程
+在 Anolis OS 8.x 系统上
+
+```
+yum update -y https://mirrors.openanolis.cn/anolis/8.6/BaseOS/x86_64/os/Packages/anolis-release-8.6-1.an8.x86_64.rpm https://mirrors.openanolis.cn/anolis/8.6/BaseOS/x86_64/os/Packages/anolis-gpg-keys-8.6-1.an8.noarch.rpm https://mirrors.openanolis.cn/anolis/8.6/BaseOS/x86_64/os/Packages/anolis-repos-8.6-1.an8.x86_64.rpm
+
+yum install -y https://mirrors.aliyun.com/epel/epel-release-latest-8.noarch.rpm
+
+cat > /etc/yum.repos.d/epao.repo << EOF
+[epao]
+name=epao
+baseurl=https://mirrors.openanolis.cn/epao/8/x86_64/
+enabled=1
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-ANOLIS
+gpgcheck=1
+EOF
+
+yum install -y tensorflow
+yum install -y pytorch
+yum install -y intel-extension-for-pytorch
+
+```
+
+
+## 成员列表
+| 成员 | 角色 |
+| ------------ | ------------ |
+| forrest_ly | maintainer |
+| wenhuanhuang | maintainer |
+
+
+## SIG仓库
+
+Source code repositories:
+- https://gitee.com/src-anolis-ai/pytorch
+- https://gitee.com/src-anolis-ai/intel-extension-for-pytorch
+- https://gitee.com/src-anolis-sig/tensorflow
+- https://gitee.com/src-anolis-sig/neural-compressor
diff --git a/sig/AI/assets/bugzilla/addsubcomponent.png b/sig/AI/assets/bugzilla/addsubcomponent.png
new file mode 100644
index 0000000000000000000000000000000000000000..da3af54f3450ea84affa34b16a33bc976ba963b7
Binary files /dev/null and b/sig/AI/assets/bugzilla/addsubcomponent.png differ
diff --git a/sig/AI/assets/bugzilla/api-key.png b/sig/AI/assets/bugzilla/api-key.png
new file mode 100644
index 0000000000000000000000000000000000000000..8da3b0b4bcd782b45eae82070449d6d781c149d0
Binary files /dev/null and b/sig/AI/assets/bugzilla/api-key.png differ
diff --git a/sig/AI/assets/bugzilla/api.png b/sig/AI/assets/bugzilla/api.png
new file mode 100644
index 0000000000000000000000000000000000000000..c5bcfd5a1c16170f395955f1b2041076da5d6f5f
Binary files /dev/null and b/sig/AI/assets/bugzilla/api.png differ
diff --git a/sig/AI/assets/bugzilla/bug-list-2.png b/sig/AI/assets/bugzilla/bug-list-2.png
new file mode 100644
index 0000000000000000000000000000000000000000..39e04916cf945d9f603632a229e19ad6b1865e63
Binary files /dev/null and b/sig/AI/assets/bugzilla/bug-list-2.png differ
diff --git a/sig/AI/assets/bugzilla/bug-list.png b/sig/AI/assets/bugzilla/bug-list.png
new file mode 100644
index 0000000000000000000000000000000000000000..a0775ffe79b52631e654895556103115f22e85d7
Binary files /dev/null and b/sig/AI/assets/bugzilla/bug-list.png differ
diff --git a/sig/AI/assets/bugzilla/bugstatus.png b/sig/AI/assets/bugzilla/bugstatus.png
new file mode 100644
index 0000000000000000000000000000000000000000..7b4e7ccaf993aca09bf37ac862b08e839fd191be
Binary files /dev/null and b/sig/AI/assets/bugzilla/bugstatus.png differ
diff --git a/sig/AI/assets/bugzilla/bugzilla-anolis.png b/sig/AI/assets/bugzilla/bugzilla-anolis.png
new file mode 100644
index 0000000000000000000000000000000000000000..cf914707ac0d4ade10b928502fb47b07d02f5253
Binary files /dev/null and b/sig/AI/assets/bugzilla/bugzilla-anolis.png differ
diff --git a/sig/AI/assets/bugzilla/bugzillarc.png b/sig/AI/assets/bugzilla/bugzillarc.png
new file mode 100644
index 0000000000000000000000000000000000000000..2b3e4d5673cdcd02b61dd1817a5e49986010060f
Binary files /dev/null and b/sig/AI/assets/bugzilla/bugzillarc.png differ
diff --git a/sig/AI/assets/bugzilla/classification.png b/sig/AI/assets/bugzilla/classification.png
new file mode 100644
index 0000000000000000000000000000000000000000..07c235f1d7f122599ad0641ee9bc21671c94f3f5
Binary files /dev/null and b/sig/AI/assets/bugzilla/classification.png differ
diff --git a/sig/AI/assets/bugzilla/deletesubcomponent.png b/sig/AI/assets/bugzilla/deletesubcomponent.png
new file mode 100644
index 0000000000000000000000000000000000000000..097430a9249544cca595902aa856c01da7133500
Binary files /dev/null and b/sig/AI/assets/bugzilla/deletesubcomponent.png differ
diff --git a/sig/AI/assets/bugzilla/edit-param.png b/sig/AI/assets/bugzilla/edit-param.png
new file mode 100644
index 0000000000000000000000000000000000000000..b3e140c9fefe0c30cffcf7dd00141ed8f998f516
Binary files /dev/null and b/sig/AI/assets/bugzilla/edit-param.png differ
diff --git a/sig/AI/assets/bugzilla/mainpage11.png b/sig/AI/assets/bugzilla/mainpage11.png
new file mode 100644
index 0000000000000000000000000000000000000000..e3c95a9747fff20215a61d4dba6fa60c75a7cf44
Binary files /dev/null and b/sig/AI/assets/bugzilla/mainpage11.png differ
diff --git a/sig/AI/assets/bugzilla/new.png b/sig/AI/assets/bugzilla/new.png
new file mode 100644
index 0000000000000000000000000000000000000000..7b65c11767943b0409538d4bcfd466c8a21de0ef
Binary files /dev/null and b/sig/AI/assets/bugzilla/new.png differ
diff --git a/sig/AI/assets/bugzilla/param-info.png b/sig/AI/assets/bugzilla/param-info.png
new file mode 100644
index 0000000000000000000000000000000000000000..9cddc2d5694f2e841ba6dec5f278e56d42989df8
Binary files /dev/null and b/sig/AI/assets/bugzilla/param-info.png differ
diff --git a/sig/AI/assets/bugzilla/plugin.png b/sig/AI/assets/bugzilla/plugin.png
new file mode 100644
index 0000000000000000000000000000000000000000..9a07422cdf8e1d6bd8d2e57f8eb8ff965c1acd4e
Binary files /dev/null and b/sig/AI/assets/bugzilla/plugin.png differ
diff --git a/sig/AI/assets/bugzilla/product.png b/sig/AI/assets/bugzilla/product.png
new file mode 100644
index 0000000000000000000000000000000000000000..fcb90e9376149b00e715fd465431a7f42778c9a1
Binary files /dev/null and b/sig/AI/assets/bugzilla/product.png differ
diff --git a/sig/AI/assets/bugzilla/sub component.png b/sig/AI/assets/bugzilla/sub component.png
new file mode 100644
index 0000000000000000000000000000000000000000..2a2806d3a09952ab3e73fd9ad2af0960bbf45c39
Binary files /dev/null and b/sig/AI/assets/bugzilla/sub component.png differ
diff --git "a/sig/AI/assets/\345\244\264\345\203\217/images.jpg" "b/sig/AI/assets/\345\244\264\345\203\217/images.jpg"
new file mode 100644
index 0000000000000000000000000000000000000000..b4971aaed7498d718798197e7c2f2169b1df5b92
Binary files /dev/null and "b/sig/AI/assets/\345\244\264\345\203\217/images.jpg" differ
diff --git "a/sig/AI/assets/\345\244\264\345\203\217/images1.png" "b/sig/AI/assets/\345\244\264\345\203\217/images1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..daa81fb4109b4dd92e69d515044a23b3ddac7f09
Binary files /dev/null and "b/sig/AI/assets/\345\244\264\345\203\217/images1.png" differ
diff --git "a/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_0.png" "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..507c5552e047b1736fd0f9397a20887b48be99c2
Binary files /dev/null and "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_0.png" differ
diff --git "a/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_1.png" "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f32a0710752c6a24215173b87c50ede8fcdf109e
Binary files /dev/null and "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_1.png" differ
diff --git "a/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_2.png" "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9c254f32e4f0a102a34e1d06514fd1687d06b40d
Binary files /dev/null and "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_2.png" differ
diff --git "a/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_3.png" "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..3d4f4bc5faba39a5348d69eea8aa0837fb7912a4
Binary files /dev/null and "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_3.png" differ
diff --git "a/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_4.png" "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9df092e6163a19c483dba4489eac80133465bae1
Binary files /dev/null and "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_4.png" differ
diff --git "a/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_0.png" "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..bc14d4826022d43df35532aa87777614833dda1e
Binary files /dev/null and "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_0.png" differ
diff --git "a/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_1.png" "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..ebbe779d6f5a95407dd5c8af2346711f288fc181
Binary files /dev/null and "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_1.png" differ
diff --git "a/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_10.png" "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_10.png"
new file mode 100644
index 0000000000000000000000000000000000000000..98fb21bb72a93b3e5870a8dbcbc069d818dda134
Binary files /dev/null and "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_10.png" differ
diff --git "a/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_11.png" "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_11.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b1cfe176f26af9e796127777138f1e0f94517687
Binary files /dev/null and "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_11.png" differ
diff --git "a/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_12.png" "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_12.png"
new file mode 100644
index 0000000000000000000000000000000000000000..3dabd3ed4a8a1498a14b49afa2bc268b720d61ab
Binary files /dev/null and "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_12.png" differ
diff --git "a/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_13.png" "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_13.png"
new file mode 100644
index 0000000000000000000000000000000000000000..2cea85e41767e9d3801c8404f359b5b0c535c8a6
Binary files /dev/null and "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_13.png" differ
diff --git "a/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_14.png" "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_14.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9dd713591c6162ea15de1b29976fcde489231d91
Binary files /dev/null and "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_14.png" differ
diff --git "a/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_2.png" "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d0eef93ec6f877248caa01ac0c06595a9fe56fea
Binary files /dev/null and "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_2.png" differ
diff --git "a/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_3.png" "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..2bc13bf9842fe6f61b8e9bb3f2c528d145b2187d
Binary files /dev/null and "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_3.png" differ
diff --git "a/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_4.png" "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..3d4f4bc5faba39a5348d69eea8aa0837fb7912a4
Binary files /dev/null and "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_4.png" differ
diff --git "a/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_5.png" "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d936ddf9426f2062c5b78608ce22b8f9484a17ef
Binary files /dev/null and "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_5.png" differ
diff --git "a/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_6.png" "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_6.png"
new file mode 100644
index 0000000000000000000000000000000000000000..580695a971df01c9b6226c96ca9bcebc7e5fa133
Binary files /dev/null and "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_6.png" differ
diff --git "a/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_7.png" "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_7.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9df092e6163a19c483dba4489eac80133465bae1
Binary files /dev/null and "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_7.png" differ
diff --git "a/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_8.png" "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_8.png"
new file mode 100644
index 0000000000000000000000000000000000000000..074c12d51cfd861b15939f35b135c447338fd5f7
Binary files /dev/null and "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_8.png" differ
diff --git "a/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_9.png" "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_9.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b206604394f29a4c6efc41a01d0cbd18247b6288
Binary files /dev/null and "b/sig/AI/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_9.png" differ
diff --git "a/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image1.png" "b/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..dc56c3468c08cf06097ee9ebb3e57c885fe23f33
Binary files /dev/null and "b/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image1.png" differ
diff --git "a/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image10png.png" "b/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image10png.png"
new file mode 100644
index 0000000000000000000000000000000000000000..08b6c16a279f36f04ba7ccff4eced26f938c04b2
Binary files /dev/null and "b/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image10png.png" differ
diff --git "a/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image12.png" "b/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image12.png"
new file mode 100644
index 0000000000000000000000000000000000000000..3a324f10168bc8a84c22299a6552250eb260b032
Binary files /dev/null and "b/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image12.png" differ
diff --git "a/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image2.png" "b/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d886f8f234d26417e81da25c9132e34c5ee625ab
Binary files /dev/null and "b/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image2.png" differ
diff --git "a/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image3.png" "b/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..c0bd643694b72df1a53fd5a11355599a7d557bad
Binary files /dev/null and "b/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image3.png" differ
diff --git "a/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image4.png" "b/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..1cbe200762088afd8a4485f81a621f3750fd8562
Binary files /dev/null and "b/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image4.png" differ
diff --git "a/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image5.png" "b/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..00ee41ea3d0c377d76e77d3f125a2a02a3716e49
Binary files /dev/null and "b/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image5.png" differ
diff --git "a/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image6.png" "b/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image6.png"
new file mode 100644
index 0000000000000000000000000000000000000000..59a3622c74b7cb494e7c26fa23cfe75bdd692679
Binary files /dev/null and "b/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image6.png" differ
diff --git "a/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image7.png" "b/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image7.png"
new file mode 100644
index 0000000000000000000000000000000000000000..7edb460401aee2fbd3696d9f63ae016916691891
Binary files /dev/null and "b/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image7.png" differ
diff --git "a/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image8.png" "b/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image8.png"
new file mode 100644
index 0000000000000000000000000000000000000000..3f8938cf760d474b1af75a5ba60956c7d6121e15
Binary files /dev/null and "b/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image8.png" differ
diff --git "a/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image9.png" "b/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image9.png"
new file mode 100644
index 0000000000000000000000000000000000000000..831c06dfce30ad23052699e99653c488e4220c67
Binary files /dev/null and "b/sig/AI/assets/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/image9.png" differ
diff --git "a/sig/AI/content/Bugzilla\347\263\273\347\273\237/Bugzilla\347\224\250\346\210\267\346\226\207\346\241\243.md" "b/sig/AI/content/Bugzilla\347\263\273\347\273\237/Bugzilla\347\224\250\346\210\267\346\226\207\346\241\243.md"
new file mode 100644
index 0000000000000000000000000000000000000000..0533529798d6e61d7980fc234ec3095ca7094bcc
--- /dev/null
+++ "b/sig/AI/content/Bugzilla\347\263\273\347\273\237/Bugzilla\347\224\250\346\210\267\346\226\207\346\241\243.md"
@@ -0,0 +1,242 @@
+## 一. Bugzilla初识
+Bugzilla是一个缺陷管理系统,可以用来管理Bug,也可以用来管理需求。Bugzilla可以通过浏览器页面创建Bug,也可以通过api接口创建Bug。
+
+- **1.1 首页**
+
+
+## 二. Bug生命周期
+
+- **2.1 新建Bug**
+ - **2.1.1 路径**
+
+ 首页->New/File a Bug->Select a classification->Select a product->Bug创建页面。具体如下:首先,在首页点击New或File a Bug按钮,进行创建Bug。
+ 
+ 然后会提示让选择一个classification, classification是Bug的一级分类。
+ 
+ 选择完classification分类后会提示选择一个product,product是Bug的二级分类。
+ 
+
+ - **2.1.2 创建页面**
+
+ 选择完product产品后会进入Bug创建页面,创建页面有一些参数需要填充,具体参数含义如下图所示:
+ 
+
+- **2.2 编辑Bug**
+ - **2.2.1 路径**
+ - 首页->Search Bug/My Bugs->Bugs List->Click the Bug->Bug编辑页面。具体如下:
+
+ 首先在首页点击My Bugs或Open Bugs assign to me or reported by me 进入Bug List 列表页。
+ 
+ 然后在Bug List列表页点击Bug ID或Summary进入Bug编辑页面。
+ 
+
+ - **2.2.2 编辑页面**
+
+ Bug编辑页面也进行Bug一些字段的修改,编辑页面的字段同Bug创建。
+ 
+
+- **2.3 关闭Bug**
+ - **2.3.1 路径**
+ - Bug编辑页面->Status->Resolved、Fixed->Save Changes
+
+ 在Bug页面编辑Status状态,当状态被修改为[RESOLVED,FIXED]时表示Bug关闭,至此Bug的生命周期结束。
+ 
+
+## 三. Bugzilla Restful Api
+
+Bugzilla 提供了对外开放的restful api接口,通过接口可以方便的对Bug进行一些操作。官方接口描述如下:[https://bugzilla.readthedocs.io/en/5.0/api/index.html#apis](https://bugzilla.readthedocs.io/en/5.0/api/index.html#apis)。
+
+- **3.1 官方Api**
+
+ 官方api包括对Bug、评论、组件、产品等的操作,具体如下:
+ 
+
+- **3.2 额外的Api**
+
+除了官方Api之外,还单独定制了一部分Api,包括User、Bug、子组件等。
+
+ - **3.2.1 Sub Component Api**
+
+ - **Get Sub Components**
+
+ 查询现有的子组件详情
+
+ - **Request**:
+ ```json
+ https://bugzilla.openanolis.cn/rest/subcomponent?ids=(bug_id)
+ ```
+ - **Params Description**:
+
+ | **name** | **type** | **description** |
+ | --- | --- | --- |
+ | bug_id | int | Bug ID |
+
+ - **Response**:
+ ```json
+ {
+ "subcomponents": [
+ {
+ "default_cc": [
+ "xxx@163.com"
+ ],
+ "is_active": true,
+ "default_docs_contact": "",
+ "id": 10,
+ "component_name": "user",
+ "level": 0,
+ "description": "rest api create subcomponent",
+ "default_qa_contact": "xxx@163.com",
+ "default_to_private": false,
+ "product_id": 2,
+ "sort_key": 0,
+ "parent_id": null,
+ "product_name": "testfarm",
+ "name_tree": [
+ "sub_user3_9"
+ ],
+ "default_assignee": "xxx@163.com",
+ "name": "sub_user3_9",
+ "agile_team": "",
+ "component_id": 2
+ }
+ ]
+ }
+ ```
+
+ - **Post Sub Component**
+
+ 添加子组件
+
+ - **Request**:
+ ```json
+ https://bugzilla.openanolis.cn/rest/subcomponent
+ ```
+
+ - **Body Description**:
+
+ | **name** | **type** | **description** |
+ | --- | --- | --- |
+ | api_key | string | api auth key |
+ | product | string | 产品名 |
+ | component | string | 组件名 |
+ | subcomponent | string | 子组件名 |
+ | description | string | 描述 |
+ | default_assignee | string | 默认指派人邮箱 |
+ | default_docs_contact | string | 默认Docs邮箱 |
+ | default_qa_contact | string | 默认QA邮箱 |
+ | default_cc | list | 抄送邮箱列表 |
+
+ - **Response**:
+ ```json
+ {
+ id: 23
+ }
+ ```
+
+ - **Delete Sub Component**
+
+ 删除子组件
+
+ - **Request**:
+ ```json
+ https://bugzilla.openanolis.cn/rest/subcomponent?api_key=(api_key)&ids=(sub_component_id)&component=(component)&product=(product)
+ ```
+
+ - **Params Description**:
+
+ | **name** | **type** | **description** |
+ | --- | --- | --- |
+ | api_key | string | api auth key |
+ | product | string | 产品名 |
+ | component | string | 组件名 |
+ | sub_component_id | int | 子组件id |
+
+ - **Response**:
+ ```json
+ {
+ Deleted: [23]
+ }
+ ```
+
+ - **3.2.2 Component Api**
+ - **Get Components**
+
+ 查询现有的所有组件
+
+ - **Request**:
+ ```json
+ https://bugzilla.openanolis.cn/rest/component
+ ```
+
+ - **Params Description**:
+
+ | **name** | **type** | **description** |
+ | --- | --- | --- |
+ | | | |
+
+ - **Response**:
+
+ ```json
+ {
+ "components" : [
+ {
+ "id" : 3, // component id
+ "name" : "com_123" // component name
+ },
+ {
+ "id" : 4,
+ "name" : "product-length"
+ },
+ {
+ "id" : 1,
+ "name" : "TestComponent"
+ },
+ {
+ "id" : 2,
+ "name" : "user"
+ },
+ {
+ "id" : 5,
+ "name" : "user2"
+ }
+ ]
+ }
+ ```
+
+## 三. Bugzilla python 命令行插件
+
+python-bugzilla-cli 命令行插件支持通过python命令行去操作Bugzilla,比如创建、编辑Bug, 子组件等。
+
+- 3.1 插件安装:
+ - 在命令行执行命令:pip install python-bugzilla-anolis 安装命令行插件,插件地址:[https://pypi.org/project/python-bugzilla-anolis/](https://pypi.org/project/python-bugzilla-anolis/)
+
+ 
+
+- 3.2 插件配置:
+ - 生成api_key: [https://bugzilla.openanolis.cn/userprefs.cgi?tab=apikey](https://bugzilla.openanolis.cn/userprefs.cgi?tab=apikey),生成的api_key需要有bug edit权限,api_key权限 和当前帐号权限一致。
+
+ 
+
+ - 配置bugzillarc文件,配置url和api_key,python-bugzilla-cli插件可自动读取配置的参数,在使用命令时无需额外携带参数,bugzillarc文件内容如下:
+
+ 
+
+- 3.3 插件使用:
+ - 配置好bugzillarc文件之后,就可以使用bugzilla-anolis命令操作Bugzilla了,使用bugzilla-anolis命令查看当前支持的所有参数:
+
+ 
+
+ - 执行sub component相关命令:
+ - 查询:
+ ```json
+ bugzilla-anolis getsubcomponent --ids=10 --ids=11
+ ```
+ 
+
+ - 添加:bugzilla-anolis addsubcomponent --product=testfarm --component=user --subcomponent=sub_user77_5 --description="rest api create subcomponent" --default_assignee=shankailun@163.com --default_docs_contact=shankailun@163.com --default_qa_contact=shankailun@163.com --default_cc="shankailun@163.com,1174224378@qq.com"
+
+ 
+
+ - 删除:bugzilla-anolis deletesubcomponent --ids=39 --product=testfarm --component=user
+
+ 
diff --git "a/sig/AI/content/Bugzilla\347\263\273\347\273\237/\351\276\231\350\234\245\344\270\273\347\253\231\351\246\226\351\241\265.link" "b/sig/AI/content/Bugzilla\347\263\273\347\273\237/\351\276\231\350\234\245\344\270\273\347\253\231\351\246\226\351\241\265.link"
new file mode 100644
index 0000000000000000000000000000000000000000..33dce3fdda5eb9dd740517631d959d2312dcf7d3
--- /dev/null
+++ "b/sig/AI/content/Bugzilla\347\263\273\347\273\237/\351\276\231\350\234\245\344\270\273\347\253\231\351\246\226\351\241\265.link"
@@ -0,0 +1 @@
+https://openanolis.cn/
\ No newline at end of file
diff --git "a/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/1_\346\246\202\350\277\260.md" "b/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/1_\346\246\202\350\277\260.md"
new file mode 100644
index 0000000000000000000000000000000000000000..9df334d5c61cdfabb44896232f0f21fc603b5133
--- /dev/null
+++ "b/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/1_\346\246\202\350\277\260.md"
@@ -0,0 +1,7 @@
+共享内存通信(Shared Memory Communication,SMC)是一种兼容 socket 层,利用共享内存操作实现高性能通信的内核网络协议栈。当共享内存通信基于远程内存直接访问(Remote Direct Memory Access,RDMA)技术实现时,称为 SMC over RDMA(SMC-R)。
+
+SMC-R 兼容 socket 接口的特点使 TCP 应用程序无需任何改造即可运行在 SMC 协议栈上;底层使用的 RDMA 网络使 SMC 拥有相较于 TCP 更好的网络性能。SMC 协议栈通过 TCP 连接自主发现对侧 SMC 能力,协商成功后使用 SMC 协议栈承载应用数据流量;协商失败则安全回退至 TCP/IP 协议栈,保证数据正常传输。
+
+阿里云 Alibaba Cloud Linux 3 操作系统基于阿里云弹性 RDMA(elastic RDMA, eRDMA)技术首次将 SMC-R 带入云上场景,实现云上 TCP 协议栈的透明无损替换,为数据库、RPC、批量数据传输等场景提供相比 TCP 更好的网络性能。相较于上游 Linux SMC-R 实现,Alibaba Cloud Linux 3 中的 SMC-R 更适配阿里云 eRDMA 技术、拥有更好的性能、可靠的稳定性、丰富成熟的透明替换方案和及时的更新维护。
+
+
diff --git "a/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/2_\345\216\237\347\220\206\350\247\243\350\257\273-\346\212\200\346\234\257\346\217\255\347\247\230\357\274\232\351\230\277\351\207\214\344\272\221\345\217\221\345\270\203\347\254\254\345\233\233\344\273\243\347\245\236\351\276\231.md" "b/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/2_\345\216\237\347\220\206\350\247\243\350\257\273-\346\212\200\346\234\257\346\217\255\347\247\230\357\274\232\351\230\277\351\207\214\344\272\221\345\217\221\345\270\203\347\254\254\345\233\233\344\273\243\347\245\236\351\276\231.md"
new file mode 100644
index 0000000000000000000000000000000000000000..66d5f2092627324adaa2debcfd8e3fe3ca0518a1
--- /dev/null
+++ "b/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/2_\345\216\237\347\220\206\350\247\243\350\257\273-\346\212\200\346\234\257\346\217\255\347\247\230\357\274\232\351\230\277\351\207\214\344\272\221\345\217\221\345\270\203\347\254\254\345\233\233\344\273\243\347\245\236\351\276\231.md"
@@ -0,0 +1,55 @@
+> 原文链接:[技术揭秘:阿里云发布第四代神龙 ,SMC-R 让网络性能提升 20%](https://mp.weixin.qq.com/s?__biz=MzUxNjE3MTcwMg==&mid=2247486197&idx=1&sn=e1b86ef6627dd13847b88e2ca367f890&chksm=f9aa382cceddb13a24c553451351aee1e0c026b0044403e0f6442e010df5e7303b07c4ce9912&scene=21#wechat_redirect)
+
+> 注:一年一度的云栖大会近日在杭州如约举行。今年的云栖大会上阿里云发布了第四代神龙架构,其中弹性 RDMA 加速能力尤其值得关注。基于弹性 RDMA,阿里云操作系统 Alibaba Cloud Linux 3 和龙蜥社区操作系统 Anolis OS 在网络方面基于社区 SMC-R 优化形成兼容 socket 的 RDMA 产品方案,旨在帮助云上应用无修改的享受 RDMA 带来的性能提升。本文将为您阐述 SMC-R 的产生背景、原理架构以及部分性能数据。
+
+近些年,随着云计算的飞速发展,特别是阿里云神龙、AWS Nitro 等硬件虚拟化方案的出现,云上的虚拟化网络性能有了质的飞跃。相比于云网络的欣欣向荣,CPU 的性能提升却似“挤牙膏”一般有些力不从心。因此,将部分原本由 CPU 承担的工作卸载到后端硬件的解决思路成为了云计算领域研究的一个“热点”。远程内存直接访问 (Remote Direct Memory Access, RDMA) 这项追求极致性能,曾经主要应用在高性能计算、高频交易等特定场景中的技术也因此进入了云厂商的数据中心。
+
+# 从 TCP 到 RDMA
+
+RDMA 作为一种旁路内核的远程内存直接访问技术,被广泛应用于数据密集型和计算密集型场景中,是高性能计算、机器学习、数据中心、海量存储等领域的重要解决方案。RDMA 在阿里巴巴已大规模稳定运行多年,支撑了阿里云 ESSD、PolarDB 等核心业务,并在双十一等重大场景得到充分验证。
+RDMA 具有零拷贝、协议栈卸载的特点。RDMA 将协议栈的实现下沉至 RDMA 网卡 (RNIC),绕过内核直接访问远程内存中的数据。由于不经过系统内核协议栈,RDMA 与传统 TCP/IP 实现相比不仅节省了协议处理和数据拷贝所需的 CPU 资源,同时也提高了网络吞吐量、降低了网络通信时延。
+
+
+
+在过去,RDMA 只能在一些数据中心网络中通过网卡和交换机紧密配合使用,部署复杂度高。但如今,阿里云弹性 RDMA 将复杂的 RDMA 技术带到云上,使普通的 ECS 用户也能使用高性能的 RDMA 传输,无需关心底层复杂的网卡、交换机等物理网络环境配置,使其成为一种亲民、普惠的技术。
+
+# 从 verbs 到 socket
+
+不过,虽然 RDMA 性能优异,但是由于 RDMA 使用的 IB verbs 接口和常用的 POSIX socket 接口存在巨大的差异,普通应用要使用 RDMA 将面临着大量的业务改造,高效的将 RDMA 应用于现有业务存在较高的技术门槛。
+所以,历史上存在一些将 RDMA 的 IB verbs 语义封装成 socket 接口的尝试,典型如 rsocket、libvma。其中,libvma 通过 LD_PRELOAD 拦截 socket 接口,转而使用用户态 verbs 完成数据传输。但这些方案存在一些缺陷:由于转换发生在用户态,一方面缺少内核统一资源管理,另一方面在兼容性上也存在一些问题。
+从资源管理和兼容的角度上看,在内核中实现 socket 接口相比于用户态来说有着天然的优势。在 Alibaba Cloud Linux 3 和 Anolis OS 中,我们提供并优化了基于 RDMA 的共享内存通信 (**Shared Memory Communications over RDMA, SMC-R**) 技术,这是一次基于内核 RDMA 实现 TCP 应用兼容的尝试。
+原生的 SMC-R 支持标准 RoCE 网络,我们对其进行了扩展,首次实现对 iWARP 的支持,可以完美的支持阿里云自研的弹性 RDMA,从而实现云上应用**零修改**的享受 RDMA 带来的性能红利。
+
+# 兼备 socket 和 RDMA 的内核实现:SMC-R
+
+用一句话来描述,SMC-R 是一套与 TCP/IP 平行的**向上兼容 TCP socket 接口,底层使用 RDMA RC 进行数据传输的协议族。**
+SMC-R 工作于内核空间,处于 socket 层和内核 RDMA 的 IB verbs 层之间。SMC-R 像是一个能力卓越的翻译兼管家,它接收用户传达的 socket 指令,转而使用 RDMA 的 IB verbs 接口管理 RDMA 资源,完成底层基于 RDMA 的数据传输。所以,用户只需将原有 socket 接口使用的协议族从 AF_INET(6) 修改为 AF_SMC 即可完成从 TCP 协议栈到 SMC-R 协议栈的转变。
+但这还不够,我们希望在零修改的前提下完成协议替换。为此,Alibaba Cloud Linux 3 和 Anolis OS 在 socket 层增加协议族替换相关的 sysctl 和白名单,提供了 net namespace 和单个应用维度下的 TCP 至 SMC-R 协议栈透明替换能力,使应用**不需要任何修改**即可让数据在 RDMA 链路这条高速公路上飞驰起来。
+
+
+
+然而,仅本地一厢情愿的使用 SMC-R 可不行,远端节点同样得具备 SMC-R 能力才能让高速公路有始有终。因此,SMC-R 具备**自动协商和安全回退 TCP** 的能力。
+SMC-R 建立 RDMA 链路时,首先会与通信对端建立 TCP 连接,双方在握手过程中通过特殊的 TCP 选项表明自身支持 SMC-R。协商成功后,SMC-R 将为用户态应用申请必要的 RDMA 资源,将接收数据缓冲区注册为可被远程节点直接访问的远程内存缓冲区 (Remote Memory Buffer, RMB),并将对应的访问密钥以及缓冲区起始地址封装成远程访问令牌 (RToken) 告知远程节点,作为其访问 RMB 的重要验证信息。
+特殊情况下,若在协商过程中发现收发两端其一不具备 RDMA 传输条件时,将触发安全回退机制。SMC-R 会使用协商过程中建立的 TCP 连接完成后续的数据传输,保证网络的可靠稳定。
+
+
+
+数据传输的高速公路建立起来后,交通规则也要安排妥当。顾名思义,SMC-R 是一种通过 RDMA 实现共享内存的通信方式,**其将环形 RMB 作为共享内存**,配合数据游标实现高效的数据传输。
+SMC-R 使用 RDMA WRITE 单边操作的方式将网络应用传递至内核的数据直接、高效地写入远程节点环形 RMB 中。同时使用 RDMA SEND/RECV 双边操作的方式交互连接数据管理 (Connection Data Control, CDC) 消息,用于更新、同步 RMB 中的数据游标 (Cursor)。针对一侧 RMB,读者更新消费者游标 (Consumer Cursor),标识即将读取的下一字节地址。为避免数据丢失,写者不会将数据写入超过消费者游标的 RMB 空间中。相似的,写者更新生产者游标 (Producer Cursor),标识即将写入的下一字节地址。为确保数据的正确性,读者不会读取超过生产者游标的 RMB 空间中的内容。就这样,两个数据游标在环形 RMB 上你追我赶,贯穿网络数据传输的始终,确保传输的安全与可靠。
+
+
+
+最后,数据在高速公路上飞驰难免会遇到差错,为了保证一切都在掌控之中,Alibaba Cloud Linux 3 和 Anolis OS 为 SMC-R 提供了一系列监控诊断接口和工具,包括控制透明替换的 sysctl、查询 SMC-R socket 状态的 proc 文件、获取 SMC-R 各维度信息的 smc-tools 工具集等,以保障网络的可监控性和易运维性。
+通过上述架构概述和理论分析,SMC-R 展现了其兼容 socket 接口,透明替换 TCP,使用 RDMA 完成底层数据传输的能力。基于这些,我们终于可以总结出 SMC-R 的核心优势:
+
+### 高性能
+
+- 更轻薄的协议栈;
+- 使用 RDMA 进行通信,网络时延更低、CPU 占用更少、吞吐量更高;
+- 高效可靠的远程环形缓冲区直接访问。
+
+### 透明替换
+- 兼容 socket 接口的 RDMA 可靠流式传输;
+- 自动协议协商和安全回退 TCP 能力;
+- net namespace 和应用维度的协议栈无损透明替换;
+- 底层兼容弹性 RDMA iWARP 和标准 RoCE 网络。
diff --git "a/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/2_\345\216\237\347\220\206\350\247\243\350\257\273-\347\263\273\345\210\227\350\247\243\350\257\273_SMC-R_\344\270\200.md" "b/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/2_\345\216\237\347\220\206\350\247\243\350\257\273-\347\263\273\345\210\227\350\247\243\350\257\273_SMC-R_\344\270\200.md"
new file mode 100644
index 0000000000000000000000000000000000000000..50ea7d54074efff6191dc9cc688e1a81f180ee74
--- /dev/null
+++ "b/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/2_\345\216\237\347\220\206\350\247\243\350\257\273-\347\263\273\345\210\227\350\247\243\350\257\273_SMC-R_\344\270\200.md"
@@ -0,0 +1,252 @@
+> 原文链接:[系列解读SMC-R:透明无感提升云上 TCP 应用网络性能(一)| 龙蜥技术](https://mp.weixin.qq.com/s?search_click_id=2359972879487335624-1672728145437-6094177369&__biz=Mzg4MTMyMTUwMQ==&mid=2247493698&idx=1&sn=1f03ea3a9025ae0a461a7346cd75b3bd&chksm=cf651b30f812922698c49f95cedf18f4f83ed16d399800cda80e5d1188d64e8bd15b408f13ba&scene=0&subscene=10000&clicktime=1672728145&enterid=1672728145&sessionid=0&ascene=65&fasttmpl_type=0&fasttmpl_fullversion=6485008-zh_CN-zip&fasttmpl_flag=0&realreporttime=1672728145471#rd)
+
+# 引言
+
+Shared Memory Communication over RDMA (SMC-R) 是一种基于 RDMA 技术、兼容 socket 接口的内核网络协议,由 IBM 提出并在 2017 年贡献至 Linux 内核。SMC-R 能够帮助 TCP 网络应用程序透明使用 RDMA,获得高带宽、低时延的网络通信服务。
+
+由于 RDMA 技术在数据中心领域的广泛使用,龙蜥社区高性能网络 SIG 认为 SMC-R 将成为下一代数据中心内核协议栈的重要方向之一。为此,我们对其进行了大量的优化,并积极将这些优化回馈到上游 Linux 社区。目前,**龙蜥社区高性能网络 SIG 是除 IBM 以外最大的 SMC-R 代码贡献团体**。由于 SMC-R 相关中文资料极少,我们希望通过一系列文章,让更多的国内读者了解并接触 SMC-R,也欢迎有兴趣的读者加入龙蜥社区高性能网络 SIG 一起沟通交流。
+
+本篇作为系列文章的第一篇,将从宏观的角度带领读者初探 SMC-R。
+
+# 从 RDMA 谈起
+
+Shared Memory Communication over RDMA 的名称包含了 SMC-R 网络协议的一大特点——基于 RDMA。因此,在介绍 SMC-R 前我们先来看看这个高性能网络领域中的绝对主力:Remote Direct Memory Access (RDMA) 技术。
+
+### 1.1 为什么需要 RDMA ?
+
+随着数据中心、分布式系统、高性能计算领域的快速发展,网络设备性能进步显著,主流物理网络带宽已达到了 25-100 Gb/s,网络时延也进入了十微秒的时代。
+然而,**网络设备性能提升的同时一个问题也逐渐显露:网络性能与 CPU 算力逐渐失配**。传统网络中,负责网络报文封装、解析和用户态/内核态间数据搬运的 CPU 在高速增长的网络带宽面前逐渐显得力不从心,面临越来越大的压力。
+以 TCP/IP 网络的一次数据发送与接收过程为例。发送节点 CPU 首先将数据从用户态内存拷贝至内核态内存,在内核态协议栈中完成数据包封装;再由 DMA 控制器将封装好的数据包搬运到 NIC 上发送到对端。接收端 NIC 获得数据包后通过 DMA 控制器搬运到内核态内存中,由内核协议栈解析,层层剥离帧首或包头后再由 CPU 将有效负载 (payload) 拷贝到用户态内存中,完成一次数据传输。
+
+
+
+在这一过程中,CPU 需要负责:
+- 用户态与内核态间的数据拷贝。
+- 网络报文的封装、解析工作。
+
+这些工作“重复低级”,占用了大量 CPU 资源 (如 100 Gb/s 的网卡跑到满带宽需要打满多个 CPU 核资源),使得 CPU 在数据密集型场景下无法将算力用到更有益的地方。
+所以,解决网络性能与 CPU 算力失配问题成为了高性能网络发展的关键。考虑到摩尔定律逐渐失效,CPU 性能短时间内发展缓慢,将网络数据处理工作从 CPU 卸载到硬件设备的思路就成为了主流解决方案。这使得以往专用于特定高性能领域的 RDMA 在通用场景下得到愈来愈多的应用。
+
+
+### 1.2 RDMA 的优势
+
+RDMA (Remote Direct Memory Access) 是一种远程内存直接访问技术,自提出以来经过 20 余年的发展已经成为了高性能网络的重要组成。那么 RDMA 是如何完成一次数据传输的呢?
+
+
+
+RDMA 网络 (用户态模式) 中,具备 RDMA 能力的网卡 RNIC 直接从发送端用户态内存中取得数据,在网卡中完成数据封装后传输到接收端,再由接收端 RNIC 将数据解析剥离,将有效负载 (payload) 直接放入用户态内存中完成数据传输。
+这一过程中 CPU 除了必要的控制面功能外,几乎不用参与数据传输。数据就像是通过 RNIC 直接写入到远程节点的内存中一样。因此,与传统网络相比,RDMA 将 CPU 从网络传输中解放了出来,使得网络传输就像是远程内存直接访问一样方便快捷。
+
+
+
+对比传统网络协议,RDMA 网络协议具有以下三个特点:
+
+- 旁路软件协议栈
+
+RDMA 网络依赖 RNIC 在网卡内部完成数据包封装与解析,旁路了网络传输相关的软件协议栈。对于用户态应用程序,RDMA 网络的数据路径旁路了整个内核;对于内核应用程序,则旁路了内核中的部分协议栈。由于旁路了软件协议栈,将数据处理工作卸载到了硬件设备,因而 RDMA 能够有效降低网络时延。
+
+- CPU 卸载
+
+RDMA 网络中,CPU 仅负责控制面工作。数据路径上,有效负载由 RNIC 的 DMA 模块在应用缓冲区和网卡缓冲区中拷贝 (应用缓冲区提前注册,授权网卡访问的前提下),不再需要 CPU 参与数据搬运,因此可以降低网络传输中的 CPU 占用率。
+
+- 内存直接访问
+
+RDMA 网络中,RNIC 一旦获得远程内存的访问权限,即可直接向远程内存中写入或从远程内存中读出数据,不需要远程节点参与,非常适合大块数据传输。
+
+# 回到 SMC-R
+
+通过上述介绍,相信读者对 RDMA 主要特点以及性能优势有了初步的了解。不过,虽然 RDMA 技术能够带来可喜的网络性能提升,但是想使用 RDMA 透明提升现有 TCP 应用的网络性能仍有困难,这是因为 RDMA 网络的使用依赖一系列新的语义接口,包括 ibverbs 接口与 rdmacm 接口 (后统称 verbs 接口)。
+
+相较于传统 POSIX socket 接口,verbs 接口数量多,且更接近硬件语义。对于已有的基于 POSIX socket 接口实现的 TCP 网络应用,想要享受 RDMA 带来的性能红利就不得不对应用程序进行大量改造,成本巨大。
+因此,我们希望能够在使用 RDMA 网络的同时沿用 socket 接口,使现有 socket 应用程序透明的享受 RDMA 服务。针对这一需求,业界提出了以下两个方案:
+
+- 其一,是基于 libvma 的用户态方案
+libvma 的原理是通过 LD_PRELOAD 来将应用所有 socket 调用引入自定义实现,在自定义实现中调用 verbs 接口,完成数据收发。但是,由于实现在用户态,libvma 一方面缺少内核统一资源管理,另一方面对 socket 接口的兼容性较差。
+
+- 其二,是基于 SMC-R 的内核态方案
+作为内核态协议栈,SMC-R 对 TCP 应用的兼容性相较于用户态方案会好很多,这种 100% 兼容意味着极低的推广和复用成本。此外,实现在内核态使得 SMC-R 协议栈中的 RDMA 资源能够被用户态不同进程共享,提高资源利用率的同时降低频繁资源申请与释放的开销。不过,完全兼容 socket 接口就意味着需要牺牲极致的 RDMA 性能 (因为用户态 RDMA 程序可以做到数据路径旁路内核与零拷贝,而 SMC-R 为了兼容 socket 接口,无法实现零拷贝),但这也换来兼容与易用,以及对比 TCP 协议栈的透明性能提升。未来,我们还计划拓展接口,以牺牲小部分兼容性的代价将零拷贝特性应用于 SMC-R,使它的性能得到进一步改善。
+
+### 2.1 透明替换 TCP
+
+> SMC-R is an open sockets over RDMA protocol that provides transparent exploitation of RDMA (for TCP based applications) while preserving key functions and qualities of service from the TCP/IP ecosystem that enterprise level servers/network depend on!
+
+SMC-R 作为一套与 TCP/IP 协议平行,向上兼容 socket 接口,底层使用 RDMA 完成共享内存通信的内核协议栈,其设计意图是为 TCP 应用提供透明的 RDMA 服务,同时保留了 TCP/IP 生态系统中的关键功能。
+为此,SMC-R 在内核中定义了新的网络协议族 AF_SMC,其 proto_ops 与 TCP 行为完全一致。
+
+```
+/* must look like tcp */
+static const struct proto_ops smc_sock_ops = {
+ .family = PF_SMC,
+ .owner = THIS_MODULE,
+ .release = smc_release,
+ .bind = smc_bind,
+ .connect = smc_connect,
+ .socketpair = sock_no_socketpair,
+ .accept = smc_accept,
+ .getname = smc_getname,
+ .poll = smc_poll,
+ .ioctl = smc_ioctl,
+ .listen = smc_listen,
+ .shutdown = smc_shutdown,
+ .setsockopt = smc_setsockopt,
+ .getsockopt = smc_getsockopt,
+ .sendmsg = smc_sendmsg,
+ .recvmsg = smc_recvmsg,
+ .mmap = sock_no_mmap,
+ .sendpage = smc_sendpage,
+ .splice_read = smc_splice_read,
+};
+```
+
+由于 SMC-R 协议支持与 TCP 行为一致的 socket 接口,使用 SMC-R 协议非常简单。总体来说有两个方法:
+
+
+
+- 其一,使用 SMC-R 协议族 AF_SMC 开发
+通过创建 AF_SMC 类型的 socket,应用程序的流量将进入到 SMC-R 协议栈;
+- 其二,透明替换协议栈
+将应用程序创建的 TCP 类型 socket 透明替换为 SMC 类型 socket。**透明替换可以通过以下两种方式实现**:
+
+- 使用 LD_PRELOAD 实现协议栈透明替换。在运行 TCP 应用程序时预加载一个动态库。在动态库中实现自定义 socket() 函数,将 TCP 应用程序创建的 AF_INET 类型 socket 转换为 AF_SMC 类型的 socket,再调用标准 socket 创建流程,从而将 TCP 应用流量引入 SMC-R 协议栈。
+ ```
+int socket(int domain, int type, int protocol)
+{
+ int rc;
+
+ if (!dl_handle)
+ initialize();
+
+ /* check if socket is eligible for AF_SMC */
+ if ((domain == AF_INET || domain == AF_INET6) &&
+ // see kernel code, include/linux/net.h, SOCK_TYPE_MASK
+ (type & 0xf) == SOCK_STREAM &&
+ (protocol == IPPROTO_IP || protocol == IPPROTO_TCP)) {
+ dbg_msg(stderr, "libsmc-preload: map sock to AF_SMC\n");
+ if (domain == AF_INET)
+ protocol = SMCPROTO_SMC;
+ else /* AF_INET6 */
+ protocol = SMCPROTO_SMC6;
+
+ domain = AF_SMC;
+ }
+
+ rc = (*orig_socket)(domain, type, protocol);
+
+ return rc;
+}
+```
+开源用户态工具集 [smc-tools](https://github.com/ibm-s390-linux/smc-tools) 中的 smc_run 指令即实现上述功能。
+- 通过 ULP + eBPF 实现协议栈透明替换。SMC-R 支持 TCP ULP 是龙蜥社区高性能网络 SIG 贡献到上游 Linux 社区的新特性。用户可以通过 setsockopt() 指定新创建的 TCP 类型 socket 转换为 SMC 类型 socket。同时,为避免应用程序改造,用户可以通过 eBPF 在合适的 hook 点 (如 BPF_CGROUP_INET_SOCK_CREATE、BPF_CGROUP_INET4_BIND、BPF_CGROUP_INET6_BIND 等) 注入 setsockopt(),实现透明替换。这种方式更适合在容器场景下可以依据自定义规则,批量的完成协议转换。
+ ```
+static int smc_ulp_init(struct sock *sk)
+{
+ struct socket *tcp = sk->sk_socket;
+ struct net *net = sock_net(sk);
+ struct socket *smcsock;
+ int protocol, ret;
+
+ /* only TCP can be replaced */
+ if (tcp->type != SOCK_STREAM || sk->sk_protocol != IPPROTO_TCP ||
+ (sk->sk_family != AF_INET && sk->sk_family != AF_INET6))
+ return -ESOCKTNOSUPPORT;
+ /* don't handle wq now */
+ if (tcp->state != SS_UNCONNECTED || !tcp->file || tcp->wq.fasync_list)
+ return -ENOTCONN;
+
+ if (sk->sk_family == AF_INET)
+ protocol = SMCPROTO_SMC;
+ else
+ protocol = SMCPROTO_SMC6;
+
+ smcsock = sock_alloc();
+ if (!smcsock)
+ return -ENFILE;
+
+ <...>
+}
+```
+```
+ SEC("cgroup/connect4")
+int replace_to_smc(struct bpf_sock_addr *addr)
+{
+ int pid = bpf_get_current_pid_tgid() >> 32;
+ long ret;
+
+ /* use-defined rules/filters, such as pid, tcp src/dst address, etc...*/
+ if (pid != DESIRED_PID)
+ return 0;
+
+ <...>
+
+ ret = bpf_setsockopt(addr, SOL_TCP, TCP_ULP, "smc", sizeof("smc"));
+ if (ret) {
+ bpf_printk("replace TCP with SMC error: %ld\n", ret);
+ return 0;
+ }
+ return 0;
+}
+```
+综合上述介绍,TCP 应用程序**透明**使用 RDMA 服务可以体现在以下两个方面:
+- TCP 协议栈透明替换为 SMC-R 协议栈
+- 利用 SMC-R 协议栈透明使用 RDMA 技术
+
+### 2.2 SMC-R 架构
+
+
+
+SMC-R 协议栈在系统内部处于 socket 层以下,RDMA 内核 verbs 层以上。是一个具备 ***"hybrid"*** 特点的内核网络协议栈。这里的 ***"hybrid"*** 主要体现在 SMC-R 协议栈中混合了 RDMA 流与 TCP 流:
+
+#### 数据流量基于 RDMA 网络传输
+
+SMC-R 使用 RDMA 网络来传递用户态应用程序的数据,使应用程序透明的享受到 RDMA 带来的性能红利,即上图中黄色部分所示。
+发送端应用程序的数据流量通过 socket 接口从应用缓冲区来到内核内存空间;接着通过 RDMA 网络直接写入远程节点的一个内核态 ringbuf (remote memory buffer, RMB) 中;最后由远程节点 SMC-R 协议栈将数据从 RMB 拷贝到接收端应用缓冲区中。
+
+
+显然,SMC-R 名称中的共享内存通信指的就是基于远程节点 RMB 进行通信。与传统的本地共享内存通信相比,SMC-R 将通信两端拓展为了两个分离的节点,利用 RDMA 实现了基于“远程”共享内存的通信。
+
+
+
+目前,RDMA 网络的主流实现有三种:InfiniBand、RoCE 和 iWARP。其中,RoCE 作为在高性能与高成本中权衡的方案,在使用 RDMA 的同时兼容以太网协议,既保证了不错的网络性能,同时也降低了网络组建成本,因此倍受企业青睐,Linux 上游社区版本的 SMC-R 也因此使用 RoCE v1 和 v2 作为其 RDMA 实现。
+而 iWARP 则是基于 TCP 实现了 RDMA,突破了其余两者对无损网络的刚性需求。iWARP 具备更好的可拓展性,非常适用于云上场景。阿里云弹性 RDMA (eRDMA) 基于 iWARP 将 RDMA 技术带到云上。**阿里云操作系统 Alibaba Cloud Linux 3 与龙蜥社区开源操作系统 Anolis 8 中的 SMC-R 也进一步支持了 eRDMA (iWARP),使云上用户透明无感的使用 RDMA 网络。**
+
+#### 依赖 TCP 流建立连接
+
+除 RDMA 流外,SMC-R 还会为每个 SMC-R 连接配备一条 TCP 连接,两者具有相同的生命周期。TCP 流在 SMC-R 协议栈中主要担负以下职责:
+
+- 动态发现对端 SMC-R
+
+在 SMC-R 连接建立前,通信两端并不知道对端是否同样支持 SMC-R。因此,两端会首先建立一条 TCP 连接。在 TCP 连接三次握手的过程中通过发送携带特殊的 TCP 选项的 SYN 包表示支持 SMC-R,同时检验对端发送的 SYN 包中的 TCP 选项。
+
+
+- 回退
+
+若在上述过程中,通信两端其一无法支持 SMC-R 协议,或是在 SMC-R 连接建立过程中无法继续,则 SMC-R 协议栈将回退至 TCP 协议栈。回退过程中,SMC-R 协议栈将应用程序持有的文件描述符对应的 socket 替换为 TCP 连接的 socket。应用程序的流量将通过这条 TCP 连接承载,以保证数据传输不会中断。
+
+- 帮助建立 SMC-R 连接
+
+若通信两端均支持 SMC-R 协议,则将通过 TCP 连接交换 SMC-R 连接建立消息 (建连过程类似 SSL 握手)。此外,还需要使用此 TCP 连接交换两侧的 RDMA 资源信息,帮助建立用于数据传输的 RDMA 链路。
+
+
+通过上述介绍,相信读者对 SMC-R 总体架构有了初步的了解。SMC-R 作为一个 ***"hybrid"*** 解决方案,充分利用了 TCP 流的通用性和 RDMA 流的高性能。后面的文章中我们将对 SMC-R 中的一次完整通信过程进行分析,届时读者将进一步体会到 ***"hybrid"*** 这一特点。
+
+本篇作为 SMC-R 系列文章的首篇,希望能够起到一个引子的作用。回顾本篇,我们主要回答了这几个问题:
+
+- 为什么要基于 RDMA ?
+
+因为 RDMA 能够带来网络性能提升 (吞吐/时延/CPU占用率);
+
+- 为什么 RDMA 能够带来性能提升?
+
+因为旁路了大量软件协议栈,将 CPU 从网络传输过程中解放出来,使数据传输就像直接写入远程内存一样简单;
+
+- 为什么需要 SMC-R ?
+
+因为 RDMA 应用基于 verbs 接口实现,已有的 TCP socket 应用若想使用 RDMA 技术改造成本高;
+
+- SMC-R 有什么优势?
+
+SMC-R 完全兼容 socket 接口,模拟 TCP socket 接口行为。使 TCP 用户态应用程序能够透明使用 RDMA 服务,不做任何改造就可以享受 RDMA 带来的性能优势。
+
+- SMC-R 的架构特点?
+
+SMC-R 架构具有 ***"hybrid"*** 的特点,融合了 RDMA 流与 TCP 流。SMC-R 协议使用 RDMA 网络传输应用数据,使用 TCP 流确认对端 SMC-R 能力、帮助建立 RDMA 链路。
diff --git "a/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/2_\345\216\237\347\220\206\350\247\243\350\257\273-\347\263\273\345\210\227\350\247\243\350\257\273_SMC-R_\344\272\214.md" "b/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/2_\345\216\237\347\220\206\350\247\243\350\257\273-\347\263\273\345\210\227\350\247\243\350\257\273_SMC-R_\344\272\214.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e347517b5031915482c23f12eca691972576749e
--- /dev/null
+++ "b/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/2_\345\216\237\347\220\206\350\247\243\350\257\273-\347\263\273\345\210\227\350\247\243\350\257\273_SMC-R_\344\272\214.md"
@@ -0,0 +1,186 @@
+> 原文链接:[系列解读 SMC-R (二):融合 TCP 与 RDMA 的 SMC-R 通信 | 龙蜥技术](https://mp.weixin.qq.com/s?search_click_id=2084229434777311559-1672728623690-5538769394&__biz=Mzg4MTMyMTUwMQ==&mid=2247494585&idx=1&sn=2d025e849833cdd3ecbe0b1754a32aef&chksm=cf6518cbf81291dd2653a014e00308e49ee257deee6545f6e82602c39963c74613c168b5e8a7&scene=0&subscene=10000&clicktime=1672728623&enterid=1672728623&sessionid=0&ascene=65&fasttmpl_type=0&fasttmpl_fullversion=6485008-zh_CN-zip&fasttmpl_flag=0&realreporttime=1672728623725&devicetype=android-29&version=28001759&nettype=WIFI&abtest_cookie=AAACAA%3D%3D&lang=zh_CN&exportkey=n_ChQIAhIQktJ6bQmIv3NiRYGRAbRosxLcAQIE97dBBAEAAAAAAMNdK7DEVIYAAAAOpnltbLcz9gKNyK89dVj0CrfxwLkASXQVVw99WBLScNOeEGq4CybsSRtMLlLXX5vSrnZi7CPSV6dwcBi%2Fq%2BETLKeRG7c4bSF%2FEPNBR80y3r3h0TSAUcw8wr1WX0WjCcS57xULJ2CFvkd%2BbavO%2FKPwMRWsSCyMneKPAd%2FPasjhI9D1fF0eVb9KKBxeuEFRIo%2FOBOydEAcuysGgtlerrjHqbwwno5Vd5qUne3Whv5%2BhgS%2FvR0DUXK212jj%2BpBm8aZDMEFnXv1M%3D&pass_ticket=LXS2YRVcmamkGMyhelL4ieilHzCrCcudro4S8I%2BudsxWwnZ7B5Mb8U1F8Q9vu59k3OVbQ8p4nfoHVEdr1Xcixw%3D%3D&wx_h)
+
+# 引言
+
+通过上一篇文章 [《系列解读 SMC-R (一):透明无感提升云上 TCP 应用网络性能》](https://openanolis.cn/sig/high-perf-network/doc/734387760257141914?)我们了解到,RDMA 相对于 TCP 具有旁路软件协议栈、卸载网络工作到硬件的特点,能有效增加网络带宽、降低网络时延与 CPU 负载。而内核网络协议 SMC-R 在利用 RDMA 技术的同时、又进一步完美兼容了 socket 接口,能够透明无感的为 TCP 应用带来网络性能提升。因此,龙蜥社区高性能网络 SIG 认为 SMC-R 将成为下一代数据中心内核协议的重要组成,对其进行了大量优化,并积极将这些优化回馈到上游 Linux 社区。
+
+本篇文章作为 SMC-R 系列的第二篇,将聚焦一次完整的 SMC-R 通信流程。通过具体的建连、传输、销毁过程,使读者进一步体会到 SMC-R 是一个融合了通用 TCP 与高性能 RDMA 的 ***"hybrid"*** 解决方案。
+
+# 通信流程
+
+如前篇所述,使用 SMC-R 协议有两种方法。其一,是在应用程序中显式创建 AF_SMC 族的 socket;其二,是利用 LD_PRELOAD 或 ULP + eBPF 的方式透明的将应用程序中的 AF_INET 族 socket 替换为 AF_SMC 族 socket。我们默认使用 SMC-R 通信的节点已经加载了 SMC 内核模块,并通过上述方式将应用程序运行在 SMC-R 协议上。接下来,**我们以 first contact (通信两端建立首个连接) 场景为例,介绍 SMC-R 通信流程。**
+
+
+### 2.1 确认对端能力
+
+使用 SMC-R 通信时,我们首先需要确认对端是否同样支持 SMC-R 协议。因此,SMC-R 协议栈为应用程序创建 SMC 类型 socket (smc socket) 的同时,还会在内核创建并维护一个与之关联的 TCP 类型 socket (clcsock),并基于 clcsock 与对端建立起 TCP 连接。
+
+
+
+在 TCP 连接三次握手中,使用 SMC-R 协议的一端发送的 SYN/ACK 中携带了特殊的 TCP 选项 (Kind = 254,Magic Number = 0xe2d4),用于表明自身支持 SMC-R。通过检查对端发送的 SYN/ACK,通信节点得知其 SMC-R 能力,进而决定是否继续使用 SMC-R 通信。
+
+
+
+
+
+### 2.2 协议回退
+
+若在上述 TCP 握手过程中,通信两端其一表示无法支持 SMC-R,则进入协议回退 (fallback) 流程。
+
+协议回退时,应用程序所持有的 fd 对应的 smc socket 将被替换为 clcsock。从此,应用程序将使用 TCP 协议通信,从而确保数据传输不会因为协议兼容问题而中断。
+
+需要注意的是,协议回退仅发生在通信协商过程中,如前文提到的 TCP 握手阶段,或是下文提到的 SMC-R 建连阶段。为便于跟踪诊断,SMC-R 协议详细分类了潜在的回退可能,用户可以通过用户态工具 smc-tools 观测到协议回退事件及原因。
+
+
+
+### 2.3 建立 SMC-R 连接
+
+若在 TCP 握手中,两端均表示支持 SMC-R,则进入 SMC-R 建连流程。SMC-R 连接的建立依赖 TCP 连接传递控制消息,这种控制消息被称为 Connection Layer Control (CLC) 消息。
+
+
+
+CLC 消息的主要职责是同步通信两端的 RDMA 资源以及共享内存等信息。使用 CLC 消息建立 SMC-R 连接的过程与 SSL 握手类似,主要包含 Proposal、Accept、Decline、Confirm 等语义。在建连过程中,若遇到不可恢复的异常 (如 RDMA 资源失效) 导致后续 SMC-R 通信无法继续,也将触发前文所述的协议回退流程。
+
+First contact 场景下,由于通信两端首次接触,两者间尚不存在使用 RDMA 通信的条件。所以,在建立首个 SMC-R 连接时,还将创建 SMC-R 通信所需的 RDMA 资源,建立 RDMA 链路,申请 RDMA 内存。
+
+
+
+#### 2.3.1 创建 RDMA 资源
+
+SMC-R 建连初期,两端根据应用程序传递的 IP 地址在本地寻找可用 (如相同 Pnet ID) 的 RDMA 设备,并基于找到的设备创建必要的 RDMA 资源,包括 Queue Pair (QP),Completion Queue (CQ),Memory Region (MR),Protect Domain (PD) 等等。
+
+其中,QP 与 CQ 是 RDMA 通信的基础,提供了一套 RDMA 使用者 (如 SMC 内核协议栈) 与 RDMA 设备 (RNIC) 之间的异步通信机制。
+
+QP 本质是存放工作任务 (Work Request, WR) 的工作队列 (Work Queue, WQ)。负责发送任务的 WQ 称为 Send Queue (SQ),负责接收任务的 WQ 称为 Receive Queue (RQ),两者总是成对出现,称为 QP。用户将希望 RNIC 完成的任务打包为工作队列元素 (Work Queue Element, WQE),post 到 QP 中。RNIC 从 QP 中取出 WQE,完成 WQE 中定义的工作。
+
+CQ 本质是存放工作完成信息 (Work Completion, WC) 的队列。RNIC 完成 WR 后,将完成信息打包为完成队列元素 (Completion Queue Element, CQE) 放入 CQ 中。用户从 CQ 中 poll 出 CQE,获悉 RNIC 已经完成某个 WR。
+
+
+
+#### 2.3.2 建立 RDMA 链路
+
+通信两端将已创建的 RDMA 资源通过 CLC 消息同步到对端,进而在两端之间建立起基于 RC (Reliable Connection) QP 的 RDMA 链路。SMC-R 中将这种点对点逻辑上的 RDMA 链路称为 SMC-R Link。一条 SMC-R Link 承载着多条 SMC-R 连接的数据流量。
+
+
+
+若通信节点之间存在不止一对可用的 RNIC,则会建立不止一条 Link。这些 Link 在逻辑上组成一个小组,称为 SMC-R Link Group。
+
+
+
+在 Linux 实现中,每个 Link Group 具备 1-3 条 Link,最多承载 255 条 SMC-R 连接。这些连接被均衡的关联到 Link Group 的某一 Link 上。应用程序通过 SMC-R 连接发送的数据将由关联的 Link (也即 RDMA 链路) 传输。
+
+同一个 Link Group 中,所有的 Link 互相“平等”。这个“平等”体现在同一 Link Group 中的 Link 具备访问 Group 中所有 SMC-R 连接收发缓冲区 (下文提到的 sndbuf 与 RMB) 的权限,具备承载任意 SMC-R 连接数据流的能力。因此,当某一 Link 失效时 (如 RNIC down),关联此 Link 的所有连接可以迁移到同 Link Group 的另一条 Link 上。这使得 SMC-R 通信稳定可靠,具备一定的容灾能力。
+
+SMC-R 中,Link (Group) 在 first contact 时创建,在最后一条 SMC-R 连接断开一段时间 (Linux 实现中为 10 mins) 后销毁,具备比连接更长的生命周期。First contact 之后创建的 SMC-R 连接都将尝试复用已有的 Link (Group)。这样的设计充分利用了已有的 RDMA 资源,避免了频繁创建与销毁带来的额外开销。
+
+#### 2.3.3 申请 RDMA 内存
+
+SMC-R 协议栈为每条 SMC-R 连接分配了独属的收发缓冲区:sndbuf (发送缓冲区) 与 RMB (接收缓冲区,Remote Memory Buffer)。这是两片地址连续,长度在 16 KB ~ 512 KB 间的内核态 ring buffer。
+
+
+
+其中,sndbuf 用于存放连接待发送的数据,被注册为 DMA 内存。本地 RNIC 设备可以直接访问 sndbuf,从中取走有效负载 (payload)。而 RMB 用于存放远程节点 RNIC 写入的数据,即连接待接收的数据。由于需要被远程节点访问,因此 RMB 被注册为 RDMA 内存。
+
+注册 RDMA 内存的过程称为 Memory Registration,主要完成以下操作:
+
+- 生成地址翻译表
+
+RDMA 使用者 (如本地/远程 SMC-R 协议栈) 通常使用虚拟地址 (VA) 描述内存,而 RNIC 则通过物理地址 (PA) 寻址。RNIC 从 WQE 或数据包中取得数据 VA 后通过查表得到 PA,进而访问正确内存空间。因此 Memory Registration 首要任务就是形成目标内存的地址翻译表。
+
+- Pin 住内存
+
+现代 OS 会置换暂不使用的内存数据,这将导致地址翻译表中的映射关系失效。因此,Memory Registration 会将目标内存 pin 住,锁定 VA-to-PA 映射关系。
+
+- 限制内存访问权限
+
+为避免内存非法访问,Memory Registration 会为目标内存生成两把内存密钥:Local Key (l_key) 和 Remote Key (r_key)。内存密钥实质是一串序列,本地或远端凭借 l_key 或 r_key 访问 RDMA 内存,确保内存访问合法。
+
+SMC-R 中,远程节点访问本地 RMB 所需的 addr 与 r_key 被封装为远程访问令牌 (Remote Token, rtoken),通过 CLC 消息传递到远端,使其具备远程访问本地 RMB 的权限。
+
+SMC-R 连接销毁后,对应的 sndbuf 与 RMB 将被回收到 Link Group 维护的内存池中,供后续新连接复用,以此减小 RDMA 内存创建/销毁对建连性能的影响。
+
+
+
+### 2.4 验证 SMC-R Link
+
+由于 first contact 场景下新建立的 SMC-R Link 尚未经过验证,所以在正式使用 Link 传输应用数据前,通信两端会基于 Link 发送 Link Layer Control (LLC) 消息,用于检验 Link 是否可用。
+
+
+
+LLC 消息通常为请求-回复模式,用于传输 Link 层面的控制信息,如添加/删除/确认 Link,确认/删除 r_key 等。
+
+
+
+| 类型 | 说明 |
+|--------------|-----------------------------------------|
+| ADD_LINK | 向 Link Group 中添加新的 Link。 |
+| CONFIRM_LINK | 确认新创建的 Link 是否能够正常工作。 |
+| DELETE_LINK | 删除一个特定的 Link 或整个 Link Group。 |
+| CONFIRM_RKEY | 新增 RMB 时通知 Link 对端。 |
+| DELETE_RKEY | 删除一个或多个 RMB 时通知 Link 对端。 |
+| TEST_LINK | 确认 Link 是否健康、活跃。 |
+
+LLC 消息的传输基于 RDMA 的 SEND 操作完成,与之相对的是后文提到的 RDMA WRITE 操作。
+
+
+
+SEND 操作又被称为“双边操作”,这是因为 SEND 操作要通信两端都参与进来。一次 SEND 的传输过程为:
+
+- 接收端 RDMA 使用者 (SMC-R 内核协议栈) 向本地 RQ 中 Post RWQE,RWQE 中记录了待接收数据的长度以及预留内存地址;
+
+- 发送端 RDMA 使用者 (SMC-R 内核协议栈) 向本地 SQ 中 Post SWQE,SWQE 中记录了待发送数据长度和内存地址。发送端 RNIC 根据 SWQE 记录的信息取出相应长度的数据发送到对端;
+
+- 接收端 RNIC 接收到数据后,取出 RQ 中的第一个 RWQE,依照其中记录的内存地址和长度存放数据;
+
+通过在 Link 上收发 CONFIRM_LINK 类型的 LLC 消息,通信两端确认了新创建的 Link 具备 RDMA 通信的能力,可以用于传输 SMC-R 连接数据。
+
+### 2.5 基于共享内存通信
+
+通过上述重重步骤,first contact 场景下 SMC-R 建连工作终于结束。接下来,应用程序将通过已建立好的 SMC-R 连接传输数据。
+
+
+
+应用程序下发到 SMC-R 连接中的数据由关联的 Link 通过 RDMA WRITE 操作写入远程节点 RMB 中。
+
+
+
+与上文提到的 SEND 操作不同,RDMA WRITE 又被称为“单边操作”。这是因为数据传输只有 RDMA WRITE 发起的一方参与,而接收数据一方的 RDMA 使用者完全不参与数据传输,也不知晓数据的到来。一次 RDMA WRITE 操作过程如下:
+
+- 前期准备阶段,接收端 RDMA 使用者 (SMC-R 内核协议栈) 将接收缓冲区注册为 RDMA 内存,将远程访问密钥 rkey 告知发送端,使其拥有直接访问接收端内存的权限,这个过程我们在前文介绍过。
+
+- 发送端 RDMA 使用者 (SMC-R 内核协议栈) 向 SQ 中 post SWQE。与 SEND 不同的是,RDMA WRITE 的 SWQE 中不仅包含数据在本地的内存地址和长度,还包含数据即将存放在接收端的内存地址,以及访问接收端内存所需的 r_key。发送端 RNIC 根据 SWQE 中记录的信息将数据传输到接收端。
+
+- 接收端 RNIC 核实数据包中的 r_key,将数据存放到指定内存地址中。此时的接收端 RDMA 使用者并不知道数据已经被写入内存。
+
+由于 RDMA WRITE 操作不需要接收端 RDMA 使用者参与,因此非常适合大量数据的直接写入。不过,由于接收端并不知晓数据到来,发送端写入数据后需要通过 SEND 操作发送控制消息通知接收端。在 SMC-R 中,这种控制消息称为 Connection Data Control (CDC) 消息。CDC 消息中包含 RMB 相关控制信息用以同步数据读写。
+
+| 内容 | 含义 |
+|----------------------------|-----------------------------------|
+| Sequence number | CDC 消息序列号 |
+| Alert token | 发送此消息的 SMC-R 连接 ID |
+| Producer cursor | RMB 数据生产游标 (写者更新) |
+| Producer cursor wrap seqno | RMB 数据生产 wrap 次数 (写者更新) |
+| Consumer cursor wrap seqno | RMB 数据消费wrap 次数 (读者更新) |
+| Consumer cursor | RMB 数据消费 游标 (读者更新) |
+
+在系列文章的第一篇中我们提到,SMC-R 名称中的“共享内存”指的是接收端的 RMB。结合上述的 RDMA WRITE 操作与 CDC 消息,SMC-R 的共享内存通信流程可以总结为:
+
+
+
+ - 发送端的数据通过 socket 接口,由应用缓冲区拷贝至内核 sndbuf 中 (图中未画出 sndbuf)
+ - 协议栈通过 RDMA WRITE 单边操作将数据写入接收端 RMB 中
+ - 发送端通过 SEND 双边操作发送 CDC 消息告知接收端有新的数据到来
+ - 接收端从 RMB 中拷贝数据至应用缓冲区
+ - 接收端通过 SEND 双边操作发送 CDC 消息告知发送端 RMB 中部分数据已被使用
+
+### 2.6 连接关闭与资源销毁
+
+结束数据传输后,主动关闭方发起 SMC-R 连接关闭流程。与 TCP 相似,SMC-R 连接也存在半关闭/全关闭状态。断开的 SMC-R 连接与 Link (Group) 解绑,相关的 sndbuf 与 RMB 也将被回收到内存池中,等待复用。同时,与 SMC-R 连接关联的 TCP 连接也进入关闭流程,最终释放。
+
+若 Link (Group) 中不再存在活跃的 SMC-R 连接,则等待一段时间后 (Linux 实现中为 10 mins) 进入Link (Group) 销毁流程。销毁 Link (Group) 将释放与之相关的所有 RDMA 资源,包括 QP、CQ、PD、MR、以及所有的 sndbuf 与 RMB。Link (Group) 销毁后,再次创建 SMC-R 连接则需要重新经历 first contact 流程。
+
+# 总结
+
+本篇作为 SMC-R 系列文章的第二篇,以 first contact 场景为例,介绍了完整的 SMC-R 通信流程。包括:通过 TCP 握手确认对端 SMC-R 能力;使用 TCP 连接传递 CLC 消息,交换 RDMA 资源、创建 RDMA 链路、建立 SMC-R 连接;通过 RDMA SEND 操作发送 LLC 消息验证 Link 可用;基于 Link 使用 RDMA WRITE 传输应用程序数据,并利用 CDC 消息同步 RMB 中数据变化;关闭 SMC-R、TCP 连接,销毁 RDMA 资源等一系列过程。
+
+上述过程充分体现了 SMC-R 的 **"hybrid"** 特点。SMC-R 既利用了 TCP 的通用性 ,如通过 TCP 连接确认对端能力,建立 SMC-R 连接与 RDMA 链路;又利用了 RDMA 的高性能 ,如通过 Link 传输应用程序数据流量。正因为如此,SMC-R 能够在兼容现有 TCP/IP 生态系统关键功能的同时为 TCP 应用提供透明无感的网络性能提升。
diff --git "a/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/3_\346\200\247\350\203\275\345\261\225\347\244\272-redis\345\222\214nginx\346\200\247\350\203\275\345\261\225\347\244\272.md" "b/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/3_\346\200\247\350\203\275\345\261\225\347\244\272-redis\345\222\214nginx\346\200\247\350\203\275\345\261\225\347\244\272.md"
new file mode 100644
index 0000000000000000000000000000000000000000..3c8c07c1acb27d002281a222f2bde02e5e7bdd2d
--- /dev/null
+++ "b/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/3_\346\200\247\350\203\275\345\261\225\347\244\272-redis\345\222\214nginx\346\200\247\350\203\275\345\261\225\347\244\272.md"
@@ -0,0 +1,140 @@
+作为在 RDMA/eRDMA 场景下对 TCP 应用透明无损替换的技术,SMC 同样也继承了 RDMA 技术的天然优势,在内存数据库、RPC、数据中心内部等场景相比 TCP 能提供更好的网络性能,包括但不限于更低的访问时延,更高的吞吐上限以及更低的 CPU 开销等。考虑到 SMC 兼容 socket 接口的特性,能够快速运行 SMC 的应用很多,因此有极其丰富的相对应的计算性能的测试工具。在本项基础性能测试中,我们选择了两台都是16vCPU 32G内存,基于ecs.c7re.4xlarge规格的添加了ERDMA网卡的阿里云ECS实例。
+
+## 软件版本
+
+- ERDMA 驱动版本:kernel driver version: 0.2.29
+- Kernel:5.10.134
+- wrk 版本:wrk [epoll]
+- nginx 版本:nginx version: nginx/1.20.1
+- redis 版本: redis-server v6.0.5
+- maven 版本:Apache Maven 3.4.5 (Red Hat 3.4.5-5.1)
+
+## 机器规格
+
+
+
+为了能够对 SMC 技术进行深入的了解,本次评测将常见应用的基础性能工具进行评测,包括
+
+1. 经典 microbenchmark
+2. 标准业务应用
+3. 数据库等基础设施
+
+本次测试包括时延测试,吞吐测试和CPU开销测试三个部分。看看 SMC 技术是如何在透明替换中保持ERDMA技术的性能收益。
+
+## Redis 应用性能
+
+作为高性能的内存数据库的代表,与复杂的传统数据库不同,包括主从同步在内的Redis的处理性能很大程度上会受到网络性能的制约,这里这里我们
+使用 经典的 Redis测试工具 redis-benchmark 来测试验证SMC-R的性能。测试脚本如下:
+
+```
+#server script
+redis-server --save '' --appendonly no --protected-mode no --daemonize yes
+```
+
+```
+#client script
+redis-benchmark -h ${serverAddress} -q -n $requests -c $connections -d $size -t GET,SET --thread ${threads}
+```
+
+### 吞吐收益
+
+在针对Redis的性能测试,这里我们使用了 redis-benmark下的 GET/SET 测试模型,对redis数据性能进行了多次测试,稳定的测试结果如下:
+
+
+
+
+
+从测试结果可以看出,无论是GET测试还是SET测试,SMC-R相对于TCP都带来了至少40%+的性能测试数据提升.
+但如果CPU开销也额外花费了40%,数据就没有显著意义了,因此CPU开销也是及其重要的数据,接下来我们将在同样的测试条件下对SMC-R和TCP的CPU开销数据进行对比。
+
+### CPU 开销
+
+
+
+从测试结果可以看出,SMC-R相对于TCP花费了额外的11%左右的CPU开销,这主要是因为显著的提升了吞吐导致用户态处理CPU增多导致的(吞吐提升了40%+)。
+另一方面,因为ERDMA提供的协议栈卸载和内核bypass能力,它允许应用程序直接通过目标主机内的内存空间进行数据传输,具有ERDMA能力的以太网卡负责将保证他们之间连接的可靠性。
+因此能够做到在大幅提高吞吐收益的同时,可以做到低CPU开销。
+
+## Nginx 应用性能
+
+nginx作为一个高性能的HTTP和反向代理服务器,在国内外被广泛应用,对于HTTP服务器来说,最重要的莫过于其响应请求的延时和处理请求的能力。
+这里我们将基于 经典的wrk/nginx测试模型 来快速验证 SMC 的性能。测试脚本如下:
+
+```
+#nginx server config
+
+user nginx;
+worker_processes auto;
+error_log /var/log/nginx/error.log;
+worker_rlimit_nofile 10240;
+pid /run/nginx.pid;
+
+# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
+include /usr/share/nginx/modules/*.conf;
+
+events {
+ worker_connections 10240;
+}
+
+http {
+ log_format main '$remote_addr - $remote_user [$time_local] "$request" '
+ '$status $body_bytes_sent "$http_referer" '
+ '"$http_user_agent" "$http_x_forwarded_for"';
+
+ access_log off;
+
+ sendfile off;
+ tcp_nopush on;
+ tcp_nodelay on;
+ keepalive_timeout 300s;
+ keepalive_requests 1000000;
+ types_hash_max_size 4096;
+
+ include /etc/nginx/mime.types;
+ default_type application/octet-stream;
+
+ # Load modular configuration files from the /etc/nginx/conf.d directory.
+ # See http://nginx.org/en/docs/ngx_core_module.html#include
+ # for more information.
+ include /etc/nginx/conf.d/*.conf;
+
+ open_file_cache max=10240000 inactive=60s;
+ open_file_cache_valid 80s;
+ open_file_cache_min_uses 1;
+
+ server {
+ listen 80 backlog=1024;
+ server_name _;
+ root /usr/share/nginx/html;
+ }
+}
+```
+
+```
+#client script
+wrk http://${server}/${path} -t${thread} -c{connection} -d30
+```
+
+对于大多数RPC应用,响应时延的重要性毋庸置疑,这直接影响到了用户能够感受到的真实时间。因此在Nginx测试中,我们重点额外引入了时延维度,接下来我们将通过一组数据来观察,SMC-R能否相对于TCP减少数据延迟,我们拭目以待。特别的,这里测试全部打满了CPU,因此CPU开销情况没有单独列出。
+
+### 时延收益
+
+这里展示了在不同文件大小,不同线程数以及不同连接数下的时延数据情况:
+
+
+
+我们可以看到,SMC-R在优化请求的时延上也有显著收益,在不同请求数据大小下,相对于TCP减少了20%到40%左右的时延,受益于ERDMA快速的协议栈处理和更短的数据路径,显著的时延收益也不足为奇了。
+因此,即使您的RPC应用不太关心吞吐的收益,SMC-R也可以帮助你在优化请求的时延上大做文章,在不需要任何代码改动的情况下,便可以使用SMC-R来获得收益。
+
+### 吞吐收益
+
+
+
+同样的,在Nginx测试中,测试的吞吐数据也同样有显著提升。如上图所示,在不同测试参数下,相对于TCP,SMC-R可以带来21%到37.6%的吞吐提升。
+
+## 结论
+
+受益于 SMC 在内核中无损透明替换的语义,SMC 兼容 socket 接口的特点使 TCP 应用程序无需任何改造即可运行在 SMC 协议栈上;底层使用的 eRDMA 网络使 SMC 拥有相较于 TCP 更好的网络性能。SMC 协议栈通过 TCP 连接自主发现对侧 SMC 能力,协商成功后使用 SMC 协议栈承载应用数据流量;协商失败则安全回退至 TCP/IP 协议栈,保证数据正常传输。阿里云 Alibaba Cloud Linux 3 操作系统基于阿里云弹性 RDMA(elastic RDMA, eRDMA)技术首次将 SMC-R 带入云上场景,实现云上 TCP 协议栈的透明无损替换,为数据库、RPC、批量数据传输等场景提供相比 TCP 更好的网络性能。相较于上游 Linux SMC-R 实现,Alibaba Cloud Linux 3 中的 SMC-R 更适配阿里云 eRDMA 技术、拥有更好的性能、可靠的稳定性、丰富成熟的透明替换方案和及时的更新维护;在这些场景中,我们可以观测到
+
+- 平均20%的延迟收益;
+- 最大40+的每CPU吞吐收益,在合适的场景中甚至可以达到50%+。
diff --git "a/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/4_\344\275\277\347\224\250\350\257\264\346\230\216-\344\275\277\347\224\250\346\214\207\345\215\227.md" "b/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/4_\344\275\277\347\224\250\350\257\264\346\230\216-\344\275\277\347\224\250\346\214\207\345\215\227.md"
new file mode 100644
index 0000000000000000000000000000000000000000..b40a89a07feb8832b33b4dab9ebc5eefcba2e4ca
--- /dev/null
+++ "b/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/4_\344\275\277\347\224\250\350\257\264\346\230\216-\344\275\277\347\224\250\346\214\207\345\215\227.md"
@@ -0,0 +1,351 @@
+Alibaba Cloud Linux 3 提供的共享内存通信(Shared Memory Communication,SMC)是一种兼容 socket 层,使用硬件卸载的共享内存技术实现的高性能内核网络协议栈。SMC 支持基于 RDMA 卸载的内存共享技术 SMC over RDMA,简称 SMC-R。
+
+SMC-R 由 IBM 于 2017 年开源至 Linux 4.11 并持续维护至今,其协议标准可参考 RFC 7609。阿里云 Alibaba Cloud Linux 3 操作系统基于阿里云弹性 RDMA(elastic RDMA,eRDMA)技术首次将 SMC-R 带上云上场景,实现对 TCP 应用透明无损的替换,提供高性能、普惠的硬件卸载网络。
+
+本文将介绍 SMC-R 及其使用方法。
+
+# 一、背景介绍
+
+SMC 基于共享内存的数据交互模型依赖 RDMA 提供的内存操作原语。
+
+RDMA 技术将网络协议栈下沉至 RDMA 网卡 (RNIC) 实现,使网络节点能够绕过内核直接访问远程内存。与传统 TCP 网络相比,RDMA 网络减少了数据在内存间拷贝的次数,降低了网络传输过程中消耗的 CPU 资源,进而提高了网络吞吐、降低了网络时延。
+
+
+
+因此,RDMA 被广泛应用于数据密集型和计算密集型场景中,是高性能计算、机器学习、数据中心、海量存储等领域的重要解决方案。
+
+过去,RDMA 只能在一些数据中心网络中通过网卡和交换机紧密配合使用,部署复杂度高。如今,阿里云弹性 RDMA 将复杂的 RDMA 技术带到云上,使普通的 ECS 用户也能使用高性能的 RDMA 传输,无需关心底层复杂的网卡、交换机等物理网络环境配置,使其成为一种亲民、普惠的技术。
+
+但是,由于 RDMA 技术基于 IB verbs 接口,相较于常用的 POSIX socket 接口存在巨大的差异。现有 socket 应用程序迁移至 RDMA 网络往往面临着大量的改造,使用 RDMA 技术仍存在较高的技术门槛。
+
+于是,为了充分挖掘弹性 RDMA 的潜力,为云上用户提供更好的网络性能,Alibaba Cloud Linux 3 与龙蜥社区 Anolis OS 提供并优化了 SMC-R。在高效使用 RDMA 技术的同时,保留对标准 TCP 应用的兼容,使更多的应用无需做任何修改便能享受 RDMA 所带来的性能红利。
+
+# 二、核心优势
+
+## 1. 高性能
+
+得益于 RDMA 技术将网络协议栈从内核卸载至硬件网卡,SMC-R 相较于传统 TCP 协议栈在合适场景下可获得更低的时延、更高的吞吐量,以及更小的 CPU 负载。
+
+- 硬件卸载;
+- 更低的网络时延、更高的吞吐、更少的 CPU 占用率;
+- 高效可靠的远程内存直接访问;
+
+## 2. 透明替换
+
+得益于 SMC-R 对 POSIX socket 接口的兼容以及协议栈透明替换能力,socket 应用程序可以在无修改的情况下完成 TCP 协议栈到 SMC-R 协议栈的切换,无需额外的应用改造或开发成本。
+
+- 兼容 socket 接口的共享内存通信;
+- 多维度协议栈无损透明替换;
+- 自动协议协商和安全回退机制;
+
+# 三、技术架构
+
+## 1. 协议层次与透明替换
+
+SMC-R 工作于内核空间,向上支持用户态程序通过 socket 接口描述的网络行为,向下使用 IB verbs 接口实现 RDMA 网络传输。RDMA 资源的使用、管理与维护均由 SMC-R 协议栈完成,应用程序不会感知到内核中的 RDMA 实体。
+
+
+
+Alibaba Cloud Linux 3 提供了进程或 net namespace 纬度的 TCP 至 SMC-R 协议栈透明替换机制。通过 LD_PRELOAD/eBFP 或 net.smc.tcp2smc sysctl 将应用程序原本的 AF_INET 协议族 socket 透明替换为 AF_SMC 协议族 socket,让网络传输运行于 SMC-R 协议栈,使应用程序不做任何修改即可享受 RDMA 带来的网络性能提升。
+
+## 2. 自动协商和安全回退
+
+SMC-R 具备自动协商协议、动态回退的能力。
+
+建立 SMC-R 通信前,协议栈首先在内核中与通信对端建立 TCP 连接,在握手过程中使用特殊的 TCP 选项表明自身支持 SMC-R,并确认对端同样支持 SMC-R。
+
+若协商成功,通信两侧 SMC-R 协议栈将创建新的,或复用已有的 RDMA 资源,建立可用的 RDMA RC 链路。从此网络传输将基于 RDMA 网络完成。
+
+若协商失败,如一侧不具备 RDMA 设备,SMC-R 协议栈将自动回退到 TCP 协议栈,使用协商时建立的 TCP 连接完成数据传输。
+
+需要注意的是,SMC-R 仅支持连接协商期间回退至 TCP 协议栈,但不支持数据传输过程中的回退。
+
+
+
+
(图片来自于 https://www.ibm.com/docs/en/aix/7.2?topic=access-shared-memory-communications-over-rdma-smc-r)
+
+## 3. 基于 RDMA 的共享内存通信
+
+完成协议协商并建立连接后,SMC-R 为每侧分配一块用于缓存待发送数据的环形缓冲区 sndbuf 和一块用于缓存待接收数据的环形缓冲区 RMB(Remote Memory Buffer)。
+
+发送端应用程序通过 socket 接口将待发送数据拷贝到本侧 sndbuf 中,由 SMC-R 协议栈通过 RDMA WRITE 操作直接高效地写入对侧节点的 RMB 中。同时,伴随着使用 RDMA SEND/RECV 操作交互连接数据管理 (Connection Data Control, CDC) 消息,用于更新、同步环形缓冲区中的数据游标 (Cursor)。
+
+接收端 SMC-R 协议栈感知到 RMB 中填入新数据后,通过 epoll 等方式告知接收端应用程序将 RMB 中的数据拷贝到用户态,完成数据传输。所以在 SMC-R 中,RMB 充当传输过程中的共享内存。
+
+
+
+# 四、应用场景
+
+## 1. 时延敏感的数据查询和处理
+
+Redis、memcached、PostgreSQL 等高性能数据查询与处理的场景,对网络性能有极高的要求。SMC-R 为应用提供无侵入式透明替换 TCP 协议栈的能力,无需应用二次开发和适配,即可为应用提供最高 50% 的 QPS 提升。
+
+## 2. 高吞吐的数据传输
+
+集群内的大规模数据交互与传输,往往需要占用大量的带宽和 CPU 资源。得益于 RDMA 技术带来的远程内存直接访问,SMC-R 在相同的吞吐性能下,CPU 资源使用显著低于传统 TCP 协议栈,为应用节省更多的计算资源。
+
+# 五、使用说明
+
+Alibaba Cloud Linux 3 提供并优化了 SMC-R 内核协议栈,并配合以完善的 SMC-R 状态监控和故障诊断工具。您可以通过下述步骤使用 SMC-R:
+
+## 1. 配置带有 ERI 的 ECS 实例
+
+SMC-R 基于 RDMA 实现。因此使用 SMC-R 前需要配置带有 ERI 的 ECS 实例,以获得云上 RDMA 能力。具体流程可以参见: [使用 ERI](https://help.aliyun.com/document_detail/336853.html?spm=a2c4g.11186623.0.0.6e244762X1zZKA)
+
+## 2. 加载 SMC 模块
+
+Alibaba Cloud Linux 3 中,SMC-R 均以内核模块的形式提供,因此首先需要加载 smc 与 smc_diag 内核模块。
+
+```
+modprobe smc
+modprobe smc_diag
+```
+
+在 dmesg 中可以观察到,模块被加载成功。
+
+```
+[60342.499847] NET: Registered protocol family 43
+[60342.499868] smc: netns ffffffff912dcf40 reserved ports for eRDMA OOB
+[60342.499869] smc: adding ib device iwp0s7 with port count 1
+[60342.499870] smc: ib device iwp0s7 port 1 has pnetid
+```
+
+**需要说明的是,由于 SMC-R + eRDMA 的实现方式的特殊性,加载 SMC-R 模块后将占用当前可访问 ERI 网卡的 net namespace 中从 33800 开始的 16 个 socket 端口用于建立 OOB 建连,若端口占用失败将无法加载 SMC-R 模块;卸载 SMC-R 模块时将解除端口占用。**
+
+## 3. 安装 smc-tools
+
+smc-tools 是 IBM 开发 SMC 监控诊断工具,拥有丰富的运维诊断功能。
+
+通过 yum 源安装 smc-tools
+
+```
+yum install -y smc-tools
+```
+
+## 4. 基于 SMC 协议栈运行 TCP socket 应用程序
+
+### 4.1 net namespace 维度透明替换
+
+Alibaba Cloud Linux 3 提供了 net namespace 纬度的协议透明替换功能。将同时符合以下所有条件的 TCP socket
+
+- family 为 AF_INET 或 AF_INET6;
+- type 为 SOCK_STREAM;
+- protocol 为 IPPROTO_IP 或 IPPROTO_TCP;
+
+替换为
+
+- family 为 AF_SMC;
+- type 为 SOCK_STREAM;
+- protocol 为 SMCPROTO_SMC 或 SMCPROTO_SMC6;
+
+的 SMC socket。
+
+
+
+
+1)打开 net namespace 范围全局替换开关 net.smc.tcp2smc
+
+```
+sysctl net.smc.tcp2smc=1
+```
+默认情况下,sysctl tcp2smc = 0,处在关闭状态。
+
+2)在此 net namespace 中运行 TCP socket 应用程序
+
+```
+./foo
+```
+
+此时 foo 应用程序创建的 TCP socket 将被透明替换为 SMC socket。通过 SMC-R 协议栈处理应用程序网络行为。如“自动协商与安全回退”小节所述,若通信对侧同样支持 SMC-R 协议并协商成功,则将基于 RDMA 网络完成数据传输;否则将安全回退使用 TCP 网络传输。
+
+3)关闭 net namespace 范围全局替换开关 net.smc.tcp2smc
+
+```
+sysctl net.smc.tcp2smc=0
+```
+
+### 4.2 进程维度透明替换
+
+Alibaba Cloud Linux 3 与 Anolis OS 还提供了进程维度的协议透明替换功能——使用 LD_PRELOAD 方式替换。使用 LD_PRELOAD 替换至 SMC 协议栈依赖 smc-tools 工具,smc-tools 的安装可见“3. 安装 smc-tools”中所述。
+
+
+
+利用 smc-tools 工具集中的脚本 smc_run 运行应用程序时,通过 LD_PRELOAD 环境变量将 smc-tools 工具集中的 libsmc-preload.so 定义为优先加载的动态库。
+libsmc-preload.so 将把应用程序及其子进程中符合以下所有条件的 TCP socket
+
+- family 为 AF_INET 或 AF_INET6;
+- type 为 SOCK_STREAM;
+- protocol 为 IPPROTO_IP 或 IPPROTO_TCP;
+
+替换为
+
+- family 为 AF_SMC;
+- type 为 SOCK_STREAM;
+- protocol 为 SMCPROTO_SMC 或 SMCPROTO_SMC6;
+
+的 SMC socket。
+
+指定 TCP socket 程序 foo 运行在 SMC-R 协议栈:
+
+```
+smc_run ./foo
+```
+
+此时 foo 应用程序创建的 TCP socket 将被透明替换为 SMC socket。通过 SMC-R 协议栈处理应用程序网络行为。如“自动协商与安全回退”小节所述,若通信对侧同样支持 SMC-R 协议并协商成功,则将基于 RDMA 网络完成数据传输;否则将安全回退使用 TCP 网络传输。
+
+## 5. 跟踪诊断 SMC-R 连接与 RDMA 资源
+
+### 5.1 smc-tools
+
+smc-tools 工具集提供了多个维度的 SMC-R 跟踪诊断,主要包括:
+
+- smcr:提供 SMC-R 相关资源统计信息;
+- smcss:提供 SMC socket 相关信息;
+
+
+**1. 使用 smcr**
+
+- 查看 smcr 指令 manual
+
+```
+man smcr
+```
+- 查看支持 SMC-R 的设备:
+
+```
+[root ~]# smcr device
+Net-Dev IB-Dev IB-P IB-State Type Crit #Links PNET-ID
+eth0 iwp0s7 1 ACTIVE 0x107f No 0
+```
+
+- 如查看 linkgroup(即 SMC-R 协议栈维护的 RDMA 链路)信息:
+
+```
+[root ~]# smcr l
+LG-ID LG-Role LG-Type VLAN #Conns PNET-ID
+00000100 CLNT SINGLE 0 32
+00000200 CLNT SINGLE 0 32
+00000300 CLNT SINGLE 0 32
+00000400 CLNT SINGLE 0 32
+00000500 CLNT SINGLE 0 32
+00000600 CLNT SINGLE 0 32
+00000700 CLNT SINGLE 0 8
+```
+此时客户端 SMC-R 协议栈共创建了 7 条 RDMA 链路,每条 RDMA 链路承载最多 32 条 SMC-R 连接。
+
+
+- 如查看各类统计信息:
+
+```
+[root@iZ2zee1mqxjh17ugngyg2bZ smc-tools]# smcr -dd stats
+SMC-R Connections Summary
+ Total connections handled 509
+SMC connections 509 (client 0, server 509)
+ v1 509
+ v2 0
+Handshake errors 0 (client 0, server 0)
+ Avg requests per SMC conn 1603405.0
+TCP fallback 0 (client 0, server 0)
+
+ RX Stats
+Data transmitted (Bytes) 17954924988 (17.95G)
+ Total requests 408066678
+Buffer full 0 (0.00%)
+ Buffer downgrades 0
+ Buffer reuses 308
+ 8KB 16KB 32KB 64KB 128KB 256KB 512KB >512KB
+ Bufs 0 0 0 0 0 509 0 0
+ Reqs 408.1M 0 0 0 0 0 0 0
+ TX Stats
+Data transmitted (Bytes) 70595498981 (70.60G)
+ Total requests 408066477
+ Buffer full 0 (0.00%)
+ Buffer full (remote) 0 (0.00%)
+ Buffer too small 0 (0.00%)
+Buffer too small (remote) 0 (0.00%)
+ Buffer downgrades 0
+ Buffer reuses 308
+ 8KB 16KB 32KB 64KB 128KB 256KB 512KB >512KB
+ Bufs 0 0 0 0 509 0 0 0
+ Reqs 408.1M 0 0 0 0 0 0 0
+
+ Extras
+ Special socket calls 508
+ cork 0
+ nodelay 508
+ sendpage 0
+ splice 0
+ urgent data 0
+```
+
+**2. 使用 smcss**
+
+- smcss 类似于 ss 工具,查看 smcss manual:
+
+```
+man smcss
+```
+
+- 查看当前所有的 SMC-R sockets 的详细信息:
+
+```
+[root ~]# smcss -R
+State UID Inode Local Address Peer Address Intf Mode Role IB-device Port Linkid GID Peer-GID
+ACTIVE 00000 0141987 192.168.99.21:33144 192.168.99.22:8090 0000 SMCR CLNT iwp0s7 01 01 0016:3e08:8b8b:0000:0000:0000:0000:0000 0016:3e10:3fb4:0000:0000:0000:0000:0000
+ACTIVE 00000 0141989 192.168.99.21:33148 192.168.99.22:8090 0000 SMCR CLNT iwp0s7 01 01 0016:3e08:8b8b:0000:0000:0000:0000:0000 0016:3e10:3fb4:0000:0000:0000:0000:0000
+ACTIVE 00000 0141991 192.168.99.21:33164 192.168.99.22:8090 0000 SMCR CLNT iwp0s7 01 01 0016:3e08:8b8b:0000:0000:0000:0000:0000 0016:3e10:3fb4:0000:0000:0000:0000:0000
+ACTIVE 00000 0141993 192.168.99.21:33168 192.168.99.22:8090 0000 SMCR CLNT iwp0s7 01 01 0016:3e08:8b8b:0000:0000:0000:0000:0000 0016:3e10:3fb4:0000:0000:0000:0000:0000
+ACTIVE 00000 0141995 192.168.99.21:33174 192.168.99.22:8090 0000 SMCR CLNT iwp0s7 01 01 0016:3e08:8b8b:0000:0000:0000:0000:0000 0016:3e10:3fb4:0000:0000:0000:0000:0000
+ACTIVE 00000 0141997 192.168.99.21:33178 192.168.99.22:8090 0000 SMCR CLNT iwp0s7 01 01 0016:3e08:8b8b:0000:0000:0000:0000:0000 0016:3e10:3fb4:0000:0000:0000:0000:0000
+```
+
+- 特别的,当 SMC-R 协议协商失败安全回退到 TCP 时,也可以通过 smcss 观察到:
+
+```
+[root@iZ2zee1mqxjh17ugngyg2aZ ~]# smcss -a
+State UID Inode Local Address Peer Address Intf Mode
+ACTIVE 00000 0156721 192.168.99.21:60188 192.168.99.22:8090 0000 TCP 0x03010000
+ACTIVE 00000 0156723 192.168.99.21:60194 192.168.99.22:8090 0000 TCP 0x03010000
+ACTIVE 00000 0156725 192.168.99.21:60204 192.168.99.22:8090 0000 TCP 0x03010000
+ACTIVE 00000 0156727 192.168.99.21:60206 192.168.99.22:8090 0000 TCP 0x03010000
+ACTIVE 00000 0156729 192.168.99.21:60214 192.168.99.22:8090 0000 TCP 0x03010000
+```
+
+最后一列的 0x03010000 是回退原因代码。回退原因代码含义如下:
+
+```
+#define SMC_CLC_DECL_MEM 0x01010000 /* insufficient memory resources */
+#define SMC_CLC_DECL_TIMEOUT_CL 0x02010000 /* timeout w4 QP confirm link */
+#define SMC_CLC_DECL_TIMEOUT_AL 0x02020000 /* timeout w4 QP add link */
+#define SMC_CLC_DECL_CNFERR 0x03000000 /* configuration error */
+#define SMC_CLC_DECL_PEERNOSMC 0x03010000 /* peer did not indicate SMC */
+#define SMC_CLC_DECL_IPSEC 0x03020000 /* IPsec usage */
+#define SMC_CLC_DECL_NOSMCDEV 0x03030000 /* no SMC device found (R or D) */
+#define SMC_CLC_DECL_NOSMCDDEV 0x03030001 /* no SMC-D device found */
+#define SMC_CLC_DECL_NOSMCRDEV 0x03030002 /* no SMC-R device found */
+#define SMC_CLC_DECL_NOISM2SUPP 0x03030003 /* hardware has no ISMv2 support */
+#define SMC_CLC_DECL_NOV2EXT 0x03030004 /* peer sent no clc v2 extension */
+#define SMC_CLC_DECL_NOV2DEXT 0x03030005 /* peer sent no clc SMC-Dv2 ext. */
+#define SMC_CLC_DECL_NOSEID 0x03030006 /* peer sent no SEID */
+#define SMC_CLC_DECL_NOSMCD2DEV 0x03030007 /* no SMC-Dv2 device found */
+#define SMC_CLC_DECL_NOUEID 0x03030008 /* peer sent no UEID */
+#define SMC_CLC_DECL_MODEUNSUPP 0x03040000 /* smc modes do not match (R or D)*/
+#define SMC_CLC_DECL_RMBE_EC 0x03050000 /* peer has eyecatcher in RMBE */
+#define SMC_CLC_DECL_OPTUNSUPP 0x03060000 /* fastopen sockopt not supported */
+#define SMC_CLC_DECL_DIFFPREFIX 0x03070000 /* IP prefix / subnet mismatch */
+#define SMC_CLC_DECL_GETVLANERR 0x03080000 /* err to get vlan id of ip device*/
+#define SMC_CLC_DECL_ISMVLANERR 0x03090000 /* err to reg vlan id on ism dev */
+#define SMC_CLC_DECL_NOACTLINK 0x030a0000 /* no active smc-r link in lgr */
+#define SMC_CLC_DECL_NOSRVLINK 0x030b0000 /* SMC-R link from srv not found */
+#define SMC_CLC_DECL_VERSMISMAT 0x030c0000 /* SMC version mismatch */
+#define SMC_CLC_DECL_MAX_DMB 0x030d0000 /* SMC-D DMB limit exceeded */
+#define SMC_CLC_DECL_NOROUTE 0x030e0000 /* SMC-Rv2 conn. no route to peer */
+#define SMC_CLC_DECL_NOINDIRECT 0x030f0000 /* SMC-Rv2 conn. indirect mismatch*/
+#define SMC_CLC_DECL_SYNCERR 0x04000000 /* synchronization error */
+#define SMC_CLC_DECL_PEERDECL 0x05000000 /* peer declined during handshake */
+#define SMC_CLC_DECL_INTERR 0x09990000 /* internal error */
+#define SMC_CLC_DECL_ERR_RTOK 0x09990001 /* rtoken handling failed */
+#define SMC_CLC_DECL_ERR_RDYLNK 0x09990002 /* ib ready link failed */
+#define SMC_CLC_DECL_ERR_REGBUF 0x09990003 /* reg rdma bufs failed */
+#define SMC_CLC_DECL_CREDITSERR 0x09990004 /* announce credits failed */
+```
diff --git "a/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/5_\346\234\200\344\275\263\345\256\236\350\267\265-\344\275\277\347\224\250SMC\345\222\214ERI\351\200\217\346\230\216\345\212\240\351\200\237Redis\345\272\224\347\224\250.md" "b/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/5_\346\234\200\344\275\263\345\256\236\350\267\265-\344\275\277\347\224\250SMC\345\222\214ERI\351\200\217\346\230\216\345\212\240\351\200\237Redis\345\272\224\347\224\250.md"
new file mode 100644
index 0000000000000000000000000000000000000000..dce39d40739c4c364085a01f9318fb50d0c83224
--- /dev/null
+++ "b/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/5_\346\234\200\344\275\263\345\256\236\350\267\265-\344\275\277\347\224\250SMC\345\222\214ERI\351\200\217\346\230\216\345\212\240\351\200\237Redis\345\272\224\347\224\250.md"
@@ -0,0 +1,160 @@
+通过本文您可以了解:如何使用 Alibaba Cloud Linux 3 操作系统提供的 SMC 高性能网络协议栈和阿里云 ERI 技术,透明加速 Redis 和应用客户端,无需修改运行环境和重新编译应用,即可获得性能提升。
+
+# 背景
+
+Redis 是一款开源的高性能内存存储,广泛运用在数据库、缓存、流计算和消息网关等场景。Redis 一大优势是提供极高的读取和写入性能,此时网络时延对于端到端的性能影响将会成倍放大。翻阅 Redis 官方文档,多次提到网络时延和带宽对于性能的影响[1][2],因此我们需要解决 Redis 默认协议栈 TCP 的性能瓶颈,降低时延和 CPU 资源消耗,进而提升性能。
+同时,Redis 社区版本尚未提供高性能网络的解决方案,在早期业务和团队规模相对较小的情况下,开发和运维一套非社区的高性能 Redis 方案的成本将会异常昂贵。并且应用访问 Redis 服务所使用的 SDK 千差万别,难以做到统一适配、维护和升级,也极大提高了接入和迁移成本。
+Alibaba Cloud Linux 3 提供了基于阿里云弹性 RDMA (ERI) 的高性能网络解决方案 SMC。SMC 兼具 DPU 卸载 RDMA 协议栈的高性能和传统 TCP 协议栈的通用性,透明替换 TCP 应用的同时,性能得到显著提升,此时应用无需任何侵入性的改造或者重新编译。
+
+# 实现方案
+
+借助阿里云 ERI 网卡和 Alibaba Cloud Linux 3 操作系统的 SMC 高性能网络协议栈,可以实现代码、环境无侵入替换 Redis 和应用。SMC 通过在内核选择性地替换 Redis 和应用的 TCP socket 链接,透明地使用 RDMA 加速传统 TCP/IP,因此我们需要准备以下环境:
+
+- ECS 使用 Alibaba Linux 3 操作系统[3];
+- ECS 启用“弹性 RDMA 接口”,确保 ECS 中有至少一张 ERI[4];
+
+## ECS 环境配置
+
+1. 创建 ECS 时,在“基础配置”页面选择最新的 Alibaba Cloud Linux 3 镜像[5],此时操作系统将默认包含 SMC 高性能网络协议栈。
+
+
+
+接下来在“网络和安全组”页面,弹性网卡中勾选“弹性 RDMA 接口”。
+
+
+
+对于已经创建的 ECS,可以选择升级到 Alibaba Cloud Linux 3 内核,或者确保数据已经安全备份的情况下更换操作系统[6]。同时添加辅助网卡并启用 ERI 能力[7]。
+
+2. ECS 启动成功后,执行下面命令验证是否包含 SMC 模块:
+
+```
+modinfo smc
+```
+
+如果命令有返回且有具体的内核模块 ko(输出结果的版本、签名等信息不一定完全相同),则说明具备 SMC 高性能网络协议栈。
+
+```
+filename: /lib/modules/5.10.134-12.al8.aarch64/kernel/net/smc/smc.ko
+alias: tcp-ulp-smc
+alias: smc
+alias: net-pf-43
+license: GPL
+description: smc socket address family
+author: Ursula Braun
+srcversion: C36162B1FA971B0FBCA3CEC
+depends: ib_core
+intree: Y
+name: smc
+vermagic: 5.10.134-12.al8.aarch64 SMP mod_unload modversions aarch64
+sig_id: PKCS#7
+signer: Aliyun Linux Driver update signing key
+sig_key: 6B:9A:30:96:2D:8A:02:77:86:25:B9:48:3D:F8:5C:D7:00:C0:91:34
+sig_hashalgo: sha256
+signature: 2B:93:6D:6D:97:86:9C:C0:33:09:FF:5A:06:18:D2:15:A1:1B:8B:85:
+B0:9B:D6:89:2D:3B:14:7F:15:7F:28:18:0F:62:88:A9:C4:74:09:96:
+F0:40:4A:65:65:10:D2:0A:61:E8:80:18:38:CA:BB:66:A2:D6:4F:03:
+31:13:86:9B:C2:0A:4D:84:77:C1:31:64:B8:F0:30:34:7A:7F:E8:5A:
+AB:6E:F6:2D:3F:06:38:BD:4C:F3:A5:FA:8F:30:C4:D9:A8:B1:BF:72:
+68:95:B7:35:C6:94:EF:D8:75:0D:90:34:00:B6:A4:44:F8:BD:47:84:
+53:FD:B0:88:ED:06:A2:AA:E4:2C:88:CC:8D:9B:D0:F6:D6:6E:EE:8B:
+6C:EA:53:B8:B0:85:C2:0B:0F:80:C9:82:76:48:49:40:AB:12:37:59:
+32:5A:8E:1A:DF:43:15:E4:09:6D:67:05:6A:F9:45:72:5D:38:4F:BF:
+47:A2:23:A1:90:A0:D5:36:B5:38:70:6B:52:C6:66:2B:4B:37:F5:6E:
+27:36:98:45:80:8D:89:9F:DB:4E:CD:2F:36:90:ED:6A:0B:56:30:CB:
+31:A9:F7:D2:D6:7D:9A:4C:81:00:6C:14:00:95:A1:8F:9F:41:3F:52:
+7E:A5:EC:9A:8E:5E:CE:DD:2B:C7:8E:A2:D9:67:27:64
+```
+
+此时执行下面命令,加载 SMC 内核模块:
+
+```
+modprobe smc
+```
+
+3. 加载 ERI 驱动[7],执行下面命令:
+
+```
+modprobe erdma
+```
+
+执行下面命令,如果命令有包含“erdma”字符串的返回则说明 ERDMA 驱动加载成功:
+
+```
+lsmod | grep erdma
+```
+
+返回结果,第二个值不一定完全相同。
+
+```
+erdma 98304 0
+```
+
+4. 使用 SMC 透明加速 Redis 需要使用 smc-tools 工具,执行下面命令获取并安装工具包。
+
+```
+sudo yum install smc-tools
+```
+
+执行下面的命令,验证工具安装成功,同时检查 ERI 是否正确注册到 SMC:
+
+```
+smcr d
+```
+
+如果返回值如下(设备名不一定完全相同),则说明 ERI 网卡已被成功注册:
+
+```
+Net-Dev IB-Dev IB-P IB-State Type Crit #Links PNET-ID
+eth0 iwp4s0 1 ACTIVE 0x107f No 0
+```
+
+执行完上述命令和检查之后,ERI 和 SMC 已经顺利加载到内核,并具备加速应用的能力。
+
+## 透明加速 Redis
+
+为了简化测试,我们使用 smc-tools 提供的 smc_run 快速透明替换 Redis 应用,更加详细的使用说明请参考使用文档[8]。
+启动 Redis 并使用 SMC 加速 TCP,执行下面命令将直接启动 Redis(此处省略详细的 Redis 配置参数):
+
+```
+smc_run redis-server # 原始启动命令为 redis-server,只需在命令头部加入 smc_run 前缀即可
+```
+
+如果 Redis 通过脚本启动,则可以使用 smc_run 直接启动脚本,SMC 加速效果将会覆盖子进程。
+
+## 透明加速应用
+
+使用 SMC 加速应用和上面 Redis 类似,我们可以使用 smc_run 快速透明替换应用的 TCP 连接,如需更复杂的替换规则(选择满足特定条件的 TCP 连接),请参考使用文档[8]。
+启动应用(此处以 redis-benchmark 为例),执行下面命令将直接启动应用:
+
+```
+smc_run redis-benchmark -h 11.213.45.34 --threads 4 -n 100000 -c 200 -d 10
+```
+
+如果通过脚本启动应用,则可以是用 smc_run 直接启动脚本,同上。
+
+## 性能收益
+
+通过 smc_run 命令分别启动 Redis 和应用后,二者间通信的 TCP 连接将会被替换为 SMC,应用访问不支持 SMC 协议的链接将会被回退为 TCP,不影响应用访问其他服务。
+此处以 redis-benchmark 结果为例,详细结果请参考性能测试[9]文档。
+
+
+
+
+
+从测试结果可以看出,无论是 GET 测试还是 SET 测试,SMC 相对于 TCP 带来了至少 40%+ 的性能测试数据提升。
+
+# 总结
+
+使用 SMC 高性能网络协议栈和阿里云弹性 RDMA 网卡,可以透明加速应用访问 Redis 的性能,满足应用对于高性能场景的需求,同时无需应用修改代码即可享受技术红利。
+
+# 引用
+
+[1] https://redis.io/docs/management/optimization/latency/#latency-induced-by-network-and-communication
+[2] https://redis.io/docs/management/optimization/benchmarks/#factors-impacting-redis-performance
+[3] https://help.aliyun.com/document_detail/111881.htm?spm=a2c4g.11186623.0.0.17e88778WwUw9r#concept-rgv-rvd-2hb
+[4] https://help.aliyun.com/document_detail/336853.html?spm=a2c4g.11186623.0.0.6e244762X1zZKA
+[5] https://help.aliyun.com/document_detail/212634.html
+[6] https://help.aliyun.com/document_detail/25436.html
+[7] https://help.aliyun.com/document_detail/336853.html
+[8]
+[9]
diff --git "a/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/6_QA.md" "b/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/6_QA.md"
new file mode 100644
index 0000000000000000000000000000000000000000..09b61540d3159f4848a0d7bf3f6bfc5e6e9f207b
--- /dev/null
+++ "b/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/6_QA.md"
@@ -0,0 +1,26 @@
+# 常见问题汇总
+
+## SMC-R 导致端口不通
+
+**Q**: 开启 SMC-R 后访问部分端口出现不通的情况
+
+**A**:
+- 解决方法
+
+载入 SMC 模块(modprobe smc),并将执行 sysctl net.smc.sysctl_smc_experiments=1 命令,将该配置打开。如需持久化该配置,可以添加到 /etc/sysctl.conf 中;
+重新发起新的 SMC 链接后将不会出现此问题。
+
+- 问题原因
+
+某些服务在处理 TCP options 时,例如网关或者反向代理服务器,会将请求的 TCP options 重放,此时 SMC 通过 TCP 握手时所携带的 TCP options 将会被重放,SMC client 将会误认为对端 server 支持 SMC 能力导致例如 curl 请求失败,但是 ping(ICMP 协议)正常。打开上述 sysctl 将会使用不同的 TCP options 解决 TCP options 重放问题。该问题经过我们验证互联网中的服务,仅存在极少数服务中,绝大多数可以正常建连。
+
+
+## SMC-R 导致部分端口不可用,返回 EADDRINUSE 错误
+
+**Q**: 加载 SMC-R 后 33800 后的 16 个端口不可用,返回 EADDRINUSE 错误
+
+**A**:
+
+- 问题原因
+
+由于 SMC-R + eRDMA 实现方式的特殊性,SMC-R 模块将会占用 ERI 所在 net namespace 下 33800 开始的 16 个端口作为 OOB 建连的预留端口,若端口占用失败则 SMC 模块加载失败。SMC 模块卸载后将会释放这些端口。
diff --git "a/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/README.md" "b/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/README.md"
new file mode 100644
index 0000000000000000000000000000000000000000..bb97a1a5129ef159d329497e98c12a95136ddd10
--- /dev/null
+++ "b/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/README.md"
@@ -0,0 +1,37 @@
+# 背景
+
+共享内存通信(Shared Memory Communication,SMC)是一种兼容 socket 层,利用共享内存操作实现高性能通信的内核网络协议栈。当共享内存通信基于远程内存直接访问(Remote Direct Memory Access,RDMA)技术实现时,称为 SMC over RDMA(SMC-R)。
+
+SMC-R 兼容 socket 接口的特点使 TCP 应用程序无需任何改造即可运行在 SMC 协议栈上;底层使用的 RDMA 网络使 SMC 拥有相较于 TCP 更好的网络性能。SMC 协议栈通过 TCP 连接自主发现对侧 SMC 能力,协商成功后使用 SMC 协议栈承载应用数据流量;协商失败则安全回退至 TCP/IP 协议栈,保证数据正常传输。
+
+阿里云 Alibaba Cloud Linux 3 操作系统基于阿里云弹性 RDMA(elastic RDMA, eRDMA)技术首次将 SMC-R 带入云上场景,实现云上 TCP 协议栈的透明无损替换,为数据库、RPC、批量数据传输等场景提供相比 TCP 更好的网络性能。相较于上游 Linux SMC-R 实现,Alibaba Cloud Linux 3 中的 SMC-R 更适配阿里云 eRDMA 技术、拥有更好的性能、可靠的稳定性、丰富成熟的透明替换方案和及时的更新维护。
+
+
+
+# 组织原则
+
+共赢、平等、开源
+
+# 目标愿景
+
+- 探索 SMC 更多可能性, 推进 SMC 在更多场景下的实现与落地
+- 促进技术交流
+- 提供技术帮助
+- 为各个伙伴提供需求输入
+- 同步各个伙伴的开发进展
+- 促进各个伙伴之间的合作
+
+# 组织形式
+
+- 定期收集参与伙伴的 topic。有 topic 的情况下, 会召开开放性会议。日常 SMC 相关讨论将以周会形式召开,会议纪要将公开并存档。
+- 通过邮件及钉钉群的方式申报交流议题
+- 开放性会议将以云会议的方式,会议开始一天前会将会议 ID 以及议题汇总发送到 SIG 相关邮件列表和钉钉群
+- 议结束后纪要通过邮件列表发出,并在 SIG 中归档
+
+# 邮件列表
+
+netdev@lists.openanolis.cn
+
+# 联系
+
+邮件列表或钉钉群: 34264214
diff --git "a/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/\351\276\231\350\234\245\344\270\273\347\253\231\351\246\226\351\241\265.link" "b/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/\351\276\231\350\234\245\344\270\273\347\253\231\351\246\226\351\241\265.link"
new file mode 100644
index 0000000000000000000000000000000000000000..33dce3fdda5eb9dd740517631d959d2312dcf7d3
--- /dev/null
+++ "b/sig/AI/content/SMC/\344\272\214\347\272\247\347\233\256\345\275\225/\351\276\231\350\234\245\344\270\273\347\253\231\351\246\226\351\241\265.link"
@@ -0,0 +1 @@
+https://openanolis.cn/
\ No newline at end of file
diff --git "a/sig/AI/content/ToneAgent\347\274\226\350\257\221\346\211\223\345\214\205\346\211\213\345\206\214.md" "b/sig/AI/content/ToneAgent\347\274\226\350\257\221\346\211\223\345\214\205\346\211\213\345\206\214.md"
new file mode 100644
index 0000000000000000000000000000000000000000..0949b8e70e5300f1cf752ca0259c1d30317b932b
--- /dev/null
+++ "b/sig/AI/content/ToneAgent\347\274\226\350\257\221\346\211\223\345\214\205\346\211\213\345\206\214.md"
@@ -0,0 +1,63 @@
+# 1. ToneAgent编译
+
+## 1.1 环境准备
+Go 1.17 及以上版本([下载地址](https://go.dev/dl/))
+
+## 1.2 下载ToneAgent
+ git clone git@gitee.com:anolis/tone-agent.git
+ cd tone-agent
+
+## 1.3 编译
+`-o` 后面是二进制的名称
+
+### 1.3.1 编译 AMD64的二进制
+ GOOS=linux GOARCH=amd64 go build -o toneagent-amd64-v102
+
+### 1.3.2 编译 ARM 的二进制
+ GOOS=linux GOARCH=arm64 go build -o toneagent-amd64-v102
+
+# 2. Linux环境二进制打包
+
+## 2.1 RPM包制作
+
+### 2.1.1 RPM环境准备
+ sudo su -c bash # 使用bash
+ yum install rpmdevtools rpmdevtools # 安装rpm打包工具
+
+### 2.1.2 打包RPM包
+ rpmdev-setuptree # 创建目录,会在用户目录下创建rpmbuild文件夹 ~/rpmbuild
+ cd # 返回用户目录
+ vi rpmbuild/SPEC/toneagent.spec # 修改创建spec的模板文件
+ mkdir rpmbuild/BUILDROOT/toneagent-0.0.1-AMD
+ cp ${二进制路径} rpmbuild/BUILDROOT/toneagent-0.0.1-AMD/ # 拷贝二进制到RPM目录
+ cd rpmbuild/SPEC/
+ rpmbuild -bb toneagent.spec # 构建rpm包
+
+### 2.1.3 RPM安装及启动
+ sudo yum -y install ${toneagent包位置} # 安装
+ sudo systemctl start toneagent # 启动
+
+## 2.2 DEB包制作
+
+### 2.1.1 环境准备
+ sudo apt instsll -y dpkg # 使用二进制打包,只需要安装这个包
+ sudo apt install -y dpkg build-essential devscripts quilt dh-make git # 扩展安装
+
+### 2.1.2 打包DEB包
+ mkdir toneagent.work
+ cd toneagent.work
+ mkdir -pv toneagent_0.0.1_amd64/{DEBIAN,bin}
+ cp ${tone-agent二进制} toneagent_0.0.1_amd64/bin/
+ echo "Package: toneagent
+ Version: 1.0
+ Architecture: arm
+ Maintainer: alibaba
+ Installed-Size: 100
+ Depends:
+ Priority: optional
+ Description: toneagent for SUNXI devices (A10,A20 ...),example is Cubieboard.
+ " >> toneagent_0.0.1_amd64/DEBIAN/control
+ dpkg -b toneagent_0.0.1_amd64 toneagent_0.0.1_amd64.deb
+
+### 2.1.3 DEB安装
+ dpkg -i toneagent_0.0.1_amd64.deb
diff --git "a/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/...Ftrace\357\274\232_osnoise_\346\200\273\350\247\210.md" "b/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/...Ftrace\357\274\232_osnoise_\346\200\273\350\247\210.md"
new file mode 100644
index 0000000000000000000000000000000000000000..782c9a33160ade07820bfa6300aa0fd6cc5779c9
--- /dev/null
+++ "b/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/...Ftrace\357\274\232_osnoise_\346\200\273\350\247\210.md"
@@ -0,0 +1,179 @@
+
+
+
+# Ftrace: osnoise 总览
+
+
+
+
+
+
+
+
+
+
+
+## 一、osnoise是什么?
+
+
+
+
+在linux系统中,一个普通线程在执行过程中会被各种各样的事件所干扰打断,如NMI、IRQ、SOFTIRQ、来自硬件的干扰以及来自其他线程的干扰。这些事件对于一个普通线程来说,就相当于噪声一样的存在。在Linux 5.14-rc1中,引入了一个新的tracer——osnoise tracer。osnoise从一个线程的视角出发,统计出所有对他有干扰的噪声,进而协助开发人员分析系统背景噪声情况。
+
+
+### 1.1 噪声分类
+
+
+在osnoise tracer中,将统计的噪声分为了以下五个大类:
+
+
++ IRQ:硬中断
++ SOFTIRQ:软中断
++ NMI:不可屏蔽中断
++ HW:来自硬件的噪声。
++ THREAD:来自其他线程的影响。
+
+
+其中,HW(hardware latency)表示某些底层硬件或者固件的行为引起的大型系统延迟。在Ftrace中,有一个名为hwlat\_detector的tracer,它的主要目的就是用来检测硬件噪声。osnoise的设计思想借鉴了hwlat\_detector。
+
+
+### 1.2 hwlat
+
+
+hwlat\_detector的工作原理简单来说就是在一段时间内,关闭irq、softirq以及抢占,然后不断的去轮询TSC(Time Stamp Counter)寄存器的值。由于关闭了中断及抢占,任意两次读取之间的间隙都是由于硬件噪声或者来自其他不可屏蔽中断的噪声(NMI)。
+
+
+如图所示:
+
+
+
+
+
+在一段时间内,采样线程不断的去循环读取TSC寄存器,在一个循环内会连续读取两次TSC寄存器。假设本次循环读取的时间分别为t1、t2,上次循环读取的时间为last\_t1、last\_t2。则:
+
+
++ t1与t2的时间之差,last\_t1、last\_t2的时间之差,称为inner\_latency。
++ t1与last\_t2的时间之差,称为outer\_latency。
++ tracing\_thresh为预设的阀值,如果观察到任何超过阀值的延迟就认为发生了噪声事件。
++ 在hwlat中,会不断的计算inner\_latency和outer\_latency。然后将其值与预设的tracing\_thresh值进行对比,如果大于tracing\_thresh,就认为发生了噪声事件。
++ 在hwlat采样期间,会同时追踪nmi中断事件。因此,观察到的任何超过阀值的延迟如果不是nmi造成的,那么就认为是hardware latency。
+
+
+### 1.3 osnoise实现
+
+
+前面我们介绍了hwlat的实现。简而言之,hwlat关闭irq、softirq、抢占等事件,通过不断的轮询TSC寄存器以及追踪NMI中断来探测延迟事件,观察到的任何延迟都是由NMI或者硬件造成的。
+
+
+osnoise的实现思想和hwlat类似,不过osnoise不会关闭irq、softirq、抢占等事件,而是在采样的同时追踪各类事件。在irq\_handler\_entry、irq\_handler\_exit、softirq\_entry、softirq\_exit、sched\_switch、nmi\_enter、nmi\_exit处也插入相应的钩子函数。进而统计出各类事件发生的次数以及持续时间。如果观测到的任意延迟不是由以上时间造成的,那么就认为是硬件噪声。
+
+
+## 二、osnoise tracer
+
+
+### 2.1 配置文件
+
+
+osnoise在`/sys/kernel/debug/tracing/` 目录下有一系列可配置文件, 含义如下:
+
+
+* **osnoise/cpus:** osnoise采样的目标cpu,默认是所有cpu。
+* **osnoise/period\_us:** osnoise线程的周期。默认是1000000ms,即1s。
+* **osnoise/runtime\_us:** osnoise线程在一个周期内的采样时间。默认是1000000ms,即1s。
+* **osnoise/stop\_tracing\_us:** 当单个噪声的最大值超过这个阀值时,停止采样。默认为0,即关闭该选项。
+* **osnoise/stop\_tracing\_total\_us:** 当总计噪声超过这个阀值时,停止采样。默认为0,即关闭该选项。
+* **tracing\_thresh**: 两次轮询TSC寄存器时间之差,被认为是噪声的最小值,单位为us。当配置为0时,默认设为5us。
+
+
+### 2.2 使用方法
+
+
+1. 将osnoise写入的current\_tracer:
+
+
+`echo osnoise > /sys/kernel/debug/tracing/current_tracer`
+
+
+2. 打开traceing\_on:
+
+
+`echo 1 > /sys/kernel/debug/tracing/tracing_on`
+
+
+3. 查看trace结果:
+
+
+`cat /sys/kernel/debug/tracing/trace`
+
+
+
+
+
+
+
+
+这里显示的是系统整体采样的结果各个字段的含义如下:
+
+
+* TASK-PID:采样线程的PID。
+* CPU:采样的CPU ID
+* TIMESTAMP:时间戳
+* RUNTIME IN US:采样时间,单位us
+* NOISE IN US:本次采样时间内的总计噪声时间,单位us。
+* %OF CPU AVAILABLE:在一个RUNTIME周期内,采样线程可以获得的cpu利用率。
+* HW、NMI、IRQ、SIRQ、THREAD:分别表示各类噪声事件发生的次数。
+
+
+## 三、osnoise trace\_point
+
+
+### 3.1 trace\_point
+
+
+osnoise除了提供tracer外,还提供了一组trace\_points,以协助开发人员对噪声进行进一步分析。可以在`/sys/kernel/debug/tracing/events/osnoise/`看到相关tracepoint:
+
+
+* **sample\_threshold:** 追踪任何高于阀值的噪声事件。阀值即为上文提到的tracing\_thresh,默认为5us。
+* **nmi\_noise:** nmi噪声,包含其持续时间。
+* **irq\_noise:** irq噪声,包含其持续时间。
+* **softirq\_noise:** softirq噪声,包含其持续时间
+* **thread\_noise:** 其他线程噪声,包含其持续时间
+
+
+### 3.2 使用方法
+
+
+前面我们已经介绍了osnoise tracer的使用,它可以让我们直观的看到整个系统级别的各种噪声事件的总和。如果我们像看到每种噪声或者是说指定噪声类型的事件的详细信息,就需要用到osnoise提供的trace\_point。
+
+
+打开trace\_point总开关:
+
+
+`echo 1 > /sys/kernel/debug/tracing/events/osnoise/enable`
+
+
+查看trace日志:
+
+
+`cat /sys/kernel/debug/tracing/trace`
+
+
+输出如下所示:
+
+
+
+
+
+
+日志中包含了所有噪声的详细信息,包括其名字,开始事件,持续时间等等。关于其输出的具体格式可以查看对应trace\_point文件夹下的format文件。
+
+
+trace\_ponit文件位置在`/sys/kernel/debug/tracing/events/osnoise/`下。
+
+
+除了总开关外,每个事件有自己单独的开关,在对应tracepoint目录下。如irq\_noise的开关为`/sys/kernel/debug/tracing/events/osnoise/irq_noise/enable`。用户可以根据自己的需求只追踪相应的事件,从而过滤掉其他不需要关注的信息。
+
+
+
+
+
diff --git "a/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/...Pstore\345\211\215\347\253\257DMESG_\344\273\243\347\240\201\345\210\206\346\236\220.md" "b/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/...Pstore\345\211\215\347\253\257DMESG_\344\273\243\347\240\201\345\210\206\346\236\220.md"
new file mode 100644
index 0000000000000000000000000000000000000000..8682851da2ed6e492c8fcc12c8ac2331a1712193
--- /dev/null
+++ "b/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/...Pstore\345\211\215\347\253\257DMESG_\344\273\243\347\240\201\345\210\206\346\236\220.md"
@@ -0,0 +1,211 @@
+
+
+
+作者:新绎
+
+
+
+## 写在前面
+
+
+pstore中提供了多种前端来实现捕获各种系统信息从而加以调试。这篇文章中,我们会对pstore其中之一的前端PSTORE\_DMESG进行分析,从原理上分析pstore如何获取当内核发生panic时kmsg信息。
+
+
+## Pstore注册kmsg\_dumper
+
+
+kmsg\_dumper结构体有两个重要成员:回调函数`dump()`以及相应的`kmsg_dump_reason`。通过对`dump()`进行实现,我们就可以将相应的log信息保存到我们希望保存的地方,并且可以通过`kmsg_dump_reason`来对需要保存的信息进行筛选。
+
+
+
+```
+//kmsg_dump.h
+/**
+* struct kmsg_dumper - kernel crash message dumper structure
+* @list: Entry in the dumper list (private)
+* @dump: Call into dumping code which will retrieve the data with
+* through the record iterator
+* @max_reason: filter for highest reason number that should be dumped
+* @registered: Flag that specifies if this is already registered
+*/
+struct kmsg_dumper {
+ struct list_head list;
+ void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason);
+ enum kmsg_dump_reason max_reason;
+ bool active;
+ bool registered;
+
+ /* private state of the kmsg iterator */
+ u32 cur_idx;
+ u32 next_idx;
+ u64 cur_seq;
+ u64 next_seq;
+};
+
+/*
+ * Keep this list arranged in rough order of priority. Anything listed after
+ * KMSG_DUMP_OOPS will not be logged by default unless printk.always_kmsg_dump
+ * is passed to the kernel.
+ */
+enum kmsg_dump_reason {
+ KMSG_DUMP_UNDEF,
+ KMSG_DUMP_PANIC,
+ KMSG_DUMP_OOPS,
+ KMSG_DUMP_EMERG,
+ KMSG_DUMP_RESTART,
+ KMSG_DUMP_HALT,
+ KMSG_DUMP_POWEROFF,
+};
+```
+
+
+我们可以看到,目前有7种定义的`kmsg\_dump\_reason`,而pstore则关心在系统出现panic时的log信息。在pstore的实现中,pstore通过`pstore\_cannot\_block\_path()`函数对相应的信息进行过滤。
+
+
+
+```
+//pstore_cannot_block_path()
+/*
+ * Should pstore_dump() wait for a concurrent pstore_dump()? If
+ * not, the current pstore_dump() will report a failure to dump
+ * and return.
+ */
+static bool pstore_cannot_block_path(enum kmsg_dump_reason reason)
+{
+ /* In NMI path, pstore shouldn't block regardless of reason. */
+ if (in_nmi())
+ return true;
+
+ switch (reason) {
+ /* In panic case, other cpus are stopped by smp_send_stop(). */
+ case KMSG_DUMP_PANIC:
+ /* Emergency restart shouldn't be blocked. */
+ case KMSG_DUMP_EMERG:
+ return true;
+ default:
+ return false;
+ }
+}
+```
+
+
+其中dmesg前端的主要工作就是为其实现一个`dump()`函数,该函数将从log buffer中读取log信息,然后将其封装为recored之后写入对应的后端设备,其主要定义如下:
+
+
+
+```
+//pstore_dump()
+static struct kmsg_dumper pstore_dumper = {
+ .dump = pstore_dump,
+}
+
+static void pstore_dump(struct kmsg_dumper *dumper,
+ enum kmsg_dump_reason reason)
+{
+ …
+ while (total < kmsg_bytes) {
+ …
+ pstore_record_init(&record, psinfo);
+ …
+ header_size = snprintf(dst, dst_size, "%s#%d Part%u\n", why,
+ oopscount, part);
+ dst_size -= header_size;
+
+ if (!kmsg_dump_get_buffer(&iter, true, dst + header_size,
+ dst_size, &dump_size))
+ break;
+
+ if (big_oops_buf) {
+ zipped_len = pstore_compress(dst, psinfo->buf,
+ header_size + dump_size,
+ psinfo->bufsize);
+ …
+ } else {
+ record.size = header_size + dump_size;
+ }
+
+ ret = psinfo->write(&record);
+ …
+ }
+ …
+}
+
+```
+
+
+## kmsg\_dump实现
+
+
+printk实现了一个`kmsg\_dump()`函数,用于方便其它模块dump内核的log buffer,当内核发生oops、panic或重启等事件时,都会调用该函数dump log信息。其代码实现如下:
+
+
+
+```
+void kmsg_dump(enum kmsg_dump_reason reason)
+{
+ …
+ list_for_each_entry_rcu(dumper, &dump_list, list) {
+ enum kmsg_dump_reason max_reason = dumper->max_reason;
+
+ if (max_reason == KMSG_DUMP_UNDEF) {
+ max_reason = always_kmsg_dump ? KMSG_DUMP_MAX :
+ KMSG_DUMP_OOPS;
+ }
+ if (reason > max_reason)
+ continue;
+
+ dumper->dump(dumper, reason);
+ }
+ rcu_read_unlock();
+}
+```
+
+
+使用`kmsg\_dump()`之前要先使用`kmsg\_dump\_register()`来注册一个dumper,用于实际的log写操作。
+
+
+我们先来看看`kmsg\_dump\_register`的定义,只定义了一个dump\_list,将系统中所有注册的dump都挂在同一个list下,这就说明系统可以注册多个dumper。
+
+
+
+```
+int kmsg_dump_register(struct kmsg_dumper *dumper)
+{
+ …
+ if (!dumper->registered) {
+ dumper->registered = 1;
+ list_add_tail_rcu(&dumper->list, &dump_list);
+ err = 0;
+ }
+ …
+}
+```
+
+
+## 总结
+
+
+pstore dmesg主要工作流程如下:
+
+
+(1)初始化一个record结构体
+
+
+(2)先向其写入pstore头信息,如dmesg reason、oops发生次数等
+
+
+(3)从log buffer中读取一行log信息
+
+
+(4)若需要压缩信息,则执行压缩操作
+
+
+(5)调用后端的写函数,将record写入相应的后端设备
+
+
+加点内容
+算22332
+
+
+
+
diff --git "a/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220.md" "b/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220.md"
new file mode 100644
index 0000000000000000000000000000000000000000..d8d8d5f7ea67371721d640d941991d8ea0ad4191
--- /dev/null
+++ "b/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220.md"
@@ -0,0 +1,641 @@
+
+
+
+前面一篇文章中,我们简要的介绍了一下osnoise的相关信息,本篇文章主要针对其源代码进行分析阐述。
+
+
+
+# 一、数据结构:
+
+
+
+```
+/*
+ * NMI runtime info.
+ */
+struct osn_nmi {
+ u64 count;
+ u64 delta_start;
+};
+
+/*
+ * IRQ runtime info.
+ */
+struct osn_irq {
+ u64 count;
+ u64 arrival_time;
+ u64 delta_start;
+};
+
+#define IRQ_CONTEXT 0
+#define THREAD_CONTEXT 1
+/*
+ * sofirq runtime info.
+ */
+struct osn_softirq {
+ u64 count;
+ u64 arrival_time;
+ u64 delta_start;
+};
+
+/*
+ * thread runtime info.
+ */
+struct osn_thread {
+ u64 count;
+ u64 arrival_time;
+ u64 delta_start;
+};
+
+/*
+ * Runtime information: this structure saves the runtime information used by
+ * one sampling thread.
+ */
+struct osnoise_variables {
+ struct task_struct *kthread;
+ bool sampling;
+ pid_t pid;
+ struct osn_nmi nmi;
+ struct osn_irq irq;
+ struct osn_softirq softirq;
+ struct osn_thread thread;
+ local_t int_counter;
+};
+```
+
+
+osnoise用来记录结果的主要数据结构为`struct osnoise_variables`其中:
+
+
++ `struct task_struct *kthread`:采样线程的tcb。
++ `bool sampling`:采样开关
++ `pit_t pid`:采样线程的pid
++ `struct osn_nmi nmi`:保存nmi噪声的相关信息
++ `struct osn_irq irq`:保存irq噪声的相关信息
++ `struct osn_softiq softirq`:保存softirq噪声的相关信息
++ `struct osn_thread thread`:保存其他线程噪声的相关信息
++ `local_t int_counter`:保存噪声的总次数
+
+
+
+# 二、工作原理:
+
+
+## 2.1 注册trace\_point
+
+
+如第一篇文章所述,osnoise引入了一组trace\_point。通过这些trace\_point,开发人员可以获取噪声的详细信息。注册trace\_point的代码如下(以irq\_noise为例):
+
+
+
+```
+TRACE_EVENT(irq_noise,
+
+ TP_PROTO(int vector, const char *desc, u64 start, u64 duration),
+
+ TP_ARGS(vector, desc, start, duration),
+
+ TP_STRUCT__entry(
+ __field( u64, start )
+ __field( u64, duration)
+ __string( desc, desc )
+ __field( int, vector )
+
+ ),
+
+ TP_fast_assign(
+ __assign_str(desc, desc);
+ __entry->vector = vector;
+ __entry->start = start;
+ __entry->duration = duration;
+ ),
+
+ TP_printk("%s:%d start %llu.%09u duration %llu ns",
+ __get_str(desc),
+ __entry->vector,
+ __print_ns_to_secs(__entry->start),
+ __print_ns_without_secs(__entry->start),
+ __entry->duration)
+);
+```
+
+
+关于trace\_point这里我们不做过多介绍,感兴趣的读者可以去内核文件`include/trace/events/osnoise.h`下查看相应源代码。
+
+
+## 2.2 注册osnoise tracer
+
+
+这部分主要是涉及到osnoise的初始化过程,该过程主要就是将osnoise注册近ftrace中并且初始化相关的tracefs。注册的过程通过`register_tracer(&osnoise_tracer)`实现。
+
+
+
+```
+static struct tracer osnoise_tracer __read_mostly = {
+ .name = "osnoise",
+ .init = osnoise_tracer_init,
+ .reset = osnoise_tracer_reset,
+ .start = osnoise_tracer_start,
+ .stop = osnoise_tracer_stop,
+ .print_header = print_osnoise_headers,
+ .allow_instances = true,
+};
+```
+
+
+## 2.3 注册tracepoint钩子函数:
+
+
+osnoise 统计信息的方式就是通过在相应的tracepoint中注册钩子函数。因此这部分即是osnoise的核心部分,本篇文章将重点分析该模块。
+
+
+osnoise首先会将各种事件的钩子函数插入对应的tracepoint中,这一动作由`osnoise_hook_events()`函数执行,将该函数裁剪后如下:
+
+
+
+```
+static int osnoise_hook_events(void)
+{
+ ...
+ retval = hook_irq_events();
+ ...
+ retval = hook_softirq_events();
+ ...
+ retval = hook_thread_events();
+ ...
+}
+```
+
+
+该函数主要是针对irq、softirq、thread事件插入一些采样函数。
+
+
+### hook\_irq\_events
+
+
+hook\_irq\_events()主要是实现对irq事件的统计。如下:
+
+
+
+```
+static int hook_irq_events(void)
+{
+ ...
+ ret = register_trace_irq_handler_entry(trace_irqentry_callback, NULL);
+ ...
+ ret = register_trace_irq_handler_exit(trace_irqexit_callback, NULL);
+ ...
+}
+```
+
+
+主要是在irq\_handler\_entry 和 irq\_handler\_exit处插入相应的处理函数。最终插入的处理函数为osnoise\_trace\_irq\_entry() 和 osnoise\_trace\_irq\_exit()。
+
+
+
+```
+void osnoise_trace_irq_entry(int id)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+
+ if (!osn_var->sampling)
+ return;
+
+ osn_var->irq.arrival_time = time_get();
+ set_int_safe_time(osn_var, &osn_var->irq.delta_start);
+ osn_var->irq.count++;
+
+ local_inc(&osn_var->int_counter);
+}
+void osnoise_trace_irq_exit(int id, const char *desc)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+ int duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ duration = get_int_safe_duration(osn_var, &osn_var->irq.delta_start);
+ trace_irq_noise(id, desc, osn_var->irq.arrival_time, duration);
+ osn_var->irq.arrival_time = 0;
+ cond_move_softirq_delta_start(osn_var, duration);
+ cond_move_thread_delta_start(osn_var, duration);
+}
+```
+
+
+在irq handler的入口处插入的函数为osnoise\_trace\_irq\_entry,分析该函数:
+
+
++ 在irq.arrival\_time中记录本次irq事件的开始时间。
++ 在irq.delta\_start中记录本次irq事件的准确开始时间。
++ irq噪声事件的次数+1。
++ 噪声事件总体次数+1。
+
+
+在这里我们发现,除了在irq.arrival\_time中记录了一个irq开始时间之外,还通过set\_int\_safe\_time函数在 irq.delta\_start中都记录了一个开始时间。那么他们之间有什么区别呢?在这里我们先按下不表,后文会对其进行解释分析。
+
+
+在irq handler的出口处插入的函数为osnoise\_trace\_irq\_exit,该函数的主要作用:
+
+
++ 根据之前记录的osn\_var->irq.delta\_start计算出本次irq事件的持续时间。
++ 调用trace\_irq\_noise将本次irq事件的**中断号,中断名称、开始时间、持续时间**放到ftrace的ringbuffer中。
++ 清空osn\_var->irq.arrival\_time 表示此次irq事件结束。
+
+
+我们注意到在该函数的末尾处有cond\_move\_softirq\_delta\_start 以及 cond\_move\_thread\_delta\_start函数。其实形如此类的函数一共有三个:
+
+
++ cond\_move\_irq\_delta\_start
++ cond\_move\_softirq\_delta\_start
++ cond\_move\_thread\_delta\_start
+
+
+函数的形式都是一样的,我们以 cond\_move\_softirq\_delta\_start()为例:
+
+
+
+```
+static inline void
+cond_move_softirq_delta_start(struct osnoise_variables *osn_var, u64 duration)
+{
+ if (osn_var->softirq.delta_start)
+ osn_var->softirq.delta_start += duration;
+}
+```
+
+
++ 这个函数会在osnoise\_trace\_irq\_exit、trace\_osnoise\_callback中调用,前者我们知道是irq事件退出时的钩子函数,而后者则是nmi事件的钩子函数。
++ 可以看到该函数的主要功能是将softirq.delta\_start的开始时间推后一个duration。
+
+
+换句话说,这个函数是为了校准低优先级事件的开始时间。以下图为例:
+
+
++ 在t1时刻进入了softirq,此时记录**softirq.arrival\_time = t1**,**softirq.delta\_time = t1**。
++ 然后在t2时刻,来了一个irq抢占了softirq,进入irq的执行函数。
++ t3时刻离开irq执行完毕继续执行softirq。irq执行时间**duration = t3-t2**。同时调用cond\_move\_softirq\_delta\_start,更新softirq开始时间**softirq.delta\_start += duration;**
++ 在t4时刻softirq执行完毕退出。
+
+
+那么本次softirq的持续时间实际上应该是t4 - (t1 + duration) = t4 - **softirq.delta\_start。**
+
+
+
+
+因此,需要高优先级的对低优先级的事件的时间进行校准。
+
+
++ 对于nmi事件,需要调用
+
+
+- cond\_move\_irq\_delta\_start
+- cond\_move\_softirq\_delta\_start
+- cond\_move\_thread\_delta\_start
+
+
++ 对于irq事件,需要调用
+
+
+- cond\_move\_softirq\_delta\_start
+- cond\_move\_thread\_delta\_start
+
+
++ 对于softirq事件,需要调用
+
+
+- cond\_move\_thread\_delta\_start
+
+
+### hook\_softirq\_events
+
+
+与irq的钩子函数一样,需要注册tracepoint softirq\_entry、softirq\_exit的钩子函数。最终注册的钩子函数如下:
+
+
+
+```
+static void trace_softirq_entry_callback(void *data, unsigned int vec_nr)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+
+ if (!osn_var->sampling)
+ return;
+
+ osn_var->softirq.arrival_time = time_get();
+ set_int_safe_time(osn_var, &osn_var->softirq.delta_start);
+ osn_var->softirq.count++;
+
+ local_inc(&osn_var->int_counter);
+}
+static void trace_softirq_exit_callback(void *data, unsigned int vec_nr)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+ int duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ if (unlikely(timerlat_enabled()))
+ if (!timerlat_softirq_exit(osn_var))
+ return;
+
+ duration = get_int_safe_duration(osn_var, &osn_var->softirq.delta_start);
+ trace_softirq_noise(vec_nr, osn_var->softirq.arrival_time, duration);
+ cond_move_thread_delta_start(osn_var, duration);
+ osn_var->softirq.arrival_time = 0;
+}
+```
+
+
+可以发现对softirq的统计方式与对irq的统计方式一摸一样,在这里我们便不做详细分析,读者可以参考上面对hook\_irq\_events()的分析。
+
+
+### hook\_thread\_events
+
+
+osnoise通过在tracepoint sched\_switch注册钩子函数,来统计thread noise。函数如下所示:
+
+
+
+```
+static void
+trace_sched_switch_callback(void *data, bool preempt,
+ struct task_struct *p,
+ struct task_struct *n,
+ unsigned int prev_state)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+
+ if (p->pid != osn_var->pid)
+ thread_exit(osn_var, p);
+
+ if (n->pid != osn_var->pid)
+ thread_entry(osn_var, n);
+}
+static void
+thread_entry(struct osnoise_variables *osn_var, struct task_struct *t)
+{
+ if (!osn_var->sampling)
+ return;
+ /*
+ * The arrival time will be used in the report, but not to compute
+ * the execution time, so it is safe to get it unsafe.
+ */
+ osn_var->thread.arrival_time = time_get();
+
+ set_int_safe_time(osn_var, &osn_var->thread.delta_start);
+
+ osn_var->thread.count++;
+ local_inc(&osn_var->int_counter);
+}
+static void
+thread_exit(struct osnoise_variables *osn_var, struct task_struct *t)
+{
+ int duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ if (unlikely(timerlat_enabled()))
+ if (!timerlat_thread_exit(osn_var))
+ return;
+
+ duration = get_int_safe_duration(osn_var, &osn_var->thread.delta_start);
+
+ trace_thread_noise(t, osn_var->thread.arrival_time, duration);
+
+ osn_var->thread.arrival_time = 0;
+}
+```
+
+
+sched\_switch()为线程切换的核心函数,在该trace\_sched\_switch函数中的p表示前一个线程,n表示下一个要执行的线程,即从线程p切换到线程n。
+
+
+此时存在三种情况:
+
+
++ 从采样线程切换到其他线程
+
+
+- 执行thread\_entry()函数,标志一个噪声的进入
+
+
++ 从其他线程切换到采样线程
+
+
+- 执行thread\_exit()函数,标志上一个噪声的结束
+
+
++ 从其他线程切换到其他线程
+
+
+- 先执行thread\_exit()函数,标志上一个噪声的结束
+- 再执行thread\_entry()函数,标志下一个噪声的进入
+
+
+换句话说,该钩子函数会统计除了采样线程外其他所有线程执行的时间。其中thread\_entry()和thread\_exit()的具体实现与上面对irq事件统计的函数实现类似,此处不再过多赘述。
+
+
+### nmi\_events
+
+
+对于NMI事件的统计比较特殊,在ftrace\_nmi\_enter和ftrace\_nmi\_exit中直接调用trace\_osnoise\_callback获取nmi noise,并且调用trace\_nmi\_noise将duration放到ftrace的ringbuffer中。
+
+
+
+```
+static inline void ftrace_nmi_exit(void)
+{
+ ...
+ if (trace_osnoise_callback_enabled)
+ trace_osnoise_callback(false);
+ ...
+}
+static inline void ftrace_nmi_exit(void)
+{
+ ...
+ if (trace_osnoise_callback_enabled)
+ trace_osnoise_callback(false);
+ ...
+}
+void trace_osnoise_callback(bool enter)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+ u64 duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ /*
+ * Currently trace_clock_local() calls sched_clock() and the
+ * generic version is not NMI safe.
+ */
+ if (!IS_ENABLED(CONFIG_GENERIC_SCHED_CLOCK)) {
+ if (enter) {
+ osn_var->nmi.delta_start = time_get();
+ local_inc(&osn_var->int_counter);
+ } else {
+ duration = time_get() - osn_var->nmi.delta_start;
+
+ trace_nmi_noise(osn_var->nmi.delta_start, duration);
+
+ cond_move_irq_delta_start(osn_var, duration);
+ cond_move_softirq_delta_start(osn_var, duration);
+ cond_move_thread_delta_start(osn_var, duration);
+ }
+ }
+
+ if (enter)
+ osn_var->nmi.count++;
+}
+```
+
+
+主要函数为trace\_osnoise\_callback(bool enter),该函数通过一个bool值来判断当前是进入nmi中断还是退出nmi中断,进而进行相应的处理,统计方法和其他事件统计方法一直。可以看到在NMI的钩子函数中,会调用到
+
+
++ cond\_move\_irq\_delta\_start(osn\_var, duration);
++ cond\_move\_softirq\_delta\_start(osn\_var, duration);
++ cond\_move\_softirq\_delta\_start(osn\_var, duration);
+
+
+这三个函数去校准其他低优先级事件的统计。与我们之前的分析一致。
+
+
+## 2.4 采样
+
+
+上面介绍了osnoise对各类事件采样的方法,接下来,我们分析一下osnoise的采样流程。osnoise开始采样的函数调用流程为osnoise\_tracer\_start->osnoise\_workload\_start->start\_per\_cpu\_kthreads->start\_kthread->osnoise\_main->run\_osnoise。
+
+
+
+采样的核心函数为run\_osnoise,将代码裁剪后如下:
+
+
+
+```
+static int run_osnoise(void)
+{
+ ...
+
+ threshold = tracing_thresh ? : 5000;
+
+ osn_var->sampling = true;
+
+ runtime = osnoise_data.sample_runtime * NSEC_PER_USEC;
+
+ stop_in = osnoise_data.stop_tracing * NSEC_PER_USEC;
+
+ start = time_get();
+
+ last_int_count = set_int_safe_time(osn_var, &last_sample);
+
+ do {
+
+ int_count = set_int_safe_time(osn_var, &sample);
+
+ noise = time_sub(sample, last_sample);
+
+ total = time_sub(sample, start);
+
+ if (total < last_total) {
+ osnoise_taint("total overflow!");
+ break;
+ }
+
+ last_total = total;
+
+ if (noise >= threshold) {
+ int interference = int_count - last_int_count;
+
+ if (noise > max_noise)
+ max_noise = noise;
+
+ if (!interference)
+ hw_count++;
+
+ sum_noise += noise;
+
+ trace_sample_threshold(last_sample, noise, interference);
+
+ if (osnoise_data.stop_tracing)
+ if (noise > stop_in)
+ osnoise_stop_tracing();
+ }
+
+ last_sample = sample;
+ last_int_count = int_count;
+
+ } while (total < runtime && !kthread_should_stop());
+
+ osn_var->sampling = false;
+
+ ...
+}
+```
+
+
+
+分析采样函数的主体逻辑流程图如下所示:
+
+
+
+
+
+即通过不断的轮询TSC寄存器,将每次轮询的间隙与预设的threshold进行对比,判断是否发生噪声,如果发生了噪声且噪声不是由其他可测量事件所造成的,就认为发生了硬件噪声。
+
+
+其中:
+
+
+* threshold :两次轮询TSC寄存器时间之差,被认为是噪声的最小值,默认设为5us。
+* osn\_var->sampling:标志位,标志是否开启采样。
+* runtime:预设的本次采样时间。
+* start :记录本次采样开始的时间
+* last\_sample : 记录上次读取tsc寄存器的值
+* sample : 记录本次读取tsc寄存器的值
+* noise = time\_sub(sample, last\_sample) : 计算本次和上次轮询tsc寄存器的时间之差。
+* total :记录从采样开始到现在所经历的时间
+* 如果noise >= threshold,则视为发生了噪声,进行统计计算
+
+
++ max\_noise: 记录最大的单个噪声值
++ interference: 记录本次噪声内事件发生的次数,如果为0则代表是硬件噪声。
++ hw\_count: 记录硬件噪声的次数,当interference为0时,增加。
+
+
+* 轮询tsc寄存器,直到total>=runtime,结束本次采样。
+
+
+
+# 三、小结
+
+
+以上便是对osnoise的代码分析。osnoise就是站在一个普通进程的视角上,统计所有会打断他的事件,包含irq、softirq、nmi、thread、hw。
+
+
+对于前四种事件内核中都提供了相应的tracepoint,只需要注册相应的回掉函数到tracepoint中即可统计到相关的信息。而hw无法被直接统计测量,因此在osnoise中就通过不断的轮询tsc寄存器,将任意两次轮询的差值与threshold进行比较,如果大于threshold就认为发生了噪声,当发生噪声时如果其他四个事件都未发生就认为发生了硬件延迟。
+
+
+由于irq、softirq、nmi、thread都有相应的tracepoint可以供我们使用,在不考虑hw的情况下我们其实可以直接在用户态实现相关信息的采集。下篇文章我们会尝试在用户态,利用bcc通过动态插桩的方式来实现一个简单的osnoise背景噪声统计工具。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git "a/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace_osnoise_\346\200\273\350\247\210.md" "b/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace_osnoise_\346\200\273\350\247\210.md"
new file mode 100644
index 0000000000000000000000000000000000000000..782c9a33160ade07820bfa6300aa0fd6cc5779c9
--- /dev/null
+++ "b/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace_osnoise_\346\200\273\350\247\210.md"
@@ -0,0 +1,179 @@
+
+
+
+# Ftrace: osnoise 总览
+
+
+
+
+
+
+
+
+
+
+
+## 一、osnoise是什么?
+
+
+
+
+在linux系统中,一个普通线程在执行过程中会被各种各样的事件所干扰打断,如NMI、IRQ、SOFTIRQ、来自硬件的干扰以及来自其他线程的干扰。这些事件对于一个普通线程来说,就相当于噪声一样的存在。在Linux 5.14-rc1中,引入了一个新的tracer——osnoise tracer。osnoise从一个线程的视角出发,统计出所有对他有干扰的噪声,进而协助开发人员分析系统背景噪声情况。
+
+
+### 1.1 噪声分类
+
+
+在osnoise tracer中,将统计的噪声分为了以下五个大类:
+
+
++ IRQ:硬中断
++ SOFTIRQ:软中断
++ NMI:不可屏蔽中断
++ HW:来自硬件的噪声。
++ THREAD:来自其他线程的影响。
+
+
+其中,HW(hardware latency)表示某些底层硬件或者固件的行为引起的大型系统延迟。在Ftrace中,有一个名为hwlat\_detector的tracer,它的主要目的就是用来检测硬件噪声。osnoise的设计思想借鉴了hwlat\_detector。
+
+
+### 1.2 hwlat
+
+
+hwlat\_detector的工作原理简单来说就是在一段时间内,关闭irq、softirq以及抢占,然后不断的去轮询TSC(Time Stamp Counter)寄存器的值。由于关闭了中断及抢占,任意两次读取之间的间隙都是由于硬件噪声或者来自其他不可屏蔽中断的噪声(NMI)。
+
+
+如图所示:
+
+
+
+
+
+在一段时间内,采样线程不断的去循环读取TSC寄存器,在一个循环内会连续读取两次TSC寄存器。假设本次循环读取的时间分别为t1、t2,上次循环读取的时间为last\_t1、last\_t2。则:
+
+
++ t1与t2的时间之差,last\_t1、last\_t2的时间之差,称为inner\_latency。
++ t1与last\_t2的时间之差,称为outer\_latency。
++ tracing\_thresh为预设的阀值,如果观察到任何超过阀值的延迟就认为发生了噪声事件。
++ 在hwlat中,会不断的计算inner\_latency和outer\_latency。然后将其值与预设的tracing\_thresh值进行对比,如果大于tracing\_thresh,就认为发生了噪声事件。
++ 在hwlat采样期间,会同时追踪nmi中断事件。因此,观察到的任何超过阀值的延迟如果不是nmi造成的,那么就认为是hardware latency。
+
+
+### 1.3 osnoise实现
+
+
+前面我们介绍了hwlat的实现。简而言之,hwlat关闭irq、softirq、抢占等事件,通过不断的轮询TSC寄存器以及追踪NMI中断来探测延迟事件,观察到的任何延迟都是由NMI或者硬件造成的。
+
+
+osnoise的实现思想和hwlat类似,不过osnoise不会关闭irq、softirq、抢占等事件,而是在采样的同时追踪各类事件。在irq\_handler\_entry、irq\_handler\_exit、softirq\_entry、softirq\_exit、sched\_switch、nmi\_enter、nmi\_exit处也插入相应的钩子函数。进而统计出各类事件发生的次数以及持续时间。如果观测到的任意延迟不是由以上时间造成的,那么就认为是硬件噪声。
+
+
+## 二、osnoise tracer
+
+
+### 2.1 配置文件
+
+
+osnoise在`/sys/kernel/debug/tracing/` 目录下有一系列可配置文件, 含义如下:
+
+
+* **osnoise/cpus:** osnoise采样的目标cpu,默认是所有cpu。
+* **osnoise/period\_us:** osnoise线程的周期。默认是1000000ms,即1s。
+* **osnoise/runtime\_us:** osnoise线程在一个周期内的采样时间。默认是1000000ms,即1s。
+* **osnoise/stop\_tracing\_us:** 当单个噪声的最大值超过这个阀值时,停止采样。默认为0,即关闭该选项。
+* **osnoise/stop\_tracing\_total\_us:** 当总计噪声超过这个阀值时,停止采样。默认为0,即关闭该选项。
+* **tracing\_thresh**: 两次轮询TSC寄存器时间之差,被认为是噪声的最小值,单位为us。当配置为0时,默认设为5us。
+
+
+### 2.2 使用方法
+
+
+1. 将osnoise写入的current\_tracer:
+
+
+`echo osnoise > /sys/kernel/debug/tracing/current_tracer`
+
+
+2. 打开traceing\_on:
+
+
+`echo 1 > /sys/kernel/debug/tracing/tracing_on`
+
+
+3. 查看trace结果:
+
+
+`cat /sys/kernel/debug/tracing/trace`
+
+
+
+
+
+
+
+
+这里显示的是系统整体采样的结果各个字段的含义如下:
+
+
+* TASK-PID:采样线程的PID。
+* CPU:采样的CPU ID
+* TIMESTAMP:时间戳
+* RUNTIME IN US:采样时间,单位us
+* NOISE IN US:本次采样时间内的总计噪声时间,单位us。
+* %OF CPU AVAILABLE:在一个RUNTIME周期内,采样线程可以获得的cpu利用率。
+* HW、NMI、IRQ、SIRQ、THREAD:分别表示各类噪声事件发生的次数。
+
+
+## 三、osnoise trace\_point
+
+
+### 3.1 trace\_point
+
+
+osnoise除了提供tracer外,还提供了一组trace\_points,以协助开发人员对噪声进行进一步分析。可以在`/sys/kernel/debug/tracing/events/osnoise/`看到相关tracepoint:
+
+
+* **sample\_threshold:** 追踪任何高于阀值的噪声事件。阀值即为上文提到的tracing\_thresh,默认为5us。
+* **nmi\_noise:** nmi噪声,包含其持续时间。
+* **irq\_noise:** irq噪声,包含其持续时间。
+* **softirq\_noise:** softirq噪声,包含其持续时间
+* **thread\_noise:** 其他线程噪声,包含其持续时间
+
+
+### 3.2 使用方法
+
+
+前面我们已经介绍了osnoise tracer的使用,它可以让我们直观的看到整个系统级别的各种噪声事件的总和。如果我们像看到每种噪声或者是说指定噪声类型的事件的详细信息,就需要用到osnoise提供的trace\_point。
+
+
+打开trace\_point总开关:
+
+
+`echo 1 > /sys/kernel/debug/tracing/events/osnoise/enable`
+
+
+查看trace日志:
+
+
+`cat /sys/kernel/debug/tracing/trace`
+
+
+输出如下所示:
+
+
+
+
+
+
+日志中包含了所有噪声的详细信息,包括其名字,开始事件,持续时间等等。关于其输出的具体格式可以查看对应trace\_point文件夹下的format文件。
+
+
+trace\_ponit文件位置在`/sys/kernel/debug/tracing/events/osnoise/`下。
+
+
+除了总开关外,每个事件有自己单独的开关,在对应tracepoint目录下。如irq\_noise的开关为`/sys/kernel/debug/tracing/events/osnoise/irq_noise/enable`。用户可以根据自己的需求只追踪相应的事件,从而过滤掉其他不需要关注的信息。
+
+
+
+
+
diff --git "a/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220.md" "b/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220.md"
new file mode 100644
index 0000000000000000000000000000000000000000..d8d8d5f7ea67371721d640d941991d8ea0ad4191
--- /dev/null
+++ "b/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220.md"
@@ -0,0 +1,641 @@
+
+
+
+前面一篇文章中,我们简要的介绍了一下osnoise的相关信息,本篇文章主要针对其源代码进行分析阐述。
+
+
+
+# 一、数据结构:
+
+
+
+```
+/*
+ * NMI runtime info.
+ */
+struct osn_nmi {
+ u64 count;
+ u64 delta_start;
+};
+
+/*
+ * IRQ runtime info.
+ */
+struct osn_irq {
+ u64 count;
+ u64 arrival_time;
+ u64 delta_start;
+};
+
+#define IRQ_CONTEXT 0
+#define THREAD_CONTEXT 1
+/*
+ * sofirq runtime info.
+ */
+struct osn_softirq {
+ u64 count;
+ u64 arrival_time;
+ u64 delta_start;
+};
+
+/*
+ * thread runtime info.
+ */
+struct osn_thread {
+ u64 count;
+ u64 arrival_time;
+ u64 delta_start;
+};
+
+/*
+ * Runtime information: this structure saves the runtime information used by
+ * one sampling thread.
+ */
+struct osnoise_variables {
+ struct task_struct *kthread;
+ bool sampling;
+ pid_t pid;
+ struct osn_nmi nmi;
+ struct osn_irq irq;
+ struct osn_softirq softirq;
+ struct osn_thread thread;
+ local_t int_counter;
+};
+```
+
+
+osnoise用来记录结果的主要数据结构为`struct osnoise_variables`其中:
+
+
++ `struct task_struct *kthread`:采样线程的tcb。
++ `bool sampling`:采样开关
++ `pit_t pid`:采样线程的pid
++ `struct osn_nmi nmi`:保存nmi噪声的相关信息
++ `struct osn_irq irq`:保存irq噪声的相关信息
++ `struct osn_softiq softirq`:保存softirq噪声的相关信息
++ `struct osn_thread thread`:保存其他线程噪声的相关信息
++ `local_t int_counter`:保存噪声的总次数
+
+
+
+# 二、工作原理:
+
+
+## 2.1 注册trace\_point
+
+
+如第一篇文章所述,osnoise引入了一组trace\_point。通过这些trace\_point,开发人员可以获取噪声的详细信息。注册trace\_point的代码如下(以irq\_noise为例):
+
+
+
+```
+TRACE_EVENT(irq_noise,
+
+ TP_PROTO(int vector, const char *desc, u64 start, u64 duration),
+
+ TP_ARGS(vector, desc, start, duration),
+
+ TP_STRUCT__entry(
+ __field( u64, start )
+ __field( u64, duration)
+ __string( desc, desc )
+ __field( int, vector )
+
+ ),
+
+ TP_fast_assign(
+ __assign_str(desc, desc);
+ __entry->vector = vector;
+ __entry->start = start;
+ __entry->duration = duration;
+ ),
+
+ TP_printk("%s:%d start %llu.%09u duration %llu ns",
+ __get_str(desc),
+ __entry->vector,
+ __print_ns_to_secs(__entry->start),
+ __print_ns_without_secs(__entry->start),
+ __entry->duration)
+);
+```
+
+
+关于trace\_point这里我们不做过多介绍,感兴趣的读者可以去内核文件`include/trace/events/osnoise.h`下查看相应源代码。
+
+
+## 2.2 注册osnoise tracer
+
+
+这部分主要是涉及到osnoise的初始化过程,该过程主要就是将osnoise注册近ftrace中并且初始化相关的tracefs。注册的过程通过`register_tracer(&osnoise_tracer)`实现。
+
+
+
+```
+static struct tracer osnoise_tracer __read_mostly = {
+ .name = "osnoise",
+ .init = osnoise_tracer_init,
+ .reset = osnoise_tracer_reset,
+ .start = osnoise_tracer_start,
+ .stop = osnoise_tracer_stop,
+ .print_header = print_osnoise_headers,
+ .allow_instances = true,
+};
+```
+
+
+## 2.3 注册tracepoint钩子函数:
+
+
+osnoise 统计信息的方式就是通过在相应的tracepoint中注册钩子函数。因此这部分即是osnoise的核心部分,本篇文章将重点分析该模块。
+
+
+osnoise首先会将各种事件的钩子函数插入对应的tracepoint中,这一动作由`osnoise_hook_events()`函数执行,将该函数裁剪后如下:
+
+
+
+```
+static int osnoise_hook_events(void)
+{
+ ...
+ retval = hook_irq_events();
+ ...
+ retval = hook_softirq_events();
+ ...
+ retval = hook_thread_events();
+ ...
+}
+```
+
+
+该函数主要是针对irq、softirq、thread事件插入一些采样函数。
+
+
+### hook\_irq\_events
+
+
+hook\_irq\_events()主要是实现对irq事件的统计。如下:
+
+
+
+```
+static int hook_irq_events(void)
+{
+ ...
+ ret = register_trace_irq_handler_entry(trace_irqentry_callback, NULL);
+ ...
+ ret = register_trace_irq_handler_exit(trace_irqexit_callback, NULL);
+ ...
+}
+```
+
+
+主要是在irq\_handler\_entry 和 irq\_handler\_exit处插入相应的处理函数。最终插入的处理函数为osnoise\_trace\_irq\_entry() 和 osnoise\_trace\_irq\_exit()。
+
+
+
+```
+void osnoise_trace_irq_entry(int id)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+
+ if (!osn_var->sampling)
+ return;
+
+ osn_var->irq.arrival_time = time_get();
+ set_int_safe_time(osn_var, &osn_var->irq.delta_start);
+ osn_var->irq.count++;
+
+ local_inc(&osn_var->int_counter);
+}
+void osnoise_trace_irq_exit(int id, const char *desc)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+ int duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ duration = get_int_safe_duration(osn_var, &osn_var->irq.delta_start);
+ trace_irq_noise(id, desc, osn_var->irq.arrival_time, duration);
+ osn_var->irq.arrival_time = 0;
+ cond_move_softirq_delta_start(osn_var, duration);
+ cond_move_thread_delta_start(osn_var, duration);
+}
+```
+
+
+在irq handler的入口处插入的函数为osnoise\_trace\_irq\_entry,分析该函数:
+
+
++ 在irq.arrival\_time中记录本次irq事件的开始时间。
++ 在irq.delta\_start中记录本次irq事件的准确开始时间。
++ irq噪声事件的次数+1。
++ 噪声事件总体次数+1。
+
+
+在这里我们发现,除了在irq.arrival\_time中记录了一个irq开始时间之外,还通过set\_int\_safe\_time函数在 irq.delta\_start中都记录了一个开始时间。那么他们之间有什么区别呢?在这里我们先按下不表,后文会对其进行解释分析。
+
+
+在irq handler的出口处插入的函数为osnoise\_trace\_irq\_exit,该函数的主要作用:
+
+
++ 根据之前记录的osn\_var->irq.delta\_start计算出本次irq事件的持续时间。
++ 调用trace\_irq\_noise将本次irq事件的**中断号,中断名称、开始时间、持续时间**放到ftrace的ringbuffer中。
++ 清空osn\_var->irq.arrival\_time 表示此次irq事件结束。
+
+
+我们注意到在该函数的末尾处有cond\_move\_softirq\_delta\_start 以及 cond\_move\_thread\_delta\_start函数。其实形如此类的函数一共有三个:
+
+
++ cond\_move\_irq\_delta\_start
++ cond\_move\_softirq\_delta\_start
++ cond\_move\_thread\_delta\_start
+
+
+函数的形式都是一样的,我们以 cond\_move\_softirq\_delta\_start()为例:
+
+
+
+```
+static inline void
+cond_move_softirq_delta_start(struct osnoise_variables *osn_var, u64 duration)
+{
+ if (osn_var->softirq.delta_start)
+ osn_var->softirq.delta_start += duration;
+}
+```
+
+
++ 这个函数会在osnoise\_trace\_irq\_exit、trace\_osnoise\_callback中调用,前者我们知道是irq事件退出时的钩子函数,而后者则是nmi事件的钩子函数。
++ 可以看到该函数的主要功能是将softirq.delta\_start的开始时间推后一个duration。
+
+
+换句话说,这个函数是为了校准低优先级事件的开始时间。以下图为例:
+
+
++ 在t1时刻进入了softirq,此时记录**softirq.arrival\_time = t1**,**softirq.delta\_time = t1**。
++ 然后在t2时刻,来了一个irq抢占了softirq,进入irq的执行函数。
++ t3时刻离开irq执行完毕继续执行softirq。irq执行时间**duration = t3-t2**。同时调用cond\_move\_softirq\_delta\_start,更新softirq开始时间**softirq.delta\_start += duration;**
++ 在t4时刻softirq执行完毕退出。
+
+
+那么本次softirq的持续时间实际上应该是t4 - (t1 + duration) = t4 - **softirq.delta\_start。**
+
+
+
+
+因此,需要高优先级的对低优先级的事件的时间进行校准。
+
+
++ 对于nmi事件,需要调用
+
+
+- cond\_move\_irq\_delta\_start
+- cond\_move\_softirq\_delta\_start
+- cond\_move\_thread\_delta\_start
+
+
++ 对于irq事件,需要调用
+
+
+- cond\_move\_softirq\_delta\_start
+- cond\_move\_thread\_delta\_start
+
+
++ 对于softirq事件,需要调用
+
+
+- cond\_move\_thread\_delta\_start
+
+
+### hook\_softirq\_events
+
+
+与irq的钩子函数一样,需要注册tracepoint softirq\_entry、softirq\_exit的钩子函数。最终注册的钩子函数如下:
+
+
+
+```
+static void trace_softirq_entry_callback(void *data, unsigned int vec_nr)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+
+ if (!osn_var->sampling)
+ return;
+
+ osn_var->softirq.arrival_time = time_get();
+ set_int_safe_time(osn_var, &osn_var->softirq.delta_start);
+ osn_var->softirq.count++;
+
+ local_inc(&osn_var->int_counter);
+}
+static void trace_softirq_exit_callback(void *data, unsigned int vec_nr)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+ int duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ if (unlikely(timerlat_enabled()))
+ if (!timerlat_softirq_exit(osn_var))
+ return;
+
+ duration = get_int_safe_duration(osn_var, &osn_var->softirq.delta_start);
+ trace_softirq_noise(vec_nr, osn_var->softirq.arrival_time, duration);
+ cond_move_thread_delta_start(osn_var, duration);
+ osn_var->softirq.arrival_time = 0;
+}
+```
+
+
+可以发现对softirq的统计方式与对irq的统计方式一摸一样,在这里我们便不做详细分析,读者可以参考上面对hook\_irq\_events()的分析。
+
+
+### hook\_thread\_events
+
+
+osnoise通过在tracepoint sched\_switch注册钩子函数,来统计thread noise。函数如下所示:
+
+
+
+```
+static void
+trace_sched_switch_callback(void *data, bool preempt,
+ struct task_struct *p,
+ struct task_struct *n,
+ unsigned int prev_state)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+
+ if (p->pid != osn_var->pid)
+ thread_exit(osn_var, p);
+
+ if (n->pid != osn_var->pid)
+ thread_entry(osn_var, n);
+}
+static void
+thread_entry(struct osnoise_variables *osn_var, struct task_struct *t)
+{
+ if (!osn_var->sampling)
+ return;
+ /*
+ * The arrival time will be used in the report, but not to compute
+ * the execution time, so it is safe to get it unsafe.
+ */
+ osn_var->thread.arrival_time = time_get();
+
+ set_int_safe_time(osn_var, &osn_var->thread.delta_start);
+
+ osn_var->thread.count++;
+ local_inc(&osn_var->int_counter);
+}
+static void
+thread_exit(struct osnoise_variables *osn_var, struct task_struct *t)
+{
+ int duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ if (unlikely(timerlat_enabled()))
+ if (!timerlat_thread_exit(osn_var))
+ return;
+
+ duration = get_int_safe_duration(osn_var, &osn_var->thread.delta_start);
+
+ trace_thread_noise(t, osn_var->thread.arrival_time, duration);
+
+ osn_var->thread.arrival_time = 0;
+}
+```
+
+
+sched\_switch()为线程切换的核心函数,在该trace\_sched\_switch函数中的p表示前一个线程,n表示下一个要执行的线程,即从线程p切换到线程n。
+
+
+此时存在三种情况:
+
+
++ 从采样线程切换到其他线程
+
+
+- 执行thread\_entry()函数,标志一个噪声的进入
+
+
++ 从其他线程切换到采样线程
+
+
+- 执行thread\_exit()函数,标志上一个噪声的结束
+
+
++ 从其他线程切换到其他线程
+
+
+- 先执行thread\_exit()函数,标志上一个噪声的结束
+- 再执行thread\_entry()函数,标志下一个噪声的进入
+
+
+换句话说,该钩子函数会统计除了采样线程外其他所有线程执行的时间。其中thread\_entry()和thread\_exit()的具体实现与上面对irq事件统计的函数实现类似,此处不再过多赘述。
+
+
+### nmi\_events
+
+
+对于NMI事件的统计比较特殊,在ftrace\_nmi\_enter和ftrace\_nmi\_exit中直接调用trace\_osnoise\_callback获取nmi noise,并且调用trace\_nmi\_noise将duration放到ftrace的ringbuffer中。
+
+
+
+```
+static inline void ftrace_nmi_exit(void)
+{
+ ...
+ if (trace_osnoise_callback_enabled)
+ trace_osnoise_callback(false);
+ ...
+}
+static inline void ftrace_nmi_exit(void)
+{
+ ...
+ if (trace_osnoise_callback_enabled)
+ trace_osnoise_callback(false);
+ ...
+}
+void trace_osnoise_callback(bool enter)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+ u64 duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ /*
+ * Currently trace_clock_local() calls sched_clock() and the
+ * generic version is not NMI safe.
+ */
+ if (!IS_ENABLED(CONFIG_GENERIC_SCHED_CLOCK)) {
+ if (enter) {
+ osn_var->nmi.delta_start = time_get();
+ local_inc(&osn_var->int_counter);
+ } else {
+ duration = time_get() - osn_var->nmi.delta_start;
+
+ trace_nmi_noise(osn_var->nmi.delta_start, duration);
+
+ cond_move_irq_delta_start(osn_var, duration);
+ cond_move_softirq_delta_start(osn_var, duration);
+ cond_move_thread_delta_start(osn_var, duration);
+ }
+ }
+
+ if (enter)
+ osn_var->nmi.count++;
+}
+```
+
+
+主要函数为trace\_osnoise\_callback(bool enter),该函数通过一个bool值来判断当前是进入nmi中断还是退出nmi中断,进而进行相应的处理,统计方法和其他事件统计方法一直。可以看到在NMI的钩子函数中,会调用到
+
+
++ cond\_move\_irq\_delta\_start(osn\_var, duration);
++ cond\_move\_softirq\_delta\_start(osn\_var, duration);
++ cond\_move\_softirq\_delta\_start(osn\_var, duration);
+
+
+这三个函数去校准其他低优先级事件的统计。与我们之前的分析一致。
+
+
+## 2.4 采样
+
+
+上面介绍了osnoise对各类事件采样的方法,接下来,我们分析一下osnoise的采样流程。osnoise开始采样的函数调用流程为osnoise\_tracer\_start->osnoise\_workload\_start->start\_per\_cpu\_kthreads->start\_kthread->osnoise\_main->run\_osnoise。
+
+
+
+采样的核心函数为run\_osnoise,将代码裁剪后如下:
+
+
+
+```
+static int run_osnoise(void)
+{
+ ...
+
+ threshold = tracing_thresh ? : 5000;
+
+ osn_var->sampling = true;
+
+ runtime = osnoise_data.sample_runtime * NSEC_PER_USEC;
+
+ stop_in = osnoise_data.stop_tracing * NSEC_PER_USEC;
+
+ start = time_get();
+
+ last_int_count = set_int_safe_time(osn_var, &last_sample);
+
+ do {
+
+ int_count = set_int_safe_time(osn_var, &sample);
+
+ noise = time_sub(sample, last_sample);
+
+ total = time_sub(sample, start);
+
+ if (total < last_total) {
+ osnoise_taint("total overflow!");
+ break;
+ }
+
+ last_total = total;
+
+ if (noise >= threshold) {
+ int interference = int_count - last_int_count;
+
+ if (noise > max_noise)
+ max_noise = noise;
+
+ if (!interference)
+ hw_count++;
+
+ sum_noise += noise;
+
+ trace_sample_threshold(last_sample, noise, interference);
+
+ if (osnoise_data.stop_tracing)
+ if (noise > stop_in)
+ osnoise_stop_tracing();
+ }
+
+ last_sample = sample;
+ last_int_count = int_count;
+
+ } while (total < runtime && !kthread_should_stop());
+
+ osn_var->sampling = false;
+
+ ...
+}
+```
+
+
+
+分析采样函数的主体逻辑流程图如下所示:
+
+
+
+
+
+即通过不断的轮询TSC寄存器,将每次轮询的间隙与预设的threshold进行对比,判断是否发生噪声,如果发生了噪声且噪声不是由其他可测量事件所造成的,就认为发生了硬件噪声。
+
+
+其中:
+
+
+* threshold :两次轮询TSC寄存器时间之差,被认为是噪声的最小值,默认设为5us。
+* osn\_var->sampling:标志位,标志是否开启采样。
+* runtime:预设的本次采样时间。
+* start :记录本次采样开始的时间
+* last\_sample : 记录上次读取tsc寄存器的值
+* sample : 记录本次读取tsc寄存器的值
+* noise = time\_sub(sample, last\_sample) : 计算本次和上次轮询tsc寄存器的时间之差。
+* total :记录从采样开始到现在所经历的时间
+* 如果noise >= threshold,则视为发生了噪声,进行统计计算
+
+
++ max\_noise: 记录最大的单个噪声值
++ interference: 记录本次噪声内事件发生的次数,如果为0则代表是硬件噪声。
++ hw\_count: 记录硬件噪声的次数,当interference为0时,增加。
+
+
+* 轮询tsc寄存器,直到total>=runtime,结束本次采样。
+
+
+
+# 三、小结
+
+
+以上便是对osnoise的代码分析。osnoise就是站在一个普通进程的视角上,统计所有会打断他的事件,包含irq、softirq、nmi、thread、hw。
+
+
+对于前四种事件内核中都提供了相应的tracepoint,只需要注册相应的回掉函数到tracepoint中即可统计到相关的信息。而hw无法被直接统计测量,因此在osnoise中就通过不断的轮询tsc寄存器,将任意两次轮询的差值与threshold进行比较,如果大于threshold就认为发生了噪声,当发生噪声时如果其他四个事件都未发生就认为发生了硬件延迟。
+
+
+由于irq、softirq、nmi、thread都有相应的tracepoint可以供我们使用,在不考虑hw的情况下我们其实可以直接在用户态实现相关信息的采集。下篇文章我们会尝试在用户态,利用bcc通过动态插桩的方式来实现一个简单的osnoise背景噪声统计工具。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git "a/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220.md" "b/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220.md"
new file mode 100644
index 0000000000000000000000000000000000000000..41ecbb17a91a745ddf9bfa70e2f998fafefc6a53
--- /dev/null
+++ "b/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220.md"
@@ -0,0 +1,558 @@
+
+
+
+作者:新绎
+
+
+
+# 写在前面
+
+
+pstore中提供了多种前端来实现捕获各种系统信息来加以调试。这篇文章中,我们会对pstore其中之一的前端`PSTORE\_CONSOLE`进行分析,从原理上分析pstore如何获取kernel printk的信息。
+
+
+# pstore console注册
+
+
+`pstore console`前端注册函数在`fs/pstore/platform.c`中被定义,通过后端初始化过程中被调用并注册,从而能够在系统执行`prink`时获取输出信息,并通过`write`方法将`prink`的输出写入到相应的后端当中。
+
+
+
+```
+static void pstore_console_write(struct console *con, const char *s, unsigned c)
+{
+ struct pstore_record record;
+
+ if (!c)
+ return;
+
+ pstore_record_init(&record, psinfo);
+ record.type = PSTORE_TYPE_CONSOLE;
+
+ record.buf = (char *)s;
+ record.size = c;
+ psinfo->write(&record);
+}
+
+static struct console pstore_console = {
+ .write = pstore_console_write,
+ .index = -1,
+};
+
+static void pstore_register_console(void)
+{
+ /* Show which backend is going to get console writes. */
+ strscpy(pstore_console.name, psinfo->name,
+ sizeof(pstore_console.name));
+ /*
+ * Always initialize flags here since prior unregister_console()
+ * calls may have changed settings (specifically CON_ENABLED).
+ */
+ pstore_console.flags = CON_PRINTBUFFER | CON_ENABLED | CON_ANYTIME;
+ register_console(&pstore_console);
+}
+```
+
+
+其中,pstore\_console的flag开启了3个选项:`CON\_PRINTBUFFER`,`CON\_ENABLED`和`CON\_ANYTIME`。
+
+
+`CON\_PRINTBUFFER`:只有开启了才会接受prink的输出
+
+
+`CON\_ENABLED`:console使能,如果没有开启这个flag需要手动使能(在cmdline中定义)
+
+
+`CON\_ANYTIME`:可以在cpu离线时进行调用
+
+
+
+```
+//console.h
+/*
+ * The interface for a console, or any other device that wants to capture
+ * console messages (printer driver?)
+ *
+ * If a console driver is marked CON_BOOT then it will be auto-unregistered
+ * when the first real console is registered. This is for early-printk drivers.
+ */
+
+#define CON_PRINTBUFFER (1)
+#define CON_CONSDEV (2) /* Last on the command line */
+#define CON_ENABLED (4)
+#define CON_BOOT (8)
+#define CON_ANYTIME (16) /* Safe to call when cpu is offline */
+#define CON_BRL (32) /* Used for a braille device */
+#define CON_EXTENDED (64) /* Use the extended output format a la /dev/kmsg */
+
+struct console {
+ char name[16];
+ void (*write)(struct console *, const char *, unsigned);
+ int (*read)(struct console *, char *, unsigned);
+ struct tty_driver *(*device)(struct console *, int *);
+ void (*unblank)(void);
+ int (*setup)(struct console *, char *);
+ int (*match)(struct console *, char *name, int idx, char *options);
+ short flags;
+ short index;
+ int cflag;
+ void *data;
+ struct console *next;
+};
+```
+
+
+# printk总览
+
+
+
+
+
+
+# printk向console输出过程分析
+
+
+pstore中注册好console之后,console会被动地获取printk的输出,接下来我们分析printk是对console进行输出。
+
+
+## cmdline解析
+
+
+如果console的flag中定义了`CON\_ENABLED`,那么console会默认使能。如果没有定义,则需要在cmdline中手动使能。
+
+
+`kernel/printk.c`中将`'console='`的解析函数`console\_setup`注册到`obs\_kernel\_param`,在kernel启动过程中会遍历所有`obs\_kernel\_param`,接着会调用`console\_setup`来解析。
+
+
+我们通过在cmdline中定义`console=xxx`则能够被`console\_setup`所解析并使能相应的console。
+
+
+
+参数是`'console='`的值字符串,如“ttyS0,115200”,`console\_setup`对`console=`参数值做解析,以ttyS0,115200为例,`buf=“ttyS”`,`idx=0`,`options="115200"`,`brl\_options=NULL`。
+
+
+
+```
+//printk.c 解析cmdline
+/*
+ * Set up a console. Called via do_early_param() in init/main.c
+ * for each "console=" parameter in the boot command line.
+ */
+static int __init console_setup(char *str)
+{
+ char buf[sizeof(console_cmdline[0].name) + 4]; /* 4 for "ttyS" */
+ char *s, *options, *brl_options = NULL;
+ int idx;
+
+ if (_braille_console_setup(&str, &brl_options))
+ return 1;
+
+ /*
+ * Decode str into name, index, options.
+ */
+ if (str[0] >= '0' && str[0] <= '9') {
+ strcpy(buf, "ttyS");
+ strncpy(buf + 4, str, sizeof(buf) - 5);
+ } else {
+ strncpy(buf, str, sizeof(buf) - 1);
+ }
+ buf[sizeof(buf) - 1] = 0;
+ options = strchr(str, ',');
+ if (options)
+ *(options++) = 0;
+#ifdef __sparc__
+ if (!strcmp(str, "ttya"))
+ strcpy(buf, "ttyS0");
+ if (!strcmp(str, "ttyb"))
+ strcpy(buf, "ttyS1");
+#endif
+ for (s = buf; *s; s++)
+ if (isdigit(*s) || *s == ',')
+ break;
+ idx = simple_strtoul(s, NULL, 10);
+ *s = 0;
+
+ __add_preferred_console(buf, idx, options, brl_options);
+ console_set_on_cmdline = 1;
+ return 1;
+}
+__setup("console=", console_setup);
+```
+
+
+`console\_setup`最后调用`\_\_add\_preferred\_console`:
+
+
+kernel利用结构体数组`console\_cmdline[8]`,最多可支持8个cmdline传入的console参数。
+
+
+`\_\_add\_preferred\_console`将name,idx,options保存到数组下一个成员`console\_cmdline`结构体中,如果数组中已有重名,则不添加,并置`selected\_console`为最新添加的`console\_cmdline`的下标。
+
+
+
+**一个例子:**
+
+
+如cmdline中有“console=ttyS0,115200 console=ttyS1,9600”
+
+
+则在`console\_cmdline[8]`数组中`console\_cmdline[0]`代表ttyS0,`console\_cmdline[1]`代表ttyS1,而`preferred\_console=1`。
+
+
+
+```
+//printk.c __add_preferred_console
+static int __add_preferred_console(char *name, int idx, char *options,
+ char *brl_options)
+{
+ struct console_cmdline *c;
+ int i;
+
+ /*
+ * See if this tty is not yet registered, and
+ * if we have a slot free.
+ */
+ for (i = 0, c = console_cmdline;
+ i < MAX_CMDLINECONSOLES && c->name[0];
+ i++, c++) {
+ if (strcmp(c->name, name) == 0 && c->index == idx) {
+ if (!brl_options)
+ preferred_console = i;
+ return 0;
+ }
+ }
+ if (i == MAX_CMDLINECONSOLES)
+ return -E2BIG;
+ if (!brl_options)
+ preferred_console = i;
+ strlcpy(c->name, name, sizeof(c->name));
+ c->options = options;
+ braille_set_options(c, brl_options);
+
+ c->index = idx;
+ return 0;
+}
+```
+
+
+## printk console选择
+
+
+printk内容会一直存在log\_buf中,log\_buf满了之后则会从头在开始存,覆盖掉原来的数据。
+
+
+log\_buf的大小由kernel `menuconfig`中的`CONFIG\_LOG\_BUF\_SHIFT`配置。
+
+
+根据printk的实现原理,printk最后调用`console\_unlock`实现log\_buf数据刷出到设备。
+
+
+kernel下每次printk打印,首先存log\_buf,然后遍历console\_drivers,找到合适console(如果有`execlusive\_console`,则往`execlusive\_console`写,如果没有,则为所有使能的console),刷出log。
+
+
+**默认情况下**`**execlusive\_console=NULL**`,所以printk默认是向所有enable的console写
+
+
+只有一种情况是指定`execlusive\_console`,就是在console注册时
+
+
+
+```
+//printk.c call_console_drivers
+/*
+ * Call the console drivers, asking them to write out
+ * log_buf[start] to log_buf[end - 1].
+ * The console_lock must be held.
+ */
+static void call_console_drivers(const char *ext_text, size_t ext_len,
+ const char *text, size_t len)
+{
+ struct console *con;
+
+ trace_console_rcuidle(text, len);
+
+ if (!console_drivers)
+ return;
+
+ for_each_console(con) {
+ if (exclusive_console && con != exclusive_console)
+ continue;
+ if (!(con->flags & CON_ENABLED))
+ continue;
+ if (!con->write)
+ continue;
+ if (!cpu_online(smp_processor_id()) &&
+ !(con->flags & CON_ANYTIME))
+ continue;
+ if (con->flags & CON_EXTENDED)
+ con->write(con, ext_text, ext_len);
+ else
+ con->write(con, text, len);
+ }
+}
+```
+
+
+## printk console注册
+
+
+注意:linux提供了early console机制(通过`CONFIG\_EARLY\_PRINTK`进行使能),用于实现为设备注册console之前的早期log的输出,对应console也称为boot console,简称bcon。这个console在kernel启动的早期阶段就会被注册,主要通过输出设备(比如串口设备)的简单的write方法直接进行数据打印。而这个write方法也就是平台实现。这时候作为输出的串口设备是基于bootloader中已经初始化完成的。
+
+
+
+1. 如果注册的是bootconsole(kernel早期启动打印),需要检查console\_drivers中没有real console,也就是说bootconsole必须是第一个注册的console。
+2. 检查new console是否是cmdline指定的console,如果是,则使能(`CON\_ENABLE`)并初始化该console
+3. 如果该new console没有使能,退出
+4. 如果new console为bootconsole,则newcon不需要输出register之前的log(`newcon->flags &= ~CON\_PRINTBUFFER`),因为如果bootconsole和new console是同一个设备则会之前的log就输出2次
+5. 把new console加入`console\_drivers`链表,对于置位`CON\_CONSDEV`的console,放在链表首
+6. 加锁
+7. 如果new console置位`CON\_PRINTBUFFER`,则将log全部刷出(暂时修改printk输出的指定唯一`exclusive\_console`为new console,保证将之前的log只输出到new console)
+8. 解锁(console\_unlock()会重新把`exclusive\_console`设置为NULL)
+9. 如果有bootconsole并且不是作为real console继续使用,则unregister bootconsole(从`console\_drivers`中删掉)
+
+```
+//printk.c register_console
+/*
+ * The console driver calls this routine during kernel initialization
+ * to register the console printing procedure with printk() and to
+ * print any messages that were printed by the kernel before the
+ * console driver was initialized.
+ *
+ * This can happen pretty early during the boot process (because of
+ * early_printk) - sometimes before setup_arch() completes - be careful
+ * of what kernel features are used - they may not be initialised yet.
+ *
+ * There are two types of consoles - bootconsoles (early_printk) and
+ * "real" consoles (everything which is not a bootconsole) which are
+ * handled differently.
+ * - Any number of bootconsoles can be registered at any time.
+ * - As soon as a "real" console is registered, all bootconsoles
+ * will be unregistered automatically.
+ * - Once a "real" console is registered, any attempt to register a
+ * bootconsoles will be rejected
+ */
+void register_console(struct console *newcon)
+{
+ int i;
+ unsigned long flags;
+ struct console *bcon = NULL;
+ struct console_cmdline *c;
+ static bool has_preferred;
+
+ if (console_drivers)
+ for_each_console(bcon)
+ if (WARN(bcon == newcon,
+ "console '%s%d' already registered\n",
+ bcon->name, bcon->index))
+ return;
+
+ /*
+ * before we register a new CON_BOOT console, make sure we don't
+ * already have a valid console
+ */
+ if (console_drivers && newcon->flags & CON_BOOT) {
+ /* find the last or real console */
+ for_each_console(bcon) {
+ if (!(bcon->flags & CON_BOOT)) {
+ pr_info("Too late to register bootconsole %s%d\n",
+ newcon->name, newcon->index);
+ return;
+ }
+ }
+ }
+
+ if (console_drivers && console_drivers->flags & CON_BOOT)
+ bcon = console_drivers;
+
+ if (!has_preferred || bcon || !console_drivers)
+ has_preferred = preferred_console >= 0;
+
+ /*
+ * See if we want to use this console driver. If we
+ * didn't select a console we take the first one
+ * that registers here.
+ */
+ if (!has_preferred) {
+ if (newcon->index < 0)
+ newcon->index = 0;
+ if (newcon->setup == NULL ||
+ newcon->setup(newcon, NULL) == 0) {
+ newcon->flags |= CON_ENABLED;
+ if (newcon->device) {
+ newcon->flags |= CON_CONSDEV;
+ has_preferred = true;
+ }
+ }
+ }
+
+ /*
+ * See if this console matches one we selected on
+ * the command line.
+ */
+ for (i = 0, c = console_cmdline;
+ i < MAX_CMDLINECONSOLES && c->name[0];
+ i++, c++) {
+ if (!newcon->match ||
+ newcon->match(newcon, c->name, c->index, c->options) != 0) {
+ /* default matching */
+ BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name));
+ if (strcmp(c->name, newcon->name) != 0)
+ continue;
+ if (newcon->index >= 0 &&
+ newcon->index != c->index)
+ continue;
+ if (newcon->index < 0)
+ newcon->index = c->index;
+
+ if (_braille_register_console(newcon, c))
+ return;
+
+ if (newcon->setup &&
+ newcon->setup(newcon, c->options) != 0)
+ break;
+ }
+
+ newcon->flags |= CON_ENABLED;
+ if (i == preferred_console) {
+ newcon->flags |= CON_CONSDEV;
+ has_preferred = true;
+ }
+ break;
+ }
+
+ if (!(newcon->flags & CON_ENABLED))
+ return;
+
+ /*
+ * If we have a bootconsole, and are switching to a real console,
+ * don't print everything out again, since when the boot console, and
+ * the real console are the same physical device, it's annoying to
+ * see the beginning boot messages twice
+ */
+ if (bcon && ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV))
+ newcon->flags &= ~CON_PRINTBUFFER;
+
+ /*
+ * Put this console in the list - keep the
+ * preferred driver at the head of the list.
+ */
+ console_lock();
+ if ((newcon->flags & CON_CONSDEV) || console_drivers == NULL) {
+ newcon->next = console_drivers;
+ console_drivers = newcon;
+ if (newcon->next)
+ newcon->next->flags &= ~CON_CONSDEV;
+ } else {
+ newcon->next = console_drivers->next;
+ console_drivers->next = newcon;
+ }
+
+ if (newcon->flags & CON_EXTENDED)
+ if (!nr_ext_console_drivers++)
+ pr_info("printk: continuation disabled due to ext consoles, expect more fragments in /dev/kmsg\n");
+
+ if (newcon->flags & CON_PRINTBUFFER) {
+ /*
+ * console_unlock(); will print out the buffered messages
+ * for us.
+ */
+ logbuf_lock_irqsave(flags);
+ console_seq = syslog_seq;
+ console_idx = syslog_idx;
+ /*
+ * We're about to replay the log buffer. Only do this to the
+ * just-registered console to avoid excessive message spam to
+ * the already-registered consoles.
+ *
+ * Set exclusive_console with disabled interrupts to reduce
+ * race window with eventual console_flush_on_panic() that
+ * ignores console_lock.
+ */
+ exclusive_console = newcon;
+ exclusive_console_stop_seq = console_seq;
+ logbuf_unlock_irqrestore(flags);
+ }
+ console_unlock();
+ console_sysfs_notify();
+
+ /*
+ * By unregistering the bootconsoles after we enable the real console
+ * we get the "console xxx enabled" message on all the consoles -
+ * boot consoles, real consoles, etc - this is to ensure that end
+ * users know there might be something in the kernel's log buffer that
+ * went to the bootconsole (that they do not see on the real console)
+ */
+ pr_info("%sconsole [%s%d] enabled\n",
+ (newcon->flags & CON_BOOT) ? "boot" : "" ,
+ newcon->name, newcon->index);
+ if (bcon &&
+ ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV) &&
+ !keep_bootcon) {
+ /* We need to iterate through all boot consoles, to make
+ * sure we print everything out, before we unregister them.
+ */
+ for_each_console(bcon)
+ if (bcon->flags & CON_BOOT)
+ unregister_console(bcon);
+ }
+}
+
+EXPORT_SYMBOL(register_console);
+```
+
+
+## printk打印级别
+
+
+printk可以根据设置的日志级别来确定这个语句最后是否能够打印出来。
+
+
+查看此文件:`cat /proc/sys/kernel/printk`
+
+
+该文件有四个数字值,它们根据日志记录消息的重要性,定义将其发送到何处。
+
+
+
+ 1. 控制台日志级别:优先级高于该值的消息将被打印至控制台
+ 2. 默认的消息日志级别:将用该优先级来打印没有优先级的消息
+ 3. 最低的控制台日志级别:控制台日志级别可被设置的最小值(最高优先级)
+ 4. 默认的控制台日志级别:控制台日志级别的缺省值
+
+内核中共提供了八种不同的日志级别,在 `linux/kernel.h` 中有相应的宏对应。
+
+
+
+```
+#define KERN_EMERG "<0>" /* systemis unusable */
+#define KERN_ALERT "<1>" /* actionmust be taken immediately */
+#define KERN_CRIT "<2>" /*critical conditions */
+#define KERN_ERR "<3>" /* errorconditions */
+#define KERN_WARNING "<4>" /* warning conditions */
+#define KERN_NOTICE "<5>" /* normalbut significant */
+#define KERN_INFO "<6>" /*informational */
+#define KERN_DEBUG "<7>" /*debug-level messages */
+```
+
+
+**可以通过在cmdline中加入“loglevel=X”的语句,来调整日志输入级别。**其中X就是我们想要设置的console\_loglevel的值。
+
+
+# 总结
+
+
+pstore实现console前端的方式很简单:通过注册一个console并且使能即可实现。
+
+
+默认情况下,printk会对所有使能的console进行输出,将log\_buf中的数据写入到使能的console当中。
+
+
+当对pstore的console进行输出时,会触发pstore console的write,将数据写入到相应后端。
+
+
+
+
+
+
+
+
diff --git "a/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220.md" "b/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220.md"
new file mode 100644
index 0000000000000000000000000000000000000000..41ecbb17a91a745ddf9bfa70e2f998fafefc6a53
--- /dev/null
+++ "b/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220.md"
@@ -0,0 +1,558 @@
+
+
+
+作者:新绎
+
+
+
+# 写在前面
+
+
+pstore中提供了多种前端来实现捕获各种系统信息来加以调试。这篇文章中,我们会对pstore其中之一的前端`PSTORE\_CONSOLE`进行分析,从原理上分析pstore如何获取kernel printk的信息。
+
+
+# pstore console注册
+
+
+`pstore console`前端注册函数在`fs/pstore/platform.c`中被定义,通过后端初始化过程中被调用并注册,从而能够在系统执行`prink`时获取输出信息,并通过`write`方法将`prink`的输出写入到相应的后端当中。
+
+
+
+```
+static void pstore_console_write(struct console *con, const char *s, unsigned c)
+{
+ struct pstore_record record;
+
+ if (!c)
+ return;
+
+ pstore_record_init(&record, psinfo);
+ record.type = PSTORE_TYPE_CONSOLE;
+
+ record.buf = (char *)s;
+ record.size = c;
+ psinfo->write(&record);
+}
+
+static struct console pstore_console = {
+ .write = pstore_console_write,
+ .index = -1,
+};
+
+static void pstore_register_console(void)
+{
+ /* Show which backend is going to get console writes. */
+ strscpy(pstore_console.name, psinfo->name,
+ sizeof(pstore_console.name));
+ /*
+ * Always initialize flags here since prior unregister_console()
+ * calls may have changed settings (specifically CON_ENABLED).
+ */
+ pstore_console.flags = CON_PRINTBUFFER | CON_ENABLED | CON_ANYTIME;
+ register_console(&pstore_console);
+}
+```
+
+
+其中,pstore\_console的flag开启了3个选项:`CON\_PRINTBUFFER`,`CON\_ENABLED`和`CON\_ANYTIME`。
+
+
+`CON\_PRINTBUFFER`:只有开启了才会接受prink的输出
+
+
+`CON\_ENABLED`:console使能,如果没有开启这个flag需要手动使能(在cmdline中定义)
+
+
+`CON\_ANYTIME`:可以在cpu离线时进行调用
+
+
+
+```
+//console.h
+/*
+ * The interface for a console, or any other device that wants to capture
+ * console messages (printer driver?)
+ *
+ * If a console driver is marked CON_BOOT then it will be auto-unregistered
+ * when the first real console is registered. This is for early-printk drivers.
+ */
+
+#define CON_PRINTBUFFER (1)
+#define CON_CONSDEV (2) /* Last on the command line */
+#define CON_ENABLED (4)
+#define CON_BOOT (8)
+#define CON_ANYTIME (16) /* Safe to call when cpu is offline */
+#define CON_BRL (32) /* Used for a braille device */
+#define CON_EXTENDED (64) /* Use the extended output format a la /dev/kmsg */
+
+struct console {
+ char name[16];
+ void (*write)(struct console *, const char *, unsigned);
+ int (*read)(struct console *, char *, unsigned);
+ struct tty_driver *(*device)(struct console *, int *);
+ void (*unblank)(void);
+ int (*setup)(struct console *, char *);
+ int (*match)(struct console *, char *name, int idx, char *options);
+ short flags;
+ short index;
+ int cflag;
+ void *data;
+ struct console *next;
+};
+```
+
+
+# printk总览
+
+
+
+
+
+
+# printk向console输出过程分析
+
+
+pstore中注册好console之后,console会被动地获取printk的输出,接下来我们分析printk是对console进行输出。
+
+
+## cmdline解析
+
+
+如果console的flag中定义了`CON\_ENABLED`,那么console会默认使能。如果没有定义,则需要在cmdline中手动使能。
+
+
+`kernel/printk.c`中将`'console='`的解析函数`console\_setup`注册到`obs\_kernel\_param`,在kernel启动过程中会遍历所有`obs\_kernel\_param`,接着会调用`console\_setup`来解析。
+
+
+我们通过在cmdline中定义`console=xxx`则能够被`console\_setup`所解析并使能相应的console。
+
+
+
+参数是`'console='`的值字符串,如“ttyS0,115200”,`console\_setup`对`console=`参数值做解析,以ttyS0,115200为例,`buf=“ttyS”`,`idx=0`,`options="115200"`,`brl\_options=NULL`。
+
+
+
+```
+//printk.c 解析cmdline
+/*
+ * Set up a console. Called via do_early_param() in init/main.c
+ * for each "console=" parameter in the boot command line.
+ */
+static int __init console_setup(char *str)
+{
+ char buf[sizeof(console_cmdline[0].name) + 4]; /* 4 for "ttyS" */
+ char *s, *options, *brl_options = NULL;
+ int idx;
+
+ if (_braille_console_setup(&str, &brl_options))
+ return 1;
+
+ /*
+ * Decode str into name, index, options.
+ */
+ if (str[0] >= '0' && str[0] <= '9') {
+ strcpy(buf, "ttyS");
+ strncpy(buf + 4, str, sizeof(buf) - 5);
+ } else {
+ strncpy(buf, str, sizeof(buf) - 1);
+ }
+ buf[sizeof(buf) - 1] = 0;
+ options = strchr(str, ',');
+ if (options)
+ *(options++) = 0;
+#ifdef __sparc__
+ if (!strcmp(str, "ttya"))
+ strcpy(buf, "ttyS0");
+ if (!strcmp(str, "ttyb"))
+ strcpy(buf, "ttyS1");
+#endif
+ for (s = buf; *s; s++)
+ if (isdigit(*s) || *s == ',')
+ break;
+ idx = simple_strtoul(s, NULL, 10);
+ *s = 0;
+
+ __add_preferred_console(buf, idx, options, brl_options);
+ console_set_on_cmdline = 1;
+ return 1;
+}
+__setup("console=", console_setup);
+```
+
+
+`console\_setup`最后调用`\_\_add\_preferred\_console`:
+
+
+kernel利用结构体数组`console\_cmdline[8]`,最多可支持8个cmdline传入的console参数。
+
+
+`\_\_add\_preferred\_console`将name,idx,options保存到数组下一个成员`console\_cmdline`结构体中,如果数组中已有重名,则不添加,并置`selected\_console`为最新添加的`console\_cmdline`的下标。
+
+
+
+**一个例子:**
+
+
+如cmdline中有“console=ttyS0,115200 console=ttyS1,9600”
+
+
+则在`console\_cmdline[8]`数组中`console\_cmdline[0]`代表ttyS0,`console\_cmdline[1]`代表ttyS1,而`preferred\_console=1`。
+
+
+
+```
+//printk.c __add_preferred_console
+static int __add_preferred_console(char *name, int idx, char *options,
+ char *brl_options)
+{
+ struct console_cmdline *c;
+ int i;
+
+ /*
+ * See if this tty is not yet registered, and
+ * if we have a slot free.
+ */
+ for (i = 0, c = console_cmdline;
+ i < MAX_CMDLINECONSOLES && c->name[0];
+ i++, c++) {
+ if (strcmp(c->name, name) == 0 && c->index == idx) {
+ if (!brl_options)
+ preferred_console = i;
+ return 0;
+ }
+ }
+ if (i == MAX_CMDLINECONSOLES)
+ return -E2BIG;
+ if (!brl_options)
+ preferred_console = i;
+ strlcpy(c->name, name, sizeof(c->name));
+ c->options = options;
+ braille_set_options(c, brl_options);
+
+ c->index = idx;
+ return 0;
+}
+```
+
+
+## printk console选择
+
+
+printk内容会一直存在log\_buf中,log\_buf满了之后则会从头在开始存,覆盖掉原来的数据。
+
+
+log\_buf的大小由kernel `menuconfig`中的`CONFIG\_LOG\_BUF\_SHIFT`配置。
+
+
+根据printk的实现原理,printk最后调用`console\_unlock`实现log\_buf数据刷出到设备。
+
+
+kernel下每次printk打印,首先存log\_buf,然后遍历console\_drivers,找到合适console(如果有`execlusive\_console`,则往`execlusive\_console`写,如果没有,则为所有使能的console),刷出log。
+
+
+**默认情况下**`**execlusive\_console=NULL**`,所以printk默认是向所有enable的console写
+
+
+只有一种情况是指定`execlusive\_console`,就是在console注册时
+
+
+
+```
+//printk.c call_console_drivers
+/*
+ * Call the console drivers, asking them to write out
+ * log_buf[start] to log_buf[end - 1].
+ * The console_lock must be held.
+ */
+static void call_console_drivers(const char *ext_text, size_t ext_len,
+ const char *text, size_t len)
+{
+ struct console *con;
+
+ trace_console_rcuidle(text, len);
+
+ if (!console_drivers)
+ return;
+
+ for_each_console(con) {
+ if (exclusive_console && con != exclusive_console)
+ continue;
+ if (!(con->flags & CON_ENABLED))
+ continue;
+ if (!con->write)
+ continue;
+ if (!cpu_online(smp_processor_id()) &&
+ !(con->flags & CON_ANYTIME))
+ continue;
+ if (con->flags & CON_EXTENDED)
+ con->write(con, ext_text, ext_len);
+ else
+ con->write(con, text, len);
+ }
+}
+```
+
+
+## printk console注册
+
+
+注意:linux提供了early console机制(通过`CONFIG\_EARLY\_PRINTK`进行使能),用于实现为设备注册console之前的早期log的输出,对应console也称为boot console,简称bcon。这个console在kernel启动的早期阶段就会被注册,主要通过输出设备(比如串口设备)的简单的write方法直接进行数据打印。而这个write方法也就是平台实现。这时候作为输出的串口设备是基于bootloader中已经初始化完成的。
+
+
+
+1. 如果注册的是bootconsole(kernel早期启动打印),需要检查console\_drivers中没有real console,也就是说bootconsole必须是第一个注册的console。
+2. 检查new console是否是cmdline指定的console,如果是,则使能(`CON\_ENABLE`)并初始化该console
+3. 如果该new console没有使能,退出
+4. 如果new console为bootconsole,则newcon不需要输出register之前的log(`newcon->flags &= ~CON\_PRINTBUFFER`),因为如果bootconsole和new console是同一个设备则会之前的log就输出2次
+5. 把new console加入`console\_drivers`链表,对于置位`CON\_CONSDEV`的console,放在链表首
+6. 加锁
+7. 如果new console置位`CON\_PRINTBUFFER`,则将log全部刷出(暂时修改printk输出的指定唯一`exclusive\_console`为new console,保证将之前的log只输出到new console)
+8. 解锁(console\_unlock()会重新把`exclusive\_console`设置为NULL)
+9. 如果有bootconsole并且不是作为real console继续使用,则unregister bootconsole(从`console\_drivers`中删掉)
+
+```
+//printk.c register_console
+/*
+ * The console driver calls this routine during kernel initialization
+ * to register the console printing procedure with printk() and to
+ * print any messages that were printed by the kernel before the
+ * console driver was initialized.
+ *
+ * This can happen pretty early during the boot process (because of
+ * early_printk) - sometimes before setup_arch() completes - be careful
+ * of what kernel features are used - they may not be initialised yet.
+ *
+ * There are two types of consoles - bootconsoles (early_printk) and
+ * "real" consoles (everything which is not a bootconsole) which are
+ * handled differently.
+ * - Any number of bootconsoles can be registered at any time.
+ * - As soon as a "real" console is registered, all bootconsoles
+ * will be unregistered automatically.
+ * - Once a "real" console is registered, any attempt to register a
+ * bootconsoles will be rejected
+ */
+void register_console(struct console *newcon)
+{
+ int i;
+ unsigned long flags;
+ struct console *bcon = NULL;
+ struct console_cmdline *c;
+ static bool has_preferred;
+
+ if (console_drivers)
+ for_each_console(bcon)
+ if (WARN(bcon == newcon,
+ "console '%s%d' already registered\n",
+ bcon->name, bcon->index))
+ return;
+
+ /*
+ * before we register a new CON_BOOT console, make sure we don't
+ * already have a valid console
+ */
+ if (console_drivers && newcon->flags & CON_BOOT) {
+ /* find the last or real console */
+ for_each_console(bcon) {
+ if (!(bcon->flags & CON_BOOT)) {
+ pr_info("Too late to register bootconsole %s%d\n",
+ newcon->name, newcon->index);
+ return;
+ }
+ }
+ }
+
+ if (console_drivers && console_drivers->flags & CON_BOOT)
+ bcon = console_drivers;
+
+ if (!has_preferred || bcon || !console_drivers)
+ has_preferred = preferred_console >= 0;
+
+ /*
+ * See if we want to use this console driver. If we
+ * didn't select a console we take the first one
+ * that registers here.
+ */
+ if (!has_preferred) {
+ if (newcon->index < 0)
+ newcon->index = 0;
+ if (newcon->setup == NULL ||
+ newcon->setup(newcon, NULL) == 0) {
+ newcon->flags |= CON_ENABLED;
+ if (newcon->device) {
+ newcon->flags |= CON_CONSDEV;
+ has_preferred = true;
+ }
+ }
+ }
+
+ /*
+ * See if this console matches one we selected on
+ * the command line.
+ */
+ for (i = 0, c = console_cmdline;
+ i < MAX_CMDLINECONSOLES && c->name[0];
+ i++, c++) {
+ if (!newcon->match ||
+ newcon->match(newcon, c->name, c->index, c->options) != 0) {
+ /* default matching */
+ BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name));
+ if (strcmp(c->name, newcon->name) != 0)
+ continue;
+ if (newcon->index >= 0 &&
+ newcon->index != c->index)
+ continue;
+ if (newcon->index < 0)
+ newcon->index = c->index;
+
+ if (_braille_register_console(newcon, c))
+ return;
+
+ if (newcon->setup &&
+ newcon->setup(newcon, c->options) != 0)
+ break;
+ }
+
+ newcon->flags |= CON_ENABLED;
+ if (i == preferred_console) {
+ newcon->flags |= CON_CONSDEV;
+ has_preferred = true;
+ }
+ break;
+ }
+
+ if (!(newcon->flags & CON_ENABLED))
+ return;
+
+ /*
+ * If we have a bootconsole, and are switching to a real console,
+ * don't print everything out again, since when the boot console, and
+ * the real console are the same physical device, it's annoying to
+ * see the beginning boot messages twice
+ */
+ if (bcon && ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV))
+ newcon->flags &= ~CON_PRINTBUFFER;
+
+ /*
+ * Put this console in the list - keep the
+ * preferred driver at the head of the list.
+ */
+ console_lock();
+ if ((newcon->flags & CON_CONSDEV) || console_drivers == NULL) {
+ newcon->next = console_drivers;
+ console_drivers = newcon;
+ if (newcon->next)
+ newcon->next->flags &= ~CON_CONSDEV;
+ } else {
+ newcon->next = console_drivers->next;
+ console_drivers->next = newcon;
+ }
+
+ if (newcon->flags & CON_EXTENDED)
+ if (!nr_ext_console_drivers++)
+ pr_info("printk: continuation disabled due to ext consoles, expect more fragments in /dev/kmsg\n");
+
+ if (newcon->flags & CON_PRINTBUFFER) {
+ /*
+ * console_unlock(); will print out the buffered messages
+ * for us.
+ */
+ logbuf_lock_irqsave(flags);
+ console_seq = syslog_seq;
+ console_idx = syslog_idx;
+ /*
+ * We're about to replay the log buffer. Only do this to the
+ * just-registered console to avoid excessive message spam to
+ * the already-registered consoles.
+ *
+ * Set exclusive_console with disabled interrupts to reduce
+ * race window with eventual console_flush_on_panic() that
+ * ignores console_lock.
+ */
+ exclusive_console = newcon;
+ exclusive_console_stop_seq = console_seq;
+ logbuf_unlock_irqrestore(flags);
+ }
+ console_unlock();
+ console_sysfs_notify();
+
+ /*
+ * By unregistering the bootconsoles after we enable the real console
+ * we get the "console xxx enabled" message on all the consoles -
+ * boot consoles, real consoles, etc - this is to ensure that end
+ * users know there might be something in the kernel's log buffer that
+ * went to the bootconsole (that they do not see on the real console)
+ */
+ pr_info("%sconsole [%s%d] enabled\n",
+ (newcon->flags & CON_BOOT) ? "boot" : "" ,
+ newcon->name, newcon->index);
+ if (bcon &&
+ ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV) &&
+ !keep_bootcon) {
+ /* We need to iterate through all boot consoles, to make
+ * sure we print everything out, before we unregister them.
+ */
+ for_each_console(bcon)
+ if (bcon->flags & CON_BOOT)
+ unregister_console(bcon);
+ }
+}
+
+EXPORT_SYMBOL(register_console);
+```
+
+
+## printk打印级别
+
+
+printk可以根据设置的日志级别来确定这个语句最后是否能够打印出来。
+
+
+查看此文件:`cat /proc/sys/kernel/printk`
+
+
+该文件有四个数字值,它们根据日志记录消息的重要性,定义将其发送到何处。
+
+
+
+ 1. 控制台日志级别:优先级高于该值的消息将被打印至控制台
+ 2. 默认的消息日志级别:将用该优先级来打印没有优先级的消息
+ 3. 最低的控制台日志级别:控制台日志级别可被设置的最小值(最高优先级)
+ 4. 默认的控制台日志级别:控制台日志级别的缺省值
+
+内核中共提供了八种不同的日志级别,在 `linux/kernel.h` 中有相应的宏对应。
+
+
+
+```
+#define KERN_EMERG "<0>" /* systemis unusable */
+#define KERN_ALERT "<1>" /* actionmust be taken immediately */
+#define KERN_CRIT "<2>" /*critical conditions */
+#define KERN_ERR "<3>" /* errorconditions */
+#define KERN_WARNING "<4>" /* warning conditions */
+#define KERN_NOTICE "<5>" /* normalbut significant */
+#define KERN_INFO "<6>" /*informational */
+#define KERN_DEBUG "<7>" /*debug-level messages */
+```
+
+
+**可以通过在cmdline中加入“loglevel=X”的语句,来调整日志输入级别。**其中X就是我们想要设置的console\_loglevel的值。
+
+
+# 总结
+
+
+pstore实现console前端的方式很简单:通过注册一个console并且使能即可实现。
+
+
+默认情况下,printk会对所有使能的console进行输出,将log\_buf中的数据写入到使能的console当中。
+
+
+当对pstore的console进行输出时,会触发pstore console的write,将数据写入到相应后端。
+
+
+
+
+
+
+
+
diff --git "a/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232DMESG_\344\273\243\347\240\201\345\210\206\346\236\220.md" "b/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232DMESG_\344\273\243\347\240\201\345\210\206\346\236\220.md"
new file mode 100644
index 0000000000000000000000000000000000000000..d5f3a1ba76f702e35bea6cc937f08a58227bc95d
--- /dev/null
+++ "b/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232DMESG_\344\273\243\347\240\201\345\210\206\346\236\220.md"
@@ -0,0 +1,212 @@
+
+
+
+作者:新绎
+
+
+
+## 写在前面
+
+
+pstore中提供了多种前端来实现捕获各种系统信息从而加以调试。这篇文章中,我们会对pstore其中之一的前端PSTORE\_DMESG进行分析,从原理上分析pstore如何获取当内核发生panic时kmsg信息。
+
+
+## Pstore注册kmsg\_dumper
+
+
+kmsg\_dumper结构体有两个重要成员:回调函数`dump()`以及相应的`kmsg_dump_reason`。通过对`dump()`进行实现,我们就可以将相应的log信息保存到我们希望保存的地方,并且可以通过`kmsg_dump_reason`来对需要保存的信息进行筛选。
+
+
+
+```
+//kmsg_dump.h
+/**
+* struct kmsg_dumper - kernel crash message dumper structure
+* @list: Entry in the dumper list (private)
+* @dump: Call into dumping code which will retrieve the data with
+* through the record iterator
+* @max_reason: filter for highest reason number that should be dumped
+* @registered: Flag that specifies if this is already registered
+*/
+struct kmsg_dumper {
+ struct list_head list;
+ void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason);
+ enum kmsg_dump_reason max_reason;
+ bool active;
+ bool registered;
+
+ /* private state of the kmsg iterator */
+ u32 cur_idx;
+ u32 next_idx;
+ u64 cur_seq;
+ u64 next_seq;
+};
+
+/*
+ * Keep this list arranged in rough order of priority. Anything listed after
+ * KMSG_DUMP_OOPS will not be logged by default unless printk.always_kmsg_dump
+ * is passed to the kernel.
+ */
+enum kmsg_dump_reason {
+ KMSG_DUMP_UNDEF,
+ KMSG_DUMP_PANIC,
+ KMSG_DUMP_OOPS,
+ KMSG_DUMP_EMERG,
+ KMSG_DUMP_RESTART,
+ KMSG_DUMP_HALT,
+ KMSG_DUMP_POWEROFF,
+};
+```
+
+
+我们可以看到,目前有7种定义的`kmsg\_dump\_reason`,而pstore则关心在系统出现panic时的log信息。在pstore的实现中,pstore通过`pstore\_cannot\_block\_path()`函数对相应的信息进行过滤。
+
+
+
+```
+//pstore_cannot_block_path()
+/*
+ * Should pstore_dump() wait for a concurrent pstore_dump()? If
+ * not, the current pstore_dump() will report a failure to dump
+ * and return.
+ */
+static bool pstore_cannot_block_path(enum kmsg_dump_reason reason)
+{
+ /* In NMI path, pstore shouldn't block regardless of reason. */
+ if (in_nmi())
+ return true;
+
+ switch (reason) {
+ /* In panic case, other cpus are stopped by smp_send_stop(). */
+ case KMSG_DUMP_PANIC:
+ /* Emergency restart shouldn't be blocked. */
+ case KMSG_DUMP_EMERG:
+ return true;
+ default:
+ return false;
+ }
+}
+```
+
+
+其中dmesg前端的主要工作就是为其实现一个`dump()`函数,该函数将从log buffer中读取log信息,然后将其封装为recored之后写入对应的后端设备,其主要定义如下:
+
+
+
+```
+//pstore_dump()
+static struct kmsg_dumper pstore_dumper = {
+ .dump = pstore_dump,
+}
+
+static void pstore_dump(struct kmsg_dumper *dumper,
+ enum kmsg_dump_reason reason)
+{
+ …
+ while (total < kmsg_bytes) {
+ …
+ pstore_record_init(&record, psinfo);
+ …
+ header_size = snprintf(dst, dst_size, "%s#%d Part%u\n", why,
+ oopscount, part);
+ dst_size -= header_size;
+
+ if (!kmsg_dump_get_buffer(&iter, true, dst + header_size,
+ dst_size, &dump_size))
+ break;
+
+ if (big_oops_buf) {
+ zipped_len = pstore_compress(dst, psinfo->buf,
+ header_size + dump_size,
+ psinfo->bufsize);
+ …
+ } else {
+ record.size = header_size + dump_size;
+ }
+
+ ret = psinfo->write(&record);
+ …
+ }
+ …
+}
+
+```
+
+
+## kmsg\_dump实现
+
+
+printk实现了一个`kmsg\_dump()`函数,用于方便其它模块dump内核的log buffer,当内核发生oops、panic或重启等事件时,都会调用该函数dump log信息。其代码实现如下:
+
+
+
+```
+void kmsg_dump(enum kmsg_dump_reason reason)
+{
+ …
+ list_for_each_entry_rcu(dumper, &dump_list, list) {
+ enum kmsg_dump_reason max_reason = dumper->max_reason;
+
+ if (max_reason == KMSG_DUMP_UNDEF) {
+ max_reason = always_kmsg_dump ? KMSG_DUMP_MAX :
+ KMSG_DUMP_OOPS;
+ }
+ if (reason > max_reason)
+ continue;
+
+ dumper->dump(dumper, reason);
+ }
+ rcu_read_unlock();
+}
+```
+
+
+使用`kmsg\_dump()`之前要先使用`kmsg\_dump\_register()`来注册一个dumper,用于实际的log写操作。
+
+
+我们先来看看`kmsg\_dump\_register`的定义,只定义了一个dump\_list,将系统中所有注册的dump都挂在同一个list下,这就说明系统可以注册多个dumper。
+
+
+
+```
+int kmsg_dump_register(struct kmsg_dumper *dumper)
+{
+ …
+ if (!dumper->registered) {
+ dumper->registered = 1;
+ list_add_tail_rcu(&dumper->list, &dump_list);
+ err = 0;
+ }
+ …
+}
+```
+
+
+## 总结
+
+
+pstore dmesg主要工作流程如下:
+
+
+(1)初始化一个record结构体
+
+
+(2)先向其写入pstore头信息,如dmesg reason、oops发生次数等
+
+
+(3)从log buffer中读取一行log信息
+
+
+(4)若需要压缩信息,则执行压缩操作
+
+
+(5)调用后端的写函数,将record写入相应的后端设备
+
+wwqwq
+
+
+
+
+
+
+
diff --git "a/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201.md" "b/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ae0745cbba745886ad0ace066854f42eb9dc8834
--- /dev/null
+++ "b/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201.md"
@@ -0,0 +1,197 @@
+
+
+
+
+作者:新绎
+
+
+## 写在前面
+
+
+目前,pstore一次只支持打开一个后端。 如果一个新的后端想稍后注册, pstore将拒绝这个请求并返回一个错误。这个设计迫使我们关闭现有后端以使用新后端。
+
+
+内核支持某些类型的后端,例如ramoops和blk。在实际使用当中,我们还可以自行实现多种类型的后端。不同的后端根据不同的场景或业务进行信息收集。因此,他们需要同时工作,以满足各种需求。
+
+
+## 原始实现
+
+
+具体来说,由于全局变量`psinfo`的存在, pstore只接受第一个注册后端。如果一个新的后端想稍后注册, pstore将拒绝这个请求并返回一个错误。
+
+
+
+```
+int pstore_register(struct pstore_info *psi)
+{
+ if (backend && strcmp(backend, psi->name)) {
+ pr_warn("ignoring unexpected backend '%s'\n", psi->name);
+ return -EPERM;
+ }
+
+ /* Sanity check flags. */
+ if (!psi->flags) {
+ pr_warn("backend '%s' must support at least one frontend\n",
+ psi->name);
+ return -EINVAL;
+ }
+
+ /* Check for required functions. */
+ if (!psi->read || !psi->write) {
+ pr_warn("backend '%s' must implement read() and write()\n",
+ psi->name);
+ return -EINVAL;
+ }
+
+ mutex_lock(&psinfo_lock);
+ if (psinfo) {
+ pr_warn("backend '%s' already loaded: ignoring '%s'\n",
+ psinfo->name, psi->name);
+ mutex_unlock(&psinfo_lock);
+ return -EBUSY;
+ }
+ ...
+}
+```
+
+
+psinfo作为后端信息的存储结构体,一个psinfo只能保存一个后端。
+
+
+
+```
+struct pstore_info {
+ struct module *owner;
+ const char *name;
+
+ spinlock_t buf_lock;
+ char *buf;
+ size_t bufsize;
+
+ struct mutex read_mutex;
+
+ int flags;
+ int max_reason;
+ void *data;
+
+ int (*open)(struct pstore_info *psi);
+ int (*close)(struct pstore_info *psi);
+ ssize_t (*read)(struct pstore_record *record);
+ int (*write)(struct pstore_record *record);
+ int (*write_user)(struct pstore_record *record,
+ const char __user *buf);
+ int (*erase)(struct pstore_record *record);
+};
+```
+
+
+## 多后端实现
+
+
+### 修改全局变量
+
+
+在原始`fs/pstore/internal.h`中定义了全局变量`psinfo`
+
+
+`extern struct pstore\_info \*psinfo;`
+
+
+psinfo为后端信息的存储结构体,一个psinfo只能保存一个后端
+
+
+修改后:
+
+
+`extern struct pstore\_backends \*psback;`
+
+
+`psback`保存了所有使能`psinfo`的双向链表头节点。
+
+
+启动`psback`以及双向链表的定义如下:
+
+
+
+```
+struct pstore_info_list {
+ struct pstore_info *psi;
+ struct list_head list;
+ int index;
+};
+
+/**
+ * struct pstore_backends - management of pstore backends
+ * @list_entry: entry of pstore backend driver information list
+ * @front_cnt: count of each enabled frontend
+ * @flag: bitmap of enabled pstore backend
+ * @fs_ready: whether the pstore filesystem is ready
+ *
+ */
+
+struct pstore_backends {
+ struct list_head list_entry;
+ int front_cnt[PSTORE_TYPE_MAX];
+ u16 flag;
+ bool fs_ready;
+};
+```
+
+
+### 前端复用
+
+
+为了防止每注册一个后端就要注册相应的前端造成过多开销,我们选择对已经注册好的前端进行复用。如果当多个后端同时使能了同一前端,那么这个前端将会把自己收集的信息多写到这几个后端当中。
+
+
+
+
+
+
+代码实现:
+
+
+
+```
+static void pstore_dump(struct kmsg_dumper *dumper,
+ enum kmsg_dump_reason reason)
+{
+ struct pstore_info_list *entry;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(entry, &psback->list_entry, list)
+ if (entry->psi->flags & PSTORE_FLAGS_DMESG)
+ pstore_do_dump(dumper, reason, entry->psi, entry->index);
+ rcu_read_unlock();
+}
+```
+
+
+通过rcu锁以及对双向链表遍历的方式,前端可以线程安全地获取所有使能的后端,并且根据后端的使能情况执行写操作。
+
+
+### 让文件系统更直观
+
+
+由于多后端的存在,不同后端的输出文件将显得格外混乱,所以通过文件夹对不同后端进行分类的想法是自然而然产生的。
+
+
+通过修改`inode.c`,在`sys/fs/pstore`下建立相应后端的子文件夹,实现文件归类
+
+
+
+
+
+
+## 总结
+
+
+多后端支持的引入让pstore的使用更加灵活,可以根据不同后端功能以及业务场景同时使能多个后端,实现互不干扰,和谐共存。
+
+
+
+
+
+
+
+
diff --git "a/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267.md" "b/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267.md"
new file mode 100644
index 0000000000000000000000000000000000000000..4236a6963503e0e0f11d62ae24994315c5b0c621
--- /dev/null
+++ "b/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267.md"
@@ -0,0 +1,88 @@
+## 简介
+
+
+基于pstore的kdump调测工具是一个用于收集并存储crash kernel启动并执行vmcore转储过程中串口打印信息的工具,为kdump提供新的feature。
+方便对crash kernel启动并执行dump过程中所遇到的问题进行定位,能够覆盖crash kernel启动的绝大部分时间点。
+目前支持内核态以及用户态信息的全收集。
+
+
+仓库链接:
+
+
+\*目前对于内核pstore的改动已完成,正在进行用户态kdumpctl的整合
+
+
+## 背景
+
+
+目前kdump服务在使用过程中难免会遇到各种问题,导致vmcore无法正常生成。而在各种使用环境和因素的情况下,可能存在问题定位没有串口可用或者需要较高权限和复杂的流程来申请CN串口,那么我们需要一个机制来对crash kernel的打印信息进行转储,方便我们后续进行查看。
+
+
+当前新版的kdump支持在vmcore转储过程中对crash kernel的dmesg顺带进行保存,如下图所示:
+
+
+
+
+
+但是,这样的dmesg信息存储需要在crash kernel成功进入用户态并执行相应的脚本进行实现,如果crash kernel在内核态启动的过程中出现panic,亦或是kdump相关脚本没有正常工作,那么dmesg将无法进行保存。所以目前的crash kernel的dmesg保存机制能覆盖问题的点比较少,我们需要一个能够cover更多问题的调测工具。
+
+
+## 原理
+
+
+### pstore相关原理及修改
+
+
+pstore相关介绍和对应的补丁修改参见:
+
+
+[Pstore总览 - OpenAnolis 龙蜥操作系统开源社区](https://openanolis.cn/sig/Cloud-Kernel/doc/623611346526568454)
+
+
+[Pstore多后端支持补丁](https://openanolis.cn/sig/Cloud-Kernel/doc/646804783491448879)
+
+
+当前的pstore的内核态与用户态的log存储逻辑如下:
+
+
+
+
+
+对于用户态信息,pmsg只会接受用户对其的输入信息,而不会主动获取。而可以产生用户态输出的程序和服务有许多,包括各种service以及dump相关脚本,如果想采用这样一个方案进行用户态信息的收集,我们需要对用户态的输出进行重定向到pmsg。这样的操作有两个比较大的问题:
+
+
+1、重定向后原有的串口将不显示输出
+
+
+2、如果想cover所有用户态输出,需要在用户态进行大量的修改
+
+
+所以,我们希望从根源上高效地解决问题。我们注意到所以用户态向串口输出都会走tty驱动,那么我们可以实现一个新的pstore前端,该前端在tty驱动前有一个hook点,我们可以直接获取到用户态向tty驱动的输出,从而获取相关的log信息。
+
+
+
+
+
+## 工具流程
+
+
+基于pstore的kdump调测工具主要工作在crash kernel中,在crash kernel中配置好pstore后端ramoops相应的参数(内存地址,预留空间大小等),在crash kernel启动过程中会使能pstore并且获取内核态以及用户态的信息,实时输出到ramoops配置好的持久化内存当中。
+
+
+由于机器重启不会掉电(正常情况下),当我们重回第一个kernel的之后,我们对那块内存进行解析,就可以获取crash kernel相应的log输出。
+
+
+
+
+
+## 使用
+
+
+我们对工具进行了包装,与kdump进行融合,pstore相关的配置将由相应的脚本自动实现,使用者无需进行配置。在正常使用过程中,我们将工具包装进了kdumpctl命令。
+
+
+只需要在crash kernel执行过后输入kdumpctl showdebug,就可以很方便地对crash kernel的log输出进行查看。
+
+
+
+
diff --git "a/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/\351\241\271\347\233\256\347\256\200\344\273\213.md" "b/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/\351\241\271\347\233\256\347\256\200\344\273\213.md"
new file mode 100644
index 0000000000000000000000000000000000000000..8f8b3d07e9fa873033a1f1dcc81e30e3c39ddcb5
--- /dev/null
+++ "b/sig/AI/content/\345\206\205\346\240\270\350\260\203\346\265\213/\351\241\271\347\233\256\347\256\200\344\273\213.md"
@@ -0,0 +1,2 @@
+致力于各种内核调测技术的研发和产品化,包括但不限于kdump/pvdump, pstore, ftrace, 各种probes, perf/pmu, ebpf等技术。
+
diff --git "a/sig/AI/content/\346\234\210\346\212\245/2021.11.01~2021.11.14.md" "b/sig/AI/content/\346\234\210\346\212\245/2021.11.01~2021.11.14.md"
new file mode 100644
index 0000000000000000000000000000000000000000..a24d8165f34553df5f6fe9bc540470f97dbfd574
--- /dev/null
+++ "b/sig/AI/content/\346\234\210\346\212\245/2021.11.01~2021.11.14.md"
@@ -0,0 +1,84 @@
+### 会议主题
+
+
+首次非正式会议, 自由讨论的形式, 聊聊龙蜥内核版本计划, 研发流程及后续双周会主题等
+
+
+### 会议时间
+
+
+2021.11.03 15:00-17:00
+
+
+### 与会人
+
+
+* 会议主持: Shiloong
+* 来自统信,龙芯, 阿里云的龙蜥社区爱好者
+
+
+### 会议纪要
+
+
+* 会议由 Shioong 发起主持, 开场简单介绍了龙蜥 ANCK 版本情况及当前基本研发流程.
+
+* [202212.md](./202212.md)
+* [202301.md](./202301.md)
+* [Bugzilla用户文档.md](../../content/Bugzilla系统/Bugzilla用户文档.md)
+
+* 自由讨论中, 谢仲天提出如何尽快参与到内核社区共建的问题. 讨论认为,
+
+
+* + 1) 主动参与: 可通过向社区贡献开源特性参与社区内核研发; 可通过积极关注 kernel-sig bug 管理平台, 积极承担特性/bug 研发任务来参与;
+ + 2) 被动参考: 确定统一接口人, 由社区统一分派研发任务.
+
+
+* + 总之社区是极其开放的, 欢迎大家积极参与其中.
+
+
+* 卢彦表示关注内核性能测试相关 benchmark 评价与测试验收标准
+
+
+* + 阿里云在这一块有多年积累, 一些成熟经验计划在社区推广;
+ + 这块建议放到社区相应的 [QA Sig](https://openanolis.cn/sig/QA) 进一步深入交流.
+
+
+* 李雪峰介绍了龙芯内核同源异构相关进展:
+
+
+* + 表示龙芯内部已经有相关计划;
+ + 因这块工作量较大, 涉及内核及工具链; 且与架构相关的bug 一般难度较大.
+ + 龙芯内部还需要进一步讨论, 以确定排期等相关事项.
+
+
+* + 会上讨论认为这块可以在龙芯 sig 里进一步对齐.
+ + 当前ANCK 已经推出5.10内核, 希望能在这个内核尽快做起来.
+
+
+* 最后大家讨论了 kernel-sig 双周会的相关问题:
+
+
+* + 目前暂定双周会固定时间为第一周周三下午3:00-5:00; 下一次双周会时间 2021.11.17 15:00-17:00;
+ + 疫情期间以线上会议为主, 待国家放开后考虑线下会议;
+
+
+* + 会上头脑风暴了双周会话题:
+
+
+* + - 双周会会有一些例行事项: 1) kernel-sig 双周大事回顾; 2) kernel-sig 相关事项决策等等;
+ - 客户现场案例分享相关: 如在真实客户现场遇到的问题, 解决方案, 经验等分享交流;
+
+
+* + - 内核子系统相关: 如内核子系统相关新特性技术分享, 实例业务应用案例等;
+ - 内核相关业界软硬技术热点研讨: 如 eBPF 应用等等;
+
+
+* + - 客户解决方案相关话题: 如1)客户具体案例分享; 2) 应用软件生态适配相关话题;
+ - ANCK 内核历史经典问题,案例分享;
+
+
+* + - 软硬件协同, 跨平台支持技术等;
+ - 内核相关系列技术讲座;
+
+
+* + - 会上大家提议后面可以发起 ACK (Anolis Cloud Kernel 开发者大会); 待国内疫情放开后, 可以考虑先搞起线下 meetup.
diff --git "a/sig/AI/content/\346\234\210\346\212\245/202212.md" "b/sig/AI/content/\346\234\210\346\212\245/202212.md"
new file mode 100644
index 0000000000000000000000000000000000000000..5ace9b5cdb18d6179cf6200f9b7b4cb5d6a49112
--- /dev/null
+++ "b/sig/AI/content/\346\234\210\346\212\245/202212.md"
@@ -0,0 +1,85 @@
+# 整体进展
+- 发布 ANCK 4.19-027 版本。
+- 初步建立了龙蜥社区第三方驱动的研发流程,并试用该流程集成了国产化网迅网卡驱动。
+- ANCK-5.10 内核产品化。
+- 成立"浪潮信息龙蜥联合实验室"。
+
+# ANCK 4.19-027 版本
+## 内核更新
+- 版本更新至 4.19.91-27
+- 重要内核缺陷及安全漏洞(CVE)修复
+- 在 namespace_unlock 中使用 synchronize_rcu_expedited 加速 rcu 宽限期,使并发启动100个 busybox 容器的速度提升19%
+- 调整 Trusted Platform Module 驱动的缓冲区大小,避免上下文切换时因内存不足报错
+- 默认使能 mq-deadline IO 调度器
+- 提升 NVMe、megaraid_sas 和 mpt3sas 三个驱动的稳定性
+- 全面支持 Aero 系列 raid 卡
+- 修复了飞腾处理器 SMMU 的硬件缺陷导致的问题
+## 自研功能
+- 支持动态开启 Group Identity 特性
+- 支持稀疏文件映射使用系统零页,减少启动虚拟机时的内存消耗
+## CVE修复列表
+详情请参考:
+- [Anolis OS 7](https://anas.openanolis.cn/errata/detail/ANSA-2023:0002)
+- [Anolis OS 8](https://anas.openanolis.cn/errata/detail/ANSA-2023:0001)
+
+重要CVE列表:
+- CVE-2021-33656
+- CVE-2021-4037
+- CVE-2021-4159
+- CVE-2022-0001
+- CVE-2022-0002
+- CVE-2022-0494
+- CVE-2022-1012
+- CVE-2022-1048
+- CVE-2022-1184
+- CVE-2022-1198
+- CVE-2022-1462
+- CVE-2022-1679
+- CVE-2022-1729
+- CVE-2022-1734
+- CVE-2022-21125
+- CVE-2022-21166
+- CVE-2022-2153
+- CVE-2022-2318
+- CVE-2022-24958
+- CVE-2022-2503
+- CVE-2022-25258
+- CVE-2022-2586
+- CVE-2022-2588
+- CVE-2022-2602
+- CVE-2022-26365
+- CVE-2022-2639
+- CVE-2022-26490
+- CVE-2022-27223
+- CVE-2022-28388
+- CVE-2022-28389
+- CVE-2022-28390
+- CVE-2022-2978
+- CVE-2022-30594
+- CVE-2022-3176
+- CVE-2022-3202
+- CVE-2022-32250
+- CVE-2022-3542
+- CVE-2022-36879
+- CVE-2022-36946
+- CVE-2022-39188
+
+# 龙蜥社区第三方驱动
+建立第三方驱动的社区研发流程:https://openanolis.cn/sig/Cloud-Kernel/doc/721476448598622343
+
+网迅网卡已经按此流程合入 ANCK :
+- 支持ANCK-5.10 10GB 网迅网卡驱动: https://gitee.com/anolis/cloud-kernel/pulls/540
+- 支持ANCK-4.19 10GB 网迅网卡驱动: https://gitee.com/anolis/cloud-kernel/pulls/709
+- 支持ANCK-4.19 1GB 网迅网卡驱动: https://gitee.com/anolis/cloud-kernel/pulls/1043
+- 支持ANCK-5.10 1GB 网迅网卡驱动: https://gitee.com/anolis/cloud-kernel/pulls/1063
+
+# 重要议题
+- 讨论并决策了将 ANCK-5.10 作为 Anolis8 的默认产品化内核,详情请点击[这里](https://gitee.com/anolis/community/blob/master/proposals/Anolis8%E4%B8%8AANCK-5.10%E4%BA%A7%E5%93%81%E5%8C%96%E7%9A%84%E6%8F%90%E8%AE%AE.md)。
+- 讨论并决策了将 ANCK-5.10 作为 Anolis23 的当前默认内核,详情请点击[这里](https://gitee.com/anolis/community/blob/master/proposals/anck-5.10%E4%BD%9C%E4%B8%BAanolis23%E7%9A%84%E5%86%85%E6%A0%B8%E9%80%89%E5%9E%8B%E7%9A%84%E6%8F%90%E8%AE%AE.md)。
+
+# 运营活动
+- [浪潮信息正式发布基于龙蜥 Anolis OS 的服务器操作系统 Inspur KOS](https://openanolis.cn/news/726244284765327879)。
+- 于2022.12.24 举办了“[龙蜥走进系列活动之走进浪潮信息 MeetUp](https://mp.weixin.qq.com/s?__biz=Mzg4MTMyMTUwMQ==&mid=2247510368&idx=1&sn=95a1d511b32670f8388745682483046a&chksm=cf655a12f812d30494be938d7bf8a46b7244711c8fb75f44e8379ab261b1fd4aeb1c8bb0805e&scene=21#wechat_redirect)",并成立了浪潮信息龙蜥联合实验室,致力于共建龙蜥社区的软硬件兼容性生态、标准建设和技术创新等。
+
+
+TC2024080403
\ No newline at end of file
diff --git "a/sig/AI/content/\346\234\210\346\212\245/2022121.md" "b/sig/AI/content/\346\234\210\346\212\245/2022121.md"
new file mode 100644
index 0000000000000000000000000000000000000000..9718d343b780e08f1638b51b2b4574014e947b74
--- /dev/null
+++ "b/sig/AI/content/\346\234\210\346\212\245/2022121.md"
@@ -0,0 +1 @@
+xcvxcvxcvxcbcvvbasdfsda
\ No newline at end of file
diff --git "a/sig/AI/content/\346\234\210\346\212\245/202301.md" "b/sig/AI/content/\346\234\210\346\212\245/202301.md"
new file mode 100644
index 0000000000000000000000000000000000000000..154fa40ad1d79cabc278e4bf3dcbffdfb9c87047
--- /dev/null
+++ "b/sig/AI/content/\346\234\210\346\212\245/202301.md"
@@ -0,0 +1,108 @@
+# 整体进展
+
+
+
+修改文件20202202-102-1201-1210201-1-
+
+
+
+
+- 发布 ANCK 5.10-013 版本。
+- 确定KABI机制整体方案。
+- 浪潮信息龙蜥联合实验室的工作事项更新。
+
+# ANCK 5.10-013 版本
+
+## 内核更新
+
+- 版本更新至 5.10.134-13
+- 重要内核缺陷及安全漏洞(CVE)修复
+- 支持用户态/dev/ioasid
+- SWIOTLB机制性能优化
+- virtio-net 打开 napi.tx 优化 TCP Small Queue 性能
+- 支持AST2600 PCIe 2D VGA Driver
+- 支持FT2500处理器
+- 支持动态开启Group identity特性
+- arm64平台默认内核启动cmdline调整
+- 添加 Compact Numa Aware (CNA) spinlock 功能支持
+- 丰富arm64的perf mem和perf c2c功能
+- fsck.xfs 支持日志恢复
+- hugetext自适应按需大页
+- 支持SGX动态内存管理
+- 使能wireguard模块
+
+## CVE修复列表
+
+详情请参考:
+
+- [Anolis OS 7](https://anas.openanolis.cn/errata/detail/ANSA-2023:0002)
+- [Anolis OS 8](https://anas.openanolis.cn/errata/detail/ANSA-2023:0001)
+
+重要CVE列表:
+
+- CVE-2021-4037
+- CVE-2022-0171
+- CVE-2022-1679
+- CVE-2022-2585
+- CVE-2022-2586
+- CVE-2022-2588
+- CVE-2022-2602
+- CVE-2022-26373
+- CVE-2022-2663
+- CVE-2022-2905
+- CVE-2022-2978
+- CVE-2022-3028
+- CVE-2022-3061
+- CVE-2022-3169
+- CVE-2022-3176
+- CVE-2022-3435
+- CVE-2022-3521
+- CVE-2022-3524
+- CVE-2022-3534
+- CVE-2022-3535
+- CVE-2022-3542
+- CVE-2022-3545
+- CVE-2022-3564
+- CVE-2022-3565
+- CVE-2022-3566
+- CVE-2022-3567
+- CVE-2022-3586
+- CVE-2022-3594
+- CVE-2022-3621
+- CVE-2022-3623
+- CVE-2022-3625
+- CVE-2022-3628
+- CVE-2022-3629
+- CVE-2022-3633
+- CVE-2022-3635
+- CVE-2022-3646
+- CVE-2022-3649
+- CVE-2022-36946
+- CVE-2022-39189
+- CVE-2022-39190
+- CVE-2022-39842
+- CVE-2022-40307
+- CVE-2022-40768
+- CVE-2022-41222
+- CVE-2022-41674
+- CVE-2022-42719
+- CVE-2022-42720
+- CVE-2022-42721
+- CVE-2022-42722
+- CVE-2022-42895
+- CVE-2022-42896
+- CVE-2022-43750
+- CVE-2022-4378
+
+# 龙蜥社区第三方驱动
+
+* 提供主流GPU在AnolisOS的Driver、CUDA、cuDNN安装测试与卸载指导文档:https://openanolis.cn/sig/AI_SIG/doc/721423765456666646
+
+# 重要议题
+
+- 调研并讨论了KABI机制的整体方案与实现细节。
+- 基于浪潮信息龙蜥联合实验室,讨论了关于整机硬件兼容性的相关事项,后续长期共建 AnolisOS 硬件兼容性标准和生态。
+
+# 运营活动
+
+- 无
diff --git "a/sig/AI/content/\346\234\210\346\212\245/\346\234\210\346\212\245\350\257\264\346\230\216.md" "b/sig/AI/content/\346\234\210\346\212\245/\346\234\210\346\212\245\350\257\264\346\230\216.md"
new file mode 100644
index 0000000000000000000000000000000000000000..68a17e8befde71495884a20eda77d2f90e6d8538
--- /dev/null
+++ "b/sig/AI/content/\346\234\210\346\212\245/\346\234\210\346\212\245\350\257\264\346\230\216.md"
@@ -0,0 +1,18 @@
+- 每月的月初总结发出上月的报告,并更新到 SIG 页面,如 2022.12
+
+- 月报包含内容:
+ + 整体进展:SIG 该月的亮点特性汇总。
+ + 具体进展:SIG 该月项目的详细进展,分别展开细节。
+ + 重要议题: SIG 该月讨论的重要议题。
+ + 运营活动: SIG 该月发生的运营活动。
+
+
+66666666666666666666666666666666666666666666666
+
+
+04444433333333333333333333333333333333--
+
+
+ 不写项目编码
+ ------------------------
+ 热呃呃呃呃呃呃呃呃呃呃呃呃呃呃呃
\ No newline at end of file
diff --git "a/sig/AI/content/\346\236\204\345\273\272\345\271\263\345\217\260ABS/LifseaOS \351\225\234\345\203\217.md" "b/sig/AI/content/\346\236\204\345\273\272\345\271\263\345\217\260ABS/LifseaOS \351\225\234\345\203\217.md"
new file mode 100644
index 0000000000000000000000000000000000000000..bbd37119efc88b08fc7c9c3c40cb24800b52034a
--- /dev/null
+++ "b/sig/AI/content/\346\236\204\345\273\272\345\271\263\345\217\260ABS/LifseaOS \351\225\234\345\203\217.md"
@@ -0,0 +1 @@
+### 敬请期待
\ No newline at end of file
diff --git "a/sig/AI/content/\346\236\204\345\273\272\345\271\263\345\217\260ABS/\344\272\221\345\216\237\347\224\237.md" "b/sig/AI/content/\346\236\204\345\273\272\345\271\263\345\217\260ABS/\344\272\221\345\216\237\347\224\237.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e2bb458610b58a3233f42d8a525a3b82a3312e54
--- /dev/null
+++ "b/sig/AI/content/\346\236\204\345\273\272\345\271\263\345\217\260ABS/\344\272\221\345\216\237\347\224\237.md"
@@ -0,0 +1,54 @@
+# 云原生
+基于微服务架构提高灵活性和可维护性,借助敏捷方法和运维自动化,利用云平台设施实现弹性伸缩、动态调度、优化资源利用率。为方便项目拥有者构建管理, ABS提供了「Docker镜像」、「云原生ACNS版本」构建功能。
+
+### Docker镜像
+持续交付提供镜像构建推送至镜像仓库服务,支持不同产品类型和OS架构的镜像文件,并存储于Docker镜像仓库,用于后续的部署任务。
+##### 新建
+点击 「+ 新建」>「Docker镜像」,进入新建页面。
+
+
+根据需求填写对应的设置参数。
+
+
+配置参数:
+
+| 名称 |描述 |
+|---|---|
+| 镜像名称 | 该产出物为镜像所用名的名称,支持自定义命名。产出物可用于后续部署任务。 |
+| 描述 | 概述镜像的内容。 |
+| 仓库地址 | 用户所用的仓库地址 |
+| 分支名称 | 用户所用的分支 |
+| Dockerfile文件路径 | Dockerfile存放的路径URL。|
+
+##### 删除
+点击镜像详情,右侧的「删除」按钮,即可完成删除。
+
+
+
+### 云原生ACNS版本
+龙蜥云原生套件是龙蜥社区社区云原生SIG输出的基于kubernetes发行版本为基础而集成的套件能力,可以提供一键式部署、开箱即用、以及丰富的云原生基础能力。
+##### 新建
+点击 「+ 新建」>「云原生ACNS版本」,进入新建页面。
+
+根据需求填写对应的设置参数。
+
+
+
+配置参数:
+
+| 名称 |描述 |
+|---|---|
+| 构建名称 | 该产出物为构建所用名的名称。 |
+| 描述 | 概述构建的内容。 |
+| 产品及版本 | 目前仅支持基于anolis-cloud-native仓库产品的ACNS构建。|
+| 镜像名称 | 默认:anolis-cloud-native |
+| 架构 | 目前仅支持x86_84。 |
+| 仓库地址 | 使用默认。 |
+| 分支名称 | 使用默认。 |
+
+##### 删除
+点击镜像详情,右侧的「删除」按钮,即可完成删除。
+
+
+
+
diff --git "a/sig/AI/content/\346\236\204\345\273\272\345\271\263\345\217\260ABS/\345\206\205\346\240\270\346\272\220\347\240\201.md" "b/sig/AI/content/\346\236\204\345\273\272\345\271\263\345\217\260ABS/\345\206\205\346\240\270\346\272\220\347\240\201.md"
new file mode 100644
index 0000000000000000000000000000000000000000..bbd37119efc88b08fc7c9c3c40cb24800b52034a
--- /dev/null
+++ "b/sig/AI/content/\346\236\204\345\273\272\345\271\263\345\217\260ABS/\345\206\205\346\240\270\346\272\220\347\240\201.md"
@@ -0,0 +1 @@
+### 敬请期待
\ No newline at end of file
diff --git "a/sig/AI/content/\346\236\204\345\273\272\345\271\263\345\217\260ABS/\350\275\257\344\273\266\345\214\205\346\236\204\345\273\272.md" "b/sig/AI/content/\346\236\204\345\273\272\345\271\263\345\217\260ABS/\350\275\257\344\273\266\345\214\205\346\236\204\345\273\272.md"
new file mode 100644
index 0000000000000000000000000000000000000000..fd138f31992c61a1083729a2b5b243e12b8956cd
--- /dev/null
+++ "b/sig/AI/content/\346\236\204\345\273\272\345\271\263\345\217\260ABS/\350\275\257\344\273\266\345\214\205\346\236\204\345\273\272.md"
@@ -0,0 +1,64 @@
+# 软件包构建
+### 介绍
+两种构建模式:\
+1.测试构建:服务开发者进行测试,不作为正式官方发布使用。\
+2.生产构建:服务于官方产品正式构建及发布使用。
+
+### 添加软件包
+ABS 提供了添加软件包的功能。你可以在项目 **从外部导入**或**从平台上选择**,将软件包添加到项目中。
+
+
+#### 从外部倒入
+ 点击 「+ 添加软件包」 >「从外部导入」 ,项目拥有者可以从Gitee仓库导入到ABS平台。
+
+
+Tips:\
+ a. 目前只支持Gitee仓库的单个软件包导入。\
+ b. 不可重复的导入相同分支下的软件包。\
+ c. 软件包描述暂不支持后期修改内容。请项目拥有者谨慎填写。
+
+#### 从平台上选择
+ 点击 「+ 添加软件包」>「从外部导入」,项目拥有者可以从ABS平台上公开软件包导入。
+
+
+
+### 构建软件包
+#### 需要完成基础设置
+创建项目,并将软件包添加到该项目。
+
+#### 项目配置产品和OS架构
+
+#### 开始构建
+##### 测试构建
+准备阶段完成后,在软件包详情页右上角点击「测试构建」即可开始。
+
+
+
+##### 生产构建
+准备阶段完成后,在软件包详情页右上角点击「生产构建」即可开始。
+
+
+然后,选择配置的产品类型。
+
+\
+确定后,跳到官方项目下构建。结束后,可查看构建结果。
+
+Tips:\
+个人项目的构建默认属于**测试构建**,rpm包如果有maintainer/contributor权限可以提交**生产构建**。
+
+#### 构建结果
+构建结束后,可查看构建结果。
+
+\
+Tips:\
+成功构建的软件包不可重复构建。
+
+构建结果分四个部分:
+- **结果状态**
+ - 根据需求展现软件包构建的龙蜥产品上和OS架构,可通过「Tab标签」切换查看详细构建信息。同时,点击「x86_64」或「Arrch64」查看详细构建日志。
+- **代码库**
+ - 将记录导入软件包的代码库、分支及提交信息,不受其他分支的影响。
+- **RPM包下载**
+ - 包含了当前产品和OS架构中的软件包、src源码包。提供用户下载到本地。
+- **YUM源**
+ - 用户可通过配置网络yum源,从指定的服务器下载并且安装。
\ No newline at end of file
diff --git "a/sig/AI/content/\346\236\204\345\273\272\345\271\263\345\217\260ABS/\351\225\234\345\203\217.md" "b/sig/AI/content/\346\236\204\345\273\272\345\271\263\345\217\260ABS/\351\225\234\345\203\217.md"
new file mode 100644
index 0000000000000000000000000000000000000000..67ffa853d8ad510f3307545da165ed3279cbb9e3
--- /dev/null
+++ "b/sig/AI/content/\346\236\204\345\273\272\345\271\263\345\217\260ABS/\351\225\234\345\203\217.md"
@@ -0,0 +1,63 @@
+# 镜像
+
+### ISO镜像
+ABS提供了Rebrand镜像构建推送至镜像仓库服务,并存储于服务器仓库,用于后续的下载和部署任务。一键构建基于Anolis OS发行版的ISO镜像。目前该功能可以支持用户自定义替换ISO镜像中的「logo文字信息」、「图片信息」等信息。
+
+#### 一.镜像列表
+镜像列表将不同阶段和架构类型的镜像集合,每个镜像有不同的构建状态组成。
+镜像列表分为4个部分:
+1. **搜索框:** 通过搜索功能,可以在快速通过镜像名称全局范围内查找镜像。
+2. **新建镜像:** 可新建ISO镜像和VHD镜像。
+3. **排序:** 按照条件筛选查找镜像。
+4. **镜像总览:** 主要提供了镜像维度和构建状态总览两个视角。
+
+
+
+#### 二.如何新建镜像和删除
+
+##### 新建
+点击 「+ 新建Rebrand镜像」 ,可以进入表单填写页,根据需求填写对应的设置参数。
+
+
+基本格式如下:
+
+| 名称 | 描述 |
+|------|------|
+| 镜像名称 | 生成镜像文件的名称。 |
+| OS 架构 | 生成的镜像能够在此架构上安装,支持x86_64和aarch64架构,更多类型正在接入中。 |
+| 产品及版本 | 基于此产品进行镜像构建,支持Anolis OS 8.4,更多产品类型正在接入中。 |
+| 镜像类型 | 生成镜像的文件格式,支持ISO镜像,更多镜像类型正在接入中。 |
+| 构建模式 | 这里是列表文本生成镜像的模式,支持最小化镜像和全量镜像。|
+| 描述 | 用于本次生成镜像的描述说明。 |
+| 系统信息 |用于修改需要rebrand包的配置信息,包含名称配置和图标配置。 |
+| 名称配置 | 用于修改anolis-release包中的信息,包含产品名称、系统名称、系统ID、官方地址等参数。 |
+| 图标配置 | 用于修改anolis-logos包中的信息,包含产品名称、系统LOGO、系统ICON、桌面背景图等参数。 |
+| 产品名称 | 对应DIST字段,例如Anolis OS 8的产品名称为;an8。|
+| 系统名称 | 勾选名称配置后为必填项,在os-release中对应NAME字段。 |
+| 系统ID | 勾选名称配置后为必填项,在os-release中对应ID字段。 |
+| 官方地址 | 勾选名称配置后为必填项,在os-release中对应HOME_URL字段。 |
+| 系统LOGO | 勾选图标配置后为必填项,svg类型图片,大小不超过1MB,尺寸不限。 |
+| 系统ICON | 勾选图标配置后为必填项,svg类型图片,大小不超过1MB,尺寸不限。 |
+| 桌面背景图 | 勾选图标配置后为必填项,png类型图片,大小不超过10MB,尺寸不限,推荐使用1920x1200px,其它尺寸可能造成显示的图片变形或模糊等问题。 |
+
+注:
+1. 最小化镜像:是指仅包含操作系统发行版的基础应用软件包的镜像,这些基础应用软件包可以保证操作系统正常启动。容量大约为1G左右。
+2. 全量镜像:是指包含了操作系统发行版的所有应用软件包的镜像。容量大约为8G左右。
+3. 选择最小化镜像模式如果替换了图标配置,在镜像安装之后并不会立即显示图片信息,需要用户手动安装桌面应用之后(例如 KDE 或者 GNOME 等),才会正常显示替换之后的图片信息。
+4. 仅支持1个构建一个镜像同时构建,如需构建多个镜像,请在上一个镜像构建完成后,再次进行构建镜像。
+
+##### 删除
+选择要删除的镜像,在详情页右上角选择「删除」即可。
+
+
+
+
+### VHD镜像
+#### 敬请期待
+
+
+
+
+
+
+
diff --git "a/sig/AI/content/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244\350\257\276\347\250\213\346\216\245\345\205\245\346\214\207\345\257\274.md" "b/sig/AI/content/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244\350\257\276\347\250\213\346\216\245\345\205\245\346\214\207\345\257\274.md"
new file mode 100644
index 0000000000000000000000000000000000000000..d13161ade3d8431eaeddc633ac4bdedc72a2e099
--- /dev/null
+++ "b/sig/AI/content/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244/\351\276\231\350\234\245\345\256\236\351\252\214\345\256\244\350\257\276\347\250\213\346\216\245\345\205\245\346\214\207\345\257\274.md"
@@ -0,0 +1,38 @@
+龙蜥实验室【创作中心】服务于实验室课程学习中心,用户可通过在创作中心创作课程,提交 PR ,管理员审核,最终进行上架。
+
+一、登录[龙蜥实验室](https://lab.openanolis.cn/),如果没有注册过龙蜥社区需要先进行注册。实验室首页如下图所示:
+
+二、打开创作中心,把鼠标放在右上角个人头像上会出现下拉选择框,选择【创作中心】
+
+三、创作课程,点击右上角【创作课程】按钮
+
+打开创作课程后填写课程信息,其中字段描述如下:
+
+1. 课程名称:课程展示的标题;2. 课程描述:课程描述;3. 课程分类:选择课程学习;4. 课程难度:分为初级、中级、高级等,选择对应的课程难度;5: 课程总时长:输入一个数字,比如30,代表用户学习完课程需要花费30min;6:课程封面图:可以上传自定义的课程封面,如果不上传则有默认封面图提供;7. 课程领域: 目前提供内核、编译器、云原生、CentOS 迁移、算法、IO、DDE等领域分类,选择一个课程所属的领域。
+
+
+填完课程基本信息后添加保存即可。
+
+三、添加章节,创作完课程之后为课程添加一个章节,在课程最后侧点击【添加章节】按钮
+
+打开添加章节后填写章节信息,其中字段描述如下:
+
+1. 章节名称:章节展示的标题;2. 章节描述:章节描述;3. 章节难度:分为初级、中级、高级等,选择对应的章节难度;5: 章节总时长:输入一个数字,比如30,代表用户学习完章节需要花费30min,此时实验室提供的机器使用时长也是30min,超过30min后机器会被自动释放;6:章节封面图:可以上传自定义的章节封面,如果不上传则有默认封面图提供;7. 排序: 章节在课程中的顺序,值为1表示是课程的第一个章节,依次类推;8. 最大并发数:章节允许同时体验的最大人数,0默认不限制,由于实验室机器资源有限,一般取值不超过10个;9. cpu架构:机器的cpu机构,目前有x86和arm 两种;10. 镜像:机器安装的系统镜像,一般选择AnolisOS 8 版本或AnolisOS 7 版本;11. 机器规格:机器提供的规格大小,一般为2c4g或2c8g(c代表cpu, g 代表内存), 其他特殊机器规格申请会被严格审核,如神龙架构的bare_metal和第七代机器ecs.g7.xlarge等。
+
+
+四、添加步骤,填写完章节信息之后,点击【添加 Steps】按钮,为章节添加一个步骤,其中
+步骤类型分为START、STEPS、FINISH, START表示步骤开始,顺序为1,STEPS 为步骤正文,FINISH 为步骤结束。右侧是一个 Markdown 输入框,用于输入步骤内容,支持预览,上传图片等操作。
+
+添加完步骤后点击保存即可,如果步骤内容中有 shell 命令, 请使用 [[ ]] 替代markdown中的代码格式,这样审核通过后可以在页面上直接点击命令将命令自动粘贴到右侧的终端内。
+
+五、提交审核,课程编写完成之后可以通过【预览】功能进行预览,没有问题之后点击【下载配置】按钮进行配置下载,下载完之后点击【提交审核】按钮
+
+点击完提交审核按钮之后,将下载下来的配置在gitee仓库(https://gitee.com/anolis/anolis-lab-courses),anolis-courses 目录下提交一个课程pr,并将pr链接填进输入框,点击确定即可。
+
+
+六、提交审核之后等待管理员审核,管理员审核通过之后在实验室课程中心就能看到了
+
+以上就是龙蜥实验室创作中心创作课程的完整过程,如使用过程中有问题,欢迎联系[基础设施 SIG 组](https://openanolis.cn/sig/SIG-Infra)。
+
+
+加点内容
diff --git a/sig/AI/sig-info.yaml b/sig/AI/sig-info.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..6158469e2cdb31f428ebc29963a9b02e92b6f9b1
--- /dev/null
+++ b/sig/AI/sig-info.yaml
@@ -0,0 +1,25 @@
+name: 人工智能兴趣小组
+en_name: AI
+home_page: https://openanolis.cn/sig/AI_SIG
+description: AI SIG致力于构建Anolis OS上AI软件栈,包括流行AI框架TensorFlow/PyTorch等,AI加速库,和相应软件方案。
+en_description: AI SIG is committed to building the AI software stack on Anolis OS, including popular AI frameworks TensorFlow/PyTorch, AI acceleration libraries, and corresponding software solutions.
+mailing_list: os@lists.openanolis.cn
+avatar: assets/头像/images.jpg
+maintainers:
+- openanolis_id: linsheng
+ gitee_id: forrest_ly
+- openanolis_id: linddd
+ gitee_id: zhonglingh
+- openanolis_id: wenhuanh
+ gitee_id:
+
+contributors:
+- openanolis_id:
+ gitee_id:
+
+repositories:
+- repo:
+ - src-anolis-ai/pytorch
+ - src-anolis-ai/intel-extension-for-pytorch
+ - src-anolis-ai/neural-compressor
+ - src-anolis-ai/tensorflow
\ No newline at end of file
diff --git a/sig/ARM_SIG/README.md b/sig/ARM_SIG/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..db01cac5f4bb7b533e880edd35e3db46843887a3
--- /dev/null
+++ b/sig/ARM_SIG/README.md
@@ -0,0 +1,13 @@
+## SIG说明
+
+ARM ARCH SIG致力于ARM架构软件生态的共建和推广,以及基于Anolis社区ANCK内核支持ARM Vendors平台。
+
+## 邮件列表
+arm-arch@lists.openanolis.cn
+
+## 代码仓库
+https://gitee.com/anolis/arm-cloud-kernel
+
+## 钉钉群
+
+欢迎使用钉钉扫码入群
diff --git a/sig/ARM_SIG/assets/EL0_Recovery.png b/sig/ARM_SIG/assets/EL0_Recovery.png
new file mode 100644
index 0000000000000000000000000000000000000000..11249e124c68c62a9a8c117ed7f8e66bbb6f718b
Binary files /dev/null and b/sig/ARM_SIG/assets/EL0_Recovery.png differ
diff --git a/sig/ARM_SIG/assets/EL2_Recovery_x86.png b/sig/ARM_SIG/assets/EL2_Recovery_x86.png
new file mode 100644
index 0000000000000000000000000000000000000000..a1233d7128fe1ec373afd5ff427620378bf40d39
Binary files /dev/null and b/sig/ARM_SIG/assets/EL2_Recovery_x86.png differ
diff --git a/sig/ARM_SIG/assets/MCA_categories.jpg b/sig/ARM_SIG/assets/MCA_categories.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..afd423dee769926c644b453975cdb6a004c7c0f8
Binary files /dev/null and b/sig/ARM_SIG/assets/MCA_categories.jpg differ
diff --git a/sig/ARM_SIG/assets/MCA_categories_2.png b/sig/ARM_SIG/assets/MCA_categories_2.png
new file mode 100644
index 0000000000000000000000000000000000000000..6a46e29955b200eab826bc0c425fe190774652e7
Binary files /dev/null and b/sig/ARM_SIG/assets/MCA_categories_2.png differ
diff --git a/sig/ARM_SIG/assets/RAS_OS_Error_Flow.png b/sig/ARM_SIG/assets/RAS_OS_Error_Flow.png
new file mode 100644
index 0000000000000000000000000000000000000000..abb2fbd9cc39832fc3ce6eb115bcca757016619c
Binary files /dev/null and b/sig/ARM_SIG/assets/RAS_OS_Error_Flow.png differ
diff --git a/sig/ARM_SIG/assets/Scrub_Recovery.png b/sig/ARM_SIG/assets/Scrub_Recovery.png
new file mode 100644
index 0000000000000000000000000000000000000000..c9ba9f5cfa19da1291fd4b9832f4c9a8061ac326
Binary files /dev/null and b/sig/ARM_SIG/assets/Scrub_Recovery.png differ
diff --git a/sig/ARM_SIG/assets/bugzilla/addsubcomponent.png b/sig/ARM_SIG/assets/bugzilla/addsubcomponent.png
new file mode 100644
index 0000000000000000000000000000000000000000..da3af54f3450ea84affa34b16a33bc976ba963b7
Binary files /dev/null and b/sig/ARM_SIG/assets/bugzilla/addsubcomponent.png differ
diff --git a/sig/ARM_SIG/assets/bugzilla/api-key.png b/sig/ARM_SIG/assets/bugzilla/api-key.png
new file mode 100644
index 0000000000000000000000000000000000000000..8da3b0b4bcd782b45eae82070449d6d781c149d0
Binary files /dev/null and b/sig/ARM_SIG/assets/bugzilla/api-key.png differ
diff --git a/sig/ARM_SIG/assets/bugzilla/api.png b/sig/ARM_SIG/assets/bugzilla/api.png
new file mode 100644
index 0000000000000000000000000000000000000000..c5bcfd5a1c16170f395955f1b2041076da5d6f5f
Binary files /dev/null and b/sig/ARM_SIG/assets/bugzilla/api.png differ
diff --git a/sig/ARM_SIG/assets/bugzilla/bug-list-2.png b/sig/ARM_SIG/assets/bugzilla/bug-list-2.png
new file mode 100644
index 0000000000000000000000000000000000000000..39e04916cf945d9f603632a229e19ad6b1865e63
Binary files /dev/null and b/sig/ARM_SIG/assets/bugzilla/bug-list-2.png differ
diff --git a/sig/ARM_SIG/assets/bugzilla/bug-list.png b/sig/ARM_SIG/assets/bugzilla/bug-list.png
new file mode 100644
index 0000000000000000000000000000000000000000..a0775ffe79b52631e654895556103115f22e85d7
Binary files /dev/null and b/sig/ARM_SIG/assets/bugzilla/bug-list.png differ
diff --git a/sig/ARM_SIG/assets/bugzilla/bugstatus.png b/sig/ARM_SIG/assets/bugzilla/bugstatus.png
new file mode 100644
index 0000000000000000000000000000000000000000..7b4e7ccaf993aca09bf37ac862b08e839fd191be
Binary files /dev/null and b/sig/ARM_SIG/assets/bugzilla/bugstatus.png differ
diff --git a/sig/ARM_SIG/assets/bugzilla/bugzilla-anolis.png b/sig/ARM_SIG/assets/bugzilla/bugzilla-anolis.png
new file mode 100644
index 0000000000000000000000000000000000000000..cf914707ac0d4ade10b928502fb47b07d02f5253
Binary files /dev/null and b/sig/ARM_SIG/assets/bugzilla/bugzilla-anolis.png differ
diff --git a/sig/ARM_SIG/assets/bugzilla/bugzillarc.png b/sig/ARM_SIG/assets/bugzilla/bugzillarc.png
new file mode 100644
index 0000000000000000000000000000000000000000..2b3e4d5673cdcd02b61dd1817a5e49986010060f
Binary files /dev/null and b/sig/ARM_SIG/assets/bugzilla/bugzillarc.png differ
diff --git a/sig/ARM_SIG/assets/bugzilla/classification.png b/sig/ARM_SIG/assets/bugzilla/classification.png
new file mode 100644
index 0000000000000000000000000000000000000000..07c235f1d7f122599ad0641ee9bc21671c94f3f5
Binary files /dev/null and b/sig/ARM_SIG/assets/bugzilla/classification.png differ
diff --git a/sig/ARM_SIG/assets/bugzilla/deletesubcomponent.png b/sig/ARM_SIG/assets/bugzilla/deletesubcomponent.png
new file mode 100644
index 0000000000000000000000000000000000000000..097430a9249544cca595902aa856c01da7133500
Binary files /dev/null and b/sig/ARM_SIG/assets/bugzilla/deletesubcomponent.png differ
diff --git a/sig/ARM_SIG/assets/bugzilla/edit-param.png b/sig/ARM_SIG/assets/bugzilla/edit-param.png
new file mode 100644
index 0000000000000000000000000000000000000000..b3e140c9fefe0c30cffcf7dd00141ed8f998f516
Binary files /dev/null and b/sig/ARM_SIG/assets/bugzilla/edit-param.png differ
diff --git a/sig/ARM_SIG/assets/bugzilla/mainpage1.png b/sig/ARM_SIG/assets/bugzilla/mainpage1.png
new file mode 100644
index 0000000000000000000000000000000000000000..e3c95a9747fff20215a61d4dba6fa60c75a7cf44
Binary files /dev/null and b/sig/ARM_SIG/assets/bugzilla/mainpage1.png differ
diff --git a/sig/ARM_SIG/assets/bugzilla/new.png b/sig/ARM_SIG/assets/bugzilla/new.png
new file mode 100644
index 0000000000000000000000000000000000000000..7b65c11767943b0409538d4bcfd466c8a21de0ef
Binary files /dev/null and b/sig/ARM_SIG/assets/bugzilla/new.png differ
diff --git a/sig/ARM_SIG/assets/bugzilla/param-info.png b/sig/ARM_SIG/assets/bugzilla/param-info.png
new file mode 100644
index 0000000000000000000000000000000000000000..9cddc2d5694f2e841ba6dec5f278e56d42989df8
Binary files /dev/null and b/sig/ARM_SIG/assets/bugzilla/param-info.png differ
diff --git a/sig/ARM_SIG/assets/bugzilla/plugin.png b/sig/ARM_SIG/assets/bugzilla/plugin.png
new file mode 100644
index 0000000000000000000000000000000000000000..9a07422cdf8e1d6bd8d2e57f8eb8ff965c1acd4e
Binary files /dev/null and b/sig/ARM_SIG/assets/bugzilla/plugin.png differ
diff --git a/sig/ARM_SIG/assets/bugzilla/product.png b/sig/ARM_SIG/assets/bugzilla/product.png
new file mode 100644
index 0000000000000000000000000000000000000000..fcb90e9376149b00e715fd465431a7f42778c9a1
Binary files /dev/null and b/sig/ARM_SIG/assets/bugzilla/product.png differ
diff --git a/sig/ARM_SIG/assets/bugzilla/sub component.png b/sig/ARM_SIG/assets/bugzilla/sub component.png
new file mode 100644
index 0000000000000000000000000000000000000000..2a2806d3a09952ab3e73fd9ad2af0960bbf45c39
Binary files /dev/null and b/sig/ARM_SIG/assets/bugzilla/sub component.png differ
diff --git a/sig/ARM_SIG/assets/m1_ras_flow.png b/sig/ARM_SIG/assets/m1_ras_flow.png
new file mode 100644
index 0000000000000000000000000000000000000000..aacfbe4232050ab2b66b0346d1bfdbb5989c0824
Binary files /dev/null and b/sig/ARM_SIG/assets/m1_ras_flow.png differ
diff --git a/sig/ARM_SIG/assets/ras_x86.png b/sig/ARM_SIG/assets/ras_x86.png
new file mode 100644
index 0000000000000000000000000000000000000000..95cba3f7f67f7c77dfee2324afff3e20656a18de
Binary files /dev/null and b/sig/ARM_SIG/assets/ras_x86.png differ
diff --git a/sig/ARM_SIG/assets/uaccess.png b/sig/ARM_SIG/assets/uaccess.png
new file mode 100644
index 0000000000000000000000000000000000000000..4325aae4893ac70cba21f7b47faedabca668657d
Binary files /dev/null and b/sig/ARM_SIG/assets/uaccess.png differ
diff --git a/sig/ARM_SIG/content/RAS/Anolis OS Cloud Kernel RAS White Paper.md b/sig/ARM_SIG/content/RAS/Anolis OS Cloud Kernel RAS White Paper.md
new file mode 100644
index 0000000000000000000000000000000000000000..aff77f788cd9a721b818e696bcaadfd047222640
--- /dev/null
+++ b/sig/ARM_SIG/content/RAS/Anolis OS Cloud Kernel RAS White Paper.md
@@ -0,0 +1,982 @@
+# Anolis OS Cloud Kernel: RAS White Paper
+
+## REVISION HISTORY
+
+| DATE | VERSION | DESCRIPTION | AUTHOR | APPROVER |
+| ---------- | ------- | --------------- | ----------------------- | ----------- |
+| 2022/12/31 | 1.0 | Initial version | Shuai Xue, Ruidong Tian | Baolin Wang |
+
+## Terms and Abbreviations
+
+| Abbreviation | Definition |
+| ------------ | ----------------------------------------------------------------------------- |
+| RAS | Reliability, Availability and Serviceability |
+| SLA | Service Level Agreement |
+| CE | Correctable Error |
+| UCE | Uncorrected Correctable Error |
+| MCA | Machine-Check Architecture |
+| CMCI | Corrected Machine Check Interrupt |
+| MCE | Machine-Check Exception |
+| SEA | Synchronous External Abort |
+| ELx | Exception levels are referred to as EL, with x as a number between 0 and 3 |
+| ECC | Error Correction Code |
+| SECDED | Single-bit Error Correction and Double-bit Error Detection |
+| TF-A | Trusted Firmware-A |
+| HEST | Hardware Error Source Table |
+| GHES | Generic Hardware Error Source |
+
+## Abstract
+
+Reliability, availability and serviceability (RAS) is a computer hardware engineering term referring to the elimination of hardware failures to ensure maximum system uptime.
+
+This document describes the memory RAS features in detail, explaining how server availability is enhanced with the memory RAS features on Yitian 710 servers running Anolis OS Cloud Kernel.
+
+## Introduction
+
+The server is one of the key components of any modern data center infrastructure. It consists of a variety of hardware parts, including processors, storage devices, PCIe devices, power supplies, and fans.
+
+In today’s hyper scale Cloud Data centers, correct server operation and data integrity are critical to ensure service continuity. In other words, we must avoid data corruption no matter data is stored in any server component (memory, cache, or processor registers) or transmitted through any platform links (Intel®UPI, PCI Express, or DMI).
+
+Server reliability, availability, and serviceability (RAS) are crucial issues for modern enterprise IT shops that deliver mission-critical applications and services, as application delivery failures can be extremely costly per hour of system downtime. Although hardware failures are rare, they are inevitable but random events, especially for large scale data centers. If such incidents are not efficiently diagnosed, the consequences may be very serious and sometimes even catastrophic, such as data corruption or server crash. which are top concerns to meet SLAs (Service Level Agreement) for cloud end users. The likelihood of such failures increases statistically with the size of the servers, data, and memory required for these deployments. Furthermore, considering today’s server system with more and more CPU cores shipped on hundreds of Virtual Machines (VM) and DDR DIMMs operating on it, the impact of server crash caused by hardware failures is much bigger than before.
+
+Modern CPU offers an extensive and robust set of RAS features in silicon to provide error detection, correction, containment, and recovery in all processors, memory, and I/O data paths based on Intel Machine Check Architecture (MCA) Recovery mechanism or ARM v8.2 RAS Extension. When a server component fails, OS with such RAS features is capable of recovery from hardware error, maximizing service availability and maintaining data integrity.
+
+## RAS Mechanism Overview
+
+### Error categories
+
+One of the most popular RAS schemes used in the memory subsystem is Error Correction Code (ECC) SECDED (Single-bit Error Correction and Double-bit Error Detection), which as its name indicates, the DDR controller can correct single-bit errors and detect double-bit errors on the received data from the DRAMs.
+
+Talking about detected hardware errors, we can classify memory errors as either corrected errors (CE) or uncorrected errors (UCE).
+
+- **Correctable Error (CE)** - the hardware error detection mechanism detected and automatically corrected the error.
+- **Uncorrected errors (UCE)** - are severe enough, hardware detects but cannot correct.
+
+
+
+Typically, uncorrectable errors further fall into three categories:
+
+- **Uncorrected Recoverable Errors (UCR)** - are uncorrected errors that have been detected and signaled but have not corrupted the processor context. For certain UCR errors, this means that once system software has performed a certain recovery action, it is possible to continue execution on this processor. UCR error reporting provides an error containment mechanism for data poisoning. It can be further divided into:
+ - **Action Required (AR)**: The error occurs in execution context. If such an error is detected, and the memory access has been architecturally executed, that error is considered “consumed”. CPU will signal a synchronous exception when an error is detected and the processor already consumes the memory. OS requires to take action (for example, offline failure page/kill failure thread) to recover this uncorrectable error.
+ - **Action Optional (AO)**: The error is detected out of processor execution context, e.g. when detected by a background scrubber or accessed by prefetch instruction. In this scenario, the data in the memory are corrupted, but OS is optional to take action to recover this uncorrectable error.
+- **Uncorrected Error (UC)** - 2 bit (uncorrectable) error occurs and can not be corrected by hardware. The processor context is corrupted and cannot continue to operate the system. OS requires to panic immediately.
+
+OS will take specific actions based on the above failures. Handling CEs is done in silicon, e.g. using ECCs and can be made transparent to system. Handling DUEs, however, can require collaboration from higher layers in the hardware-software stack, from silicon to virtual memory manager, to the operating system (OS), and sometimes even the application layer.
+
+### X86 MCA Recovery
+
+The new Intel Xeon Scalable Family processors support recovery from some memory errors based on the Machine Check Architecture (MCA) Recovery mechanism. The figure shows a basic workflow with legacy MCA or EMCA.
+
+Prior to enhanced machine check architecture (EMCA), IA32-legacy version of Machine Check Architecture (MCA) implemented error handling where all the errors were logged in architected registers (MC banks) and signaled to OS/hypervisor. CMCI is signaled only when CE is over threshold and OS CMCI handler, aka, `threshold_interrupt` read MC Banks and other HW registers for further error handling. MCE is signaled when uncorrected or fatal errors are detected and its handler `do_machine_check` will poison the page and then kill current thread in memory failure.
+
+EMCA enables BIOS-based recovery from errors which redirects MCE and CMCI to firmware first (via SMI) before sending it to the OS error handler. It allows firmware first to handle, collect, and build enhanced error logs then report to system software.
+
+
+
+### ARM v8.2 RAS Extension
+
+The RAS Extension is a mandatory extension to the Armv8.2 architecture, and it is an optional extension to the Armv8.0 and Armv8.1 architectures. The figure shows a basic workflow with Firmware First mode.
+
+
+- Prerequisite: System boot and init
+
+ - Platform RAS driver init: BL31 initializes SPM (includes MM dispatcher) and SDEI dispatcher, UEFI query and update error source info in HEST
+ - OS RAS driver init: HEST driver scans HEST table and registers error handlers by APEI notification, e.g. SDEI, SEA, GPIO, etc.
+
+1. RAS event (UE or CE) occurred, the event will be routed to EL3 (SPM).
+2. SPM routes the event to RAS error handler in S-EL0 (MM Foundation).
+3. MM Foundation creates the CPER blobs by the info from RAS Extension.
+4. SPM notifies RAS event through APEI notification, e.g. SDEI, SEA, etc. to call the corresponding OS registered handler.
+5. OS gets the CPER blobs by Error Status Address block, processes the error, and tries to recover.
+6. OS reports the error event by RAS tracepoints.
+7. rasdaemon log error info from RAS event to recorder.
+
+For example, the platform specifies SDEI as an APEI notification to handle RAS events. As part of initialization, the kernel registers a handler for a platform event, enables the event, and unmasks the current PE. At a later point in time, a critical event, e.g. DDR UE interrupt is trapped into EL3. EL3 performs a first-level triage of the event, and a RAS component assumes further handling. The dispatch completes, but intends to involve Non-secure world UEFI in further handling, and therefore decides to explicitly dispatch an event (which the kernel had already registered for).
+
+## RAS Solution on ANCK
+
+Modern CPU offers an extensive and robust set of RAS features in silicon to provide error detection, correction, containment, and recovery in all processors, memory, and I/O data paths based on Intel Machine Check Architecture (MCA) Recovery mechanism or ARM v8.2 RAS Extension. The RAS mechanism is intended to assist CPU designers and CPU debuggers in diagnosing, isolating, and understanding processor failures. It is also intended to help system administrators detect transient and age-related failures, suffered during long-term operation of the server.
+
+To reduce systems downtime, the OS recovery process for ensuring reliable hardware performance is to detect and correct errors where possible, recover from uncorrectable errors through either physical or logical replacement of a failing component or data path, and prevent future errors by replacing in timely fashion components most likely to fail.
+
+The figure shows the system error handling flow with Anolis OS.
+
+
+
+### Memory Failure Recovery
+
+The RAS mechanism is used to detect, signal, and record machine fault information. Some of these faults are correctable, whereas others are uncorrectable. The Memory Failure Recovery capabilities of RAS mechanism allow systems to continue to operate when an uncorrected error is detected in the system. If not for these capabilities, the system would crash and might require hardware replacement or a system reboot.
+
+When an uncorrectable error is detected on a requested memory address, data poisoning is used to inform the CPU that the data requested has an uncorrectable error. When the hardware detects an uncorrectable memory error, it routes a poison bit along with the data to the CPU. For the Intel architecture, when the CPU detects this poison bit, it sends a processor interrupt signal to the operating system to notify it of this error. The operating system can then examine the uncorrectable memory error, determine if the software can recover, and perform recovery actions via an interrupt handler.
+
+Memory Failure Recovery handles UCR errors including:
+
+- AR are synchronous Errors. There are two types of such errors signaled as data abort or instruction abort. For example, data abort is detected by Data Cache Unit (DCU) and instruction abort is detected by Instruction Fetch Unit (IFU) which are both signaled as Machine Check Exception. The analogy exception is Synchronous External Abort in Arm64 platform.
+
+- AO are asynchronous Errors. Such errors are detected by memory patrol scrub, prefetch, Last Level Cache (LLC) explicit writeback transaction for X86 platform or store less than ECC protection granularity, e.g. per 64 bit on Neoverse N1 and N2.
+
+The kernel will attempt to hard-offline the page, by trying to unmap the page or killing any owner, or triggering IO errors if needed. This may kill any processes accessing the page. The kernel will avoid to access this page assuming it's poisoned by the hardware.
+Let's dive into more details about Anolis OS Cloud Kernel running on Severs capable of Intel MCA Recovery or ARM v8.2 RAS Extension.
+
+#### User Space Action Required Recovery
+
+In Linux, user memory and kernel memory are independent and implemented in separate address spaces. The address spaces are virtualized, meaning that the addresses are abstracted from physical memory (through a process detailed shortly). In fact, the kernel itself resides in one address space, and each process resides in its own address space, so each process can be isolated completely and protected by the paging mechanism. These address spaces consist of virtual memory addresses, permitting many processes with independent address spaces to refer to a considerably smaller physical address space (the physical memory in the machine). Not only is this convenient, but it's also secure, because each address space is independent and isolated and therefore secure. One isolated address space per process is the basis of preventing the fault from being propagated to the enclosing scope or process.
+
+Without OS memory failure recovery and hardware data poisoning support, once a process is consuming poison, it will be regarded as a fatal event and the kernel will crash immediately. When the OS kernel receives the UCE events, the `memory_failure` function (HWPoison handler) analyzes the log to verify if recovery is feasible. It then takes actions to offline the affected memory page and logs the event in the
+mcelog or RAS tracepoint, and the possible results of the actions appear to be ignoring, recovery, delay, and failure.
+
+The HWPoison handler starts the recovery action by isolating the affected page and declaring it with a “poisoned” tag to disallow any reuse of the page. In the case of an AR-instruction abort event, the HWPoison handler then reloads the 4KB page containing the instruction to a new physical page and resumes normal operation. In the case of an AR-data abort event, the HWPoison handler triggers a “SIGBUS” event to take further recovery action by notifying only the accessing process or any owner process which is configured by hwpoison-aware technique like prctl or early kill. The application has a choice to either reload the data and resume normal execution, or terminate the application to avoid crashing the entire system.
+
+
+
+#### Kernel Space Action Required Recovery
+
+The kernel itself resides in one address space, and contains a process scheduler, networking stack, virtual file system, and device drivers for hardware support, to name just a few, shared by all user space processes. When a user space application requires the services provided by the kernel, it will signal the kernel to execute a syscall, and switch to kernel mode for the duration of the syscall execution. In principle, if any UCE error was triggered while executing OS kernel code, then the UCE error will be fatal.
+Kernel also provides user space memory access APIs for cross-space data movement from or to user memory. Cross-space data movements are limited to perform in Linux by special functions, defined in ``. Such a movement is either performed by a generic (memcpy-like) function or by functions optimized for a specific data size (char, short, int, long); The role of the data-movement functions is shown in following figure as it relates to the types involved for copy (simple vs. aggregate), note, not all user access API is showed.
+
+
+
+For example, when a user process tries to write a buffer to a file, kernel will copy the data from userspace and then write them to disk. If a UCE error occurs in the userspace buffer, kernel will consume the poison data while copying data from userspace. In such case, a system wide reboot is not unnecessary. The point behind Kernel Space Action Required Recovery is that the poison data manipulated by kernel is owned by the user process. If the application that initiated the copy and owned corrupt data can be easily identified by the kernel, it is possible to isolate the corrupt data by marking the affected page with the ‘poison’ tag and terminating the initiator/impacted applications to stop the corrupt data from spreading.
+
+The mechanism is to track uaccess in extable in advance and change pc to fixup handler while handling synchronous Errors. Then the uaccess will jump to fixup handler which then endups the uaccess process. If the exception is fixuped correctly, the kernel can avoid panic. In the copy from user case, e.g. initiated by write(2), it is not even necessary to send a SIGBUS. System calls should return -EFAULT or a short count for write(2). The Figure shows the basic workflow for Arm64 platform and the implementation of the X86 platform is similar.
+
+
+
+#### Action Optional Recovery: Patrol Scrub
+
+ECC Patrol Scrubber is a common block in DDR Controller (DDRC) capable of generating initialization write commands, periodic read commands, periodic RMW commands, and correction RMW commands. It proactively searches the system memory, repairing correctable errors. Periodic scrubbing is performed by the ECC Patrol Scrubber to prevent the accumulation of single-bit errors and increase the reliability of the system by correcting single-bit ECC errors in time, before they turn into uncorrectable 2-bit errors.
+When an uncorrectable 2-bit error is detected by Patrol Scrubber, an interrupt will be signaled. In such case, kernel will just unmap the poisoned page because no process is accessing the poison data by default.
+
+On X86 old generation platform, after the patrol scrub detects memory uncorrected data errors, it will report the OS by MCE. The new generation like Intel® Xeon® Processor-based platforms have an `UCE_TO_CE_DOWNGRAGE` mode where the users can request the memory controller to report UCE found by the patrol scrubber as a corrected type. It is also called ‘downgrading patrol scrub CE/SRAO to CE’. Those errors are signaled by using CMCI, a process less disruptive than a machine check and thus helps avoid double MCE interrupts to crash the system. We recommend setting it on.
+
+
+
+#### Action Optional Recovery: Prefetch
+
+Many modern processors implement implicit hardware prefetching and support software prefetching. With software prefetching the programmer or compiler inserts prefetch instructions into the program. For example, Prefetch from Memory (`PRFM`) enables code to provide a hint to the memory system that data from a particular address will be used by the program soon. While for implicit hardware prefetching, the processor monitors the memory access pattern of the running program and tries to predict what data the program will access next and prefetches that data.
+
+If a prefetch request accesses to poison data, an asynchronous error will be detected and an interrupt will be signaled, e.g. CMCI on Intel Icelake and SPI on Yitian 710. In such case, kernel will just unmap the poison page like Patrol Scrub error.
+
+Another prefetch scenario we observed is that the poisoned page may still be accessed even though all its owned user processes are killed. After a page is poisoned, it will never be reused, e.g. reallocated to other processes. The problem is that the poisoned page is only unmapped from the page table of user-space process, the kernel page table of the linear mapping range is not considered. It requires dynamically splitting the target linear mapping into PTE granularity and then clearing the PTE valid attribute of the related virtual address while processing memory failure. As a result, the poisoned page will be marked as not-present, which avoids speculative and prefetch access.
+
+#### Action Optional Recovery: Store
+
+Write is another type of request which may read the poison data from DDR controller. On Yitian 710, L2 cache is protected by a per 64-bit ECC scheme, a write less than 64bit will trigger asynchronous External Aborts, signaled as SErrors. Similarly, an asynchronous interrupt CMCI is signaled on X86 platform. In such case, it requires firmware to take extra care that does not notify kernel as a fatal error to avoid a system wide reboot.
+
+Unlike read access, write access does not cause error propagation. When such an error is detected, kernel will regard it as AO asynchronous error and only unmap the poisoned page. However, the write did not take effect, resulting in data loss. A subsequent 64-bit write access has the opportunity to correct this error. When the process trie to consume the poisoned page, the HWPoison handler triggers a “SIGBUS” event to take further recovery action by notifying only the accessing process or any owner process which is configured by hwpoison-aware technique like prctl or early kill.
+
+#### HWPoison-aware Strategy
+
+There are in principle two hwpoison-aware strategies to kill processes on poison:
+
+- just unmap the data and wait for an actual reference before killing
+- kill all processes that have the corrupted and not reloadable page mapped as soon as the corruption is detected.
+
+Both have advantages and disadvantages and should be used in different situations. **Right now both are implemented and can be switched** with a new sysctl vm.memory_failure_early_kill. The default is late kill. Applications can override this setting individually with the PR_MCE_KILL prctl. For example, if early kill is set by `sysctl -w vm.memory_failure_early_kill=1`, kernel will kill any process which mapped the poison page when an uncorrectable 2-bit error is detected by Patrol Scrubber.
+
+Note, the kill is done using a catchable SIGBUS with BUS_MCEERR_AO, so processes can handle this if they want to. While for AR synchronous errors, the kill is done using a catchable SIGBUS with BUS_MCEERR_AR.
+
+### Memory Predictive Failure Analysis with Rasdeamon
+
+When a 1-bit error is detected, it is transparently corrected by the hardware ECC mechanism, and internal counters are updated. If a correctable fault occurs in the memory, we don't need to perform any recovery action on the OS. However, if we continue to see correctable errors, then perhaps the memory is failing. To avoid the possibility of future uncorrectable faults on the same page, we can copy the data to a different page and mark the page as offline. This is the mechanism used by Memory Predictive Failure Analysis (PFA).
+
+The PFA is powered by the userspace rasdaemon package. Rasdaemon written by Mauro Carvalho Chehab is one of the tools to gather MCE information. Previously, the task was performed by the mcelog package. However, the driver it depends on has been deprecated after kernel 4.12, we recommend switching to the new generation rasdaemon solution.
+
+If a memory error is detected and signaled, the OS related handler reports them to userspace through RAS tracepoints with EDAC decoded DIMM statistics for accounting and predictive failure analysis. Rasdeamon runs as a daemon that monitors the platform RAS reports from the Linux kernel trace events. And it optionally records RAS events via Sqlite3 which has the benefit of keeping a persistent record of the RAS events. Based on statistical results, some actions can be configured and taken to prevent corrected errors from evoluting into uncorrected errors. For example, specify soft offline action or hard offline action when exceeding a page error threshold within refresh cycles, e.g. 50 CEs perf 24 hours. When a soft action is specified, the kernel will then attempt to soft-offline it, by moving the contents elsewhere or dropping it if possible. The kernel will then be placed on the bad page list and never be reused. The page is still accessible, not poisoned. The kernel will never kill anything for this, but rather fail the offline.
+
+Note, the RAS feature is only covered but not limited to memory, the processor, PCIe, and Platform(e.g. CMN, GIC, SMMU, etc) RAS are also supported on Anolis OS Cloud Kernel.
+
+## RAS Validation Guide
+
+EINJ provides a hardware error injection mechanism. It is very useful for debugging and testing APEI and RAS features in general. In this white paper, we take Yitian 710 running Anolis OS as an example. Note that this guide is also suitable for other platforms with advanced RAS features.
+
+### Prerequisite
+
+#### BIOS Requirement
+
+You need to check whether your BIOS supports EINJ first. For Panjiu M Series equipped with Yitian 710, make ensure to set the following configuration properly.
+
+```bash
+[Platform Configuration][Processor Configuration][CPU Poison]
+[Platform Configuration][Memory RAS Configuration][Poison]
+[Platform Configuration][Memory RAS Configuration][CE threshold ]<0>
+[Platform Configuration][Memory RAS Configuration][Ecc]
+[Platform Configuration][PCI-E Configuration][PCIe RAS Support]
+[Platform Configuration][PCI-E Configuration][AER CE]
+[Platform Configuration][Advance Configuration][Global RAS Enable]
+[Platform Configuration][Advance Configuration][EINJ Enable]
+[Platform Configuration][Advance Configuration][Route EA to El3]
+```
+
+#### OS Requirement
+
+Then, you need to check whether your BIOS supports EINJ. For that, look for early boot messages similar to this one, e.g. on Yitian 710 :
+
+```bash
+#dmesg | grep EINJ
+[ 0.000000] ACPI: EINJ 0x00000000F8FAFE18 000150 (v01 PTG PTG01 00000000 PTG 20200717)
+```
+
+which shows that the BIOS is exposing an EINJ table - it is the mechanism through which the injection is done.
+
+By default, the EINJ driver is built-in on Anolis OS. If you build kernel from scratch, make sure the following are options enabled in your kernel configuration:
+
+```shell
+CONFIG_DEBUG_FS
+CONFIG_ACPI_APEI
+CONFIG_ACPI_APEI_EINJ
+```
+
+Check if the einj module is loaded:
+
+```shell
+$ lsmod | grep einj
+einj 16384 0
+```
+
+If not, load the einj modules by yourself
+
+```shell
+modprobe einj
+```
+
+### EINJ Interface
+
+The EINJ user interface is in \/apei/einj, by default, `/sys/kernel/debug/apei/einj`.
+
+```bash
+#ls /sys/kernel/debug/apei/einj/
+available_error_type error_inject error_type flags notrigger param1 param2 param3 param4 vendor vendor_flags
+```
+
+The standard error types for the EINJ interface include Processor, Memory, PCIe, and Platform. The file `available_error_type`displays the supported standard error types and their severities, e.g.
+
+```bash
+#cat /sys/kernel/debug/apei/einj/available_error_type
+0x00000001 Processor Correctable
+0x00000002 Processor Uncorrectable non-fatal
+0x00000004 Processor Uncorrectable fatal
+0x00000008 Memory Correctable
+0x00000010 Memory Uncorrectable non-fatal
+0x00000020 Memory Uncorrectable fatal
+0x00000040 PCI Express Correctable
+0x00000080 PCI Express Uncorrectable non-fatal
+0x00000100 PCI Express Uncorrectable fatal
+0x00000200 Platform Correctable
+0x00000400 Platform Uncorrectable non-fatal
+0x00000800 Platform Uncorrectable fatal
+```
+
+The error injection mechanism is a two-step process.
+
+- First select an error specified all necessary error parameters including`error_type`,`flags`,`param{1-4}`and `notrigger`,then write any integer to `error_inject` to inject the error.
+- The second step performs some actions to trigger it. Setting `notrigger` to 1 skips the trigger phase, which may allow the user to cause the error in some other context by a simple access to the CPU, memory location, or device that is the target of the error injection. Setting `notrigger` to 0, the BIOS should trigger the error internally, e.g. by kicking the patrol scrubber. Whether this actually works depends on what operations the BIOS actually includes in the trigger phase.
+
+Please refer to the kernel document for more details about EINJ user interface format.
+
+#### Error Injection Examples with APEI Debugfs
+
+In this section, we show examples to inject errors with APEI Debugfs on Yitian 710.
+
+##### Processor Uncorrectable non-fatal
+
+```bash
+APEI_IF=/sys/kernel/debug/apei/einj
+echo 33 > $APEI_IF/param3 # APIC ID
+echo 0x1 > $APEI_IF/flags
+echo 0x00000002 > $APEI_IF/error_type
+echo 1 > $APEI_IF/error_inject
+```
+
+The dmesg log:
+
+```bash
+[ 1820.578688] {3}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 4
+[ 1820.589434] {3}[Hardware Error]: event severity: recoverable
+[ 1820.595078] {3}[Hardware Error]: precise tstamp: 2023-01-02 17:23:02
+[ 1820.601503] {3}[Hardware Error]: Error 0, type: recoverable
+[ 1820.607147] {3}[Hardware Error]: section_type: ARM processor error
+[ 1820.613485] {3}[Hardware Error]: MIDR: 0x00000000410fd490
+[ 1820.619041] {3}[Hardware Error]: Multiprocessor Affinity Register (MPIDR): 0x0000000081210000
+[ 1820.627723] {3}[Hardware Error]: running state: 0x1
+[ 1820.632759] {3}[Hardware Error]: Power State Coordination Interface state: 0
+[ 1820.639965] {3}[Hardware Error]: Error info structure 0:
+[ 1820.645435] {3}[Hardware Error]: num errors: 1
+[ 1820.650037] {3}[Hardware Error]: error_type: 0, cache error
+[ 1820.655854] {3}[Hardware Error]: error_info: 0x0000000000800015
+[ 1820.662019] {3}[Hardware Error]: transaction type: Instruction
+[ 1820.668183] {3}[Hardware Error]: cache level: 2
+[ 1820.673045] {3}[Hardware Error]: the error has not been corrected
+[ 1820.679470] {3}[Hardware Error]: type: CORE (0x41), ras_count:1
+[ 1820.685461] {3}[Hardware Error]: sub_type: 0x0
+[ 1820.689977] {3}[Hardware Error]: fr: 0x10a9a2, ctrl: 0x0, status: 0x44800007, addr: 0x800e9f716acea53d
+[ 1820.699352] {3}[Hardware Error]: misc0: 0x4, misc1: 0x0, misc2: 0x0, misc3: 0x0
+```
+
+##### Processor Uncorrectable fatal
+
+Script to inject and trigger processor uncorrectable fatal error. Note, a fatal error will cause the kernel to panic.
+
+```bash
+APEI_IF=/sys/kernel/debug/apei/einj
+echo 33 > $APEI_IF/param3 # APIC ID
+echo 0x1 > $APEI_IF/flags
+echo 0x00000004 > $APEI_IF/error_type
+echo 1 > $APEI_IF/error_inject
+```
+
+The dmesg log:
+
+```bash
+[10862.838686] {10}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 3
+[10862.838687] {10}[Hardware Error]: event severity: fatal
+[10862.838688] {10}[Hardware Error]: precise tstamp: 2023-01-02 19:53:43
+[10862.838688] {10}[Hardware Error]: Error 0, type: fatal
+[10862.838688] {10}[Hardware Error]: section_type: ARM processor error
+[10862.838689] {10}[Hardware Error]: MIDR: 0x00000000410fd490
+[10862.838689] {10}[Hardware Error]: Multiprocessor Affinity Register (MPIDR): 0x0000000081210000
+[10862.838689] {10}[Hardware Error]: running state: 0x1
+[10862.838690] {10}[Hardware Error]: Power State Coordination Interface state: 0
+[10862.838690] {10}[Hardware Error]: Error info structure 0:
+[10862.838691] {10}[Hardware Error]: num errors: 1
+[10862.838691] {10}[Hardware Error]: error_type: 0, cache error
+[10862.838691] {10}[Hardware Error]: error_info: 0x0000000000800015
+[10862.838692] {10}[Hardware Error]: transaction type: Instruction
+[10862.838692] {10}[Hardware Error]: cache level: 2
+[10862.838693] {10}[Hardware Error]: the error has not been corrected
+[10862.838693] {10}[Hardware Error]: type: CORE (0x41), ras_count:1
+[10862.838693] {10}[Hardware Error]: sub_type: 0x0
+[10862.838694] {10}[Hardware Error]: fr: 0x10a9a2, ctrl: 0x0, status: 0x74000007, addr: 0x800e9f716acea53d
+[10862.838694] {10}[Hardware Error]: misc0: 0x4, misc1: 0x0, misc2: 0x0, misc3: 0x0
+[10862.838695] Kernel panic - not syncing: Fatal hardware error!
+```
+
+#### Memory
+
+##### Correctable
+
+Firstly, run a `victim` program in the background. The `victim` is one of the ras-tools which allocates a page in userspace and dumps the virtual and physical address of the page, and then holds on to trigger.
+
+```bash
+#victim -d &
+[1] 12472
+physical address of (0xffff87fb2000) = 0x89a0f8000
+Hit any key to trigger error:
+[1]+ Stopped victim -d
+```
+
+Then run the bellow script to inject and trigger memory correct error. Note, the CE recovery is usually implemented as a threshold based error reporting mechanism. The default threshold for CE is 5000, in other words, the hardware only signal interrupt per 5000 CE errors. To test the feature, we configure CE threshold as 0.
+
+```bash
+echo 0x89a0f8000 > $APEI_IF/param1
+echo 0xfffffffffffff000 > $APEI_IF/param2
+echo 0x1 > $APEI_IF/flags
+echo 0x00000008 > $APEI_IF/error_type
+echo 1 > $APEI_IF/error_inject
+```
+
+The dmesg log:
+
+```bash
+[ 1555.991595] EDAC MC0: 1 CE single-symbol chipkill ECC on unknown memory (node:0 card:0 module:0 rank:0 bank_group:4 bank_address:2 device:0 row:616 column:1024 chip_id:0 page:0x89a0f8 offset:0x0 grain:1 syndrome:0x0 - APEI location: node:0 card:0 module:0 rank:0 bank_group:4 bank_address:2 device:0 row:616 column:1024 chip_id:0 status(0x0000000000000400): Storage error in DRAM memory)
+[ 1555.991600] {1}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 2
+[ 1555.991602] {1}[Hardware Error]: It has been corrected by h/w and requires no further action
+[ 1555.991602] {1}[Hardware Error]: event severity: corrected
+[ 1555.991604] {1}[Hardware Error]: precise tstamp: 2023-01-02 17:18:38
+[ 1555.991604] {1}[Hardware Error]: Error 0, type: corrected
+[ 1555.991606] {1}[Hardware Error]: section_type: memory error
+[ 1555.991606] {1}[Hardware Error]: error_status: Storage error in DRAM memory (0x0000000000000400)
+[ 1555.991607] {1}[Hardware Error]: physical_address: 0x000000089a0f8000
+[ 1555.991608] {1}[Hardware Error]: node:0 card:0 module:0 rank:0 bank_group:4 bank_address:2 device:0 row:616 column:1024 chip_id:0
+[ 1555.991609] {1}[Hardware Error]: error_type: 4, single-symbol chipkill ECC
+[ 1555.991610] {1}[Hardware Error]: type: DDR (0x50), ras_count:1
+[ 1555.991611] {1}[Hardware Error]: sub_type: 0x0
+[ 1555.991612] {1}[Hardware Error]: fr: 0x1000200000022, ctrl: 0x0, status: 0x0, addr: 0x0
+[ 1555.991612] {1}[Hardware Error]: misc0: 0x0, misc1: 0x0, misc2: 0x200000000000000, misc3: 0x900000000000000
+```
+
+##### Memory UnCorrectable Non-fatal
+
+Firstly, run a `victim` program in the background as the last section described.
+
+```bash
+#victim -d &
+physical address of (0xffff962d0000) = 0x9f8acb000
+Hit any key to trigger error:
+[1]+ Stopped victim -d
+```
+
+Then run the bellow script to inject and trigger memory correct error. Here, we specify `notrigger` to 0 to let the firmware kick the DDRC scrubber to trigger the error.
+
+```bash
+APEI_IF=/sys/kernel/debug/apei/einj
+echo 0x400a4919000 > $APEI_IF/param1
+echo 0xfffffffffffff000 > $APEI_IF/param2
+echo 0x1 > $APEI_IF/flags
+echo 0x00000010 > $APEI_IF/error_type
+echo 0x0 > $APEI_IF/notrigger
+echo 1 > $APEI_IF/error_inject
+```
+
+The dmesg log:
+
+```bash
+[ 211.121855] {1}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 2
+[ 211.132646] {1}[Hardware Error]: event severity: recoverable
+[ 211.138292] {1}[Hardware Error]: precise tstamp: 2022-12-30 15:26:40
+[ 211.144717] {1}[Hardware Error]: Error 0, type: recoverable
+[ 211.150362] {1}[Hardware Error]: section_type: memory error
+[ 211.156096] {1}[Hardware Error]: error_status: Storage error in DRAM memory (0x0000000000000400)
+[ 211.165125] {1}[Hardware Error]: physical_address: 0x00000400a4919000
+[ 211.171725] {1}[Hardware Error]: node:0 card:7 module:0 rank:0 bank_group:7 bank_address:0 device:0 row:146 column:1152 chip_id:0
+[ 211.183619] {1}[Hardware Error]: error_type: 14, scrub uncorrected error
+[ 211.190479] {1}[Hardware Error]: type: DDR (0x50), ras_count:1
+[ 211.196383] {1}[Hardware Error]: sub_type: 0x0
+[ 211.200899] {1}[Hardware Error]: fr: 0x1000200000353, ctrl: 0x0, status: 0x0, addr: 0x0
+[ 211.208974] {1}[Hardware Error]: misc0: 0x0, misc1: 0x0, misc2: 0x0, misc3: 0x200000000000500
+[ 211.218375] Memory failure: 0x400a4919: recovery action for dirty LRU page: Recovered
+```
+
+At this point, the allocated physical page is unmapped and poisoned, any read access will trigger a page fault.
+If we move the background process `victim`on current Linux shell to the foreground and hit any key, the victim will trigger a page fault and receive a SIGBUS signal due to the poisoned PTE entry. Because the `victim`process does not register the SIGBUS handler, it will be killed.
+
+```bash
+#fg
+victim -d
+
+Access time at Fri Dec 30 15:38:14 2022
+
+Bus error
+```
+
+We can also specify `notrigger` to 1 to let the firmware skip the trigger phase and allow the `victim` process to access the target of the error injection so that the error will be detected in execution context.
+
+Firstly, select a page and inject an error to it, while explicitly skipping the firmware trigger phase.
+
+```bash
+#victim -d &
+[1] 9522
+physical address of (0xffffaed6d000) = 0x400aa6dd000
+Hit any key to trigger error:
+[1]+ Stopped victim -d
+
+APEI_IF=/sys/kernel/debug/apei/einj
+
+echo 0x400aa6dd000 > $APEI_IF/param1
+echo 0xfffffffffffff000 > $APEI_IF/param2
+echo 0x1 > $APEI_IF/flags
+echo 0x00000010 > $APEI_IF/error_type
+echo 0x1 > $APEI_IF/notrigger
+echo 1 > $APEI_IF/error_inject
+```
+
+Then move the background process `victim` on current Linux shell to the foreground and hit any key, so that the error will be triggered in execution context. The kernel will poison the page and unmap it, then send SIGBUS to the process which accesses the page.
+
+```bash
+#fg
+victim -d
+
+Access time at Fri Dec 30 15:39:26 2022
+
+Bus error
+```
+
+The dmesg log:
+
+```bash
+[ 799.958832] {3}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 2
+[ 799.969533] {3}[Hardware Error]: event severity: recoverable
+[ 799.975179] {3}[Hardware Error]: precise tstamp: 2022-12-30 15:36:29
+[ 799.981603] {3}[Hardware Error]: Error 0, type: recoverable
+[ 799.987248] {3}[Hardware Error]: section_type: memory error
+[ 799.992978] {3}[Hardware Error]: error_status: Storage error in DRAM memory (0x0000000000000400)
+[ 800.002007] {3}[Hardware Error]: physical_address: 0x00000400aa6dd000
+[ 800.008607] {3}[Hardware Error]: node:0 card:5 module:0 rank:1 bank_group:1 bank_address:0 device:0 row:169 column:1664 chip_id:0
+[ 800.020500] {3}[Hardware Error]: error_type: 5, multi-symbol chipkill ECC
+[ 800.027446] {3}[Hardware Error]: type: DDR (0x50), ras_count:1
+[ 800.033351] {3}[Hardware Error]: sub_type: 0x0
+[ 800.037866] {3}[Hardware Error]: fr: 0x1001000100000000, ctrl: 0xf000000000920004, status: 0xd800000Cor0040](0xadd040000d0receiveaecntr=526(d1.subch3), cnt=0x1
+[ 800.060436] {3}[Hardware Error]: misc0: 0x3f00000000040307, misc1: 0xd00000000030cd18, misc2: 0x4015, misc3: 0x200000000000100
+[ 800.072366] Memory failure: 0x400aa6dd: recovery action for dirty LRU page: Recovered
+```
+
+### RAS-tools
+
+We can also test and validate RAS features of whole system stack across hardware, firmware and OS via ras-tools. Ras-tools are an excellent set of tools to inject and test RAS ability on X86 and Arm64 platforms based on the APEI EINJ interface.
+
+| tools | fatal | arch | Description | Usage |
+| ----------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------ |
+| einj_mem_uc | See help | x86、Arm | inject an error and then trigger it in one of a variety of ways. | ./einj_mem_uc # See help for testname |
+| cmcistorm | No | x86 | use EINJ to inject a bunch of soft errors, then consume them all as fast as possible. | ./cmcistorm # e.g./cmcistorm 20 1 |
+| hornet | No | x86、Arm | Start a process (or point to an existing one) and inject an uncorrectable memory error to a targeted or randomly chosen memory address | ./hornet -p PID |
+| lmce | No | x86 | local mce | ./lmce |
+| mca-recover | No | x86、Arm | Set up to get zapped by a machine check (injected elsewhere) recovery function reports physical address of new page - so we can inject to that and repeat over and over. | ./mca-recover |
+| rep_ce_page | No | x86、Arm | loop using EINJ to inject a soft error, consuming after each until the page is taken offline. | ./rep_ce_page |
+| vtop | No | x86、Arm | Given a process if and virtual address, dig around in /proc/id/pagemap to find the physical address (if present) behind the virtual one. | ./vtop |
+| memattr | No | Arm | Example of the Linux kernel driver that allows a user-space program to mmap a buffer of contiguous physical memory with specific memory attribute. | cd pgprot-drv
make
insmod pgprot_drv.ko pgprot=4
../memattr|
+| ras-tolerance | No | Arm | This driver allows to overwrite error severity to a lower level at runtime, recoverable by default. It is useful for test. | cd ras-tolerance
make
insmod ras_tolerance.ko|
+
+#### Install
+
+On servers running Anolis OS, you can install ras-tools through `yum`. On other OSes, you could build it from scratch.
+
+``` bash
+yum install ras-tools
+```
+
+#### Memory Failure Recovery Validation
+
+The `einj_mem_uc` tool allocates pages, injects an error and then triggers it in one of a variety of ways. It intends to do a coverage test for testing the Linux RAS related features, including CPU/Memory error containment and recovery.
+
+##### AR Validation
+
+###### User Space AR-data Recovery
+
+In the case of an AR-data abort event e.g. `single`, `doube`,`split`,`hugetlb`,etc, the kernel will attempt to hard-offline the page, by poisoning the page and killing accessing process. For example, `single` case, it injects an uncorrected error and triggers the error by reading a byte.
+
+```bash
+# einj_mem_uc single
+0: single vaddr = 0xffff857a3400 paddr = 8e6157400
+injecting ...
+triggering ...
+signal 7 code 4 addr 0xffff857a3400
+page not present
+Test passed
+```
+
+`einj_mem_uc` will print the received signal and its code, in the above case,
+
+- signal 7: SIGBUS
+- code 4: BUS_MCEERR_AR 4
+
+The dmesg log:
+
+```bash
+[ 1785.908893] EDAC MC0: 1 UE multi-symbol chipkill ECC on unknown memory (node:0 card:0 module:0 rank:0 bank_group:1 bank_address:2 device:0 row:920 column:896 chip_id:0 page:0x8e6157 offset:0x400 grain:1 - APEI location: node:0 card:0 module:0 rank:0 bank_group:1 bank_address:2 device:0 row:920 column:896 chip_id:0 status(0x0000000000000400): Storage error in DRAM memory)
+[ 1785.908900] {1}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 2
+[ 1785.919531] {1}[Hardware Error]: event severity: recoverable
+[ 1785.925176] {1}[Hardware Error]: precise tstamp: 2023-01-17 18:05:09
+[ 1785.931600] {1}[Hardware Error]: Error 0, type: recoverable
+[ 1785.937244] {1}[Hardware Error]: section_type: memory error
+[ 1785.942975] {1}[Hardware Error]: error_status: Storage error in DRAM memory (0x0000000000000400)
+[ 1785.952004] {1}[Hardware Error]: physical_address: 0x00000008e6157400
+[ 1785.958603] {1}[Hardware Error]: node:0 card:0 module:0 rank:0 bank_group:1 bank_address:2 device:0 row:920 column:896 chip_id:0
+[ 1785.970409] {1}[Hardware Error]: error_type: 5, multi-symbol chipkill ECC
+[ 1785.977355] {1}[Hardware Error]: type: DDR (0x50), common_reg_nr:1
+[ 1785.983606] {1}[Hardware Error]: Synchronous Exception taken in EL0
+[ 1785.989944] {1}[Hardware Error]: ESR: 0x92000410, ELR: 0x403abc, FAR: 0xfa00a88, SCR: 0x403073d, SCTLR: 0x30cd183f, LR: 0x403abc
+[ 1786.001578] {1}[Hardware Error]: ECCERRCNT: 0x10000, ECCSTAT: 0x0, ADVECCSTAT: 0x8000002, ECCSYMBOL: 0x170000, ECCERRCNTSTAT: 0x0, ECCERRCNT0: 0x0, ECCERRCNT1: 0x0, ECCCADDR0: 0x0, ECCCADDR1: 0x0, ECCCDATA0: 0x0, ECCCDATA1: 0x0, ECCUADDR0: 0x398, ECCUADDR1: 0x1020380, ECCUDATA0: 0x1ff, ECCUDATA1: 0x0
+[ 1786.036640] Memory failure: 0x8e6157: recovery action for dirty LRU page: Recovered
+
+```
+
+###### User Space AR-instruction Recovery
+
+In the case of an AR-instruction abort event, e.g. `instr`, it injects an uncorrected error and triggers the error by reading a byte. The kernel will attempt to hard-offline the page. It unmaps the corrupted page, reloads the 4KB page containing the instruction to a new physical page and resumes normal operation.
+
+```bash
+# einj_mem_uc instr
+0: instr vaddr = 0x403000 paddr = 8bba93000
+injecting ...
+triggering ...
+Test passed
+```
+
+The dmesg log:
+
+```bash
+[ 1945.804589] EDAC MC0: 1 UE multi-symbol chipkill ECC on unknown memory (node:0 card:7 module:0 rank:1 bank_group:1 bank_address:3 device:0 row:527 column:640 chip_id:0 page:0x40883e65 offset:0x0 grain:1 - APEI location: node:0 card:7 module:0 rank:1 bank_group:1 bank_address:3 device:0 row:527 column:640 chip_id:0 status(0x0000000000000400): Storage error in DRAM memory)
+[ 1945.804596] {3}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 2
+[ 1945.815209] {3}[Hardware Error]: event severity: recoverable
+[ 1945.820854] {3}[Hardware Error]: precise tstamp: 2023-01-17 18:07:49
+[ 1945.827280] {3}[Hardware Error]: Error 0, type: recoverable
+[ 1945.832924] {3}[Hardware Error]: section_type: memory error
+[ 1945.838654] {3}[Hardware Error]: error_status: Storage error in DRAM memory (0x0000000000000400)
+[ 1945.847683] {3}[Hardware Error]: physical_address: 0x0000040883e65000
+[ 1945.854283] {3}[Hardware Error]: node:0 card:7 module:0 rank:1 bank_group:1 bank_address:3 device:0 row:527 column:640 chip_id:0
+[ 1945.866089] {3}[Hardware Error]: error_type: 5, multi-symbol chipkill ECC
+[ 1945.873035] {3}[Hardware Error]: type: DDR (0x50), common_reg_nr:1
+[ 1945.879286] {3}[Hardware Error]: Synchronous Exception taken in EL0
+[ 1945.885625] {3}[Hardware Error]: ESR: 0x82000010, ELR: 0x403000, FAR: 0x403000, SCR: 0x403073d, SCTLR: 0x30cd183f, LR: 0x403f94
+[ 1945.906459] {3}[Hardware Error]: ECCERRCNT: 0x10000, ECCSTAT: 0x0, ADVECCSTAT: 0x8000002, ECCSYMBOL: 0x140000, ECCERRCNTSTAT: 0x0, ECCERRCNT0: 0x0, ECCERRCNT1: 0x0, ECCCADDR0: 0x0, ECCCADDR1: 0x0, ECCCDATA0: 0x0, ECCCDATA1: 0x0, ECCUADDR0: 0x100020f, ECCUADDR1: 0x1030280, ECCUDATA0: 0x1ff, ECCUDATA1: 0x0
+[ 1945.934071] Memory failure: 0x40883e65: corrupted page was clean: dropped without side effects
+[ 1945.934084] Memory failure: 0x40883e65: recovery action for clean LRU page: Recovered
+```
+
+###### Kernel Space AR Recovery
+
+Kernel Space AR Recovery is only supported on X86 platform and we are still working on it on Arm64 platform. The recovery is evaluated on X86 icelake processor.
+
+First, inject an uncorrected error and trigger it by writing a buffer to a file. Kernel will copy data from user space and then write to disk.
+
+```bash
+# einj_mem_uc copyin -f
+0: copyin vaddr = 0x7f8f873e2400 paddr = 2869c1400
+injecting ...
+triggering ...
+einj_mem_uc: couldn't write temp file (errno=14)
+Big surprise ... still running. Thought that would be fatal
+Saw local machine check
+Test passed
+```
+
+As we can see, the process is still running and the return errno for the write(2) is EFAULT(14).
+
+The dmesg log:
+
+```bash
+SetMemoryDeviceStatus UCE error. Data = 00 4C A5 01 02 00 06 01 05 00 00 00 00 00 Status = Success
+[15322.535921] mce: Kernel accessed poison in user space at 2869c1400
+[15322.536023] {2}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 0
+[15322.542117] Memory failure: 0x2869c1: recovery action for dirty LRU page: Recovered
+[15322.550382] {2}[Hardware Error]: event severity: recoverable
+[15322.550385] {2}[Hardware Error]: Error 0, type: recoverable
+[15322.558042] Memory failure: 0x2869c1: already hardware poisoned
+[15322.563710] {2}[Hardware Error]: fru_text: Card02, ChnF, DIMM0
+[15322.563712] {2}[Hardware Error]: section_type: memory error
+[15322.586981] {2}[Hardware Error]: error_status: Storage error in DRAM memory (0x0000000000000400)
+[15322.596027] {2}[Hardware Error]: physical_address: 0x00000002869c1400
+[15322.602650] {2}[Hardware Error]: node:1 card:5 module:0 rank:0 bank:13 device:0 row:2075 column:8
+[15322.611783] {2}[Hardware Error]: error_type: 3, multi-bit ECC
+[15322.617710] {2}[Hardware Error]: DIMM location: not present. DMI handle: 0x0000
+[15322.625304] Memory failure: 0x2869c1: already hardware poisoned
+[15322.631827] EDAC MC6: 1 UE memory read error on CPU_SrcID#1_MC#2_Chan#1_DIMM#0 (channel:1 slot:0 page:0x2869c1 offset:0x400 grain:32 - err_code:0x00a0:0x0091 SystemAddress:0x2869c1400 ProcessorSocketId:0x1 MemoryControllerId:0x2 ChannelAddress:0x2069c000 ChannelId:0x1 RankAddress:0x1034e000 PhysicalRankId:0x0 DimmSlotId:0x0 Row:0x81b Column:0x8 Bank:0x1 BankGroup:0x3 ChipSelect:0x0 ChipId:0x0)
+[15322.667403] EDAC MC6: 1 UE memory read error on CPU_SrcID#1_MC#2_Chan#1_DIMM#0 (channel:1 slot:0 page:0x2869c1 offset:0x400 grain:32 - err_code:0x0000:0x009f SystemAddress:0x2869c1400 ProcessorSocketId:0x1 MemoryControllerId:0x2 ChannelAddress:0x2069c000 ChannelId:0x1 RankAddress:0x1034e000 PhysicalRankId:0x0 DimmSlotId:0x0 Row:0x81b Column:0x8 Bank:0x1 BankGroup:0x3 ChipSelect:0x0 ChipId:0x0)
+```
+
+futex(2) is another system call in which kernel copies data from user space. Inject an uncorrected error and trigger it by issuing `FUTEX_WAIT` operation.
+
+```bash
+# einj_mem_uc futex -f
+0: futex vaddr = 0x7f8a1da83400 paddr = 25751d400
+injecting ...
+triggering ...
+futex returned with errno=14
+Big surprise ... still running. Thought that would be fatal
+Unusual number of MCEs seen: 2
+Test passed
+```
+
+There are many retries in futex(2) mechanism, so it is possible to see many MCEs.
+
+The dmesg log:
+
+```bash
+SetMemoryDeviceStatus UCE error. Data = 00 4C A5 01 02 00 06 01 05 00 00 00 00 00 Status = Success
+[15521.242381] mce: Kernel accessed poison in user space at 25751d400
+[15521.242437] {4}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 0
+[15521.248581] Memory failure: 0x25751d: recovery action for dirty LRU page: Recovered
+[15521.256842] {4}[Hardware Error]: event severity: recoverable
+[15521.256845] {4}[Hardware Error]: Error 0, type: recoverable
+[15521.256847] {4}[Hardware Error]: fru_text: Card02, ChnF, DIMM0
+[15521.264506] Memory failure: 0x25751d: already hardware poisoned
+[15521.270172] {4}[Hardware Error]: section_type: memory error
+[15521.270173] {4}[Hardware Error]: error_status: Storage error in DRAM memory (0x0000000000000400)
+[15521.270174] {4}[Hardware Error]: physical_address: 0x000000025751d400
+[15521.309103] {4}[Hardware Error]: node:1 card:5 module:0 rank:0 bank:4 device:0 row:1882 column:896
+[15521.318322] {4}[Hardware Error]: error_type: 3, multi-bit ECC
+[15521.324252] {4}[Hardware Error]: DIMM location: not present. DMI handle: 0x0000
+[15521.331824] {4}[Hardware Error]: Error 1, type: recoverable
+[15521.337484] {4}[Hardware Error]: section_type: memory error
+[15521.343240] {4}[Hardware Error]: error_status: Storage error in DRAM memory (0x0000000000000400)
+[15521.352286] {4}[Hardware Error]: physical_address: 0x000000025751d400
+[15521.358910] {4}[Hardware Error]: node:1
+[15521.363017] {4}[Hardware Error]: error_type: 3, multi-bit ECC
+[15521.369040] Memory failure: 0x25751d: already hardware poisoned
+[15521.374974] Memory failure: 0x25751d: already hardware poisoned
+[15521.381515] EDAC MC6: 1 UE memory read error on CPU_SrcID#1_MC#2_Chan#1_DIMM#0 (channel:1 slot:0 page:0x25751d offset:0x400 grain:32 - err_code:0x00a0:0x0091 SystemAddress:0x25751d400 ProcessorSocketId:0x1 MemoryControllerId:0x2 ChannelAddress:0x1d751c00 ChannelId:0x1 RankAddress:0xeba9c00 PhysicalRankId:0x0 DimmSlotId:0x0 Row:0x75a Column:0x380 Bank:0x0 BankGroup:0x1 ChipSelect:0x0 ChipId:0x0)
+[15521.417060] EDAC MC6: 1 UE memory read error on CPU_SrcID#1_MC#2_Chan#1_DIMM#0 (channel:1 slot:0 page:0x25751d offset:0x400 grain:32 - err_code:0x0000:0x009f SystemAddress:0x25751d400 ProcessorSocketId:0x1 MemoryControllerId:0x2 ChannelAddress:0x1d751c00 ChannelId:0x1 RankAddress:0xeba9c00 PhysicalRankId:0x0 DimmSlotId:0x0 Row:0x75a Column:0x380 Bank:0x0 BankGroup:0x1 ChipSelect:0x0 ChipId:0x0)
+[15521.452740] EDAC MC6: 1 UE memory read error on CPU_SrcID#1_MC#2_Chan#1_DIMM#0 (channel:1 slot:0 page:0x25751d offset:0x400 grain:32 - err_code:0x0000:0x009f SystemAddress:0x25751d400 ProcessorSocketId:0x1 MemoryControllerId:0x2 ChannelAddress:0x1d751c00 ChannelId:0x1 RankAddress:0xeba9c00 PhysicalRankId:0x0 DimmSlotId:0x0 Row:0x75a Column:0x380 Bank:0x0 BankGroup:0x1 ChipSelect:0x0 ChipId:0x0)
+```
+
+##### AO Validation
+
+###### AO Patrol Recovery
+
+In the case of an AO event e.g. `patrol`, the kernel will attempt to hard-offline the page, by just poisoning and unmapping the page. Inject and trigger patrol error. Note, in this section, the HWPoison-aware strategy is default late kill.
+
+```bash
+# einj_mem_uc patrol
+0: patrol vaddr = 0xffff9d523400 paddr = 400a2575400
+injecting ...
+triggering ...
+page not present
+Test passed
+```
+
+The dmesg log:
+
+```bash
+[ 2026.290450] EDAC MC0: 1 UE scrub uncorrected error on unknown memory (node:0 card:6 module:0 rank:0 bank_group:2 bank_address:3 device:0 row:137 column:640 chip_id:0 page:0x400a2575 offset:0x400 grain:1 - APEI location: node:0 card:6 module:0 rank:0 bank_group:2 bank_address:3 device:0 row:137 column:640 chip_id:0 status(0x0000000000000400): Storage error in DRAM memory)
+[ 2026.290460] {4}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 2
+[ 2026.301258] {4}[Hardware Error]: event severity: recoverable
+[ 2026.306903] {4}[Hardware Error]: precise tstamp: 2023-01-17 18:09:10
+[ 2026.313328] {4}[Hardware Error]: Error 0, type: recoverable
+[ 2026.318972] {4}[Hardware Error]: section_type: memory error
+[ 2026.324703] {4}[Hardware Error]: error_status: Storage error in DRAM memory (0x0000000000000400)
+[ 2026.333732] {4}[Hardware Error]: physical_address: 0x00000400a2575400
+[ 2026.340331] {4}[Hardware Error]: node:0 card:6 module:0 rank:0 bank_group:2 bank_address:3 device:0 row:137 column:640 chip_id:0
+[ 2026.352138] {4}[Hardware Error]: error_type: 14, scrub uncorrected error
+[ 2026.358998] {4}[Hardware Error]: type: DDR (0x50), common_reg_nr:1
+[ 2026.365249] {4}[Hardware Error]: Interrupt: 843
+[ 2026.369852] {4}[Hardware Error]: ECCERRCNT: 0x40000, ECCSTAT: 0x0, ADVECCSTAT: 0x88000002, ECCSYMBOL: 0xec0000, ECCERRCNTSTAT: 0x0, ECCERRCNT0: 0x0, ECCERRCNT1: 0x0, ECCCADDR0: 0x0, ECCCADDR1: 0x0, ECCCDATA0: 0x0, ECCCDATA1: 0x0, ECCUADDR0: 0x89, ECCUADDR1: 0x2030280, ECCUDATA0: 0x1ff, ECCUDATA1: 0x0
+[ 2026.397264] Memory failure: 0x400a2575: recovery action for dirty LRU page: Recovered
+```
+
+###### AO Prefetch Recovery
+
+First, inject an uncorrected error and trigger it by explicitly performing a `prfm`. The platform will signal an interrupt.
+
+```bash
+#einj_mem_uc prefetch
+0: prefetch vaddr = 0xffffbe03f400 paddr = 8c17eb400
+injecting ...
+triggering ...
+page not present
+Test passed
+```
+
+The dmesg log:
+
+```bash
+[ 7616.802823] {1}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 2
+[ 7616.813922] {1}[Hardware Error]: event severity: recoverable
+[ 7616.819566] {1}[Hardware Error]: Error 0, type: recoverable
+[ 7616.825210] {1}[Hardware Error]: section_type: memory error
+[ 7616.830940] {1}[Hardware Error]: error_status: 0x0000000000000400
+[ 7616.837191] {1}[Hardware Error]: physical_address: 0x00000008c17eb400
+[ 7616.843791] {1}[Hardware Error]: node: 0 card: 0 module: 0 rank: 1 bank_group: 3 bank_address: 0 device: 0 row: 773 column: 1408
+[ 7616.855597] {1}[Hardware Error]: error_type: 5, multi-symbol chipkill ECC
+[ 7616.862543] {1}[Hardware Error]: type: DDR (0x50), ras_count:1
+[ 7616.868447] {1}[Hardware Error]: sub_type: 0x0
+[ 7616.872962] {1}[Hardware Error]: fr: 0x1000200000026, ctrl: 0x0, status: 0x0, addr: 0x0
+[ 7616.881036] {1}[Hardware Error]: misc0: 0x0, misc1: 0x0, misc2: 0x0, misc3: 0x200000000000100
+[ 7616.889888] Memory failure: 0x8c17eb: recovery action for dirty LRU page: Recovered
+```
+
+###### AO Store Recovery
+
+First, inject an uncorrected error and trigger it by writing a byte. The write size is less than 64 bits and the platform will signal a SError.
+
+```bash
+# einj_mem_uc strbyte
+0: strbyte vaddr = 0xffffa3651400 paddr = 400afd01400
+injecting ...
+triggering ...
+page not present
+Test passed
+```
+
+The dmesg log:
+
+```bash
+[ 2378.241939] EDAC MC0: 1 UE multi-symbol chipkill ECC on unknown memory (node:0 card:5 module:0 rank:0 bank_group:2 bank_address:1 device:0 row:191 column:128 chip_id:0 page:0x400afd01 offset:0x400 grain:1 - APEI location: node:0 card:5 module:0 rank:0 bank_group:2 bank_address:1 device:0 row:191 column:128 chip_id:0 status(0x0000000000000400): Storage error in DRAM memory)
+[ 2378.241945] {5}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 2
+[ 2378.252573] {5}[Hardware Error]: event severity: recoverable
+[ 2378.258217] {5}[Hardware Error]: precise tstamp: 2023-01-17 18:15:02
+[ 2378.264642] {5}[Hardware Error]: Error 0, type: recoverable
+[ 2378.270286] {5}[Hardware Error]: section_type: memory error
+[ 2378.276017] {5}[Hardware Error]: error_status: Storage error in DRAM memory (0x0000000000000400)
+[ 2378.285045] {5}[Hardware Error]: physical_address: 0x00000400afd01400
+[ 2378.291644] {5}[Hardware Error]: node:0 card:5 module:0 rank:0 bank_group:2 bank_address:1 device:0 row:191 column:128 chip_id:0
+[ 2378.303451] {5}[Hardware Error]: error_type: 5, multi-symbol chipkill ECC
+[ 2378.310398] {5}[Hardware Error]: type: DDR (0x50), common_reg_nr:1
+[ 2378.316649] {5}[Hardware Error]: SError
+[ 2378.320558] {5}[Hardware Error]: ECCERRCNT: 0x10000, ECCSTAT: 0x0, ADVECCSTAT: 0x8000002, ECCSYMBOL: 0x6f0000, ECCERRCNTSTAT: 0x0, ECCERRCNT0: 0x0, ECCERRCNT1: 0x0, ECCCADDR0: 0x0, ECCCADDR1: 0x0, ECCCDATA0: 0x0, ECCCDATA1: 0x0, ECCUADDR0: 0xbf, ECCUADDR1: 0x2010080, ECCUDATA0: 0x1ff, ECCUDATA1: 0x0
+[ 2378.360399] Memory failure: 0x400afd01: recovery action for dirty LRU page: Recovered
+```
+
+In contrast, inject an uncorrected error and trigger it by writing a quad word. The write size is 64 bits and the platform will not signal SErrors.
+
+```bash
+# einj_mem_uc strqword
+0: strqword vaddr = 0xffff991b5400 paddr = 92b73c400
+injecting ...
+triggering ...
+Manually take page offline
+Test passed
+```
+
+The dmesg log:
+
+```bash
+[270286.564242] Memory failure: 0x92b73c: recovery action for dirty LRU page: Recovered
+```
+
+##### QEMU Validation
+
+First, start a VM with a stdio monitor which allows giving complex commands to the QEMU emulator.
+
+```bash
+qemu-system-aarch64 -enable-kvm \
+ -cpu host \
+ -M virt,gic-version=3 \
+ -m 8G \
+ -d guest_errors \
+ -rtc base=localtime,clock=host \
+ -smp cores=2,threads=2,sockets=2 \
+ -object memory-backend-ram,id=mem0,size=4G \
+ -object memory-backend-ram,id=mem1,size=4G \
+ -numa node,memdev=mem0,cpus=0-3,nodeid=0 \
+ -numa node,memdev=mem1,cpus=4-7,nodeid=1 \
+ -bios /usr/share/AAVMF/AAVMF_CODE.fd \
+ -drive driver=qcow2,media=disk,cache=writeback,if=virtio,id=alinu1_rootfs,file=/media/nvme/shawn.xs/qemu/aliyun_3_arm64_20G_alpha_alibase_20210425.qcow2 \
+ -netdev user,id=n1,hostfwd=tcp::5555-:22 \
+ -serial telnet:localhost:4321,server,nowait \
+ -device virtio-net-pci,netdev=n1 \
+ -monitor stdio
+QEMU 7.2.0 monitor - type 'help' for more information
+(qemu) VNC server running on 127.0.0.1:5900
+```
+
+Login guest and install ras-tools, then run `einj_mem_uc` to allocate a page in userspace, dumps the virtual and physical address of the page. The `-j` is to skip error injection and `-k` is to wait for a kick.
+
+``` bash
+$ einj_mem_uc single -j -k
+0: single vaddr = 0xffffb2f27000 paddr = 154aba000
+```
+
+Run command `gpa2hpa` in QEMU monitor and it will print the host physical address at which the guest’s physical address addr is mapped.
+
+``` bash
+(qemu) gpa2hpa 0x151f21400
+Host physical address for 0x154aba000 (mem1) is 0x92b3c5000
+```
+
+Inject an uncorrected error via the APEI interface to the finally translated host physical address on host.
+
+``` bash
+echo 0x92b3c5000 > /sys/kernel/debug/apei/einj/param1
+echo 0xfffffffffffff000 > /sys/kernel/debug/apei/einj/param2
+echo 0x0 > /sys/kernel/debug/apei/einj/flags
+echo 0x10 > /sys/kernel/debug/apei/einj/error_type
+echo 1 > /sys/kernel/debug/apei/einj/notrigger
+echo 1 > /sys/kernel/debug/apei/einj/error_inject
+```
+
+Then kick `einj_mem_uc` to trigger the error by writing "trigger_start". In this example, the kick is done on host.
+
+``` bash
+#ssh -p 5555 root@localhost "echo trigger > ~/trigger_start"
+```
+
+We will observe that the QEMU process exit.
+
+``` bash
+(qemu) qemu-system-aarch64: Hardware memory error!
+```
+
+The dmesg log:
+
+``` bash
+[ 2705.654424] EDAC MC0: 1 UE multi-symbol chipkill ECC on unknown memory (node:0 card:0 module:0 rank:1 bank_group:4 bank_address:2 device:0 row:1196 column:640 chip_id:0 page:0x92b3c5 offset:0x0 grain:1 - APEI location: node:0 card:0 module:0 rank:1 bank_group:4 bank_address:2 device:0 row:1196 column:640 chip_id:0 status(0x0000000000000400): Storage error in DRAM memory)
+[ 2705.654432] {6}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 2
+[ 2705.665047] {6}[Hardware Error]: event severity: recoverable
+[ 2705.670692] {6}[Hardware Error]: precise tstamp: 2023-01-17 18:20:29
+[ 2705.677118] {6}[Hardware Error]: Error 0, type: recoverable
+[ 2705.682762] {6}[Hardware Error]: section_type: memory error
+[ 2705.688492] {6}[Hardware Error]: error_status: Storage error in DRAM memory (0x0000000000000400)
+[ 2705.697521] {6}[Hardware Error]: physical_address: 0x000000092b3c5000
+[ 2705.704121] {6}[Hardware Error]: node:0 card:0 module:0 rank:1 bank_group:4 bank_address:2 device:0 row:1196 column:640 chip_id:0
+[ 2705.716014] {6}[Hardware Error]: error_type: 5, multi-symbol chipkill ECC
+[ 2705.722960] {6}[Hardware Error]: type: DDR (0x50), common_reg_nr:1
+[ 2705.729212] {6}[Hardware Error]: Synchronous Exception taken in EL0
+[ 2705.735551] {6}[Hardware Error]: ESR: 0x92000410, ELR: 0x401880, FAR: 0xffffb2e8c1d8, SCR: 0x403073d, SCTLR: 0x30cd183f, LR: 0x401840
+[ 2705.747619] {6}[Hardware Error]: ECCERRCNT: 0x10000, ECCSTAT: 0x0, ADVECCSTAT: 0x8000002, ECCSYMBOL: 0x60000, ECCERRCNTSTAT: 0x0, ECCERRCNT0: 0x0, ECCERRCNT1: 0x0, ECCCADDR0: 0x0, ECCCADDR1: 0x0, ECCCDATA0: 0x0, ECCCDATA1: 0x0, ECCUADDR0: 0x10004ac, ECCUADDR1: 0x4020280, ECCUDATA0: 0x1ff, ECCUDATA1: 0x0
+[ 2705.887179] EDAC MC0: 1 UE multi-symbol chipkill ECC on unknown memory (node:0 card:0 module:0 rank:1 bank_group:4 bank_address:2 device:0 row:1196 column:640 chip_id:0 page:0x92b3c5 offset:0x0 grain:1 - APEI location: node:0 card:0 module:0 rank:1 bank_group:4 bank_address:2 device:0 row:1196 column:640 chip_id:0 status(0x0000000000000400): Storage error in DRAM memory)
+[ 2705.887181] {7}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 2
+[ 2705.897824] {7}[Hardware Error]: event severity: recoverable
+[ 2705.903468] {7}[Hardware Error]: precise tstamp: 2023-01-17 18:20:29
+[ 2705.909893] {7}[Hardware Error]: Error 0, type: recoverable
+[ 2705.915537] {7}[Hardware Error]: section_type: memory error
+[ 2705.921267] {7}[Hardware Error]: error_status: Storage error in DRAM memory (0x0000000000000400)
+[ 2705.930296] {7}[Hardware Error]: physical_address: 0x000000092b3c5000
+[ 2705.936895] {7}[Hardware Error]: node:0 card:0 module:0 rank:1 bank_group:4 bank_address:2 device:0 row:1196 column:640 chip_id:0
+[ 2705.948790] {7}[Hardware Error]: error_type: 5, multi-symbol chipkill ECC
+[ 2705.955736] {7}[Hardware Error]: type: DDR (0x50), common_reg_nr:1
+[ 2705.961988] {7}[Hardware Error]: Synchronous Exception taken in EL0
+[ 2705.968326] {7}[Hardware Error]: ESR: 0x92000410, ELR: 0x401880, FAR: 0xffffb2e8c1d8, SCR: 0x403073d, SCTLR: 0x30cd183f, LR: 0x401840
+[ 2705.980394] {7}[Hardware Error]: ECCERRCNT: 0x0, ECCSTAT: 0x0, ADVECCSTAT: 0x0, ECCSYMBOL: 0x0, ECCERRCNTSTAT: 0x0, ECCERRCNT0: 0x0, ECCERRCNT1: 0x0, ECCCADDR0: 0x0, ECCCADDR1: 0x0, ECCCDATA0: 0x0, ECCCDATA1: 0x0, ECCUADDR0: 0x10004ac, ECCUADDR1: 0x4020280, ECCUDATA0: 0x0, ECCUDATA1: 0x0
+[ 2706.006235] Memory failure: 0x92b3c5: Sending SIGBUS to qemu-system-aar:32293 due to hardware memory corruption
+[ 2706.078549] Memory failure: 0x92b3c5: recovery action for dirty LRU page: Recovered
+[ 2706.092539] Memory failure: 0x92b3c5: already hardware poisoned
+[ 2706.118501] EDAC MC0: 1 UE multi-symbol chipkill ECC on unknown memory (node:0 card:0 module:0 rank:0 bank_group:1 bank_address:2 device:0 row:920 column:896 chip_id:0 page:0x0 offset:0x0 grain:1 - APEI location: node:0 card:0 module:0 rank:0 bank_group:1 bank_address:2 device:0 row:920 column:896 chip_id:0 status(0x0000000000000400): Storage error in DRAM memory)
+```
+
+Note, QEMU registers SIGBUS handler and sets `PR_MCE_KILL_EARLY` by `prctl`. When an AO error occurs, e.g. detected by scrubber, kernel will also send SIGBUS but with sicode `BUS_MCEERR_AO 5`.
+
+##### HWPoison-aware Strategy
+
+First, check the strategy on your system.
+
+```bash
+#sysctl vm.memory_failure_early_kill
+vm.memory_failure_early_kill = 0
+```
+
+Change to early kill mode:
+
+```bash
+#sysctl -w vm.memory_failure_early_kill=1
+vm.memory_failure_early_kill = 1
+```
+
+Then inject a `patrol` error to see the kernel behavior.
+
+```bash
+#./einj_mem_uc patrol
+0: patrol vaddr = 0xffffbe4b8400 paddr = 901656400
+injecting ...
+triggering ...
+signal 7 code 5 addr 0xffffbe4b8000
+Unexpected SIGBUS
+page not present
+Test passed
+```
+
+As we expected, the kernel sends SIGBUS to kill the process even though it does not access the poison data. The `code 5` here means `BUS_MCEERR_AO 5`.
+
+#### Memory Predictive Failure Analysis Validation
+
+First of all, you'll need to install **rasdeamon**, it's packaged for most Linux distributions:
+
+```bash
+yum install rasdaemon
+```
+
+Then we'll setup **rasdaemon** to launch at startup and to record events to an on-disk sqlite database.
+
+```bash
+# systemctl enable rasdaemon
+# systemctl start rasdaemon
+```
+
+Here, we manually change the `PAGE_CE_THRESHOLD="5"` in config file `/etc/sysconfig/rasdaemon` so that we can inject and exceed a page error threshold more easily. Note, run-time configuration is unsupported, service restart is needed.
+
+```bash
+# systemctl restart rasdaemon
+```
+
+Run `victim` with `-p` option to help test PFA function. The `victim` allocates a page in userspace, dumps the virtual and physical address of the page, and checks the physical address in a loop while. Then inject to the physical address 5 times and it will trigger soft action in which kernel soft-offline the old page, by moving the contents to a new page.
+
+```bash
+#victim -d -p
+physical address of (0xffffa5a66000) = 0x967cf1000
+Page was replaced. New physical address = 0x8bce3e000
+```
+
+## Acknowledgment
+
+Thanks to the developers who contributed to the Linux and Anolis communities.
+
+## Reference
+
+1. [https://www.intel.com/content/www/us/en/developer/articles/technical/new-reliability-availability-and-serviceability-ras-features-in-the-intel-xeon-processor.html](https://www.intel.com/content/www/us/en/developer/articles/technical/new-reliability-availability-and-serviceability-ras-features-in-the-intel-xeon-processor.html)
+2. Reliability, Availability and Serviceability (RAS) Integration and Validation Guide for the Intel® Xeon® Processor E7- v3 Family: [https://www.intel.com/content/dam/develop/external/us/en/documents/emca2-integration-validation-guide-556978.pdf](https://www.intel.com/content/dam/develop/external/us/en/documents/emca2-integration-validation-guide-556978.pdf)
+3. [https://docs.kernel.org/admin-guide/ras.html](https://docs.kernel.org/admin-guide/ras.html)
+4. [https://static.linaro.org/connect/sfo17/Presentations/SFO17-203%20-%20Reliability%2C%20Availability%2C%20and%20Serviceability%20%28RAS%29%20on%20ARM64%20status.pdf](https://static.linaro.org/connect/sfo17/Presentations/SFO17-203%20-%20Reliability%2C%20Availability%2C%20and%20Serviceability%20%28RAS%29%20on%20ARM64%20status.pdf)
+5. Intel® 64 and IA-32 Architectures Software Developer’s Manual
+6. [https://developer.ibm.com/articles/l-kernel-memory-access/](https://developer.ibm.com/articles/l-kernel-memory-access/)
+7. [https://docs.kernel.org/admin-guide/sysctl/vm.html#memory-failure-early-kill](https://docs.kernel.org/admin-guide/sysctl/vm.html#memory-failure-early-kill)
+8. Programming persistent memory: A comprehensive guide for developers
+9. [https://trustedfirmware-a.readthedocs.io/en/latest/components/sdei.html](https://trustedfirmware-a.readthedocs.io/en/latest/components/sdei.html#id2)
\ No newline at end of file
diff --git "a/sig/ARM_SIG/content/RAS/Bugzilla\347\224\250\346\210\267\346\226\207\346\241\243.md" "b/sig/ARM_SIG/content/RAS/Bugzilla\347\224\250\346\210\267\346\226\207\346\241\243.md"
new file mode 100644
index 0000000000000000000000000000000000000000..1113c0978742398e8e8543a9b1a309cedb3bb9a6
--- /dev/null
+++ "b/sig/ARM_SIG/content/RAS/Bugzilla\347\224\250\346\210\267\346\226\207\346\241\243.md"
@@ -0,0 +1,242 @@
+## 一. Bugzilla初识
+Bugzilla是一个缺陷管理系统,可以用来管理Bug,也可以用来管理需求。Bugzilla可以通过浏览器页面创建Bug,也可以通过api接口创建Bug。
+
+- **1.1 首页**
+
+
+## 二. Bug生命周期
+
+- **2.1 新建Bug**
+ - **2.1.1 路径**
+
+ 首页->New/File a Bug->Select a classification->Select a product->Bug创建页面。具体如下:首先,在首页点击New或File a Bug按钮,进行创建Bug。
+ 
+ 然后会提示让选择一个classification, classification是Bug的一级分类。
+ 
+ 选择完classification分类后会提示选择一个product,product是Bug的二级分类。
+ 
+
+ - **2.1.2 创建页面**
+
+ 选择完product产品后会进入Bug创建页面,创建页面有一些参数需要填充,具体参数含义如下图所示:
+ 
+
+- **2.2 编辑Bug**
+ - **2.2.1 路径**
+ - 首页->Search Bug/My Bugs->Bugs List->Click the Bug->Bug编辑页面。具体如下:
+
+ 首先在首页点击My Bugs或Open Bugs assign to me or reported by me 进入Bug List 列表页。
+ 
+ 然后在Bug List列表页点击Bug ID或Summary进入Bug编辑页面。
+ 
+
+ - **2.2.2 编辑页面**
+
+ Bug编辑页面也进行Bug一些字段的修改,编辑页面的字段同Bug创建。
+ 
+
+- **2.3 关闭Bug**
+ - **2.3.1 路径**
+ - Bug编辑页面->Status->Resolved、Fixed->Save Changes
+
+ 在Bug页面编辑Status状态,当状态被修改为[RESOLVED,FIXED]时表示Bug关闭,至此Bug的生命周期结束。
+ 
+
+## 三. Bugzilla Restful Api
+
+Bugzilla 提供了对外开放的restful api接口,通过接口可以方便的对Bug进行一些操作。官方接口描述如下:[https://bugzilla.readthedocs.io/en/5.0/api/index.html#apis](https://bugzilla.readthedocs.io/en/5.0/api/index.html#apis)。
+
+- **3.1 官方Api**
+
+ 官方api包括对Bug、评论、组件、产品等的操作,具体如下:
+ 
+
+- **3.2 额外的Api**
+
+除了官方Api之外,还单独定制了一部分Api,包括User、Bug、子组件等。
+
+ - **3.2.1 Sub Component Api**
+
+ - **Get Sub Components**
+
+ 查询现有的子组件详情
+
+ - **Request**:
+ ```json
+ https://bugzilla.openanolis.cn/rest/subcomponent?ids=(bug_id)
+ ```
+ - **Params Description**:
+
+ | **name** | **type** | **description** |
+ | --- | --- | --- |
+ | bug_id | int | Bug ID |
+
+ - **Response**:
+ ```json
+ {
+ "subcomponents": [
+ {
+ "default_cc": [
+ "xxx@163.com"
+ ],
+ "is_active": true,
+ "default_docs_contact": "",
+ "id": 10,
+ "component_name": "user",
+ "level": 0,
+ "description": "rest api create subcomponent",
+ "default_qa_contact": "xxx@163.com",
+ "default_to_private": false,
+ "product_id": 2,
+ "sort_key": 0,
+ "parent_id": null,
+ "product_name": "testfarm",
+ "name_tree": [
+ "sub_user3_9"
+ ],
+ "default_assignee": "xxx@163.com",
+ "name": "sub_user3_9",
+ "agile_team": "",
+ "component_id": 2
+ }
+ ]
+ }
+ ```
+
+ - **Post Sub Component**
+
+ 添加子组件
+
+ - **Request**:
+ ```json
+ https://bugzilla.openanolis.cn/rest/subcomponent
+ ```
+
+ - **Body Description**:
+
+ | **name** | **type** | **description** |
+ | --- | --- | --- |
+ | api_key | string | api auth key |
+ | product | string | 产品名 |
+ | component | string | 组件名 |
+ | subcomponent | string | 子组件名 |
+ | description | string | 描述 |
+ | default_assignee | string | 默认指派人邮箱 |
+ | default_docs_contact | string | 默认Docs邮箱 |
+ | default_qa_contact | string | 默认QA邮箱 |
+ | default_cc | list | 抄送邮箱列表 |
+
+ - **Response**:
+ ```json
+ {
+ id: 23
+ }
+ ```
+
+ - **Delete Sub Component**
+
+ 删除子组件
+
+ - **Request**:
+ ```json
+ https://bugzilla.openanolis.cn/rest/subcomponent?api_key=(api_key)&ids=(sub_component_id)&component=(component)&product=(product)
+ ```
+
+ - **Params Description**:
+
+ | **name** | **type** | **description** |
+ | --- | --- | --- |
+ | api_key | string | api auth key |
+ | product | string | 产品名 |
+ | component | string | 组件名 |
+ | sub_component_id | int | 子组件id |
+
+ - **Response**:
+ ```json
+ {
+ Deleted: [23]
+ }
+ ```
+
+ - **3.2.2 Component Api**
+ - **Get Components**
+
+ 查询现有的所有组件
+
+ - **Request**:
+ ```json
+ https://bugzilla.openanolis.cn/rest/component
+ ```
+
+ - **Params Description**:
+
+ | **name** | **type** | **description** |
+ | --- | --- | --- |
+ | | | |
+
+ - **Response**:
+
+ ```json
+ {
+ "components" : [
+ {
+ "id" : 3, // component id
+ "name" : "com_123" // component name
+ },
+ {
+ "id" : 4,
+ "name" : "product-length"
+ },
+ {
+ "id" : 1,
+ "name" : "TestComponent"
+ },
+ {
+ "id" : 2,
+ "name" : "user"
+ },
+ {
+ "id" : 5,
+ "name" : "user2"
+ }
+ ]
+ }
+ ```
+
+## 三. Bugzilla python 命令行插件
+
+python-bugzilla-cli 命令行插件支持通过python命令行去操作Bugzilla,比如创建、编辑Bug, 子组件等。
+
+- 3.1 插件安装:
+ - 在命令行执行命令:pip install python-bugzilla-anolis 安装命令行插件,插件地址:[https://pypi.org/project/python-bugzilla-anolis/](https://pypi.org/project/python-bugzilla-anolis/)
+
+ 
+
+- 3.2 插件配置:
+ - 生成api_key: [https://bugzilla.openanolis.cn/userprefs.cgi?tab=apikey](https://bugzilla.openanolis.cn/userprefs.cgi?tab=apikey),生成的api_key需要有bug edit权限,api_key权限 和当前帐号权限一致。
+
+ 
+
+ - 配置bugzillarc文件,配置url和api_key,python-bugzilla-cli插件可自动读取配置的参数,在使用命令时无需额外携带参数,bugzillarc文件内容如下:
+
+ 
+
+- 3.3 插件使用:
+ - 配置好bugzillarc文件之后,就可以使用bugzilla-anolis命令操作Bugzilla了,使用bugzilla-anolis命令查看当前支持的所有参数:
+
+ 
+
+ - 执行sub component相关命令:
+ - 查询:
+ ```json
+ bugzilla-anolis getsubcomponent --ids=10 --ids=11
+ ```
+ 
+
+ - 添加:bugzilla-anolis addsubcomponent --product=testfarm --component=user --subcomponent=sub_user77_5 --description="rest api create subcomponent" --default_assignee=shankailun@163.com --default_docs_contact=shankailun@163.com --default_qa_contact=shankailun@163.com --default_cc="shankailun@163.com,1174224378@qq.com"
+
+ 
+
+ - 删除:bugzilla-anolis deletesubcomponent --ids=39 --product=testfarm --component=user
+
+ 
diff --git "a/sig/ARM_SIG/content/profile_features/16K\345\216\237\345\255\220\345\206\231.md" "b/sig/ARM_SIG/content/profile_features/16K\345\216\237\345\255\220\345\206\231.md"
new file mode 100644
index 0000000000000000000000000000000000000000..3b2bd0e323cf22bdbf81edffe4725de3d5659d39
--- /dev/null
+++ "b/sig/ARM_SIG/content/profile_features/16K\345\216\237\345\255\220\345\206\231.md"
@@ -0,0 +1,54 @@
+# 优化原理
+MySQL InnoDB 的 page size 一般为 16KB,数据校验也是按 16KB 页面来计算的。但操作系统写入磁盘是以 4KB 页进行的,因此在极端场景如掉电,操作系统无法保证 InnoDB 的 16KB 页的原子写入,即 partial write。
+为了解决 partial write 问题,MySQL 在将脏数据 flush 到数据文件时,会先将脏数据拷贝到 double write buffer,之后通过 double write buffer 写入到共享表空间,再调用 fsync 刷到数据文件。
+因此,数据页面存在双倍的写入,这在实际应用场景可能带来如下问题:
+1)云盘场景,额外占用存储带宽,抖动问题变多;
+2)传统物理机场景,额外的写入会降低 SSD 的寿命(TBW 为 SSD 的生命周期重要指标之一)。
+大致原理图如下:
+
+Double Write 介绍:
+[https://dev.mysql.com/doc/refman/8.0/en/innodb-doublewrite-buffer.html](https://dev.mysql.com/doc/refman/8.0/en/innodb-doublewrite-buffer.html)
+16k 原子写方案旨在通过文件系统 COW 异地更新的机制,确保 MySQL 16k 页面原子写入,同时对 MySQL 应用无侵入,优化 MySQL 的性能和数据写入量,解决 Double Write 带来的额外带宽占用以及降低 SSD 寿命等问题。
+# 使用方法
+1、下载 OpenAnolis 社区 SIG 的特性分支代码,并编译安装。
+```
+git clone git@gitee.com:anolis/storage-cloud-kernel.git git checkout feature/atomic-write make anolis_defconfig make -j64 -s sudo make modules_install -j64 -s sudo make install sudo reboot
+```
+2、安装 MySQL 和客户端:
+```
+sudo yum install mariadb mariadb-server mariadb-devel
+```
+3、创建 xfs 数据盘并挂载,用于保存 MySQL 数据库。 (注意需确保 xfsprogs 版本支持 reflink 特性)
+```
+sudo mkfs.xfs -m reflink=1 sudo mount sudo chown -R mysql:mysql
+```
+例如:
+```
+sudo mkfs.xfs -m reflink=1 /dev/vdb sudo mount /dev/vdb /var/lib/mysql sudo chown -R mysql:mysql /var/lib/mysql
+```
+4、修改 MySQL 配置文件 /etc/my.cnf,使用 direct 写入,并关闭 double write。例如:
+```
+[mysqld] datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock ... innodb_file_per_table innodb_page_size = 16384 innodb_buffer_pool_size = 12288M innodb_use_native_aio = 0 innodb_flush_method = O_DIRECT innodb_doublewrite = 0 # 已支持 16k 原子写,无需 double write
+```
+
+- 设置 mysql db 目录为原子写目录,如:
+```
+sudo chattr +c /var/lib/mysql
+```
+
+- dmesg 将显示原子写已针对目录开启信息:
+```
+[ 330.918099] XFS (vdb): atomic write set on dir ino 128
+```
+6、启动 mysqld 服务。
+```
+sudo systemctl start mariadb
+```
+7、下载并编译 sysbench。
+```
+git clone https://github.com/akopytov/sysbench.git cd sysbench ./autogen.sh ./configure make -j64 -s sudo make install
+```
+8、运行测试。
+```
+sudo ./test-mysql.sh
+```
diff --git a/sig/ARM_SIG/content/profile_features/E0PD.md b/sig/ARM_SIG/content/profile_features/E0PD.md
new file mode 100644
index 0000000000000000000000000000000000000000..929fdae913b28f996c623546d7296da6f5d04b07
--- /dev/null
+++ b/sig/ARM_SIG/content/profile_features/E0PD.md
@@ -0,0 +1,89 @@
+# 优化原理
+E0PD是ARMv8.5扩展引入的一个硬件防护特性,它用来替代KPTI避免来自用户态的Meltdown漏洞攻击。KPTI技术通过在返回用户态时unmap kernel space的方式避免内核地址空间的暴露,因此在退出内核态时unmap内核页表以及在进入内核态时重新映射内核页表会带来极大性能开销。E0PD在硬件侧防护内核地址空间从而使内核可以绕过KPTI,因而带来性能提升。
+
+在内核优化方面,开启E0PD绕过KPTI的代码如下(省略一些无关的代码片段)。在boot阶段,内核调用unmap_kernel_at_el0函数检测是否需要开启KPTI unmap内核地址空间功能,其中的重要一项检测就是调用kaslr_requires_kpti,在此函数内检查硬件是否支持E0PD并且内核是否打开E0PD,若是则返回false,表示不需要启用KPTI功能。
+
+```
+static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */
+
+static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
+ int scope)
+{
+ …………
+
+ /* Useful for KASLR robustness */
+ if (kaslr_requires_kpti()) {
+ if (!__kpti_forced) {
+ str = "KASLR";
+ __kpti_forced = 1;
+ }
+ }
+
+ …………
+
+ /* Forced? */
+ if (__kpti_forced) {
+ pr_info_once("kernel page table isolation forced %s by %s\n",
+ __kpti_forced > 0 ? "ON" : "OFF", str);
+ return __kpti_forced > 0;
+ }
+
+ …………
+}
+```
+```
+/*
+ * This check is triggered during the early boot before the cpufeature
+ * is initialised. Checking the status on the local CPU allows the boot
+ * CPU to detect the need for non-global mappings and thus avoiding a
+ * pagetable re-write after all the CPUs are booted. This check will be
+ * anyway run on individual CPUs, allowing us to get the consistent
+ * state once the SMP CPUs are up and thus make the switch to non-global
+ * mappings if required.
+ */
+bool kaslr_requires_kpti(void)
+{
+ if (!IS_ENABLED(CONFIG_RANDOMIZE_BASE))
+ return false;
+
+ /*
+ * E0PD does a similar job to KPTI so can be used instead
+ * where available.
+ */
+ if (IS_ENABLED(CONFIG_ARM64_E0PD)) {
+ u64 mmfr2 = read_sysreg_s(SYS_ID_AA64MMFR2_EL1);
+ if (cpuid_feature_extract_unsigned_field(mmfr2,
+ ID_AA64MMFR2_E0PD_SHIFT))
+ return false;
+ }
+
+ /*
+ * Systems affected by Cavium erratum 24756 are incompatible
+ * with KPTI.
+ */
+ if (IS_ENABLED(CONFIG_CAVIUM_ERRATUM_27456)) {
+ extern const struct midr_range cavium_erratum_27456_cpus[];
+
+ if (is_midr_in_range_list(read_cpuid_id(),
+ cavium_erratum_27456_cpus))
+ return false;
+ }
+
+ return kaslr_offset() > 0;
+}
+```
+#
+使用方法
+## 使用Alinux3.2208及以后版本
+Alinux3在2208版本(内核版本5.10.134)已默认启用
+说明:从upstream打上E0PD相关patch(anck 5.10已经合入),
+
+- 3e6c69a arm64: Add initial support for E0PD
+- 92ac6fd arm64: Don't use KPTI where we have E0PD
+## 编译内核时启用E0PD特性
+如果需要自己编译内核,可以在编译参数中打开E0PD配置
+```
+CONFIG_ARM64_E0PD=y
+```
+# 性能收益
+KPTI的内核地址空间map、unmap操作在通用路径上,所以E0PD对KPTI的优化影响广泛。在我们的测试中,E0PD优化对基础benchmark和E2E应该都带来了5-23%的大幅度性能提升。
diff --git a/sig/ARM_SIG/content/profile_features/EXT4 Fast Commit.md b/sig/ARM_SIG/content/profile_features/EXT4 Fast Commit.md
new file mode 100644
index 0000000000000000000000000000000000000000..f288f453e47a278d23b2e685a635ffbb05a1ebec
--- /dev/null
+++ b/sig/ARM_SIG/content/profile_features/EXT4 Fast Commit.md
@@ -0,0 +1,63 @@
+# 优化原理
+Fast Commit 是 Linux 5.10 引入的一个新的轻量级日志方案,根据 ATC-17 的论文 “iJournaling: Fine-Grained Journaling for Improving the Latency of Fsync System Call” 实现。
+在常用的 ext4 data=ordered 日志模式下,fsync() 系统调用会因为无关 IO 操作导致显著的时延。Fast Commit 根据写入日志中的元数据反推,只提交与当前 transaction 相关的操作,从而优化 fsync() 的时延。
+启用 Fast Commit 特性后,系统中将会有两个日志,快速提交日志用于可以优化的操作,常规日志用于标准提交。其中 Fast Commit 日志包含上一次标准提交之后执行的操作。
+从作者的 benchmark 测试数据来看,打开 Fast Commit 特性后,本地 ext4 文件系统有 20% ~ 200% 的性能提升;NFS 场景也有 30% ~ 75% 的性能提升。
+
+| Benchmark | Config | w/o Fast Commit | w/ Fast Commit | Delta |
+| --- | --- | --- | --- | --- |
+| Fsmark
+Fsmark | Local, 8 threads
+NFS, 4 threads | 1475.1 files/s
+299.4 files/s | 4309.8 files/s
+409.45 files/s | +192.2%
++36.8% |
+| Dbench
+Dbench | Local, 2 procs
+NFS, 2 procs | 33.32 MB/s
+8.84 MB/s | 70.87 MB/s
+11.88 MB/s | +112.7%
++34.4% |
+| Dbench
+Dbench | Local, 10 procs
+NFS, 10 procs | 90.48 MB/s
+34.62 MB/s | 110.12 MB/s
+52.83 MB/s | +21.7%
++52.6% |
+| FileBench
+FileBench | Local, 16 threads
+NFS, 16 threads | 10442.3 ops/s
+1531.3 ops/s | 18617.8 ops/s
+2681.5 ops/s | +78.3%
++75.1% |
+
+# 使用方法
+## 获取支持Fast Commit特性的e2fsprogs
+### 使用Alinux3.2208及以后版本
+Alinux3在2208版本(e2fsprogs版本高于1.46.0)已默认启用该特性
+### 下载最新的 e2fsprogs 包并编译
+```
+wget https://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git/snapshot/e2fsprogs-1.46.2.tar.gz
+tar -xvf e2fsprogs-1.46.2.tar.gz
+cd e2fsprogs-1.46.2
+./configure
+make
+```
+## 格式化打开Fast Commit特性
+```
+./misc/mke2fs -t ext4 -O fast_commit /dev/vdc1
+```
+dumpe2fs 可以看到已经打开 fast commit:
+
+```
+Filesystem features: has_journal ext_attr resize_inode dir_index fast_commit filetype extent 64bit flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
+```
+此外,超级块中多出 Overhead blocks 字段:
+
+```
+Overhead blocks: 126828
+```
+同时,Journal size 也由默认的 128M 变成 130M,应该是默认 fast commit journal size 为 journal size / 64 带来的增量:
+```
+Journal size: 130M
+```
diff --git "a/sig/ARM_SIG/content/profile_features/LSE\346\214\207\344\273\244\351\233\206\347\274\226\350\257\221\344\274\230\345\214\226.md" "b/sig/ARM_SIG/content/profile_features/LSE\346\214\207\344\273\244\351\233\206\347\274\226\350\257\221\344\274\230\345\214\226.md"
new file mode 100644
index 0000000000000000000000000000000000000000..1a3ec04fb968ba119a06310b830816bf4786f932
--- /dev/null
+++ "b/sig/ARM_SIG/content/profile_features/LSE\346\214\207\344\273\244\351\233\206\347\274\226\350\257\221\344\274\230\345\214\226.md"
@@ -0,0 +1,6 @@
+# 优化原理
+LSE(Large System Extensions)是ARMv8.1新增的原子操作指令集。
+在LSE之前,如果想实现某个原子操作,必须要使用带有load_acquire/store_release的指令,如LDXR和STXR,但这两个指令的操作本质上是很多CPU核去抢某个内存变量的独占访问,以前ARM主要用来在低功耗设备上运行,CPU核并不多,不会存在太大的问题。但在数据中心发展场景下,ARM处理器已经发展到几十上百核,如果还是独占访问会存在严重的性能问题。因此,为了支持这种大型系统,在ARMv8.1中特意加入了大量原生原子操作指令以优化性能。在有较多多线程竞争的场景下,使用LSE指令集会有比较明显的性能提升。
+# 使用方法
+倚天710建议指定march=armv8.6+sve2 mtune=neoverse-n1
+PS: LSE在armv8.1以后by default支持,指定armv8.6或neoverse-n1 都会使用LSE进行编译
diff --git a/sig/ARM_SIG/content/profile_features/LTO.md b/sig/ARM_SIG/content/profile_features/LTO.md
new file mode 100644
index 0000000000000000000000000000000000000000..cb74acb22aac12d24573e5503b78cd257e0dd6b7
--- /dev/null
+++ b/sig/ARM_SIG/content/profile_features/LTO.md
@@ -0,0 +1,96 @@
+# 优化原理
+LTO,顾名思义,就是在链接的时候,继续做一系列的优化。又由于编译器的优化器是以IR为输入,因此编译器在链接时优化的编译过程中将每个源文件生成的不再是真正的二进制文件,而是"LTO对象文件"。这些文件中存储的不是二进制代码,而是编译器生成的IR。
+链接时,编译器会将所有"LTO对象文件"合并到一起,合并后生成的巨大IR文件包含了所有源代码信息,这样就能跨文件对所有源代码(合并后的IR文件)进行集中的分析和优化,并生成一个真正的二进制文件,链接并得到可执行文件。因为编译器能够一次性看到所有源代码的信息,所以它做的分析具有更高的确定性和准确性,能够实施的优化也要多得多。
+但在使用LTO优化大型的应用程序的时候,“链接”阶段将所有"LTO对象文件"合并成一个IR文件并生成的单个二进制文件可能非常庞大,这给系统虚拟内存造成很大压力,导致频繁内存换页,最终影响编译、链接的效率,甚至出现out of memory错误。
+实际上,GCC编译器在LTO阶段首先会将所有文件中的符号表(symbol table)信息和调用图(call graph)信息合并到一起,这样不仅能跨文件对所有的函数进行全局的分析,而且内存压力也较小。WPA(whole program analysis, 全局分析)阶段会确定具体的优化策略,并依据优化策略将所有的"LTO对象文件"合并成一或多个IR文件。
+
+这些IR文件再次并发经过优化器优化后,生成真正的二进制对象文件并传递给真正的链接器进行链接,最后得到可执行文件。
+
+# 使用方法
+举例说明如何使用LTO来进行编译优化:
+
+- 编写了一个包含两个源文件(source1.c 和 source2.c)和一个头文件(source2.h)的程序。由于头文件中非常简单地包含了source2.c中的函数原型, 所以并没有列出。
+```
+/* source1.c */
+#include // scanf_s and printf.
+#include "source2.h"
+int square(int x) { return x*x; }
+int main() {
+ int n = 5, m;
+ scanf("%d", &m);
+ printf("The square of %d is %d.\n", n, square(n));
+ printf("The square of %d is %d.\n", m, square(m));
+ printf("The cube of %d is %d.\n", n, cube(n));
+ printf("The sum of %d is %d.\n", n, sum(n));
+ printf("The sum of cubes of %d is %d.\n", n, sumOfCubes(n));
+ printf("The %dth prime number is %d.\n", n, getPrime(n));
+}
+```
+```
+/* source2.c */
+#include // sqrt.
+#include // bool, true and false.
+#include "source2.h"
+int cube(int x) { return x*x*x; }
+int sum(int x) {
+ int result = 0;
+ for (int i = 1; i <= x; ++i) result += i;
+ return result;
+}
+int sumOfCubes(int x) {
+ int result = 0;
+ for (int i = 1; i <= x; ++i) result += cube(i);
+ return result;
+}
+static
+bool isPrime(int x) {
+ for (int i = 2; i <= (int)sqrt(x); ++i) {
+ if (x % i == 0) return false;
+ }
+ return true;
+}
+int getPrime(int x) {
+ int count = 0;
+ int candidate = 2;
+ while (count != x) {
+ if (isPrime(candidate))
+ ++count;
+ }
+ return candidate;
+}
+```
+source1.c文件包含两个函数,有一个参数并返回这个参数的平方的square函数,以及程序的main函数。main函数调用source2.c中除了isPrime之外的所有函数。source2.c有5个函数。cube返回一个数的三次方;sum函数返回从1到给定数的和;sumOfCubes返回1到给定数的三次方的和;isPrime用于判断一个数是否是质数;getPrime函数返回第x个质数。笔者省略掉了容错处理因为那并非本文的重点。
+这些代码简单但是很有用。其中一些函数只进行简单的运算,一些需要简单的循环。getPrime是当中最复杂的函数,包含一个while循环且在循环内部调用了也包含一个循环的isPrime函数。通过这些函数,我们将在LTO下看到函数内联,常量折叠等编译器最重要,最常见的优化。
+
+- 编译命令(gcc版本是9.0.1)
+```
+# Non-LTO:
+gcc source1.c source2.c -O2 -o source-nolto
+# LTO:
+gcc source1.c source2.c -flto -O2 -o source-lto
+```
+
+- 检查source-nolto的汇编
+```
+1. 可以发现square被main函数inline了,对于第一次square(n)的调用,由于n在编译时刻可知,所以代码
+ 被常数25替代,对于square的第二次调用square(m),由于m的值在编译时是未知的,所以编译器不能对
+ 计算估值。
+2. 可以发现isPrime被getPrime函数inline了,这是由于candidate有初始值,inline后可以做常量折叠;
+ 另外一方面,isPrime是static函数,且只有getPrime调用了它,inline之后,可以将这个函数当作dead
+ code删除,减小代码体积。
+```
+
+- 检查source-lto的汇编
+```
+1. 可以看到除了scanf之外的所有函数都被作为了内联函数,因为在GCC LTO的WPA阶段, 这些函数的定义都是
+ 可见的。并且,由n编译时刻已知,编译器在编译时刻就会完成函数square(n), cube(n),sum(n)和
+ sumOfCubes(n)的计算。
+2. LTO获得了30%以上的性能提升
+```
+
+- 结论
+```
+1. 某些优化,当其作用于整个程序级别时,往往比其作用于局部时更加有效,函数内联就是这种类型的优化之一。
+2. 事实上,大多数优化都在全局范围内都更加有效,这也就是我们编译大型应用程序时,推荐使用LTO的原因和理由。
+3. FireFox、Chrome、 Mysql等大型应用使用LTO build都获得了5%-15%不等的性能提升
+```
diff --git a/sig/ARM_SIG/content/profile_features/PGO.md b/sig/ARM_SIG/content/profile_features/PGO.md
new file mode 100644
index 0000000000000000000000000000000000000000..26d1b71ad90ddb206ba6944b7a8e23d5e943bce0
--- /dev/null
+++ b/sig/ARM_SIG/content/profile_features/PGO.md
@@ -0,0 +1,97 @@
+# 优化原理
+PGO全称profile guided optimization,主要是为了解决传统编译器在执行优化的时候,只是是基于静态代码信息,而不去考虑用户可能的输入,从而无法有效对代码进行有效优化的问题。
+PGO可以分为三个阶段,分别是instrument,train,optimize三个阶段。在instrument阶段中,会先对应用做一次编译。在这次编译中,编译器会向代码中插入一下指令,以便下一阶段可以收集数据。插入的指令分为三种类型,分别用来统计:
+
+1. 每个函数被执行了多少次
+1. 每个分支被执行了多少次(例如if-else的场景)
+1. 某些变量的值(主要用于switch-case的场景)
+
+在train阶段中,用户需要使用最常用的输入来运行上一阶段编译生成的应用。由于上一阶段已经做好了收集数据的准备,在经过train阶段之后,该应用最常见的使用场景对应的数据就会被收集下来。
+最后阶段是optimization阶段。在该阶段中,编译器会利用上一阶段收集到的数据,对应用进行重新编译。由于上一阶段的数据来自于用户输入的最常见的用户场景,那么最后优化得到的结果就能在该场景下有更好的优化。
+# 使用方法
+举例说明如何使用PGO来进行编译优化:
+编写一段C++代码,该代码用较为低效的方式来判断一个数字是否为质数。代码如下:
+```
+//test.cpp
+#include
+#include
+using namespace std;
+int main(int argc, char** argv){
+ int num0 = atoi(argv[1]);
+ int num1 = atoi(argv[1]);
+ int branch = atoi(argv[2]);
+ if (branch < 1){
+ for (int i=2;i<=num0;i++){
+ if (num0%i==0){
+ cout<> (5 * (scale) + 1)) & TLBI_RANGE_MASK) - 1)
+```
+scale的值按照0逐渐递增,结合num值,统计出此次刷新的页数。
+```bash
+#define __TLBI_RANGE_PAGES(num, scale) \
+ ((unsigned long)((num) + 1) << (5 * (scale) + 1))
+```
+按照rvale1is格式,将地址start, 以及scale和num值,写入rvale1is寄存器中,对页进行刷新操作。
+```bash
+__TLBI_VADDR_RANGE(start, asid, scale, num, tlb_level);
+__tlbi(rvale1is, addr);
+__tlbi_user(rvale1is, addr);
+```
+更多可参考
+[https://developer.arm.com/documentation/ddi0595/2021-12/AArch64-Instructions/TLBI-RVALE1IS--TLBI-RVALE1ISNXS--TLB-Range-Invalidate-by-VA--Last-level--EL1--Inner-Shareable](https://developer.arm.com/documentation/ddi0595/2021-12/AArch64-Instructions/TLBI-RVALE1IS--TLBI-RVALE1ISNXS--TLB-Range-Invalidate-by-VA--Last-level--EL1--Inner-Shareable)
+# 使用方法
+### 使用Alinux3.2208及以后版本
+Alinux3在2208版本(内核版本5.10.134-12_rc1)已默认启用该特性
diff --git "a/sig/ARM_SIG/content/profile_features/code_hugepage - \344\273\243\347\240\201\345\244\247\351\241\265.md" "b/sig/ARM_SIG/content/profile_features/code_hugepage - \344\273\243\347\240\201\345\244\247\351\241\265.md"
new file mode 100644
index 0000000000000000000000000000000000000000..9c7a33424a32da4f5667b5cc4b2a8d59a7647be6
--- /dev/null
+++ "b/sig/ARM_SIG/content/profile_features/code_hugepage - \344\273\243\347\240\201\345\244\247\351\241\265.md"
@@ -0,0 +1,70 @@
+# 优化原理
+代码大页特性主要为大代码段业务服务,可以降低程序的iTLB miss,从而提升程序性能。
+# 使用方法
+在Alinux3/Anolis8上,该特性默认是关闭的。可以使用sysfs接口进行启用,启用方式有三种不同的方式。
+## 启用方法
+方式一:仅打开二进制和动态库大页
+```
+echo 1 > /sys/kernel/mm/transparent_hugepage/hugetext_enabled
+```
+方式二:仅打开可执行匿名大页
+```
+echo 2 > /sys/kernel/mm/transparent_hugepage/hugetext_enabled
+```
+方式三:同时打开以上两类大页
+```
+echo 3 > /sys/kernel/mm/transparent_hugepage/hugetext_enabled
+```
+## 关闭方法
+使用sysfs接口关闭代码大页:
+```
+echo 0 > /sys/kernel/mm/transparent_hugepage/hugetext_enabled
+```
+同时,注意释放已使用的大页,也有几种不同方式:
+方式一:清理整个系统的page cache
+```
+echo 3 > /proc/sys/vm/drop_caches
+```
+方式二:清理单个文件的page cache
+```
+vmtouch -e //target
+```
+方式三:清理遗留大页
+```
+echo 1 > /sys/kernel/debug/split_huge_pages
+```
+## 检查是否启用代码大页
+查看/proc//smaps中FilePmdMapped字段可确定是否使用了代码大页。
+扫描进程代码大页使用数量(**单位KB**):
+```
+cat /proc//smaps | grep FilePmdMapped | awk '{sum+=$2}END{print"Sum= ",sum}'
+```
+# 性能收益
+该特性在不同平台优化效果不同,主要原因在于平台TLB的设计。当前已知较适用场景包括mysql、postgresql以及oceanbase,优化效果在5~8%。
+
+---
+
+# 附录-1:进一步优化——Padding
+## 优化原理
+Padding特性是对代码大页特性的优化,主要解决在分配给大页使用的内存剩余量不足以再分配出一个新的大页时导致的内存碎片问题。该特性需要在启用代码大页的基础上使用,不可独立使用。
+> 举例说明:当二进制文件末尾剩余text段由于不足2M而无法使用大页,当剩余text大小超过hugetext_pad_threshold值,可将其填充为2M text,保证可使用上大页。
+
+## 使用方法
+### 启用方法
+同样使用sysfs接口启用padding特性:
+```
+echo [0~2097151] > /sys/kernel/mm/transparent_hugepage/hugetext_pad_threshold
+```
+> 建议一般情况写4096即可:echo 4096 > /sys/kernel/mm/transparent_hugepage/hugetext_pad_threshold
+
+### 关闭方法
+使用sysfs接口关闭padding特性,同时注意释放已使用的大页(参考“代码大页”的关闭方法)。
+```
+echo 0 > /sys/kernel/mm/transparent_hugepage/hugetext_pad_threshold
+```
+# 附录-2:注意事项
+
+1. 打开、关闭并不意味着立即合并、拆散大页,hugetext 是异步的。
+1. 如果一段代码曾经被整理成大页,即使关闭 hugetext 功能,还是会大页映射。
+1. 在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop_caches` 来回收整理的大页,下次就是小页映射了。
+1. 想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
diff --git a/sig/ARM_SIG/sig-info.yaml b/sig/ARM_SIG/sig-info.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..470ee0a9841a3c1d6f46c5808a9bde51fa23c17c
--- /dev/null
+++ b/sig/ARM_SIG/sig-info.yaml
@@ -0,0 +1,14 @@
+name: ARM 架构 SIG
+en_name: ARM ARCH SIG
+home_page: https://openanolis.cn/sig/ARM_ARCH_SIG
+description: ARM ARCH SIG致力于ARM架构软件生态的共建和推广,以及基于Anolis社区ANCK内核支持ARM Vendors平台。
+en_description: ARM ARCH SIG is committed to co-construct and promote the software ecology of the ARM architecture,and support ARM vendors platform.
+mailing_list: arm-arch@lists.openanolis.cn
+maintainers:
+- openanolis_id: baolinwang
+- openanolis_id: zaiping
+- openanolis_id: feifeijs
+- openanolis_id: Jack_phytium
+repositories:
+- repo:
+ - anolis/arm-cloud-kernel
diff --git a/sig/Anolis_FoundUI_SIG/README.md b/sig/Anolis_FoundUI_SIG/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..8e98c8dd299266eaefb48d57a19c6332a1591952
--- /dev/null
+++ b/sig/Anolis_FoundUI_SIG/README.md
@@ -0,0 +1,22 @@
+## SIG主页
+https://openanolis.cn/sig/foundui
+
+## SIG目标
+FoundUI是中科方德自研的桌面环境,FoundUI-SIG活动内容以桌面环境、自研应用、上游包的开发、缺陷修复与维护为主,依托中科方德在操作系统领域的技术积累和经验,孵化基于FoundUI的Anolis操作系统相关项目,向社区输出体验优秀的开源产品。
+
+## SIG主要工作
+桌面环境、应用产品规划开发、缺陷修复与维护,上游包维护。
+
+## 代码仓库
+https://gitee.com/src-anolis-foundui
+
+## 成员列表
+| 成员 | 角色 |
+| ------------------------------------------------------ | ----------- |
+| [fd-zhangtao](https://gitee.com/fd-zhangtao) | maintainer |
+| [qiangaoyang](https://gitee.com/qiangaoyang) | contributor |
+| [leaf_boat_sailor](https://gitee.com/leaf_boat_sailor) | contributor |
+| [maqiang0712](https://gitee.com/maqiang0712) | contributor |
+
+## 小组例会
+月度例会 review 项目进展情况
\ No newline at end of file
diff --git a/sig/zhongjie05/content/.keep "b/sig/Anolis_FoundUI_SIG/content/SIG\344\276\213\344\274\232/SIG\344\276\213\344\274\232(202308-2023-12).md"
similarity index 100%
rename from sig/zhongjie05/content/.keep
rename to "sig/Anolis_FoundUI_SIG/content/SIG\344\276\213\344\274\232/SIG\344\276\213\344\274\232(202308-2023-12).md"
diff --git "a/sig/Anolis_FoundUI_SIG/content/\347\224\250\346\210\267\346\214\207\345\215\227/\346\214\207\345\215\227.md" "b/sig/Anolis_FoundUI_SIG/content/\347\224\250\346\210\267\346\214\207\345\215\227/\346\214\207\345\215\227.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/sig/Anolis_FoundUI_SIG/sig-info.yaml b/sig/Anolis_FoundUI_SIG/sig-info.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..adf53367a4660cb89064b992a5abe25abd88a007
--- /dev/null
+++ b/sig/Anolis_FoundUI_SIG/sig-info.yaml
@@ -0,0 +1,22 @@
+name: FoundUI
+en_name: FoundUI
+home_page: https://openanolis.cn/sig/foundui
+
+description: FoundUI是中科方德自研的桌面环境,FoundUI-SIG活动内容以桌面环境、自研应用、上游包的开发、缺陷修复与维护为主,依托中科方德在操作系统领域的技术积累和经验,孵化基于FoundUI的Anolis操作系统相关项目,向社区输出体验优秀的开源产品。
+en_description: FoundUI is a desktop environment self-developed by ZKFOND. The activities of FoundUI-SIG focus on desktop environment, self-developed applications, development of upstream packages, defect repair and maintenance, relying on ZKFOND's technical accumulation and experience in the field of operating systems, to incubate projects related to the Anolis operating system based on FoundUI, and to output open-source products with excellent experience to the community.
+
+maintainers:
+- openanolis_id: fd-zhangtao
+ gitee_id: fd-zhangtao
+
+contributors:
+- openanolis_id: qiangy
+ gitee_id: qiangaoyang
+- openanolis_id: ruizhe
+ gitee_id: leaf_boat_sailor
+- openanolis_id: maqiang
+ gitee_id: maqiang0712
+
+repositories:
+- repo:
+ - src-anolis-foundui
\ No newline at end of file
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/Cloud_Kernel_\344\272\247\345\223\201\347\256\200\344\273\213/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/Cloud_Kernel_\344\272\247\345\223\201\347\256\200\344\273\213/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..8e463b096dfb28b1ad1697b2ee4ea21fbc80e846
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/Cloud_Kernel_\344\272\247\345\223\201\347\256\200\344\273\213/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/VPP-IPSec/dual_machine_topology.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/VPP-IPSec/dual_machine_topology.png"
new file mode 100644
index 0000000000000000000000000000000000000000..36af6fd7eda94deaa039e7a45d77c3ef32719082
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/VPP-IPSec/dual_machine_topology.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/VPP-IPSec/single_machine_topology.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/VPP-IPSec/single_machine_topology.png"
new file mode 100644
index 0000000000000000000000000000000000000000..75a554c64933607d62b48a5ac5cb99b53c4f2562
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/VPP-IPSec/single_machine_topology.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/VPP-IPSec/worker_bound_to_nic.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/VPP-IPSec/worker_bound_to_nic.png"
new file mode 100644
index 0000000000000000000000000000000000000000..811208fe709f360025e259c54c041cbb68105e52
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/VPP-IPSec/worker_bound_to_nic.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/dingding_group_qa.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/dingding_group_qa.png"
new file mode 100644
index 0000000000000000000000000000000000000000..c5b855ba68d171d8ff86213120b6db9abb79bcf8
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/dingding_group_qa.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/solution/5_phases.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/solution/5_phases.png"
new file mode 100644
index 0000000000000000000000000000000000000000..4babe9ef8805022b171dbf38424448e2ef87d86f
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/solution/5_phases.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/solution/theory.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/solution/theory.png"
new file mode 100644
index 0000000000000000000000000000000000000000..1ad202661dca1c0ed58f682cbf32645223092bc5
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/solution/theory.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.11.14\343\200\221Cloud_Kernel\344\273\243\347\240\201\345\220\210\345\271\266\346\265\201\347\250\213\345\217\230\346\233\264/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.11.14\343\200\221Cloud_Kernel\344\273\243\347\240\201\345\220\210\345\271\266\346\265\201\347\250\213\345\217\230\346\233\264/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..62dc7b6b0032e519b579904258e138907fd55970
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.11.14\343\200\221Cloud_Kernel\344\273\243\347\240\201\345\220\210\345\271\266\346\265\201\347\250\213\345\217\230\346\233\264/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b3d694d5986e8236c6689d2576c38dc8aef02474
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..89e8edb07188edf919b880e5caf9bad3cb072d1e
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..0ea00c803d57b2689cd4a5edcce4de3c35b62e7b
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..0457558710f096384b44c13d0390ad788b0db560
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..380ae5996919384b397842341f37a4698d1109cf
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9304c3aebcd602970c06d5fdfbdd326cbadee253
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f0782be572dff8e4befca5989fb7f32feaae883f
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..1e0d3c14fcded55abd4f2ad39479abb5c76f0050
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..fa7da5d383820ff2a6d0ddaff29938e36fb360e7
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..80187bd3d11a7edb94ab2237e0c30dc217eb0c83
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f2bb4248a9386583e637d85d8009b4e28a21a722
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..fddcb74f5c9a9e7b6ae714d7527695b8af147661
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..a841c6380b4c5ac16d172b524940b5fd030b3927
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232DMESG_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232DMESG_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..dec01fec232e11cca5e54a6ccc32e21b199575cb
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232DMESG_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..ab5f3485686d34b385b7706bfb22a28259777941
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..8416444ae596818142b187f27a5895531e155e63
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..bb5c37e746e0b78a77903d6b279b9d351aa32922
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..ca310e0f41e61f3e0964ac19704fd07af704fe7e
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..7324b7e19438810c058546a055c640be709f4843
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..2af59d1371fb10ecaa3324e5aa4f746d1008c783
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..4527db2df8937827d6fd7876e0382533ef0e69e9
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..cd6474e495ea5ab1483f9ee937b6f4d5c39062a5
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_5.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..da4ad25a7cca35fc9876d6ff26879246fbbe7586
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_5.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..47b10a693407189e1e7703c470b51df2e2048013
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..a47ed97da917f61f81b8c28c0174d9e4479b8fa3
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..ba86bbe47e77a4b3dd6b48493c289b1ddd20040f
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..49048ef55c3ff70684bf0f0f35b9d8b365384be9
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f59092869cc9c39b595c95109b7d84117f66b9ea
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..74072b56ea1bb7cba1eb3f03ba735fb70627abf7
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..248e6445b9869598280f71ea4c43c880be85533e
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_10.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_10.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9d2cee1c3836c8da875c7baf12a890a4e59365fd
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_10.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_11.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_11.png"
new file mode 100644
index 0000000000000000000000000000000000000000..dfe650b0c62a67a8500cb5f65daf0e99fefe8663
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_11.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..3b16ced8c3e1ff7d506c40d37d66c5c86dce9382
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b986cb29b49d6dad487ae789c5fcfa58ff76e6fb
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..05753d4cc7cb7f87f81b93eaa010cb9ac9850b11
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_5.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..85bc9f951e34353ac0c023e58f2fc336475f2f63
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_5.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_6.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_6.png"
new file mode 100644
index 0000000000000000000000000000000000000000..45282ecfb0c0d2d8fe1c4f919e09a04a8a2f5547
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_6.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_7.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_7.png"
new file mode 100644
index 0000000000000000000000000000000000000000..45282ecfb0c0d2d8fe1c4f919e09a04a8a2f5547
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_7.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_8.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_8.png"
new file mode 100644
index 0000000000000000000000000000000000000000..7af6ece254049856eeab8bb11ff3e19ab332fdfa
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_8.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_9.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_9.png"
new file mode 100644
index 0000000000000000000000000000000000000000..a7104e9b46e0f6e24b72020d653e3140fede8eda
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_9.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..369ef9d313640f62bba3459944af705a3365f75a
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..83526fa8cf9970957ce61102244f0dd759a70cf3
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..95472b08774a80401adc22b5701848d397c3c909
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..efacbe74a8b24f0969a4245002cc3fd75f3c92b1
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..44799418f12fd06d4922fcb7740a8bf6367e753d
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..727fb493b49b429143195a68ef00d4d3406d41cd
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f05d93a1edc145b8c315cbd62f4084c36708122c
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f6c03f4ce83423ee42454a2027b99a8bb71b16ef
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..a798ff256c3f6abc0b1dfaa200bab76962adbb3b
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..bb5c5e8ec2ee954701e0c49a2b7209462b5fe610
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f863b7c1a111f35db9fc16742807cbf611520b29
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..e9c0f9d166126e8fde6cd3d822cd982a38fef0f5
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..0f3a2dd7b0c1d288b5673f0e37d4f005113ef4a9
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_5.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..0bddeb4655513c3a1dd7291d4c29e5092c4734ff
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_5.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..7f37c60b633e2dd00d64a2a4efafc88a0447c32b
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..2145aec1966cfbc621be0efa9eaa865abb517c59
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..a0af706ace2308e440a572caffcdfbdd3d2d0a97
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..7cbcbc9dce3471d2404f2f5d923c195a2c3de2b2
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d5c16cc68db0638fb6eae6d42ab0c751fcc79dd8
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..59ebe6c002c5994c6084e7af37152d6ae226928f
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..e7f35b123c413f2f023e4c83f9129812cb7ea674
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d37b6c3d8e347bb277f4036910acc10d7b72f756
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d2d969a0f704ee9268077b9ea3f7cd227ae480a9
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..a5499779a58080c817c8ff36d8064c495ac1e5b6
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_5.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..43959c1a7372c156ae31431fd7725dc19dc7577d
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_5.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..4d3c493790bdc85217baadab774837db8174b1c5
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..209fc652359363a47a41ec2218fd8bc173baf27f
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..691cc43166d4c318395cd51b1e0fecbbe98274a7
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..413371b395a8f3c1b791f2a1dd0edaaf0832c15f
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..01d195ccff245f413daaa53619e9586d9af29037
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..a526e09cca6111af785c2eb4ef8bd013c091a1d4
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..31f6d007f009bcc149452e15fefcd16fff0bf5f5
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_5.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d7cf172a4603d4613e9700e81420563cf8747ba4
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_5.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_6.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_6.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f80f8094a9b3398ccba84fc258522191857ee6d3
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_6.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..cd4e2172e8b9225fa5843634ec8b38778e32cf5b
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..54c06edbd4dda8bcf171eb06bbf0eb274623a2ed
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b7c769b0ad81dfa9720abd13839b38cd7f37a2b8
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..c93631f36ea52dc552571594af9c14445b58bf36
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..3a2b0b7f3590b03626f0cf287a5b7fb51b71e4a0
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_5.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..184e9226627bcea1d2b40b749ba5fdebb35f7b13
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_5.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_6.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_6.png"
new file mode 100644
index 0000000000000000000000000000000000000000..93b0c090d2a688b08de89c82ba4ce26dc138ec54
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_6.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_7.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_7.png"
new file mode 100644
index 0000000000000000000000000000000000000000..2eb64a4df5cdda266178b2575c88ef1da134d200
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_7.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_8.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_8.png"
new file mode 100644
index 0000000000000000000000000000000000000000..e8065d561c7ad9c7bdd4d47b398befe6234d6ac7
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_8.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_9.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_9.png"
new file mode 100644
index 0000000000000000000000000000000000000000..51a44717b0d1347a64a6721304a301d63aaf372a
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_9.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..4adf2fd8ec3b352a1eef36a715895b59472fd0c4
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..501748e393b27959d95ddf79066a2c9c1c840db2
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b88cf41c53388655041dbec55f3c7d6094c1f959
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..30b5718cf47bd0a7604c4febe56ad8c5b6b3f67e
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..e9d50acfa8c565b1731e4355999efa1a4efa08eb
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..88d9e372a0ddd57408e351ba5391faac0358ba73
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..2b698da7f47590295eb2fc53179c64bdcfe4ed55
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..7c37a1db235aa78013ca7faaf1158263ff0579ea
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9c47e4e9b8bee43d6b33f01345a6ea2d6c585e49
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d68ee6d6911568f4952bb704ced2bd7426578374
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..c257a26648e809c2e37549e2fe4472300e6a9d1a
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..be45fa1e21ea22de702cafabaa8b8467084a066c
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b1bed8770605d31e48a5184beb182ed6e53f4695
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..2704bb5aaac5e2a48480b1174ad4db673358e3be
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d68ee6d6911568f4952bb704ced2bd7426578374
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..1bbd3dd0a6d3b53d767f4f5f508a7cb0ef717b30
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..e791ecb3d3090cf1efc8e562a2af9e9fe7a2d100
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..500f8c9925971c4b339cc352fc4cec6b59229220
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..507c5552e047b1736fd0f9397a20887b48be99c2
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f32a0710752c6a24215173b87c50ede8fcdf109e
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9c254f32e4f0a102a34e1d06514fd1687d06b40d
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..3d4f4bc5faba39a5348d69eea8aa0837fb7912a4
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9df092e6163a19c483dba4489eac80133465bae1
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..bc14d4826022d43df35532aa87777614833dda1e
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..ebbe779d6f5a95407dd5c8af2346711f288fc181
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_10.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_10.png"
new file mode 100644
index 0000000000000000000000000000000000000000..98fb21bb72a93b3e5870a8dbcbc069d818dda134
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_10.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_11.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_11.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b1cfe176f26af9e796127777138f1e0f94517687
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_11.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_12.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_12.png"
new file mode 100644
index 0000000000000000000000000000000000000000..3dabd3ed4a8a1498a14b49afa2bc268b720d61ab
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_12.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_13.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_13.png"
new file mode 100644
index 0000000000000000000000000000000000000000..2cea85e41767e9d3801c8404f359b5b0c535c8a6
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_13.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_14.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_14.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9dd713591c6162ea15de1b29976fcde489231d91
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_14.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d0eef93ec6f877248caa01ac0c06595a9fe56fea
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..2bc13bf9842fe6f61b8e9bb3f2c528d145b2187d
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..3d4f4bc5faba39a5348d69eea8aa0837fb7912a4
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_5.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d936ddf9426f2062c5b78608ce22b8f9484a17ef
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_5.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_6.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_6.png"
new file mode 100644
index 0000000000000000000000000000000000000000..580695a971df01c9b6226c96ca9bcebc7e5fa133
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_6.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_7.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_7.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9df092e6163a19c483dba4489eac80133465bae1
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_7.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_8.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_8.png"
new file mode 100644
index 0000000000000000000000000000000000000000..074c12d51cfd861b15939f35b135c447338fd5f7
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_8.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_9.png" "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_9.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b206604394f29a4c6efc41a01d0cbd18247b6288
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/assets/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_9.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/9-VPP-IPSec HCT crypto\346\217\222\344\273\266\351\233\206\346\211\213\345\206\214/0-\345\256\211\345\205\250\345\212\237\350\203\275\351\205\215\347\275\256\350\246\201\346\261\202.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/9-VPP-IPSec HCT crypto\346\217\222\344\273\266\351\233\206\346\211\213\345\206\214/0-\345\256\211\345\205\250\345\212\237\350\203\275\351\205\215\347\275\256\350\246\201\346\261\202.md"
new file mode 100644
index 0000000000000000000000000000000000000000..d81b6418bf2a95da14a93763b908ef24db82ccff
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/9-VPP-IPSec HCT crypto\346\217\222\344\273\266\351\233\206\346\211\213\345\206\214/0-\345\256\211\345\205\250\345\212\237\350\203\275\351\205\215\347\275\256\350\246\201\346\261\202.md"
@@ -0,0 +1,123 @@
+# 安全功能配置要求
+
+## 硬件配置要求
+
+安全功能包括CSV、TPM2.0、TCM2.0、TPCM、TDM、TKM、HCT等,这些功能依赖CPU硬件、BIOS,表1是各种CPU型号所属的CPU代际信息,表2是各代际CPU使用安全功能的硬件配置版本要求。
+
+表 1 各CPU型号对应的海光CPU代际
+
+| CPU代际 | CPU型号 |
+| --- | --- |
+| 海光2号 | 32XX,52XX,72XX |
+| 海光C86-3G | 33XX,53XX,73XX |
+| 海光C86-4G | 343X,748X,749X,548X |
+
+表 2 安全功能的硬件配置版本要求
+
+| 配置 | CPU | BIOS |
+| --- | --- | --- |
+| 1 | 海光2号
| #**要求1**#:1.两种方法都可以确认bios是否支持相应的功能,方法如下
(1)PI版本为2.1.0.4或以上,通过机器型号和厂商沟通确认
(2)Bootloader 版本号为1.2.55 或以上,Bootloader 版本号可以通过bios 查看,方法在下面章节说明
2. 必须支持CSV、fTPM2.0、fTCM2.0、TPCM等安全功能
BIOS必须满足以上2点要求,如果不满足请直接联系整机厂商
|
+| 2 | 海光C86-3G
| 同 #**要求1**# |
+| 3 | 海光C86-4G | #**要求2**#:1. 两种方法都可以确认bios是否支持相应的功能,方法如下
(1)PI版本为4.2.0.0或以上,通过机器型号和厂商沟通确认
(2)Bootloader版本要求,lscpu \|grep Model 查看Model 对应的值,根据具体的值确认版本要求,版本要求如下
1)4: Bootloader版本为3.5.3.1或以上
2)6: Bootloader版本为 3.7.3.37或以上
Bootloader 版本号可以通过bios 查看,方法在下面章节说明
2. 必须支持CSV、fTPM2.0、fTCM2.0、TPCM等安全功能
BIOS必须满足以上2点要求,如果不满足请直接联系整机厂商
**注意:**
如果用户希望测试`CSV3`的kernel启动hash验证和秘密注入等功能(CSV3密钥封印,CSV3全磁盘加密,CSV3机密容器 等依赖于这些功能),要求安全固件的版本号(即build id)>= `2200`。如果版本号 < `2200`,用户需要联系OEM厂商获取指定PI版本的BIOS,以`PI4.6.x`为前缀的PI版本要求>=`PI4.6.0.5`,以`PI4.2.x`为前缀的PI版本要求>=`PI4.2.0.10`。 |
+
+## Bootloader 版本查看
+海光2号配置
+```
+Setup Utility -> Advanced -> PSP Firmware Versions
+```
+
+海光C86-4G配置
+```
+Chipset -> PSP Firmware Versions
+```
+如下图:
+
+
+## 国产OS安全功能支持情况
+
+> 您可根据表格中OS的版本,支持的CPU型号,及支持的安全功能;选择您需要的OS。推荐使用版本更高的OS,其支持的安全功能更为完善。
+>
+> 备注: 表格中,如果TPM2-TOOLS版本低于5.5(不包含5.5),则TCM有两个命令不支持:ecc encrypt/decrypt
+
+表 2 国产OS安全功能支持情况
+
+| 厂商 | OS版本
内核版本
| 支持的CPU型号 | 机密
计算
| 可信
计算
| 密码
技术
| 软件版本 |
+| :---------- | :------------------------------------------------- | :------------------------------------------- | :------------------- | :---------------------------------- | :------------------------------------------- | :----------------------------------------------------------- |
+| 龙蜥 | 8.8
kernel:5.10
| 海光2号
海光C86-3G
| CSV
1
| TPM
TPCM
TDM
| | qemu:6.2.0
edk2:20220126
tpm2-tools:4.1.1
tpm2-tss:2.3.2
grub2:2.02
tpm2-abrmd: 2.3.3
|
+| | 8.9
kernel:5.10
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2,3
| TPM
TPCM
TDM
TCM
| TKM
HCT
| 同上 |
+| | 23.1
kernel:5.10
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2,3
| TPM
TPCM
TDM
TCM
| TKM
HCT
| qemu: 8.2.0
edk2:202302
tpm2-tools:5.5
tpm2-tss:4.0.1
grub2:2.06
tpm2-abrmd: 3.0.0
|
+| | 23.1 GA
kernel:6.6
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2,3
| TPM
TPCM
TDM
TCM
| CCP
TKM
| qemu: 8.2
edk2:202402
tpm2-tools:5.5
tpm2-tss:4.0.1
grub2:2.12
tpm2-abrmd: 3.0.0
|
+| 麒麟 | 服务器V10
SP3 2303
kernel:4.19
| 海光2号
海光C86-3G
| CSV
1
| TPM
TPCM
TDM
| CCP | qemu: 4.1.0
edk2:202002
tpm2-tools:5.0
tpm2-tss:3.0.3
grub2:2.04
tpm2-abrmd: 2.3.3
|
+| | 服务器V10
SP3 2403
kernel:4.19
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2,3
| TPM
TPCM
TDM
TCM
| TKM
HCT
| 同上 |
+| | 服务器V11
kernel:6.6
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2,3
| TPM
TPCM
TDM
TCM
| TKM
HCT
| qemu: 8.2
edk2:202311
tpm2-tools:5.5.1
tpm2-tss:4.0.1
grub2:2.12
tpm2-abrmd: 3.0.0
|
+| | 桌面V10
SP1 2303
kernel:
5.4.18
| 海光2号
海光C86-3G
| CSV
1
| TPM
TPCM
TDM
| CCP
TKM
HCT
需update2以上
| qemu: 4.2.1
edk2:201911
|
+| | 桌面V10
SP1 2403
kernel:
5.4.18
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2
| TPM
TPCM
TDM
| TKM
HCT
| 同上 |
+| | 桌面V11
kernel:6.6
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2,3
| TPM
TPCM
TDM
TCM
| TKM
HCT
| qemu: 8.2
edk2:202402
tpm2-tools:5.6
tpm2-tss:4.0.1
grub2:2.12
tpm2-abrmd: 3.0.0
|
+| 统信 | 服务器
1060
kernel:
4.19.90
| 海光2号
海光C86-3G
| CSV
1
| TPM
TPCM
TDM
| CCP | qemu: 4.1.0
edk2:202002
tpm2-tools:5.0
tpm2-tss:3.0.3
grub2:2.04
tpm2-abrmd: 2.3.3
|
+| | 服务器
1070
kernel:
4.19.90
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2,3
| TPM
TPCM
TDM
TCM
| TKM
HCT
| qemu: 6.2.0
其他同上
|
+| | 桌面
1060
kernel:
4.19.90
| 海光2号
海光C86-3G
| CSV
1
| TPM
TPCM
TDM
| CCP | qemu: 3.1.3
edk2:201811
tpm2-tools:3.1.3
tpm2-tss:2.1.0
grub2:2.04
tpm2-abrmd: 2.1.0
|
+| | 桌面
1070
kernel:
4.19.90
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2
| TPM
TPCM
TDM
TCM
| TKM
HCT
| qemu: 3.1.3
edk2:201811
tpm2-tools:5.4
tpm2-tss:3.2.2
grub2:2.04
tpm2-abrmd: 3.0.0
|
+| 方德 | 服务器
V3.0
kernel:
4.19.113
| 海光2号
海光C86-3G
| CSV
1
| TPM
TPCM
TDM
| CCP | qemu: 2.12.0
edk2:201903
tpm2-tools:4.1.1
tpm2-tss:2.3.2
grub2:2.02
|
+| | 服务器
V4.0
kernel:
4.19.113
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2,3
| TPM
TPCM
TDM
TCM
| TKM
HCT
| qemu: 4.2.0/7.2
edk2:201903
tpm2-tools:5.6
tpm2-tss:4.0.1
grub2:2.04
tpm2-abrmd: 2.3.3
|
+| | 桌面
V5.0
kernel:
5.4.100
| 海光2号
海光C86-3G
| CSV
1
| TPM
TPCM
TDM
| CCP | grub2:2.04
tpm2-tools:4.1.1
tpm2-tss:2.3.2
|
+| 腾讯信创 | kernel:
4.19.278
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2,3
| TPM
TPCM
TDM
| TKM
HCT
| qemu: 6.2.0
edk2:202111
tpm2-tools:4.1.1
tpm2-tss:2.3.2
grub2:2.04
tpm2-abrmd: 2.3.3
|
+| 麒麟信安 | kernel:
4.19.90
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2,3
| TPM
TPCM
TDM
| TKM
HCT
| qemu: 4.1.0
edk2:202202
tpm2-tools:5.0
tpm2-tss:3.0.3
grub2:2.04
tpm2-abrmd: 2.3.3
|
+| OpenCloudOS | 9.2
kernel:
6.6
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2,3
| TPM
TPCM
TDM
TCM
| TKM
HCT
| qemu: 8.2
edk2:20230524
tpm2-tools:5.5
tpm2-tss:4.0.1
grub2:2.12
tpm2-abrmd: 2.4.1
|
+| 浪潮云 | kernel:
4.19.91
| 海光2号
海光C86-3G
| | TPCM | | grub2:2.02 |
+| 曙光云 | kernel:
5.10.134
| 海光2号
海光C86-3G
| CSV
1,2
| | TKM
HCT
| qemu:3.1.1/7.2 |
+| BC-Linux | kernel:
5.10.0-182
| 海光2号
海光C86-3G
| CSV
1,2
| | | |
+| 新华三 | kernel:
5.10.0-136
| 海光2号
海光C86-3G
| CSV
1,2
| | | qemu: 5.0
libvirt: 6.3
|
+
+## BIOS安装及设置要求
+
+### 1. 加密虚拟化功能
+
+要使用HYGON加密虚拟化功能(CSV,CSV2,CSV3),必须进入BIOS设置,通过以下路径打开SMEE功能,并设置SEV-ES ASID Space Limit为1。
+*注:PI2104以上的版本,不需要设置SEV-ES ASID Space Limit为*
+
+#### CPU BIOS配置参考
+**BIOS界面因厂家不同各有区别,如果找不到对应选项请联系厂家确认**
+
+海光2号配置
+
+```
+HYGON CBS -> Moksha Common Options
+```
+```
+Setup Utility -> Advanced -> HYGON CBS -> Core Common Options
+```
+效果如下图:
+
+
+
+海光C86-4G配置
+```
+Advanced -> HYGON CBS -> Core Common Options
+```
+效果如下图:
+
+
+### 2. DCU直通功能
+
+要使用DCU直通功能,必须进入BIOS设置,通过以下路径打开IOMMU功能。
+
+#### CPU BIOS配置参考
+海光2号配置
+```
+HYGON CBS -> NBIO Common Options -> NB Configuration -> IOMMU
+```
+```
+Setup Utility -> Advanced -> HYGON CBS -> NBIO Common Options
+```
+
+效果如下图:
+
+
+
+海光C86-4G配置
+```
+Advanced -> HYGON CBS -> NBIO Common Options
+```
+效果如下图:
+
+
\ No newline at end of file
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/9-VPP-IPSec HCT crypto\346\217\222\344\273\266\351\233\206\346\211\213\345\206\214/1-VPP-IPSec HCT crypto\346\217\222\344\273\266\351\233\206\347\224\250\346\210\267\346\211\213\345\206\214.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/9-VPP-IPSec HCT crypto\346\217\222\344\273\266\351\233\206\346\211\213\345\206\214/1-VPP-IPSec HCT crypto\346\217\222\344\273\266\351\233\206\347\224\250\346\210\267\346\211\213\345\206\214.md"
new file mode 100644
index 0000000000000000000000000000000000000000..98201bc54a9310e0fcc028275a354f3858e53c2a
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/9-VPP-IPSec HCT crypto\346\217\222\344\273\266\351\233\206\346\211\213\345\206\214/1-VPP-IPSec HCT crypto\346\217\222\344\273\266\351\233\206\347\224\250\346\210\267\346\211\213\345\206\214.md"
@@ -0,0 +1,597 @@
+
+# 1. 概要
+
+## 1.1. VPP的IPSec功能介绍
+
+VPP是思科(CISCO)公司主导的[FD.io](https://fd.io/)(快速数据输入/输出)开源项目中的一个子项目,提供网络层L2-L4快速处理网络数据的功能,整个项目由c语言编写,运行在linux用户态,详见官方wiki([https://wiki.fd.io/view/VPP](https://wiki.fd.io/view/VPP))。IPSec是为IP网络提供安全性的协议和服务的集合,它是VPN(Virtual Private Network,虚拟专用网)中常用的一种技术。通信双方通过IPsec建立加密隧道,IP数据包通过加密隧道进行传输,有效保证了数据在不安全的网络环境如Internet中传输的安全性,详见rfc文档:
+
+-
+-
+-
+
+VPP内置了IPSec功能,其实现方式具有高度的可扩展性和灵活性,支持多种软硬件优化技术,除了可选择自带的处理引擎外,还为开发者提供了模块化框架,允许以插件形式开发自己的加速引擎,从而为更广泛的高性能处理方案提供了适配能力,可以在不同的硬件平台上实现最优性能。
+本文描述的HCT crypto插件集基于该框架开发。
+
+## 1.2. 用于VPP IPSec的HCT crypto插件集
+
+海光密码技术(HCT, Hygon Cryptographic Technology)是基于海光密码协处理器和密码指令集自主设计研发的一套密码算法加速软件开发套件。HCT充分利用海光平台密码加速特性,整合底层海光密码计算资源,为用户上层应用提供高性能密码计算能力。关于HCT的使用介绍详见[HCT用户手册](https://openanolis.cn/sig/Hygon-Arch/doc/865622263675623238)。
+HCT crypto插件集依赖HCT提供的密码运算能力,利用VPP框架提供的插件机制,实现了两个加密插件,分别是HCT异步插件和HCT同步插件,可在VPP IPSec应用中充分发挥海光处理器的国密算法加速能力。
+
+## 1.3. 参考部署环境
+
+| 组件 | 版本信息 |
+| ------------ | -------------------------- |
+| CPU | 单路7385 C86 CPU |
+| 内存 | 128GB DDR4 |
+| 系统发行版 | Ubuntu 18.04 LTS |
+| 内核 | Linux kernel 5.4.19 |
+| gcc | 7.5.0 |
+| OpenSSL | 1.1.1c |
+| numa | 2.0.12 |
+| HCT套件 | hct_2.0.0.20241030_release |
+| 网卡 |mellanox MCX556A-EDAT |
+
+以上环境为本文撰写时使用的环境,仅供参考。其他具备海光密码加速特性的平台都能使用本文描述的技术。
+
+# 2. 源码和编译
+
+## 2.1. 源码介绍
+
+HCT crypto插件集基于VPP的**stable/2101**分支开发,如果用户需要使用其他分支,可基于本案提交的补丁进行移植。
+源码下载包含了VPP全部源码以及本项目新增的两个插件:[项目源码](https://gitee.com/anolis/vpp)
+
+### 2.1.1. VPP框架修改
+
+插件使用国密算法,需要引用VPP IPSec框架中与算法相关的定义,原生VPP中没有定义国密算法,所以增加了国密算法相关内容,改动的文件在VPP框架代码“src/vnet/ipsec”目录和“src/vnet/crypto”目录。
+
+### 2.1.2. 新增插件
+
+HCT crypto插件集提供的两个插件分别为:
+
+- 同步功能插件 crypto_hct_sync
+- 异步功能插件 crypto_hct_async
+
+同名源码目录放置在路径“src/plugins”下。
+
+## 2.2. 准备编译环境
+
+### 2.2.1. 删除冲突组件
+
+系统中已安装的VPP或DPDK会对编译和运行产生干扰,造成不确定的错误。编译前确认当前系统环境中是否曾经安装过VPP或者DPDK,通过如下命令:
+debian类系统:
+
+```bash
+dpkg -l | grep vpp
+dpkg -l | grep DPDK
+```
+
+centos类系统:
+
+```bash
+yum list installed | grep vpp
+yum list installed | grep DPDK
+```
+
+如果已安装过,先卸载对应的VPP或者DPDK组件,否则源码编译过程和运行过程可能会出错。
+
+### 2.2.2. 联网环境
+
+在联网条件下,clone或下载本项目源码后,进入源码根目录:
+
+```bash
+cd vpp-21.01
+git checkout stable/2101
+```
+
+这里一定注意checkout到stable/2101分支,因为本插件集是基于这个分支开发并提交的。
+VPP编译过程所需的各类工具、依赖软件,均由VPP的make系统解决,无需手动安装,仅需执行以下命令即可自动探测当前系统环境并安装缺失的依赖:
+
+```bash
+make install-dep # 安装编译过程所需依赖包
+make install-ext-deps # 安装运行过程所需依赖包
+```
+
+根据网络环境,以上两个命令的执行时间可能较长,需要耐心等待。
+
+### 2.2.3. 离线环境
+
+离线环境下VPP源码和所有依赖都需要手动拷贝、安装。源码从本案链接下载后拷贝到离线环境即可;编译工具依赖包的离线安装需要根据编译过程提示的错误信息,逐一下载离线包进行安装,根据包管理系统按需操作,不再赘述。
+下面描述运行时依赖包的下载,有两种方法获取“make install-ext-deps”命令下载安装的软件包:
+
+- **方法一:** 从曾经联网编译过相同版本的VPP的机器上,VPP目录的“**build/external**”下,拷贝“**downloads**”文件夹到离线编译的机器上VPP源码目录相同路径“**build/external**”下即可。
+- **方法二:** 查看VPP根目录“**build/external/packages**”下的各个“**\*.mk**”文件,这些文件分别对应了不同软件包的makefile脚本,用文本编辑器打开这些文件,从中找到下载链接,使用可联网机器输入链接即可下载,下载的压缩包放入目录“**build/external/downloads**”(没有downloads目录则创建一个)下即可。以DPDK为例说明下载方法:
+查看“build/external/packages/dpdk.mk”的内容:
+
+```makefile
+...
+dpdk_version ?= 20.11
+dpdk_base_url ?= http://fast.dpdk.org/rel
+dpdk_tarball := dpdk-$(dpdk_version).tar.xz
+...
+dpdk_url := $(dpdk_base_url)/$(dpdk_tarball)
+...
+```
+
+可以组合出下载DPDK的路径为: 。
+获取其他依赖包,如rdma、quicly等的下载路径,过程类似,不再赘述。
+所有软件包都下载完毕并放入指定目录后,在源码根目录执行:
+
+```bash
+touch build-root/.deps.ok
+```
+
+创建“.deps.ok”的目的是为编译系统建立锚点,使其越过下载步骤执行后续编译。
+
+## 2.3. 编译
+
+1. 编译命令
+在源码根目录执行:
+
+```bash
+make build #编译debug版
+make build-release #编译release版
+```
+
+VPP编译完成后,可执行程序和相关的库都在源码目录下生成,根据编译的类型是debug还是release,生成的可执行文件和库的位置在源码目录下:
+
+- debug版: 可执行文件路径 **build-root/install-vpp_debug-native/vpp/bin/**,库路径 **build-root/install-vpp_debug-native/vpp/lib/**
+- release版: 可执行文件路径 **build-root/install-vpp-native/vpp/bin/**, 库路径 **build-root/install-vpp-native/vpp/lib/**
+
+# 3. 运行
+
+## 3.1. 运行环境
+
+### 3.1.1. 安装hct
+
+本案所述插件运行依赖于HCT提供的接口,运行前需要安装HCT,详细安装步骤见[HCT用户手册](https://openanolis.cn/sig/Hygon-Arch/doc/865622263675623238)。
+
+### 3.1.2. 配置大页内存
+
+不配置大页内存也可以运行,但是配置大页内存可以大幅提高程序性能,建议进行配置。
+在/etc/default/grub文件中,修改“GRUB_CMDLINE_LINUX”参数内容:default_hugepagesz(默认大页大小,设为1G)、hugepagesz(大页大小,设为1G)、hugepages(大页个数,根据具体平台而定),修改后如下所示:
+
+```bash
+GRUB_CMDLINE_LINUX="... default_hugepagesz=1G hugepagesz=1G hugepages=32 ..."
+```
+
+其中“hugepages”的数量,在海光3系cpu上不低于4,在海光5系cpu上不低于8,在海光7系cpu上不低于16。
+修改并保存/etc/default/grub文件后,**更新grub并重启后生效**:
+debian类系统:
+
+```bash
+sudo update-grub
+sudo reboot
+```
+
+centos类系统:
+
+```bash
+sudo grub2-mkconfig -o /boot/grub2/grub.cfg # bios引导
+```
+
+或
+
+```bash
+sudo grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg # UEFI引导
+```
+
+## 3.2. 运行命令
+
+进入DUT1的VPP可执行文件路径,**使用root权限运行命令**:
+
+```bash
+sudo ./vpp -c
+```
+
+其中/path/to/config-file是VPP启动配置文件(文本格式),VPP自带一个基础的示例模板,位于build-root/install-vpp-native/VPP/etc/VPP/startup.conf,在该文件的基础上,文件名和内容均可以按需修改,文件内容的含义参见 文档相关章节。
+
+## 3.3. 测试方案
+
+可使用单机测试或者双机测试本案插件,它们的特点如下:
+
+- **单机测试**
+ 只用一台机器,即可完成IPSec业务闭环,即打流、加密、解密均在一台机器上完成,不需要额外的机器和测试仪,但受限于单机性能同时运行两个VPP以及打流,不能测出目标机型在真实业务环境下的加解密能力;
+- **多机测试**
+ 用三台机器(两台作为IPSec网关,一台作为打流机)或两台机器(作为IPSec网关) + 专业网络测试仪。这种方式下测试流量由专门的机器发出,模拟真实业务流量。目标机只执行IPSec网关的角色,只要网卡总带宽足够,就可以测出实际加解密能力。
+
+下面采用**单机测试演示同步插件**的使用,采用**多机测试演示异步插件**的使用。 但需要明确的是,单机演示异步插件,多机演示同步插件都是可以的,这里只是为了不占用过多篇幅,可以举一反三。
+
+### 3.3.1. 单机测试
+
+用单机测试演示同步插件的使用。
+
+#### 3.3.1.1. 测试拓扑
+
+单机测试仅需一台机器,没有对外网络连接的需求,通过对linux网络命名空间和VPP的设置,在同一台机器上模拟两个VPP实体通信过程:
+
+
+
+#### 3.3.1.2. 配置文件
+
+以下是设置主机网络的脚本set_host_net.sh内容:
+
+```bash
+sudo ip netns add ns0 # 新建网络命名空间ns0
+sudo ip link add name vpp0 type veth peer name host_vpp0 # 创建虚拟以太网口对(vpp0和host_vpp0)
+sudo ip link set vpp0 up # 设置虚拟网口vpp0状态为up
+sudo ip link set host_vpp0 netns ns0 # 将上面创建好的以太网口对中host_vpp0放入ns0命名空间,它的对端留在默认命名空间
+sudo ip netns exec ns0 ip link set lo up # 使能ns0命名空间中的回环接口
+sudo ip netns exec ns0 ip link set host_vpp0 up # 设置虚拟网口host_vpp0状态为up
+sudo ip netns exec ns0 ip addr add 192.168.1.1/24 dev host_vpp0 # 为ns0中的虚拟网口host_vpp0设置ip地址
+sudo ip netns exec ns0 ip route add default via 192.168.1.2 dev host_vpp0 # 为ns0创建默认路由,其网关地址“192.168.1.2”属于虚拟网口host_vpp0的对端网口,即“vpp0”,“vpp0”将在VPP的配置文件中启用
+
+# 与上面类似,创建了另一个网络命名空间ns1,余下类似
+sudo ip netns add ns1
+sudo ip link add name vpp1 type veth peer name host_vpp1
+sudo ip link set vpp1 up
+sudo ip link set host_vpp1 netns ns1
+sudo ip netns exec ns1 ip link set lo up
+sudo ip netns exec ns1 ip link set host_vpp1 up
+sudo ip netns exec ns1 ip addr add 192.168.2.1/24 dev host_vpp1
+sudo ip netns exec ns1 ip route add default via 192.168.2.2 dev host_vpp1
+```
+
+VPP配置文件dut1-sync-start内容如下:
+
+```text
+unix {
+ nodaemon
+ log /var/log/VPP/VPP.log
+ full-coredump
+ interactive
+ startup-config /path/to/dut1-net-sync-conf
+}
+cpu {
+ main-core 1
+ corelist-workers 6,7
+}
+plugins {
+ plugin crypto_hct_sync_plugin.so {enable} # 使能本项目定义的同步插件
+}
+buffers { buffers-per-numa 133320 }
+memory { main-heap-size 2G }
+statseg { size 1G }
+```
+
+“dut1-sync-start”文件中,“startup-config /path/to/dut1-net-sync-conf”一行是指定网络参数配置的,配置的内容写在dut1-net-sync-conf文件中,该文件内容如下:
+
+```text
+create host-interface name vpp0 hw-addr fa:16:29:29:29:29 # 接管外部创建的虚拟网口vpp0,并为其设置mac地址(在这里被重命名为“host-vpp0”)
+set interface state host-vpp0 up # 使能host-vpp0网口
+set interface ip address host-vpp0 192.168.1.2/24 # 设置host-vpp0网口ip地址
+create interface memif id 0 slave # VPP创建mem内存接口memif0/0,用于和另一个VPP里的内存接口连接,模拟以太网直连通信
+set interface state memif0/0 up
+set interface ip address memif0/0 192.168.3.1/24
+create ipip tunnel src 192.168.3.1 dst 192.168.3.2 # 创建IP-in-IP隧道
+ipsec sa add 11 spi 1001 esp crypto-key 4339314b55523947594d6d3547666b45 crypto-alg sm4-cbc integ-key 4339314b55523947594d6d3547666b45 integ-alg sm3 salt 0x11223344 # 创建SA参数,指定加密算法和完整性校验算法,以及相关密钥
+ipsec tunnel protect ipip0 sa-in 11 sa-out 11 # 为IP-in-IP隧道绑定SA,形成IPSec隧道
+ip route add 192.168.2.1/32 via 192.168.3.2 ipip0 # 添加转发路由,将目标地址路由到指定隧道上
+set interface unnumbered ipip0 use memif0/0 # 将IPSec隧道接口设置为无编号接口并借用memif接口IP地址
+set interface state ipip0 up # 使能隧道接口
+set crypto handler all hct_sync # 设置密码引擎为同步引擎“hct_sync”
+```
+
+另一个VPP配置文件dut2-sync-start内容如下:
+
+```text
+unix {
+ nodaemon
+ log /var/log/vpp/vpp.log
+ full-coredump
+ interactive
+ startup-config /{path}/dut2-net-sync-conf
+}
+cpu {
+ main-core 1
+ corelist-workers 6,7
+}
+plugins {
+ plugin crypto_hct_sync_plugin.so {enable} # 使能本项目定义的同步插件
+}
+buffers { buffers-per-numa 133320 }
+memory { main-heap-size 2G }
+statseg { size 1G }
+```
+
+其中dut2-net-sync-conf内容如下:
+
+```text
+create host-interface name vpp1 hw-addr fa:16:19:19:19:19
+set interface state host-vpp1 up
+set interface ip address host-vpp1 192.168.2.2/24
+create interface memif id 0 master
+set interface state memif0/0 up
+set interface ip address memif0/0 192.168.3.2/24
+create ipip tunnel src 192.168.3.2 dst 192.168.3.1
+ipsec sa add 11 spi 1001 esp crypto-key 4339314b55523947594d6d3547666b45 crypto-alg sm4-cbc integ-key 4339314b55523947594d6d3547666b45 integ-alg sm3 salt 0x11223344
+ipsec tunnel protect ipip0 sa-in 11 sa-out 11
+ip route add 192.168.1.0/24 via 192.168.3.1 ipip0
+set interface unnumbered ipip0 use memif0/0
+set interface state ipip0 up
+set crypto handler all hct_sync
+```
+
+可以通过以下命令验证:
+启动VPP发送实例以及接收实例:
+
+```bash
+sudo ./vpp -c
+sudo ./vpp -c
+```
+
+在其中一个网络空间中用ping测试到达对端网络空间的连通性:
+
+```bash
+sudo ip netns exec ns0 ping 192.168.2.1
+```
+
+如果ping包正常回应,则证明单机数据拓扑已经连通,接下来可以使用iperf等工具在ns0侧的host_vpp0和ns1侧的host_vpp1上进行压力测试。最简单的命令如:
+
+```bash
+sudo ip netns exec ns0 iperf -s
+sudo ip netns exec ns1 iperf -c 192.168.1.1
+```
+
+### 3.3.2. 多机测试
+
+用多机测试演示异步插件的使用。
+
+#### 3.3.2.1. 测试拓扑
+
+下图所示为多机测试的拓扑连接:
+
+
+
+图中DUT1和DUT2分别代表两台运行了VPP的机器,CPU为Hygon 7385单路,拥有4个DIE,开启超线程后一共有64个逻辑核。每台机器配置一块物理网卡(2个PF设备分裂出8个VF设备),每个网卡的IP地址、BDF、连接关系见图中所示,将三台机器按图示连接形成环状,由网络测试仪发出测试流,以顺时针方向的流为例,数据流从网络测试仪的1,2,3,4口分别流出,通过DUT1加密后送往DUT2,由DUT2解密后,通过网络测试仪的5,6,7,8四个口流回并由网络测试仪完成统计和数据呈现。
+
+#### 3.3.2.2. 绑定网卡到用户态驱动
+
+多机测试使用真实的网卡,在VPP中通过DPDK控制真实的网卡收发,需要将网卡从默认的内核驱动解绑,然后绑定到用户态驱动,以便DPDK可以接管。
+**特别注意:** **mellanox的网卡**驱动比较特殊,其自带DPDK的适配层,所以**不需要执行这一步**。
+DPDK可以支持“igb_uio”、“uio_pci_generic” 或者 “vfio-pci”这三种用户态驱动,确认自己的系统支持哪一种驱动,然后使用DPDK驱动绑定脚本执行相应的解绑和绑定操作,需要注意的是,编译完成后DPDK的驱动绑定脚本在源码目录下:“build-root/install-vpp-native/external/bin/dpdk-devbind.py”,举例说明使用方式:
+先加载vfio-pci驱动程序:
+
+```bash
+sudo modprobe vfio-pci
+```
+
+查看系统当前的网卡驱动情况:
+
+```bash
+cd build-root/install-vpp-native/external/bin/
+sudo ./dpdk-devbind.py -s
+Network devices using DPDK-compatible driver
+============================================
+0000:82:00.0 '82599EB 10-GbE NIC' drv=vfio-pci unused=ixgbe
+0000:82:00.1 '82599EB 10-GbE NIC' drv=vfio-pci unused=ixgbe
+
+Network devices using kernel driver
+===================================
+0000:04:00.0 'I350 1-GbE NIC' if=eth0 drv=igb unused=vfio-pci *Active*
+0000:04:00.1 'I350 1-GbE NIC' if=eth1 drv=igb unused=vfio-pci
+0000:04:00.2 'I350 1-GbE NIC' if=eth2 drv=igb unused=vfio-pci
+0000:04:00.3 'I350 1-GbE NIC' if=eth3 drv=igb unused=vfio-pci
+
+Other network devices
+=====================
+
+```
+
+要将设备eth1“04:00.1”绑定到vfio-pci驱动程序:
+
+```bash
+sudo ip link set dev eth1 down #先在系统中将eth1的端口状态设置为down,以便可以绑定到启动驱动上,如vfio-pci
+sudo ./dpdk-devbind.py -b vfio-pci 04:00.1
+```
+
+或者,
+
+```bash
+sudo ./dpdk-devbind.py -b vfio-pci eth1
+```
+
+更详细的使用详见dpdk文档:
+
+#### 3.3.2.3. 配置文件
+
+**Tips:** 如果单台机器上有多块物理网卡,尽量将网卡分散插入不同NUMA节点所属的PCIE插槽中,这样可以将流量尽可能分散到不同NUMA节点上,减少跨NUMA节点通信,提高并行处理效率。
+
+为节约篇幅,下面仅以DUT1的配置文件“dut1-async-start”为例,对与本引擎有关,或需要强调的内容进行注释和说明。
+
+```text
+unix {
+ nodaemon
+ log /var/log/vpp/vpp.logP
+ interactive
+ full-coredump
+ cli-listen /run/vpp/cli.sock
+ startup-config /path/to/dut1-net-async-conf # 内部配置文件
+}
+
+cpu {
+ main-core 0 # 0号核心绑定给VPP主线程使用
+ corelist-workers 1~63 # 1~63号核心分别绑定给worker线程使用
+}
+
+plugins {
+ plugin crypto_hct_async_plugin.so {enable} # 使能本项目定义的异步插件
+}
+buffers { buffers-per-numa 133320 }
+dpdk {
+ no-multi-seg
+ dev default{
+ num-rx-queues 1
+ }
+ dev 0000:21:00.2 # 从这里开始的dev均为网卡,"0000:21:00.2"是该网卡的BDF
+ {
+ workers 0 # 绑定0号worker处理“0000:21:00.2”这个网卡的数据,以下同理
+ name eth0 # 为本网卡接口取个名字,命名任意,方便使用即可
+ }
+ dev 0000:21:00.3
+ {
+ workers 7
+ name eth1
+ }
+ dev 0000:21:00.4
+ {
+ workers 15
+ name eth2
+ }
+ dev 0000:21:00.5
+ {
+ workers 23
+ name eth3
+ }
+ dev 0000:21:00.6
+ {
+ workers 0
+ name eth4
+ }
+ dev 0000:21:00.7
+ {
+ workers 7
+ name eth5
+ }
+ dev 0000:21:01.0
+ {
+ workers 15
+ name eth6
+ }
+ dev 0000:21:01.1
+ {
+ workers 23
+ name eth7
+ }
+ blacklist 8086:1521
+ no-multi-seg
+}
+
+memory { main-heap-size 2G }
+statseg { size 1G }
+```
+
+多机测试需要绑定网卡,以上展示的dut1-async-start文件中,每个“dev xxx {worker n}”小节中的worker后的数字,代表第几号worker,该worker负责dev xxx的数据收发。为充分发挥性能,该数字的选取遵循如下原则:
+先查看系统中该网卡属于哪个NUMA节点,绑定第几号worker应从该NUMA节点包含的逻辑核中选取(core与worker一一对应)。若不保证每个NUMA节点上都有网卡,那么网卡分配方式按NUMA节点距离由近到远分配。原则是尽量让每个NUMA节点上都有一个核在处理网卡数据,例如0000:21:00.2在NUMA 2上,那么这个数字选择NUMA 2上的第一个worker即可,在VPP的cli中执行“show threads”命令,如下图所示:
+
+
+
+上图中,“lcore”列代表了cpu的逻辑核,“core”列代表了cpu的物理核,“socket state”列代表了cpu的numa id,“name”列代表了worker的命名,命名最后的数字即worker编号。
+本例比较特殊,每台机器只有一块网卡(网卡上有两个PF接口),插在NUMA 2的pcie上,从这块网卡的两个PF接口分别分离出4个VF接口。按照上述原则,为了对数据处理进行负载均衡,将“21:00.2、21:00.6”两个VF网卡分配给NUMA 0的worker 0,“21:00.3、21:00.7”分配给NUMA 1的worker 7,以此类推。
+
+前面展示的“dut1-async-start”文件中,“startup-config /path/to/dut1-net-async-conf”一行是指定网络参数配置的,配置的内容写在dut1-net-async-conf文件中,该文件内容如下:
+
+```text
+# 设置各接口IP地址
+set interface ip address eth0 192.168.2.1/24
+set interface ip address eth1 192.168.3.1/24
+set interface ip address eth2 192.168.4.1/24
+set interface ip address eth3 192.168.5.1/24
+set interface ip address eth4 172.16.6.1/24
+set interface ip address eth5 172.16.7.1/24
+set interface ip address eth6 172.16.8.1/24
+set interface ip address eth7 172.16.9.1/24
+
+# 开启ipsec异步模式(若使用同步插件,这句不写)
+set ipsec async mode on
+
+# 创建IP-in-IP隧道
+create ipip tunnel src 192.168.2.1 dst 192.168.2.2
+create ipip tunnel src 192.168.3.1 dst 192.168.3.2
+create ipip tunnel src 192.168.4.1 dst 192.168.4.2
+create ipip tunnel src 192.168.5.1 dst 192.168.5.2
+
+# 创建SA参数,指定加密算法和完整性校验算法,以及相关密钥
+ipsec sa add 10 spi 1000 esp crypto-key 4339314b55523947594d6d3547666b45 crypto-alg sm4-cbc integ-key 4339314b55523947594d6d3547666b45 integ-alg sm3 salt 0x11223344
+ipsec sa add 11 spi 1001 esp crypto-key 4339314b55523947594d6d3547666b45 crypto-alg sm4-cbc integ-key 4339314b55523947594d6d3547666b45 integ-alg sm3 salt 0x11223344
+ipsec sa add 12 spi 1002 esp crypto-key 4339314b55523947594d6d3547666b45 crypto-alg sm4-cbc integ-key 4339314b55523947594d6d3547666b45 integ-alg sm3 salt 0x11223344
+ipsec sa add 13 spi 1003 esp crypto-key 4339314b55523947594d6d3547666b45 crypto-alg sm4-cbc integ-key 4339314b55523947594d6d3547666b45 integ-alg sm3 salt 0x11223344
+
+# 为IP-in-IP隧道绑定SA,形成IPSec隧道
+ipsec tunnel protect ipip0 sa-in 10 sa-out 10
+ipsec tunnel protect ipip1 sa-in 11 sa-out 11
+ipsec tunnel protect ipip2 sa-in 12 sa-out 12
+ipsec tunnel protect ipip3 sa-in 13 sa-out 13
+
+# 添加转发路由,将目标地址路由到指定隧道上
+ip route add 172.30.6.0/24 via 192.168.2.2 ipip0
+ip route add 172.30.7.0/24 via 192.168.3.2 ipip1
+ip route add 172.30.8.0/24 via 192.168.4.2 ipip2
+ip route add 172.30.9.0/24 via 192.168.5.2 ipip3
+
+# 将IPSec隧道接口设置为无编号接口并借用物理接口IP地址
+set interface unnumbered ipip0 use eth0
+set interface unnumbered ipip1 use eth1
+set interface unnumbered ipip2 use eth2
+set interface unnumbered ipip3 use eth3
+
+# 使能各物理接口和隧道接口
+set interface state eth0 up
+set interface state eth1 up
+set interface state eth2 up
+set interface state eth3 up
+set interface state eth4 up
+set interface state eth5 up
+set interface state eth6 up
+set interface state eth7 up
+set interface state ipip0 up
+set interface state ipip1 up
+set interface state ipip2 up
+set interface state ipip3 up
+
+# 设置密码引擎为异步引擎“hct_async”
+set crypto async handler hct_async all
+```
+
+DUT2与DUT1的配置类似,按照拓扑修改对应参数即可。
+以上网络参数在VPP初始化时加载,以静态方式打通IPSec隧道,加载完成后,即可开启网络测试仪打流测试。
+**Tips:** 特别注意,在网络参数中定义加解密引擎时:
+
+- 如果使用异步hct插件,必须加上“set ipsec async mode on”和“set crypto async handler hct_async all”这两句;
+- 如果使用同步插件,只写“set crypto handler all hct_sync”即可。
+
+# 4. FAQ
+
+## 4.1. 用户组不存在?
+
+运行VPP后提示:“group vpp does not exist”,添加对应的组即可:
+
+```bash
+sudo groupadd vpp
+```
+
+## 4.2. 日志文件创建失败?
+
+运行VPP后提示:“couldn't open log '/var/log/vpp/vpp.log'”,是因为“/var/log/vpp”目录不存在,创建即可:
+
+```bash
+sudo mkdir -p /var/log/vpp
+```
+
+## 4.3. 编译时提示缺少python库?
+
+编译过程出现类似错误:
+
+```text
+ModuleNotFoundError: No module named 'ply'
+```
+
+这类错误多出现在离线编译时,由于没有经过“make install-dep”过程,可能会有一些依赖软件包没有安装,需要离线安装Python的ply库,其他类似错误也要按需离线安装缺失的库或软件包。
+
+## 4.4. 如何打包安装?
+
+编译完成后,打包、安装:
+debian类系统:
+
+```bash
+make pkg-deb
+# deb包生成于build-root目录下
+sudo dpkg -i ./build-root/*.deb
+```
+
+centos类系统:
+
+```bash
+make pkg-rpm
+# rpm包生成于build-root目录下
+sudo rpm -i ./build-root/*.rpm
+```
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/9-VPP-IPSec HCT crypto\346\217\222\344\273\266\351\233\206\346\211\213\345\206\214/2-VPP-IPSec HCT crypto\346\217\222\344\273\266\351\233\206\347\224\250\346\210\267\346\211\213\345\206\214.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/9-VPP-IPSec HCT crypto\346\217\222\344\273\266\351\233\206\346\211\213\345\206\214/2-VPP-IPSec HCT crypto\346\217\222\344\273\266\351\233\206\347\224\250\346\210\267\346\211\213\345\206\214.md"
new file mode 100644
index 0000000000000000000000000000000000000000..98201bc54a9310e0fcc028275a354f3858e53c2a
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/9-VPP-IPSec HCT crypto\346\217\222\344\273\266\351\233\206\346\211\213\345\206\214/2-VPP-IPSec HCT crypto\346\217\222\344\273\266\351\233\206\347\224\250\346\210\267\346\211\213\345\206\214.md"
@@ -0,0 +1,597 @@
+
+# 1. 概要
+
+## 1.1. VPP的IPSec功能介绍
+
+VPP是思科(CISCO)公司主导的[FD.io](https://fd.io/)(快速数据输入/输出)开源项目中的一个子项目,提供网络层L2-L4快速处理网络数据的功能,整个项目由c语言编写,运行在linux用户态,详见官方wiki([https://wiki.fd.io/view/VPP](https://wiki.fd.io/view/VPP))。IPSec是为IP网络提供安全性的协议和服务的集合,它是VPN(Virtual Private Network,虚拟专用网)中常用的一种技术。通信双方通过IPsec建立加密隧道,IP数据包通过加密隧道进行传输,有效保证了数据在不安全的网络环境如Internet中传输的安全性,详见rfc文档:
+
+-
+-
+-
+
+VPP内置了IPSec功能,其实现方式具有高度的可扩展性和灵活性,支持多种软硬件优化技术,除了可选择自带的处理引擎外,还为开发者提供了模块化框架,允许以插件形式开发自己的加速引擎,从而为更广泛的高性能处理方案提供了适配能力,可以在不同的硬件平台上实现最优性能。
+本文描述的HCT crypto插件集基于该框架开发。
+
+## 1.2. 用于VPP IPSec的HCT crypto插件集
+
+海光密码技术(HCT, Hygon Cryptographic Technology)是基于海光密码协处理器和密码指令集自主设计研发的一套密码算法加速软件开发套件。HCT充分利用海光平台密码加速特性,整合底层海光密码计算资源,为用户上层应用提供高性能密码计算能力。关于HCT的使用介绍详见[HCT用户手册](https://openanolis.cn/sig/Hygon-Arch/doc/865622263675623238)。
+HCT crypto插件集依赖HCT提供的密码运算能力,利用VPP框架提供的插件机制,实现了两个加密插件,分别是HCT异步插件和HCT同步插件,可在VPP IPSec应用中充分发挥海光处理器的国密算法加速能力。
+
+## 1.3. 参考部署环境
+
+| 组件 | 版本信息 |
+| ------------ | -------------------------- |
+| CPU | 单路7385 C86 CPU |
+| 内存 | 128GB DDR4 |
+| 系统发行版 | Ubuntu 18.04 LTS |
+| 内核 | Linux kernel 5.4.19 |
+| gcc | 7.5.0 |
+| OpenSSL | 1.1.1c |
+| numa | 2.0.12 |
+| HCT套件 | hct_2.0.0.20241030_release |
+| 网卡 |mellanox MCX556A-EDAT |
+
+以上环境为本文撰写时使用的环境,仅供参考。其他具备海光密码加速特性的平台都能使用本文描述的技术。
+
+# 2. 源码和编译
+
+## 2.1. 源码介绍
+
+HCT crypto插件集基于VPP的**stable/2101**分支开发,如果用户需要使用其他分支,可基于本案提交的补丁进行移植。
+源码下载包含了VPP全部源码以及本项目新增的两个插件:[项目源码](https://gitee.com/anolis/vpp)
+
+### 2.1.1. VPP框架修改
+
+插件使用国密算法,需要引用VPP IPSec框架中与算法相关的定义,原生VPP中没有定义国密算法,所以增加了国密算法相关内容,改动的文件在VPP框架代码“src/vnet/ipsec”目录和“src/vnet/crypto”目录。
+
+### 2.1.2. 新增插件
+
+HCT crypto插件集提供的两个插件分别为:
+
+- 同步功能插件 crypto_hct_sync
+- 异步功能插件 crypto_hct_async
+
+同名源码目录放置在路径“src/plugins”下。
+
+## 2.2. 准备编译环境
+
+### 2.2.1. 删除冲突组件
+
+系统中已安装的VPP或DPDK会对编译和运行产生干扰,造成不确定的错误。编译前确认当前系统环境中是否曾经安装过VPP或者DPDK,通过如下命令:
+debian类系统:
+
+```bash
+dpkg -l | grep vpp
+dpkg -l | grep DPDK
+```
+
+centos类系统:
+
+```bash
+yum list installed | grep vpp
+yum list installed | grep DPDK
+```
+
+如果已安装过,先卸载对应的VPP或者DPDK组件,否则源码编译过程和运行过程可能会出错。
+
+### 2.2.2. 联网环境
+
+在联网条件下,clone或下载本项目源码后,进入源码根目录:
+
+```bash
+cd vpp-21.01
+git checkout stable/2101
+```
+
+这里一定注意checkout到stable/2101分支,因为本插件集是基于这个分支开发并提交的。
+VPP编译过程所需的各类工具、依赖软件,均由VPP的make系统解决,无需手动安装,仅需执行以下命令即可自动探测当前系统环境并安装缺失的依赖:
+
+```bash
+make install-dep # 安装编译过程所需依赖包
+make install-ext-deps # 安装运行过程所需依赖包
+```
+
+根据网络环境,以上两个命令的执行时间可能较长,需要耐心等待。
+
+### 2.2.3. 离线环境
+
+离线环境下VPP源码和所有依赖都需要手动拷贝、安装。源码从本案链接下载后拷贝到离线环境即可;编译工具依赖包的离线安装需要根据编译过程提示的错误信息,逐一下载离线包进行安装,根据包管理系统按需操作,不再赘述。
+下面描述运行时依赖包的下载,有两种方法获取“make install-ext-deps”命令下载安装的软件包:
+
+- **方法一:** 从曾经联网编译过相同版本的VPP的机器上,VPP目录的“**build/external**”下,拷贝“**downloads**”文件夹到离线编译的机器上VPP源码目录相同路径“**build/external**”下即可。
+- **方法二:** 查看VPP根目录“**build/external/packages**”下的各个“**\*.mk**”文件,这些文件分别对应了不同软件包的makefile脚本,用文本编辑器打开这些文件,从中找到下载链接,使用可联网机器输入链接即可下载,下载的压缩包放入目录“**build/external/downloads**”(没有downloads目录则创建一个)下即可。以DPDK为例说明下载方法:
+查看“build/external/packages/dpdk.mk”的内容:
+
+```makefile
+...
+dpdk_version ?= 20.11
+dpdk_base_url ?= http://fast.dpdk.org/rel
+dpdk_tarball := dpdk-$(dpdk_version).tar.xz
+...
+dpdk_url := $(dpdk_base_url)/$(dpdk_tarball)
+...
+```
+
+可以组合出下载DPDK的路径为: 。
+获取其他依赖包,如rdma、quicly等的下载路径,过程类似,不再赘述。
+所有软件包都下载完毕并放入指定目录后,在源码根目录执行:
+
+```bash
+touch build-root/.deps.ok
+```
+
+创建“.deps.ok”的目的是为编译系统建立锚点,使其越过下载步骤执行后续编译。
+
+## 2.3. 编译
+
+1. 编译命令
+在源码根目录执行:
+
+```bash
+make build #编译debug版
+make build-release #编译release版
+```
+
+VPP编译完成后,可执行程序和相关的库都在源码目录下生成,根据编译的类型是debug还是release,生成的可执行文件和库的位置在源码目录下:
+
+- debug版: 可执行文件路径 **build-root/install-vpp_debug-native/vpp/bin/**,库路径 **build-root/install-vpp_debug-native/vpp/lib/**
+- release版: 可执行文件路径 **build-root/install-vpp-native/vpp/bin/**, 库路径 **build-root/install-vpp-native/vpp/lib/**
+
+# 3. 运行
+
+## 3.1. 运行环境
+
+### 3.1.1. 安装hct
+
+本案所述插件运行依赖于HCT提供的接口,运行前需要安装HCT,详细安装步骤见[HCT用户手册](https://openanolis.cn/sig/Hygon-Arch/doc/865622263675623238)。
+
+### 3.1.2. 配置大页内存
+
+不配置大页内存也可以运行,但是配置大页内存可以大幅提高程序性能,建议进行配置。
+在/etc/default/grub文件中,修改“GRUB_CMDLINE_LINUX”参数内容:default_hugepagesz(默认大页大小,设为1G)、hugepagesz(大页大小,设为1G)、hugepages(大页个数,根据具体平台而定),修改后如下所示:
+
+```bash
+GRUB_CMDLINE_LINUX="... default_hugepagesz=1G hugepagesz=1G hugepages=32 ..."
+```
+
+其中“hugepages”的数量,在海光3系cpu上不低于4,在海光5系cpu上不低于8,在海光7系cpu上不低于16。
+修改并保存/etc/default/grub文件后,**更新grub并重启后生效**:
+debian类系统:
+
+```bash
+sudo update-grub
+sudo reboot
+```
+
+centos类系统:
+
+```bash
+sudo grub2-mkconfig -o /boot/grub2/grub.cfg # bios引导
+```
+
+或
+
+```bash
+sudo grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg # UEFI引导
+```
+
+## 3.2. 运行命令
+
+进入DUT1的VPP可执行文件路径,**使用root权限运行命令**:
+
+```bash
+sudo ./vpp -c
+```
+
+其中/path/to/config-file是VPP启动配置文件(文本格式),VPP自带一个基础的示例模板,位于build-root/install-vpp-native/VPP/etc/VPP/startup.conf,在该文件的基础上,文件名和内容均可以按需修改,文件内容的含义参见 文档相关章节。
+
+## 3.3. 测试方案
+
+可使用单机测试或者双机测试本案插件,它们的特点如下:
+
+- **单机测试**
+ 只用一台机器,即可完成IPSec业务闭环,即打流、加密、解密均在一台机器上完成,不需要额外的机器和测试仪,但受限于单机性能同时运行两个VPP以及打流,不能测出目标机型在真实业务环境下的加解密能力;
+- **多机测试**
+ 用三台机器(两台作为IPSec网关,一台作为打流机)或两台机器(作为IPSec网关) + 专业网络测试仪。这种方式下测试流量由专门的机器发出,模拟真实业务流量。目标机只执行IPSec网关的角色,只要网卡总带宽足够,就可以测出实际加解密能力。
+
+下面采用**单机测试演示同步插件**的使用,采用**多机测试演示异步插件**的使用。 但需要明确的是,单机演示异步插件,多机演示同步插件都是可以的,这里只是为了不占用过多篇幅,可以举一反三。
+
+### 3.3.1. 单机测试
+
+用单机测试演示同步插件的使用。
+
+#### 3.3.1.1. 测试拓扑
+
+单机测试仅需一台机器,没有对外网络连接的需求,通过对linux网络命名空间和VPP的设置,在同一台机器上模拟两个VPP实体通信过程:
+
+
+
+#### 3.3.1.2. 配置文件
+
+以下是设置主机网络的脚本set_host_net.sh内容:
+
+```bash
+sudo ip netns add ns0 # 新建网络命名空间ns0
+sudo ip link add name vpp0 type veth peer name host_vpp0 # 创建虚拟以太网口对(vpp0和host_vpp0)
+sudo ip link set vpp0 up # 设置虚拟网口vpp0状态为up
+sudo ip link set host_vpp0 netns ns0 # 将上面创建好的以太网口对中host_vpp0放入ns0命名空间,它的对端留在默认命名空间
+sudo ip netns exec ns0 ip link set lo up # 使能ns0命名空间中的回环接口
+sudo ip netns exec ns0 ip link set host_vpp0 up # 设置虚拟网口host_vpp0状态为up
+sudo ip netns exec ns0 ip addr add 192.168.1.1/24 dev host_vpp0 # 为ns0中的虚拟网口host_vpp0设置ip地址
+sudo ip netns exec ns0 ip route add default via 192.168.1.2 dev host_vpp0 # 为ns0创建默认路由,其网关地址“192.168.1.2”属于虚拟网口host_vpp0的对端网口,即“vpp0”,“vpp0”将在VPP的配置文件中启用
+
+# 与上面类似,创建了另一个网络命名空间ns1,余下类似
+sudo ip netns add ns1
+sudo ip link add name vpp1 type veth peer name host_vpp1
+sudo ip link set vpp1 up
+sudo ip link set host_vpp1 netns ns1
+sudo ip netns exec ns1 ip link set lo up
+sudo ip netns exec ns1 ip link set host_vpp1 up
+sudo ip netns exec ns1 ip addr add 192.168.2.1/24 dev host_vpp1
+sudo ip netns exec ns1 ip route add default via 192.168.2.2 dev host_vpp1
+```
+
+VPP配置文件dut1-sync-start内容如下:
+
+```text
+unix {
+ nodaemon
+ log /var/log/VPP/VPP.log
+ full-coredump
+ interactive
+ startup-config /path/to/dut1-net-sync-conf
+}
+cpu {
+ main-core 1
+ corelist-workers 6,7
+}
+plugins {
+ plugin crypto_hct_sync_plugin.so {enable} # 使能本项目定义的同步插件
+}
+buffers { buffers-per-numa 133320 }
+memory { main-heap-size 2G }
+statseg { size 1G }
+```
+
+“dut1-sync-start”文件中,“startup-config /path/to/dut1-net-sync-conf”一行是指定网络参数配置的,配置的内容写在dut1-net-sync-conf文件中,该文件内容如下:
+
+```text
+create host-interface name vpp0 hw-addr fa:16:29:29:29:29 # 接管外部创建的虚拟网口vpp0,并为其设置mac地址(在这里被重命名为“host-vpp0”)
+set interface state host-vpp0 up # 使能host-vpp0网口
+set interface ip address host-vpp0 192.168.1.2/24 # 设置host-vpp0网口ip地址
+create interface memif id 0 slave # VPP创建mem内存接口memif0/0,用于和另一个VPP里的内存接口连接,模拟以太网直连通信
+set interface state memif0/0 up
+set interface ip address memif0/0 192.168.3.1/24
+create ipip tunnel src 192.168.3.1 dst 192.168.3.2 # 创建IP-in-IP隧道
+ipsec sa add 11 spi 1001 esp crypto-key 4339314b55523947594d6d3547666b45 crypto-alg sm4-cbc integ-key 4339314b55523947594d6d3547666b45 integ-alg sm3 salt 0x11223344 # 创建SA参数,指定加密算法和完整性校验算法,以及相关密钥
+ipsec tunnel protect ipip0 sa-in 11 sa-out 11 # 为IP-in-IP隧道绑定SA,形成IPSec隧道
+ip route add 192.168.2.1/32 via 192.168.3.2 ipip0 # 添加转发路由,将目标地址路由到指定隧道上
+set interface unnumbered ipip0 use memif0/0 # 将IPSec隧道接口设置为无编号接口并借用memif接口IP地址
+set interface state ipip0 up # 使能隧道接口
+set crypto handler all hct_sync # 设置密码引擎为同步引擎“hct_sync”
+```
+
+另一个VPP配置文件dut2-sync-start内容如下:
+
+```text
+unix {
+ nodaemon
+ log /var/log/vpp/vpp.log
+ full-coredump
+ interactive
+ startup-config /{path}/dut2-net-sync-conf
+}
+cpu {
+ main-core 1
+ corelist-workers 6,7
+}
+plugins {
+ plugin crypto_hct_sync_plugin.so {enable} # 使能本项目定义的同步插件
+}
+buffers { buffers-per-numa 133320 }
+memory { main-heap-size 2G }
+statseg { size 1G }
+```
+
+其中dut2-net-sync-conf内容如下:
+
+```text
+create host-interface name vpp1 hw-addr fa:16:19:19:19:19
+set interface state host-vpp1 up
+set interface ip address host-vpp1 192.168.2.2/24
+create interface memif id 0 master
+set interface state memif0/0 up
+set interface ip address memif0/0 192.168.3.2/24
+create ipip tunnel src 192.168.3.2 dst 192.168.3.1
+ipsec sa add 11 spi 1001 esp crypto-key 4339314b55523947594d6d3547666b45 crypto-alg sm4-cbc integ-key 4339314b55523947594d6d3547666b45 integ-alg sm3 salt 0x11223344
+ipsec tunnel protect ipip0 sa-in 11 sa-out 11
+ip route add 192.168.1.0/24 via 192.168.3.1 ipip0
+set interface unnumbered ipip0 use memif0/0
+set interface state ipip0 up
+set crypto handler all hct_sync
+```
+
+可以通过以下命令验证:
+启动VPP发送实例以及接收实例:
+
+```bash
+sudo ./vpp -c
+sudo ./vpp -c
+```
+
+在其中一个网络空间中用ping测试到达对端网络空间的连通性:
+
+```bash
+sudo ip netns exec ns0 ping 192.168.2.1
+```
+
+如果ping包正常回应,则证明单机数据拓扑已经连通,接下来可以使用iperf等工具在ns0侧的host_vpp0和ns1侧的host_vpp1上进行压力测试。最简单的命令如:
+
+```bash
+sudo ip netns exec ns0 iperf -s
+sudo ip netns exec ns1 iperf -c 192.168.1.1
+```
+
+### 3.3.2. 多机测试
+
+用多机测试演示异步插件的使用。
+
+#### 3.3.2.1. 测试拓扑
+
+下图所示为多机测试的拓扑连接:
+
+
+
+图中DUT1和DUT2分别代表两台运行了VPP的机器,CPU为Hygon 7385单路,拥有4个DIE,开启超线程后一共有64个逻辑核。每台机器配置一块物理网卡(2个PF设备分裂出8个VF设备),每个网卡的IP地址、BDF、连接关系见图中所示,将三台机器按图示连接形成环状,由网络测试仪发出测试流,以顺时针方向的流为例,数据流从网络测试仪的1,2,3,4口分别流出,通过DUT1加密后送往DUT2,由DUT2解密后,通过网络测试仪的5,6,7,8四个口流回并由网络测试仪完成统计和数据呈现。
+
+#### 3.3.2.2. 绑定网卡到用户态驱动
+
+多机测试使用真实的网卡,在VPP中通过DPDK控制真实的网卡收发,需要将网卡从默认的内核驱动解绑,然后绑定到用户态驱动,以便DPDK可以接管。
+**特别注意:** **mellanox的网卡**驱动比较特殊,其自带DPDK的适配层,所以**不需要执行这一步**。
+DPDK可以支持“igb_uio”、“uio_pci_generic” 或者 “vfio-pci”这三种用户态驱动,确认自己的系统支持哪一种驱动,然后使用DPDK驱动绑定脚本执行相应的解绑和绑定操作,需要注意的是,编译完成后DPDK的驱动绑定脚本在源码目录下:“build-root/install-vpp-native/external/bin/dpdk-devbind.py”,举例说明使用方式:
+先加载vfio-pci驱动程序:
+
+```bash
+sudo modprobe vfio-pci
+```
+
+查看系统当前的网卡驱动情况:
+
+```bash
+cd build-root/install-vpp-native/external/bin/
+sudo ./dpdk-devbind.py -s
+Network devices using DPDK-compatible driver
+============================================
+0000:82:00.0 '82599EB 10-GbE NIC' drv=vfio-pci unused=ixgbe
+0000:82:00.1 '82599EB 10-GbE NIC' drv=vfio-pci unused=ixgbe
+
+Network devices using kernel driver
+===================================
+0000:04:00.0 'I350 1-GbE NIC' if=eth0 drv=igb unused=vfio-pci *Active*
+0000:04:00.1 'I350 1-GbE NIC' if=eth1 drv=igb unused=vfio-pci
+0000:04:00.2 'I350 1-GbE NIC' if=eth2 drv=igb unused=vfio-pci
+0000:04:00.3 'I350 1-GbE NIC' if=eth3 drv=igb unused=vfio-pci
+
+Other network devices
+=====================
+
+```
+
+要将设备eth1“04:00.1”绑定到vfio-pci驱动程序:
+
+```bash
+sudo ip link set dev eth1 down #先在系统中将eth1的端口状态设置为down,以便可以绑定到启动驱动上,如vfio-pci
+sudo ./dpdk-devbind.py -b vfio-pci 04:00.1
+```
+
+或者,
+
+```bash
+sudo ./dpdk-devbind.py -b vfio-pci eth1
+```
+
+更详细的使用详见dpdk文档:
+
+#### 3.3.2.3. 配置文件
+
+**Tips:** 如果单台机器上有多块物理网卡,尽量将网卡分散插入不同NUMA节点所属的PCIE插槽中,这样可以将流量尽可能分散到不同NUMA节点上,减少跨NUMA节点通信,提高并行处理效率。
+
+为节约篇幅,下面仅以DUT1的配置文件“dut1-async-start”为例,对与本引擎有关,或需要强调的内容进行注释和说明。
+
+```text
+unix {
+ nodaemon
+ log /var/log/vpp/vpp.logP
+ interactive
+ full-coredump
+ cli-listen /run/vpp/cli.sock
+ startup-config /path/to/dut1-net-async-conf # 内部配置文件
+}
+
+cpu {
+ main-core 0 # 0号核心绑定给VPP主线程使用
+ corelist-workers 1~63 # 1~63号核心分别绑定给worker线程使用
+}
+
+plugins {
+ plugin crypto_hct_async_plugin.so {enable} # 使能本项目定义的异步插件
+}
+buffers { buffers-per-numa 133320 }
+dpdk {
+ no-multi-seg
+ dev default{
+ num-rx-queues 1
+ }
+ dev 0000:21:00.2 # 从这里开始的dev均为网卡,"0000:21:00.2"是该网卡的BDF
+ {
+ workers 0 # 绑定0号worker处理“0000:21:00.2”这个网卡的数据,以下同理
+ name eth0 # 为本网卡接口取个名字,命名任意,方便使用即可
+ }
+ dev 0000:21:00.3
+ {
+ workers 7
+ name eth1
+ }
+ dev 0000:21:00.4
+ {
+ workers 15
+ name eth2
+ }
+ dev 0000:21:00.5
+ {
+ workers 23
+ name eth3
+ }
+ dev 0000:21:00.6
+ {
+ workers 0
+ name eth4
+ }
+ dev 0000:21:00.7
+ {
+ workers 7
+ name eth5
+ }
+ dev 0000:21:01.0
+ {
+ workers 15
+ name eth6
+ }
+ dev 0000:21:01.1
+ {
+ workers 23
+ name eth7
+ }
+ blacklist 8086:1521
+ no-multi-seg
+}
+
+memory { main-heap-size 2G }
+statseg { size 1G }
+```
+
+多机测试需要绑定网卡,以上展示的dut1-async-start文件中,每个“dev xxx {worker n}”小节中的worker后的数字,代表第几号worker,该worker负责dev xxx的数据收发。为充分发挥性能,该数字的选取遵循如下原则:
+先查看系统中该网卡属于哪个NUMA节点,绑定第几号worker应从该NUMA节点包含的逻辑核中选取(core与worker一一对应)。若不保证每个NUMA节点上都有网卡,那么网卡分配方式按NUMA节点距离由近到远分配。原则是尽量让每个NUMA节点上都有一个核在处理网卡数据,例如0000:21:00.2在NUMA 2上,那么这个数字选择NUMA 2上的第一个worker即可,在VPP的cli中执行“show threads”命令,如下图所示:
+
+
+
+上图中,“lcore”列代表了cpu的逻辑核,“core”列代表了cpu的物理核,“socket state”列代表了cpu的numa id,“name”列代表了worker的命名,命名最后的数字即worker编号。
+本例比较特殊,每台机器只有一块网卡(网卡上有两个PF接口),插在NUMA 2的pcie上,从这块网卡的两个PF接口分别分离出4个VF接口。按照上述原则,为了对数据处理进行负载均衡,将“21:00.2、21:00.6”两个VF网卡分配给NUMA 0的worker 0,“21:00.3、21:00.7”分配给NUMA 1的worker 7,以此类推。
+
+前面展示的“dut1-async-start”文件中,“startup-config /path/to/dut1-net-async-conf”一行是指定网络参数配置的,配置的内容写在dut1-net-async-conf文件中,该文件内容如下:
+
+```text
+# 设置各接口IP地址
+set interface ip address eth0 192.168.2.1/24
+set interface ip address eth1 192.168.3.1/24
+set interface ip address eth2 192.168.4.1/24
+set interface ip address eth3 192.168.5.1/24
+set interface ip address eth4 172.16.6.1/24
+set interface ip address eth5 172.16.7.1/24
+set interface ip address eth6 172.16.8.1/24
+set interface ip address eth7 172.16.9.1/24
+
+# 开启ipsec异步模式(若使用同步插件,这句不写)
+set ipsec async mode on
+
+# 创建IP-in-IP隧道
+create ipip tunnel src 192.168.2.1 dst 192.168.2.2
+create ipip tunnel src 192.168.3.1 dst 192.168.3.2
+create ipip tunnel src 192.168.4.1 dst 192.168.4.2
+create ipip tunnel src 192.168.5.1 dst 192.168.5.2
+
+# 创建SA参数,指定加密算法和完整性校验算法,以及相关密钥
+ipsec sa add 10 spi 1000 esp crypto-key 4339314b55523947594d6d3547666b45 crypto-alg sm4-cbc integ-key 4339314b55523947594d6d3547666b45 integ-alg sm3 salt 0x11223344
+ipsec sa add 11 spi 1001 esp crypto-key 4339314b55523947594d6d3547666b45 crypto-alg sm4-cbc integ-key 4339314b55523947594d6d3547666b45 integ-alg sm3 salt 0x11223344
+ipsec sa add 12 spi 1002 esp crypto-key 4339314b55523947594d6d3547666b45 crypto-alg sm4-cbc integ-key 4339314b55523947594d6d3547666b45 integ-alg sm3 salt 0x11223344
+ipsec sa add 13 spi 1003 esp crypto-key 4339314b55523947594d6d3547666b45 crypto-alg sm4-cbc integ-key 4339314b55523947594d6d3547666b45 integ-alg sm3 salt 0x11223344
+
+# 为IP-in-IP隧道绑定SA,形成IPSec隧道
+ipsec tunnel protect ipip0 sa-in 10 sa-out 10
+ipsec tunnel protect ipip1 sa-in 11 sa-out 11
+ipsec tunnel protect ipip2 sa-in 12 sa-out 12
+ipsec tunnel protect ipip3 sa-in 13 sa-out 13
+
+# 添加转发路由,将目标地址路由到指定隧道上
+ip route add 172.30.6.0/24 via 192.168.2.2 ipip0
+ip route add 172.30.7.0/24 via 192.168.3.2 ipip1
+ip route add 172.30.8.0/24 via 192.168.4.2 ipip2
+ip route add 172.30.9.0/24 via 192.168.5.2 ipip3
+
+# 将IPSec隧道接口设置为无编号接口并借用物理接口IP地址
+set interface unnumbered ipip0 use eth0
+set interface unnumbered ipip1 use eth1
+set interface unnumbered ipip2 use eth2
+set interface unnumbered ipip3 use eth3
+
+# 使能各物理接口和隧道接口
+set interface state eth0 up
+set interface state eth1 up
+set interface state eth2 up
+set interface state eth3 up
+set interface state eth4 up
+set interface state eth5 up
+set interface state eth6 up
+set interface state eth7 up
+set interface state ipip0 up
+set interface state ipip1 up
+set interface state ipip2 up
+set interface state ipip3 up
+
+# 设置密码引擎为异步引擎“hct_async”
+set crypto async handler hct_async all
+```
+
+DUT2与DUT1的配置类似,按照拓扑修改对应参数即可。
+以上网络参数在VPP初始化时加载,以静态方式打通IPSec隧道,加载完成后,即可开启网络测试仪打流测试。
+**Tips:** 特别注意,在网络参数中定义加解密引擎时:
+
+- 如果使用异步hct插件,必须加上“set ipsec async mode on”和“set crypto async handler hct_async all”这两句;
+- 如果使用同步插件,只写“set crypto handler all hct_sync”即可。
+
+# 4. FAQ
+
+## 4.1. 用户组不存在?
+
+运行VPP后提示:“group vpp does not exist”,添加对应的组即可:
+
+```bash
+sudo groupadd vpp
+```
+
+## 4.2. 日志文件创建失败?
+
+运行VPP后提示:“couldn't open log '/var/log/vpp/vpp.log'”,是因为“/var/log/vpp”目录不存在,创建即可:
+
+```bash
+sudo mkdir -p /var/log/vpp
+```
+
+## 4.3. 编译时提示缺少python库?
+
+编译过程出现类似错误:
+
+```text
+ModuleNotFoundError: No module named 'ply'
+```
+
+这类错误多出现在离线编译时,由于没有经过“make install-dep”过程,可能会有一些依赖软件包没有安装,需要离线安装Python的ply库,其他类似错误也要按需离线安装缺失的库或软件包。
+
+## 4.4. 如何打包安装?
+
+编译完成后,打包、安装:
+debian类系统:
+
+```bash
+make pkg-deb
+# deb包生成于build-root目录下
+sudo dpkg -i ./build-root/*.deb
+```
+
+centos类系统:
+
+```bash
+make pkg-rpm
+# rpm包生成于build-root目录下
+sudo rpm -i ./build-root/*.rpm
+```
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/9-VPP-IPSec HCT crypto\346\217\222\344\273\266\351\233\206\346\211\213\345\206\214/3-VPP-IPSec HCT crypto\346\217\222\344\273\266\351\233\206\347\224\250\346\210\267\346\211\213\345\206\214.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/9-VPP-IPSec HCT crypto\346\217\222\344\273\266\351\233\206\346\211\213\345\206\214/3-VPP-IPSec HCT crypto\346\217\222\344\273\266\351\233\206\347\224\250\346\210\267\346\211\213\345\206\214.md"
new file mode 100644
index 0000000000000000000000000000000000000000..98201bc54a9310e0fcc028275a354f3858e53c2a
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/9-VPP-IPSec HCT crypto\346\217\222\344\273\266\351\233\206\346\211\213\345\206\214/3-VPP-IPSec HCT crypto\346\217\222\344\273\266\351\233\206\347\224\250\346\210\267\346\211\213\345\206\214.md"
@@ -0,0 +1,597 @@
+
+# 1. 概要
+
+## 1.1. VPP的IPSec功能介绍
+
+VPP是思科(CISCO)公司主导的[FD.io](https://fd.io/)(快速数据输入/输出)开源项目中的一个子项目,提供网络层L2-L4快速处理网络数据的功能,整个项目由c语言编写,运行在linux用户态,详见官方wiki([https://wiki.fd.io/view/VPP](https://wiki.fd.io/view/VPP))。IPSec是为IP网络提供安全性的协议和服务的集合,它是VPN(Virtual Private Network,虚拟专用网)中常用的一种技术。通信双方通过IPsec建立加密隧道,IP数据包通过加密隧道进行传输,有效保证了数据在不安全的网络环境如Internet中传输的安全性,详见rfc文档:
+
+-
+-
+-
+
+VPP内置了IPSec功能,其实现方式具有高度的可扩展性和灵活性,支持多种软硬件优化技术,除了可选择自带的处理引擎外,还为开发者提供了模块化框架,允许以插件形式开发自己的加速引擎,从而为更广泛的高性能处理方案提供了适配能力,可以在不同的硬件平台上实现最优性能。
+本文描述的HCT crypto插件集基于该框架开发。
+
+## 1.2. 用于VPP IPSec的HCT crypto插件集
+
+海光密码技术(HCT, Hygon Cryptographic Technology)是基于海光密码协处理器和密码指令集自主设计研发的一套密码算法加速软件开发套件。HCT充分利用海光平台密码加速特性,整合底层海光密码计算资源,为用户上层应用提供高性能密码计算能力。关于HCT的使用介绍详见[HCT用户手册](https://openanolis.cn/sig/Hygon-Arch/doc/865622263675623238)。
+HCT crypto插件集依赖HCT提供的密码运算能力,利用VPP框架提供的插件机制,实现了两个加密插件,分别是HCT异步插件和HCT同步插件,可在VPP IPSec应用中充分发挥海光处理器的国密算法加速能力。
+
+## 1.3. 参考部署环境
+
+| 组件 | 版本信息 |
+| ------------ | -------------------------- |
+| CPU | 单路7385 C86 CPU |
+| 内存 | 128GB DDR4 |
+| 系统发行版 | Ubuntu 18.04 LTS |
+| 内核 | Linux kernel 5.4.19 |
+| gcc | 7.5.0 |
+| OpenSSL | 1.1.1c |
+| numa | 2.0.12 |
+| HCT套件 | hct_2.0.0.20241030_release |
+| 网卡 |mellanox MCX556A-EDAT |
+
+以上环境为本文撰写时使用的环境,仅供参考。其他具备海光密码加速特性的平台都能使用本文描述的技术。
+
+# 2. 源码和编译
+
+## 2.1. 源码介绍
+
+HCT crypto插件集基于VPP的**stable/2101**分支开发,如果用户需要使用其他分支,可基于本案提交的补丁进行移植。
+源码下载包含了VPP全部源码以及本项目新增的两个插件:[项目源码](https://gitee.com/anolis/vpp)
+
+### 2.1.1. VPP框架修改
+
+插件使用国密算法,需要引用VPP IPSec框架中与算法相关的定义,原生VPP中没有定义国密算法,所以增加了国密算法相关内容,改动的文件在VPP框架代码“src/vnet/ipsec”目录和“src/vnet/crypto”目录。
+
+### 2.1.2. 新增插件
+
+HCT crypto插件集提供的两个插件分别为:
+
+- 同步功能插件 crypto_hct_sync
+- 异步功能插件 crypto_hct_async
+
+同名源码目录放置在路径“src/plugins”下。
+
+## 2.2. 准备编译环境
+
+### 2.2.1. 删除冲突组件
+
+系统中已安装的VPP或DPDK会对编译和运行产生干扰,造成不确定的错误。编译前确认当前系统环境中是否曾经安装过VPP或者DPDK,通过如下命令:
+debian类系统:
+
+```bash
+dpkg -l | grep vpp
+dpkg -l | grep DPDK
+```
+
+centos类系统:
+
+```bash
+yum list installed | grep vpp
+yum list installed | grep DPDK
+```
+
+如果已安装过,先卸载对应的VPP或者DPDK组件,否则源码编译过程和运行过程可能会出错。
+
+### 2.2.2. 联网环境
+
+在联网条件下,clone或下载本项目源码后,进入源码根目录:
+
+```bash
+cd vpp-21.01
+git checkout stable/2101
+```
+
+这里一定注意checkout到stable/2101分支,因为本插件集是基于这个分支开发并提交的。
+VPP编译过程所需的各类工具、依赖软件,均由VPP的make系统解决,无需手动安装,仅需执行以下命令即可自动探测当前系统环境并安装缺失的依赖:
+
+```bash
+make install-dep # 安装编译过程所需依赖包
+make install-ext-deps # 安装运行过程所需依赖包
+```
+
+根据网络环境,以上两个命令的执行时间可能较长,需要耐心等待。
+
+### 2.2.3. 离线环境
+
+离线环境下VPP源码和所有依赖都需要手动拷贝、安装。源码从本案链接下载后拷贝到离线环境即可;编译工具依赖包的离线安装需要根据编译过程提示的错误信息,逐一下载离线包进行安装,根据包管理系统按需操作,不再赘述。
+下面描述运行时依赖包的下载,有两种方法获取“make install-ext-deps”命令下载安装的软件包:
+
+- **方法一:** 从曾经联网编译过相同版本的VPP的机器上,VPP目录的“**build/external**”下,拷贝“**downloads**”文件夹到离线编译的机器上VPP源码目录相同路径“**build/external**”下即可。
+- **方法二:** 查看VPP根目录“**build/external/packages**”下的各个“**\*.mk**”文件,这些文件分别对应了不同软件包的makefile脚本,用文本编辑器打开这些文件,从中找到下载链接,使用可联网机器输入链接即可下载,下载的压缩包放入目录“**build/external/downloads**”(没有downloads目录则创建一个)下即可。以DPDK为例说明下载方法:
+查看“build/external/packages/dpdk.mk”的内容:
+
+```makefile
+...
+dpdk_version ?= 20.11
+dpdk_base_url ?= http://fast.dpdk.org/rel
+dpdk_tarball := dpdk-$(dpdk_version).tar.xz
+...
+dpdk_url := $(dpdk_base_url)/$(dpdk_tarball)
+...
+```
+
+可以组合出下载DPDK的路径为: 。
+获取其他依赖包,如rdma、quicly等的下载路径,过程类似,不再赘述。
+所有软件包都下载完毕并放入指定目录后,在源码根目录执行:
+
+```bash
+touch build-root/.deps.ok
+```
+
+创建“.deps.ok”的目的是为编译系统建立锚点,使其越过下载步骤执行后续编译。
+
+## 2.3. 编译
+
+1. 编译命令
+在源码根目录执行:
+
+```bash
+make build #编译debug版
+make build-release #编译release版
+```
+
+VPP编译完成后,可执行程序和相关的库都在源码目录下生成,根据编译的类型是debug还是release,生成的可执行文件和库的位置在源码目录下:
+
+- debug版: 可执行文件路径 **build-root/install-vpp_debug-native/vpp/bin/**,库路径 **build-root/install-vpp_debug-native/vpp/lib/**
+- release版: 可执行文件路径 **build-root/install-vpp-native/vpp/bin/**, 库路径 **build-root/install-vpp-native/vpp/lib/**
+
+# 3. 运行
+
+## 3.1. 运行环境
+
+### 3.1.1. 安装hct
+
+本案所述插件运行依赖于HCT提供的接口,运行前需要安装HCT,详细安装步骤见[HCT用户手册](https://openanolis.cn/sig/Hygon-Arch/doc/865622263675623238)。
+
+### 3.1.2. 配置大页内存
+
+不配置大页内存也可以运行,但是配置大页内存可以大幅提高程序性能,建议进行配置。
+在/etc/default/grub文件中,修改“GRUB_CMDLINE_LINUX”参数内容:default_hugepagesz(默认大页大小,设为1G)、hugepagesz(大页大小,设为1G)、hugepages(大页个数,根据具体平台而定),修改后如下所示:
+
+```bash
+GRUB_CMDLINE_LINUX="... default_hugepagesz=1G hugepagesz=1G hugepages=32 ..."
+```
+
+其中“hugepages”的数量,在海光3系cpu上不低于4,在海光5系cpu上不低于8,在海光7系cpu上不低于16。
+修改并保存/etc/default/grub文件后,**更新grub并重启后生效**:
+debian类系统:
+
+```bash
+sudo update-grub
+sudo reboot
+```
+
+centos类系统:
+
+```bash
+sudo grub2-mkconfig -o /boot/grub2/grub.cfg # bios引导
+```
+
+或
+
+```bash
+sudo grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg # UEFI引导
+```
+
+## 3.2. 运行命令
+
+进入DUT1的VPP可执行文件路径,**使用root权限运行命令**:
+
+```bash
+sudo ./vpp -c
+```
+
+其中/path/to/config-file是VPP启动配置文件(文本格式),VPP自带一个基础的示例模板,位于build-root/install-vpp-native/VPP/etc/VPP/startup.conf,在该文件的基础上,文件名和内容均可以按需修改,文件内容的含义参见 文档相关章节。
+
+## 3.3. 测试方案
+
+可使用单机测试或者双机测试本案插件,它们的特点如下:
+
+- **单机测试**
+ 只用一台机器,即可完成IPSec业务闭环,即打流、加密、解密均在一台机器上完成,不需要额外的机器和测试仪,但受限于单机性能同时运行两个VPP以及打流,不能测出目标机型在真实业务环境下的加解密能力;
+- **多机测试**
+ 用三台机器(两台作为IPSec网关,一台作为打流机)或两台机器(作为IPSec网关) + 专业网络测试仪。这种方式下测试流量由专门的机器发出,模拟真实业务流量。目标机只执行IPSec网关的角色,只要网卡总带宽足够,就可以测出实际加解密能力。
+
+下面采用**单机测试演示同步插件**的使用,采用**多机测试演示异步插件**的使用。 但需要明确的是,单机演示异步插件,多机演示同步插件都是可以的,这里只是为了不占用过多篇幅,可以举一反三。
+
+### 3.3.1. 单机测试
+
+用单机测试演示同步插件的使用。
+
+#### 3.3.1.1. 测试拓扑
+
+单机测试仅需一台机器,没有对外网络连接的需求,通过对linux网络命名空间和VPP的设置,在同一台机器上模拟两个VPP实体通信过程:
+
+
+
+#### 3.3.1.2. 配置文件
+
+以下是设置主机网络的脚本set_host_net.sh内容:
+
+```bash
+sudo ip netns add ns0 # 新建网络命名空间ns0
+sudo ip link add name vpp0 type veth peer name host_vpp0 # 创建虚拟以太网口对(vpp0和host_vpp0)
+sudo ip link set vpp0 up # 设置虚拟网口vpp0状态为up
+sudo ip link set host_vpp0 netns ns0 # 将上面创建好的以太网口对中host_vpp0放入ns0命名空间,它的对端留在默认命名空间
+sudo ip netns exec ns0 ip link set lo up # 使能ns0命名空间中的回环接口
+sudo ip netns exec ns0 ip link set host_vpp0 up # 设置虚拟网口host_vpp0状态为up
+sudo ip netns exec ns0 ip addr add 192.168.1.1/24 dev host_vpp0 # 为ns0中的虚拟网口host_vpp0设置ip地址
+sudo ip netns exec ns0 ip route add default via 192.168.1.2 dev host_vpp0 # 为ns0创建默认路由,其网关地址“192.168.1.2”属于虚拟网口host_vpp0的对端网口,即“vpp0”,“vpp0”将在VPP的配置文件中启用
+
+# 与上面类似,创建了另一个网络命名空间ns1,余下类似
+sudo ip netns add ns1
+sudo ip link add name vpp1 type veth peer name host_vpp1
+sudo ip link set vpp1 up
+sudo ip link set host_vpp1 netns ns1
+sudo ip netns exec ns1 ip link set lo up
+sudo ip netns exec ns1 ip link set host_vpp1 up
+sudo ip netns exec ns1 ip addr add 192.168.2.1/24 dev host_vpp1
+sudo ip netns exec ns1 ip route add default via 192.168.2.2 dev host_vpp1
+```
+
+VPP配置文件dut1-sync-start内容如下:
+
+```text
+unix {
+ nodaemon
+ log /var/log/VPP/VPP.log
+ full-coredump
+ interactive
+ startup-config /path/to/dut1-net-sync-conf
+}
+cpu {
+ main-core 1
+ corelist-workers 6,7
+}
+plugins {
+ plugin crypto_hct_sync_plugin.so {enable} # 使能本项目定义的同步插件
+}
+buffers { buffers-per-numa 133320 }
+memory { main-heap-size 2G }
+statseg { size 1G }
+```
+
+“dut1-sync-start”文件中,“startup-config /path/to/dut1-net-sync-conf”一行是指定网络参数配置的,配置的内容写在dut1-net-sync-conf文件中,该文件内容如下:
+
+```text
+create host-interface name vpp0 hw-addr fa:16:29:29:29:29 # 接管外部创建的虚拟网口vpp0,并为其设置mac地址(在这里被重命名为“host-vpp0”)
+set interface state host-vpp0 up # 使能host-vpp0网口
+set interface ip address host-vpp0 192.168.1.2/24 # 设置host-vpp0网口ip地址
+create interface memif id 0 slave # VPP创建mem内存接口memif0/0,用于和另一个VPP里的内存接口连接,模拟以太网直连通信
+set interface state memif0/0 up
+set interface ip address memif0/0 192.168.3.1/24
+create ipip tunnel src 192.168.3.1 dst 192.168.3.2 # 创建IP-in-IP隧道
+ipsec sa add 11 spi 1001 esp crypto-key 4339314b55523947594d6d3547666b45 crypto-alg sm4-cbc integ-key 4339314b55523947594d6d3547666b45 integ-alg sm3 salt 0x11223344 # 创建SA参数,指定加密算法和完整性校验算法,以及相关密钥
+ipsec tunnel protect ipip0 sa-in 11 sa-out 11 # 为IP-in-IP隧道绑定SA,形成IPSec隧道
+ip route add 192.168.2.1/32 via 192.168.3.2 ipip0 # 添加转发路由,将目标地址路由到指定隧道上
+set interface unnumbered ipip0 use memif0/0 # 将IPSec隧道接口设置为无编号接口并借用memif接口IP地址
+set interface state ipip0 up # 使能隧道接口
+set crypto handler all hct_sync # 设置密码引擎为同步引擎“hct_sync”
+```
+
+另一个VPP配置文件dut2-sync-start内容如下:
+
+```text
+unix {
+ nodaemon
+ log /var/log/vpp/vpp.log
+ full-coredump
+ interactive
+ startup-config /{path}/dut2-net-sync-conf
+}
+cpu {
+ main-core 1
+ corelist-workers 6,7
+}
+plugins {
+ plugin crypto_hct_sync_plugin.so {enable} # 使能本项目定义的同步插件
+}
+buffers { buffers-per-numa 133320 }
+memory { main-heap-size 2G }
+statseg { size 1G }
+```
+
+其中dut2-net-sync-conf内容如下:
+
+```text
+create host-interface name vpp1 hw-addr fa:16:19:19:19:19
+set interface state host-vpp1 up
+set interface ip address host-vpp1 192.168.2.2/24
+create interface memif id 0 master
+set interface state memif0/0 up
+set interface ip address memif0/0 192.168.3.2/24
+create ipip tunnel src 192.168.3.2 dst 192.168.3.1
+ipsec sa add 11 spi 1001 esp crypto-key 4339314b55523947594d6d3547666b45 crypto-alg sm4-cbc integ-key 4339314b55523947594d6d3547666b45 integ-alg sm3 salt 0x11223344
+ipsec tunnel protect ipip0 sa-in 11 sa-out 11
+ip route add 192.168.1.0/24 via 192.168.3.1 ipip0
+set interface unnumbered ipip0 use memif0/0
+set interface state ipip0 up
+set crypto handler all hct_sync
+```
+
+可以通过以下命令验证:
+启动VPP发送实例以及接收实例:
+
+```bash
+sudo ./vpp -c
+sudo ./vpp -c
+```
+
+在其中一个网络空间中用ping测试到达对端网络空间的连通性:
+
+```bash
+sudo ip netns exec ns0 ping 192.168.2.1
+```
+
+如果ping包正常回应,则证明单机数据拓扑已经连通,接下来可以使用iperf等工具在ns0侧的host_vpp0和ns1侧的host_vpp1上进行压力测试。最简单的命令如:
+
+```bash
+sudo ip netns exec ns0 iperf -s
+sudo ip netns exec ns1 iperf -c 192.168.1.1
+```
+
+### 3.3.2. 多机测试
+
+用多机测试演示异步插件的使用。
+
+#### 3.3.2.1. 测试拓扑
+
+下图所示为多机测试的拓扑连接:
+
+
+
+图中DUT1和DUT2分别代表两台运行了VPP的机器,CPU为Hygon 7385单路,拥有4个DIE,开启超线程后一共有64个逻辑核。每台机器配置一块物理网卡(2个PF设备分裂出8个VF设备),每个网卡的IP地址、BDF、连接关系见图中所示,将三台机器按图示连接形成环状,由网络测试仪发出测试流,以顺时针方向的流为例,数据流从网络测试仪的1,2,3,4口分别流出,通过DUT1加密后送往DUT2,由DUT2解密后,通过网络测试仪的5,6,7,8四个口流回并由网络测试仪完成统计和数据呈现。
+
+#### 3.3.2.2. 绑定网卡到用户态驱动
+
+多机测试使用真实的网卡,在VPP中通过DPDK控制真实的网卡收发,需要将网卡从默认的内核驱动解绑,然后绑定到用户态驱动,以便DPDK可以接管。
+**特别注意:** **mellanox的网卡**驱动比较特殊,其自带DPDK的适配层,所以**不需要执行这一步**。
+DPDK可以支持“igb_uio”、“uio_pci_generic” 或者 “vfio-pci”这三种用户态驱动,确认自己的系统支持哪一种驱动,然后使用DPDK驱动绑定脚本执行相应的解绑和绑定操作,需要注意的是,编译完成后DPDK的驱动绑定脚本在源码目录下:“build-root/install-vpp-native/external/bin/dpdk-devbind.py”,举例说明使用方式:
+先加载vfio-pci驱动程序:
+
+```bash
+sudo modprobe vfio-pci
+```
+
+查看系统当前的网卡驱动情况:
+
+```bash
+cd build-root/install-vpp-native/external/bin/
+sudo ./dpdk-devbind.py -s
+Network devices using DPDK-compatible driver
+============================================
+0000:82:00.0 '82599EB 10-GbE NIC' drv=vfio-pci unused=ixgbe
+0000:82:00.1 '82599EB 10-GbE NIC' drv=vfio-pci unused=ixgbe
+
+Network devices using kernel driver
+===================================
+0000:04:00.0 'I350 1-GbE NIC' if=eth0 drv=igb unused=vfio-pci *Active*
+0000:04:00.1 'I350 1-GbE NIC' if=eth1 drv=igb unused=vfio-pci
+0000:04:00.2 'I350 1-GbE NIC' if=eth2 drv=igb unused=vfio-pci
+0000:04:00.3 'I350 1-GbE NIC' if=eth3 drv=igb unused=vfio-pci
+
+Other network devices
+=====================
+
+```
+
+要将设备eth1“04:00.1”绑定到vfio-pci驱动程序:
+
+```bash
+sudo ip link set dev eth1 down #先在系统中将eth1的端口状态设置为down,以便可以绑定到启动驱动上,如vfio-pci
+sudo ./dpdk-devbind.py -b vfio-pci 04:00.1
+```
+
+或者,
+
+```bash
+sudo ./dpdk-devbind.py -b vfio-pci eth1
+```
+
+更详细的使用详见dpdk文档:
+
+#### 3.3.2.3. 配置文件
+
+**Tips:** 如果单台机器上有多块物理网卡,尽量将网卡分散插入不同NUMA节点所属的PCIE插槽中,这样可以将流量尽可能分散到不同NUMA节点上,减少跨NUMA节点通信,提高并行处理效率。
+
+为节约篇幅,下面仅以DUT1的配置文件“dut1-async-start”为例,对与本引擎有关,或需要强调的内容进行注释和说明。
+
+```text
+unix {
+ nodaemon
+ log /var/log/vpp/vpp.logP
+ interactive
+ full-coredump
+ cli-listen /run/vpp/cli.sock
+ startup-config /path/to/dut1-net-async-conf # 内部配置文件
+}
+
+cpu {
+ main-core 0 # 0号核心绑定给VPP主线程使用
+ corelist-workers 1~63 # 1~63号核心分别绑定给worker线程使用
+}
+
+plugins {
+ plugin crypto_hct_async_plugin.so {enable} # 使能本项目定义的异步插件
+}
+buffers { buffers-per-numa 133320 }
+dpdk {
+ no-multi-seg
+ dev default{
+ num-rx-queues 1
+ }
+ dev 0000:21:00.2 # 从这里开始的dev均为网卡,"0000:21:00.2"是该网卡的BDF
+ {
+ workers 0 # 绑定0号worker处理“0000:21:00.2”这个网卡的数据,以下同理
+ name eth0 # 为本网卡接口取个名字,命名任意,方便使用即可
+ }
+ dev 0000:21:00.3
+ {
+ workers 7
+ name eth1
+ }
+ dev 0000:21:00.4
+ {
+ workers 15
+ name eth2
+ }
+ dev 0000:21:00.5
+ {
+ workers 23
+ name eth3
+ }
+ dev 0000:21:00.6
+ {
+ workers 0
+ name eth4
+ }
+ dev 0000:21:00.7
+ {
+ workers 7
+ name eth5
+ }
+ dev 0000:21:01.0
+ {
+ workers 15
+ name eth6
+ }
+ dev 0000:21:01.1
+ {
+ workers 23
+ name eth7
+ }
+ blacklist 8086:1521
+ no-multi-seg
+}
+
+memory { main-heap-size 2G }
+statseg { size 1G }
+```
+
+多机测试需要绑定网卡,以上展示的dut1-async-start文件中,每个“dev xxx {worker n}”小节中的worker后的数字,代表第几号worker,该worker负责dev xxx的数据收发。为充分发挥性能,该数字的选取遵循如下原则:
+先查看系统中该网卡属于哪个NUMA节点,绑定第几号worker应从该NUMA节点包含的逻辑核中选取(core与worker一一对应)。若不保证每个NUMA节点上都有网卡,那么网卡分配方式按NUMA节点距离由近到远分配。原则是尽量让每个NUMA节点上都有一个核在处理网卡数据,例如0000:21:00.2在NUMA 2上,那么这个数字选择NUMA 2上的第一个worker即可,在VPP的cli中执行“show threads”命令,如下图所示:
+
+
+
+上图中,“lcore”列代表了cpu的逻辑核,“core”列代表了cpu的物理核,“socket state”列代表了cpu的numa id,“name”列代表了worker的命名,命名最后的数字即worker编号。
+本例比较特殊,每台机器只有一块网卡(网卡上有两个PF接口),插在NUMA 2的pcie上,从这块网卡的两个PF接口分别分离出4个VF接口。按照上述原则,为了对数据处理进行负载均衡,将“21:00.2、21:00.6”两个VF网卡分配给NUMA 0的worker 0,“21:00.3、21:00.7”分配给NUMA 1的worker 7,以此类推。
+
+前面展示的“dut1-async-start”文件中,“startup-config /path/to/dut1-net-async-conf”一行是指定网络参数配置的,配置的内容写在dut1-net-async-conf文件中,该文件内容如下:
+
+```text
+# 设置各接口IP地址
+set interface ip address eth0 192.168.2.1/24
+set interface ip address eth1 192.168.3.1/24
+set interface ip address eth2 192.168.4.1/24
+set interface ip address eth3 192.168.5.1/24
+set interface ip address eth4 172.16.6.1/24
+set interface ip address eth5 172.16.7.1/24
+set interface ip address eth6 172.16.8.1/24
+set interface ip address eth7 172.16.9.1/24
+
+# 开启ipsec异步模式(若使用同步插件,这句不写)
+set ipsec async mode on
+
+# 创建IP-in-IP隧道
+create ipip tunnel src 192.168.2.1 dst 192.168.2.2
+create ipip tunnel src 192.168.3.1 dst 192.168.3.2
+create ipip tunnel src 192.168.4.1 dst 192.168.4.2
+create ipip tunnel src 192.168.5.1 dst 192.168.5.2
+
+# 创建SA参数,指定加密算法和完整性校验算法,以及相关密钥
+ipsec sa add 10 spi 1000 esp crypto-key 4339314b55523947594d6d3547666b45 crypto-alg sm4-cbc integ-key 4339314b55523947594d6d3547666b45 integ-alg sm3 salt 0x11223344
+ipsec sa add 11 spi 1001 esp crypto-key 4339314b55523947594d6d3547666b45 crypto-alg sm4-cbc integ-key 4339314b55523947594d6d3547666b45 integ-alg sm3 salt 0x11223344
+ipsec sa add 12 spi 1002 esp crypto-key 4339314b55523947594d6d3547666b45 crypto-alg sm4-cbc integ-key 4339314b55523947594d6d3547666b45 integ-alg sm3 salt 0x11223344
+ipsec sa add 13 spi 1003 esp crypto-key 4339314b55523947594d6d3547666b45 crypto-alg sm4-cbc integ-key 4339314b55523947594d6d3547666b45 integ-alg sm3 salt 0x11223344
+
+# 为IP-in-IP隧道绑定SA,形成IPSec隧道
+ipsec tunnel protect ipip0 sa-in 10 sa-out 10
+ipsec tunnel protect ipip1 sa-in 11 sa-out 11
+ipsec tunnel protect ipip2 sa-in 12 sa-out 12
+ipsec tunnel protect ipip3 sa-in 13 sa-out 13
+
+# 添加转发路由,将目标地址路由到指定隧道上
+ip route add 172.30.6.0/24 via 192.168.2.2 ipip0
+ip route add 172.30.7.0/24 via 192.168.3.2 ipip1
+ip route add 172.30.8.0/24 via 192.168.4.2 ipip2
+ip route add 172.30.9.0/24 via 192.168.5.2 ipip3
+
+# 将IPSec隧道接口设置为无编号接口并借用物理接口IP地址
+set interface unnumbered ipip0 use eth0
+set interface unnumbered ipip1 use eth1
+set interface unnumbered ipip2 use eth2
+set interface unnumbered ipip3 use eth3
+
+# 使能各物理接口和隧道接口
+set interface state eth0 up
+set interface state eth1 up
+set interface state eth2 up
+set interface state eth3 up
+set interface state eth4 up
+set interface state eth5 up
+set interface state eth6 up
+set interface state eth7 up
+set interface state ipip0 up
+set interface state ipip1 up
+set interface state ipip2 up
+set interface state ipip3 up
+
+# 设置密码引擎为异步引擎“hct_async”
+set crypto async handler hct_async all
+```
+
+DUT2与DUT1的配置类似,按照拓扑修改对应参数即可。
+以上网络参数在VPP初始化时加载,以静态方式打通IPSec隧道,加载完成后,即可开启网络测试仪打流测试。
+**Tips:** 特别注意,在网络参数中定义加解密引擎时:
+
+- 如果使用异步hct插件,必须加上“set ipsec async mode on”和“set crypto async handler hct_async all”这两句;
+- 如果使用同步插件,只写“set crypto handler all hct_sync”即可。
+
+# 4. FAQ
+
+## 4.1. 用户组不存在?
+
+运行VPP后提示:“group vpp does not exist”,添加对应的组即可:
+
+```bash
+sudo groupadd vpp
+```
+
+## 4.2. 日志文件创建失败?
+
+运行VPP后提示:“couldn't open log '/var/log/vpp/vpp.log'”,是因为“/var/log/vpp”目录不存在,创建即可:
+
+```bash
+sudo mkdir -p /var/log/vpp
+```
+
+## 4.3. 编译时提示缺少python库?
+
+编译过程出现类似错误:
+
+```text
+ModuleNotFoundError: No module named 'ply'
+```
+
+这类错误多出现在离线编译时,由于没有经过“make install-dep”过程,可能会有一些依赖软件包没有安装,需要离线安装Python的ply库,其他类似错误也要按需离线安装缺失的库或软件包。
+
+## 4.4. 如何打包安装?
+
+编译完成后,打包、安装:
+debian类系统:
+
+```bash
+make pkg-deb
+# deb包生成于build-root目录下
+sudo dpkg -i ./build-root/*.deb
+```
+
+centos类系统:
+
+```bash
+make pkg-rpm
+# rpm包生成于build-root目录下
+sudo rpm -i ./build-root/*.rpm
+```
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/a.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/a.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/a.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/acbsds.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/acbsds.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/acbsds.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/dvdvdv.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/dvdvdv.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/dvdvdv.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test000/a.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test000/a.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test000/a.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test000/aA.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test000/aA.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test000/aA.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test000/aaa.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test000/aaa.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test000/aaa.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test000/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/abc.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test000/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/abc.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test000/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/abc.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test000/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/gddgdfd\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2432.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test000/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/gddgdfd\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2432.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test000/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/gddgdfd\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2432.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test000/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2431.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test000/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2431.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test000/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2431.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test000/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2432.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test000/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2432.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test000/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2432.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test000/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2250/a.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test000/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2250/a.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test000/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2250/a.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test000/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2250/c.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test000/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2250/c.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test000/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2250/c.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/aaa.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/aaa.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/aaa.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/abc.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/abc.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/abc.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/abcd/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2252\346\226\207\346\241\243.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/abcd/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2252\346\226\207\346\241\243.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/abcd/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2252\346\226\207\346\241\243.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/abcd/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2252\346\226\207\346\241\24302.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/abcd/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2252\346\226\207\346\241\24302.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/abcd/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2252\346\226\207\346\241\24302.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/eeeeeee.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/eeeeeee.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/eeeeeee.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\243.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\243.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\243.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2431.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2431.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2431.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2432.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2432.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2432.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2433.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2433.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2433.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2434.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2434.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2434.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2435.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2435.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2435.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2436.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2436.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2436.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2437.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2437.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2437.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2438.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2438.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2438.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2252/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2252\346\226\207\346\241\243.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2252/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2252\346\226\207\346\241\243.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2252/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2252\346\226\207\346\241\243.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2252/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2252\346\226\207\346\241\24302.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2252/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2252\346\226\207\346\241\24302.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2252/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2252\346\226\207\346\241\24302.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2253/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2253\346\226\207\346\241\243.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2253/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2253\346\226\207\346\241\243.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2253/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2253\346\226\207\346\241\243.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2253/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2253\346\226\207\346\241\24302.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2253/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2253\346\226\207\346\241\24302.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2253/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2253\346\226\207\346\241\24302.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\225.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\225.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\225.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\22510.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\22510.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\22510.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\2252.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\2252.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\2252.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\2254.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\2254.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\2254.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\2255.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\2255.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\2255.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\2256.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\2256.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\2256.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\2257.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\2257.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\2257.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\2258.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\2258.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\2258.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\2259.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\2259.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test001/\346\200\247\350\203\275\346\265\213\350\257\2259.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test002/a.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/a.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/a.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test002/aA.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/aA.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/aA.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test002/aaa.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/aaa.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/aaa.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test002/abc.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/abc.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/abc.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test002/tttfsdfsdf.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/tttfsdfsdf.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/tttfsdfsdf.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/abc.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/abc.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/abc.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/gddgdfd\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2432.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/gddgdfd\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2432.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/gddgdfd\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2432.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\243.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\243.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\243.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2430.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2430.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2430.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2431.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2431.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2431.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2432.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2432.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\344\272\214\347\272\247\347\233\256\345\275\225\346\226\207\346\241\2432.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\347\233\256\345\275\225\346\226\207\346\241\243.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\347\233\256\345\275\225\346\226\207\346\241\243.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\225/\347\233\256\345\275\225\346\226\207\346\241\243.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2250/a.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2250/a.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2250/a.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2250/c.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2250/c.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/test002/\344\272\214\347\272\247\347\233\256\345\275\225\346\265\213\350\257\2250/c.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\344\275\277\347\224\250\346\211\213\345\206\214/CentOS 7\350\277\201\347\247\273Anolis OS 7\346\211\213\345\206\214.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\344\275\277\347\224\250\346\211\213\345\206\214/CentOS 7\350\277\201\347\247\273Anolis OS 7\346\211\213\345\206\214.md"
deleted file mode 100644
index 92d3de09984066188a0b3919c62d8d6360d54b43..0000000000000000000000000000000000000000
--- "a/sig/Anolis\350\277\201\347\247\273SIG/content/\344\275\277\347\224\250\346\211\213\345\206\214/CentOS 7\350\277\201\347\247\273Anolis OS 7\346\211\213\345\206\214.md"
+++ /dev/null
@@ -1,67 +0,0 @@
-# 1 迁移注意事项
-
-Anolis OS 7生态上和依赖管理上保持跟CentOS7.x兼容,一键式迁移脚本centos2anolis.py,实现CentOS7.x到Anolis OS 7的平滑迁移。
-
-使用迁移脚本前需要注意如下事项:
-
-* 迁移涉及到软件包的重新安装,是不可逆过程,执行迁移前务必做好系统备份。
-* 迁移过程涉及到访问Anolis OS的官方repo,需要确保待迁移环境网络能够正常访问Anolis OS repo。
-* 需要使用root用户执行。
-* 迁移过程依赖于yum,确保yum组件能够正常运行。
-* 迁移脚本提供了Anolis OS repo访问加速的功能,如果访问Anolis OS官方repo速度较慢,可以通过-s选项进行加速访问。
-* Anolis OS 不提供i686架构的软件包,如您系统上安装了CentOS的i686架构的软件包,则无法正常迁移。
-# 2 部署迁移工具
-下载迁移脚本:
-```
-wget https://mirrors.openanolis.cn/migration/anolis-migration.repo -O /etc/yum.repos.d/anolis-migration.repo
-```
-安装迁移脚本运行依赖:
-```
-yum -y install centos2anolis
-```
-3 迁移执行
-```
-centos2anolis.py
-```
-迁移完成后,系统会提示如下信息,表示迁移成功,重启即可进入Anolis OS系统。
-
-
-
-centos2anolis.py提供了-V选项,用于记录迁移前后的软件包信息,您可以根据需要判断是否添加选项。添加-V选项,迁移完成后会在/var/tmp目录下生成迁移前后的rpm信息,命名格式为:
-```
-# 迁移前
-$(hostname)-rpms-list-before.log
-$(hostname)-rpms-verified-before.log
-# 迁移后
-$(hostname)-rpms-list-after.log
-$(hostname)-rpms-verified-after.log
-```
-# 4 迁移后验证
-查看OS版本:
-```
-# cat /etc/os-release
-NAME="Anolis OS"
-VERSION="7.9"
-ID="anolis"
-ID_LIKE="rhel fedora centos"
-VERSION_ID="7.9"
-PRETTY_NAME="Anolis OS 7.9"
-ANSI_COLOR="0;31"
-HOME_URL="https://openanolis.cn/"
-BUG_REPORT_URL="https://bugs.openanolis.cn/"
-
-CENTOS_MANTISBT_PROJECT="CentOS-7"
-CENTOS_MANTISBT_PROJECT_VERSION="7"
-REDHAT_SUPPORT_PRODUCT="centos"
-REDHAT_SUPPORT_PRODUCT_VERSION="7"
-```
-#5 FAQ
-1)就地迁移失败是否可回滚?
-
-迁移工具不支持回滚,迁移失败无法恢复到迁移初始状态,迁移前务必做好系统备份。
-
-2)迁移出现问题怎么办?
-
-a. 先在龙蜥社区知识库查看是否有同样的问题。
-
-b. 保存迁移工具执行报错信息,并提供初始系统信息(系统版本,内核,软件包列表等等),附上迁移日志文件/var/log/centos2anolis.log,及时与我们联系获取帮助。
\ No newline at end of file
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\344\275\277\347\224\250\346\211\213\345\206\214/CentOS 7\350\277\201\347\247\273Anolis OS 8\346\211\213\345\206\214.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\344\275\277\347\224\250\346\211\213\345\206\214/CentOS 7\350\277\201\347\247\273Anolis OS 8\346\211\213\345\206\214.md"
deleted file mode 100644
index d15c5fd065b9f3780d40d05110bb8b1e5dd9fce7..0000000000000000000000000000000000000000
--- "a/sig/Anolis\350\277\201\347\247\273SIG/content/\344\275\277\347\224\250\346\211\213\345\206\214/CentOS 7\350\277\201\347\247\273Anolis OS 8\346\211\213\345\206\214.md"
+++ /dev/null
@@ -1,155 +0,0 @@
-1 迁移原理与注意事项
-
-CentOS7.x到Anolis OS 8,无论是内核,基础软件包,工具链都发生了较大的变化。迁移工具需要考虑这些变化带来的兼容性问题。OpenAnolis社区提供的迁移工具leapp包含了迁移评估,迁移实施,配置还原等步骤,用于实现CentOS7.x到Anolis OS 8的就地迁移。
-
-1.1 迁移评估
-
-leapp扫描待迁移系统,搜集内核,软件包,系统配置基础信息,同时与目标系统(Anolis OS)进行对比分析,对于不兼容项给出影响分析和解决方案。如内核角度给出Anolis OS 中不再支持的内核特性,硬件驱动;软件角度给出系统命令的变更项,提示用户适配业务程序。leapp的迁移评估报告会给出当前系统中所有可能影响到迁移的影响项目,当这些影响项目都被解决后,用户才能够继续做迁移实施。同时业务程序可根据评估报告中的兼容性提示来适配迁移业务程序。
-
-1.2 迁移实施
-
-leapp首先搜集当前的系统信息,记录需要在重启后恢复的配置(如selinux状态)。迁移实施过程中,工具首先按照当前系统安装的软件包列表,并根据CentOS7.x到Anolis OS 8的软件包映射关系,从Anolis OS repo上提前下载迁移所需要的软件包,并基于Anolis OS的软件包制作upgrade-initramfs,在下一次重启后,系统自动进入upgrade-initramfs,并触发所有软件包的就地升级。在所有的软件包就地升级完成后,自动重启进入系统配置还原阶段,待所有的信息都完成配置后,系统重启进入新的OS,完成OS的就地迁移。
-
-2 部署迁移工具
-选项一 从本地 yum 源安装迁移工具
-
-1. 如果待迁移系统无法访问龙蜥 mirror,首先建议在内网搭建一套本地yum源。(如何做本地yum源 用户名: rsync_user , 密码: Rsync@2020) ,然后通过本地源安装迁移工具。假设本地源地址为 http://local.repo.com/anolis , 则下载迁移工具软件源:
-
-wget http://local.repo.com/anolis/migration/anolis-migration.repo -O /etc/yum.repos.d/anolis-migration.repo
-
-2. 然后执行下述命令将 /etc/yum.repos.d/anolis-migration.repo 里面的baseurl地址替换为本地源地址。
-
-sed -i "s#baseurl=https://mirrors.openanolis.cn/#baseurl=http://local.repo.com/#" /etc/yum.repos.d/anolis-migration.repo
-sed -i "s#gpgkey=https://mirrors.openanolis.cn/#gpgkey=http://local.repo.com/#" /etc/yum.repos.d/anolis-migration.repo
-
-3. 安装迁移工具:
-
-pip list | grep requests && pip uninstall requests urllib3 -y
-yum -y install leapp
-yum -y install python-urllib3 python-requests
-
-备注:重新安装 python-requests 和 python-urllib3 是为了解决迁移过程中可能发生的软件包升级冲突。
-
-4. 执行下述命令将 /etc/leapp/files/leapp_upgrade_repositories.repo 里面的baseurl地址替换为本地源地址。
-
-sed -i "s#baseurl=https://mirrors.openanolis.cn/#baseurl=http://local.repo.com/#" /etc/leapp/files/leapp_upgrade_repositories.repo
-
-选项二 从社区 yum 源(mirrors.openanolis.cn) 安装迁移工具
-
-如果待迁移系统可以联网,则下载迁移工具软件源:
-
-wget https://mirrors.openanolis.cn/anolis/migration/anolis-migration.repo -O /etc/yum.repos.d/anolis-migration.repo
-
-
-安装迁移工具:
-
-pip list | grep requests && pip uninstall requests urllib3 -y
-yum -y install leapp
-yum -y install python-urllib3 python-requests
-3 迁移前评估
-
-成功部署工具后,运行工具的评估命令来对系统环境进行扫描评估:
-
-leapp preupgrade --no-rhsm
-
-上述命令是默认评估迁移到带 ANCK 内核的龙蜥OS,如果你想评估迁移到带 RHCK 内核的龙蜥OS请执行下面的命令
-
-leapp preupgrade --no-rhsm --disablerepo=anolis_plus
-3.1 查看评估报告
-
-评估命令执行完成后,会生成评估报告,在/var/log/leapp/leapp-report.txt中,报告中详细列举出当前OS与目标OS系统间的升级分析报告,每一个报告点都包含影响等级,影响范围以及解决方案。
-
-当评估工具认为报告点影响到了OS的就地升级,这些报告点问题就必须解决,否则无法实施就地迁移。
-
-报告样式如下,包含影响等级,影响概述,影响详细信息,推荐解决方案。
-
-上述报告提示用户在Anolis OS中默认没有python命令,系统中默认提供的是不向前兼容的python3,并且python2只是有限支持,用户需要尽快将业务程序尽快迁移到使用python3。同时报告也给出了解决方案来使系统默认提供python命令。
-
-3.2 基于评估报告处理迁移前问题
-
-迁移评估报告中一旦遇到影响到就地迁移的因素,会禁止做迁移实施,将这些影响因素都解决后才能够继续实施迁移。如果遇到影响迁移实施的因素,迁移评估结果显示如下:
-
-按照报告的提示,在/var/log/leapp/leapp-report.txt可以获取到详细的报告信息,同时UPGRADE INHIBITED给出的影响升级的因素也可以在/var/log/leapp/answerfile文件中查看。
-
-# cat /var/log/leapp/answerfile
-[remove_pam_pkcs11_module_check]
-# Title: None
-# Reason: Confirmation
-# =================== remove_pam_pkcs11_module_check.confirm ==================
-# Label: Disable pam_pkcs11 module in PAM configuration? If no, the upgrade process will be interrupted.
-# Description: PAM module pam_pkcs11 is no longer available in Anolis 8 since it was replaced by SSSD.
-# Type: bool
-# Default: None
-# Available choices: True/False
-# Unanswered question. Uncomment the following line with your answer
-# confirm =
-
-解决方案,在新的Anolis OS 8中不再支持pam_pkcs11,所以我们直接选择删除该不支持的选项:
-
-leapp answer --section remove_pam_pkcs11_module_check.confirm=True
-
-Anolis OS 8中默认的PermitRootLogin行为是prohibit-password,禁止root用户登陆,如果不显式设置PermitRootLogin yes则会在迁移后影响root用户密码登陆。
-
-解决方案:修改sshd_config 配置文件,允许root用户登录
-
-sed -i 's/#PermitRootLogin yes/PermitRootLogin yes/' /etc/ssh/sshd_config
-
-解决了上述影响因素后,可以再次执行leapp preupgrade --no-rhsm或者 leapp preupgrade --no-rhsm --disablerepo=anolis_plus 再次评估是否有影响迁移的因素。若没有影响迁移的因素,结果如下:
-
-3.2.4 迁移实施
-
-解决了评估报告中所有影响就地迁移的问题后,即可实施迁移。
-
-leapp upgrade --no-rhsm
-
-上述命令是默认迁移到带 ANCK 内核的龙蜥OS,如果你想迁移到带 RHCK 内核的龙蜥OS请执行下面的命令
-
-leapp upgrade --no-rhsm --disablerepo=anolis_plus
-
-该步骤涉及到从目标系统(Anolis OS repo)上下载软件包用于就地升级,确保待迁移环境能够正常访问Anolis OS repo。
-
-上述命令执行成功后,还可以通过/var/log/leapp/leapp-report.txt查看迁移报告,该报告除了包含评估报告外,还包含对目标系统repo的可行性评估,如果目标系统软件包不符合迁移要求,会给出提示。
-
-以下图为例,Anolis OS 8中不再支持kde,评估报告中给出了这样的提示:
-
-一切就绪,执行结果如下:
-
-接下来需要执行 reboot 命令,reboot后OS进入一个隔离环境自动进行实质的迁移操作。
-
-待系统迁移完成后,OS 会再次自动重启进入迁移后的系统。这一步骤涉及到2次OS重启以及相关的迁移操作故耗时较长。
-
-3.2.5 迁移后验证
-
-就地迁移完成后,进入新的操作系统,可以通过/var/log/leapp/leapp-report.txt查看迁移报告,报告中会包含就地迁移以及迁移后的系统详细报告信息,也可以通过/var/log/leapp/leapp-upgrade.txt查看就地迁移的执行日志。
-
-查看报告/var/log/leapp/leapp-report.txt可以获取升级过程中的一些信息,比如因为某些原因软件包没有升级成功,需要手动处理这些软件包。
-
-/var/log/leapp/leapp-upgrade.txt则记录了整个迁移过程,
-
-迁移完成后,可通过一系列基础操作查看OS版本,如/etc/os-release查看OS版本。
-
-迁移完成后,应用程序可以通过自身的指标查看是否能够正常运行。
-
-4 FAQ
-
-1)执行“leapp upgrade --no-rhsm”时出现因网络问题下载软件包失败,如何解决?
-
-修改/etc/leapp/files/leapp_upgrade_repositories.repo文件,将mirrors.openanolis.cn替换为mirrors.aliyun.com
-
-2) 待迁移环境需要配置代理访问外网,leapp运行过程中下载软件包报错,如何解决?
-
-leapp执行过程中真正生效的repo是/etc/leapp/files/leapp_upgrade_repositories.repo,修改/etc/leapp/files/leapp_upgrade_repositories.repo 文件,为每个repo配置代理,
-
-3)如何确认迁移前后软件包变化?
-
-使用leapp进行OS迁移后,可通过迁移日志/var/log/leapp/leapp-upgrade.log查看软件包更新详细信息。
-
-4)就地迁移失败是否可回滚?
-
-迁移工具不支持回滚,迁移失败无法恢复到迁移初始状态,迁移前务必做好系统备份。
-
-5)迁移出现问题怎么办?
-
-迁移过程中出现任何问题,可保存当前迁移工具执行报错信息,并提供初始系统信息(系统版本,内核,软件包列表等等),及时与我们联系获取帮助。
-
-
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.11.14\343\200\221Cloud_Kernel\344\273\243\347\240\201\345\220\210\345\271\266\346\265\201\347\250\213\345\217\230\346\233\264.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.11.14\343\200\221Cloud_Kernel\344\273\243\347\240\201\345\220\210\345\271\266\346\265\201\347\250\213\345\217\230\346\233\264.md"
new file mode 100644
index 0000000000000000000000000000000000000000..0159d93f720a60c6c1b2ea52a892799ce4c6fff8
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.11.14\343\200\221Cloud_Kernel\344\273\243\347\240\201\345\220\210\345\271\266\346\265\201\347\250\213\345\217\230\346\233\264.md"
@@ -0,0 +1,93 @@
+大家好,我们对龙蜥社区内核代码仓库Cloud Kernel的代码贡献流程进行了优化。
+
+
+我们已于2022年11月9日上线了自动添加reviewed-by签名和PR link的功能,后续合入PR将不再需要开发者手动force push,请各位龙蜥社区开发者和maintainer注意流程的变更。
+
+
+# 变更内容
+
+
+原来合入的流程为:
+
+
+1. fork Cloud Kernel仓库
+2. 提bugzilla
+3. 编写代码,提交至个人仓库
+4. 提交PR,通过门禁测试
+5. maintainer review通过,在PR评论区给出reviewed-by签名
+6. 在commit中添加reviewed-by签名和PR link
+7. force push
+8. 开发者评论/checksig检查签名
+9. maintainer评论/merge合入代码
+
+
+
+新的流程优化掉了第6、7、8步,省掉了手动添加reviewed-by和PR link,force push以及check-sig的动作,让大家在合入代码时更加方便。
+
+
+# 注意事项
+
+
+## 对于开发者
+
+
+如果您是Cloud Kernel开发者:
+
+
+1. 不用再手动添加reviewed-by和PR link,然后再force push。只要拿到了maintainer的Rewiewed-by签名,就不用管后续的事情了。
+2. 标签变化。新增自动签名功能后,后续PR将不再支持/check-sig命令和anolis\_sign\_pass等标签,改由anolis\_merge\_pass等标签标识合入状态。
+3. 在/merge以后,会有一个非常短暂的时间窗口,这期间从仓库git fetch的代码是不带Reviewed-by/Acked-by签名的,这可能对您的开发造成些微影响。
+ - 该问题与门禁实现有关。门禁会先调用OpenAPI关闭PR(这阶段会合入不带签名的commit),再通过force push的方式将带有前面的commit刷到devel-4.19/devel-5.10开发分支。
+ - 如果您在git fetch后发现有这个问题,请重置一下您的分支
+ - 如果您在提交新的PR时发现有这个问题,请通过git rebase解决
+
+
+## 对于Maintainer
+
+
+如果您是Cloud Kernel Maintainer:
+
+
+1. 只有在小龙提示自动签名完成以后,才算作代码合入成功。这之前,小龙会先合入PR,但并不是一个最终的状态。
+
+
+
+
+
+2. 该功能支持添加多个maintainer的签名。
+3. 非maintainer的签名,也会被门禁自动挑选合入到commit log中。
+4. 以Xiao Long 为例,不支持的签名格式有:
+
+
+
+
+| | |
+| --- | --- |
+| 示例 | 说明 |
+| /merge Reviewed-by: Xiao Long | 将/merge直接与签名放在同一行内。这会被门禁视为传参给/merge,目前不支持传参。请将二者放到不同行内 |
+
+
+4. 以Xiao Long 为例,支持的签名格式有:
+
+
+
+
+| | |
+| --- | --- |
+| 示例 | 说明 |
+| Reviewed-by: Xiao Long | 正常的reviewed-by签名 |
+| Acked-by: Xiao Long | 正常的acked-by签名 |
+| reviewed-by: Xiao Long | 首字母小写 |
+| acked-by: Xiao Long | 首字母小写 |
+| Acked-by: Xiao Long xiaolong@openanolis.org | 不带尖括号(在网页渲染时,尖括号会被视为html的标记,从而不展示) |
+| reviewed-by: Xiao Long | "-by:"后不带空格 |
+| `Reviewed-by: Xiao Long ` | 签名带有反引号(用于在PR界面保留尖括号) |
+| balabala reviewed-by: Xiao Long balabala | 签名隐藏在一行中,前后有内容 |
+| balabala balabala reviewed-by: Xiao Long balabala | 签名隐藏在一段中 |
+| /merge | 不加任何评论,直接/merge。若最终/merge的maintainer未显式给出任何回复,则门禁会自动加上该maintainer的签名 |
+| /mergeReviewed-by: Xiao Long | 在/merge时,新起一行,顺便加上了签名 |
+| 第一个评论:Acked-by: Xiao Long
+第二个评论:Reviewed-by: Xiao Long | 先给了acked-by签名,再给了reviewed-by签名。最终使用acked-by,原则上是哪种先出现用哪个。 |
+| 在commit log中: Acked-by: Xiao Long 在PR评论中: Reviewed-by: Xiao Long | commit log中已有签名。最终会保留commit log中的签名,该功能用于兼容老的合入机制。 |
+| | |
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264.md"
new file mode 100644
index 0000000000000000000000000000000000000000..eed4fad9888959ebd06a4bb6874fd339f44400e0
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264.md"
@@ -0,0 +1,95 @@
+
+# 1. 背景
+
+
+当前,对于Cloud Kernel的某些commit,开发者们无法根据commit log获取到bugzilla链接中的相关背景信息。这是因为:
+
+
+* commit log中只有bugzilla的ID(即`ANBZ: #xxx` 信息)
+* 受限于某些原因,bugzilla当前并未向所有人开放浏览权限。
+
+
+
+
+
+**为了满足开发者们对Cloud Kernel的commit进行溯源的需要**,同时考虑到gitee上的PR链接对所有人开放了浏览权限,因此我们决定对现有开发流程进行优化。
+
+
+具体而言如下:
+
+
+首先,在commit log里面加上了PR链接,如此可通过commit log反查到PR。
+
+
+接下来,要求开发者们在提交PR时,在PR正文中带上bugzilla信息以及背景描述信息,如此:
+
+
+* 如果用户有bugzilla权限,就可以看到bugzilla信息。
+* 如果用户没有bugzilla权限,那么可以通过PR了解到commit的背景。
+
+
+
+
+
+此外,考虑到开发流程变得更加严格,更加冗长了,我们也正在优化门禁,未来将上线自动添加PR链接及reviewed-by签名的功能,简化流程。
+
+
+当前流程给您带来的不便,请多多谅解。
+
+
+# 2. 变更指南
+
+
+## 2.1 从未向Cloud Kernel提交过代码
+
+
+如果您从未向Cloud Kernel提交过代码,请参考新规范全文。一步步跟着操作就行,每个步骤我们都有示例。
+
+
+新规范的链接在这里:
+
+
+我们将规范拆分成了总体流程、bugzilla规范、commit规范和PR规范四篇。
+
+
+
+
+
+## 2.2 已熟悉原有提交流程
+
+
+如果您已经熟悉原来的那套流程,即:制作补丁、开bugzilla、提PR。
+
+
+那么,**以下步骤需要注意**:
+
+
+**1. 提交PR时,请按照规定格式来写**,而不像之前那样很随意。**该规则已纳入门禁检测**。
+
+
+PR格式要求带上bugzilla链接和**技术背景描述**(不低于10个字)。请把PR的正文当做向linux社区发送补丁的时候cover-letter那样对待,以便让龙蜥社区开发者了解技术背景。
+
+
+参考链接:。
+
+[参考链接](https://openanolis.cn/sig/Cloud-Kernel/doc/607605992881480196)
+
+
+
+
+
+**2.** 在PR review完毕,准备添加reviewer的签名后/merge合并时,原来只需要在commit log里面加上reviewed-by即可,现在**要求还要加上PR链接**。**该规则已纳入门禁检测。**
+
+
+参考链接:。
+
+
+
+
+
+具体案例您可以参考[这个PR](https://gitee.com/anolis/cloud-kernel/commit/4a1a5547bd7ec65d734368ac8e93e415c52220f0):
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.8.3\343\200\221Cloud_Kernel_devel-5.10\345\210\206\346\224\257\345\217\230\346\233\264.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.8.3\343\200\221Cloud_Kernel_devel-5.10\345\210\206\346\224\257\345\217\230\346\233\264.md"
new file mode 100644
index 0000000000000000000000000000000000000000..593e2547d6d6bfda7d99f779ef4f815f117c39ba
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.8.3\343\200\221Cloud_Kernel_devel-5.10\345\210\206\346\224\257\345\217\230\346\233\264.md"
@@ -0,0 +1,10 @@
+大家好,因ANCK 5.10新版本发布的需要,我们基于linux社区5.10.134的代码进行了rebase。
+目前Cloud Kennel仓库的devel-5.10与release-5.10的代码均已被force push。
+
+请大家注意:
+1. 未合入的PR将会发生冲突。
+2. 请检查自己的代码,重新拉取新的devel-5.10分支进行开发。
+
+仓库地址:
+https://gitee.com/anolis/cloud-kernel
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.9.28\343\200\221Anolis8_5.10.134-12\347\211\210\346\234\254\345\206\205\346\240\270\345\217\221\345\270\203.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.9.28\343\200\221Anolis8_5.10.134-12\347\211\210\346\234\254\345\206\205\346\240\270\345\217\221\345\270\203.md"
new file mode 100644
index 0000000000000000000000000000000000000000..fa201cab86e086d257a88bc858340498385afbfe
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.9.28\343\200\221Anolis8_5.10.134-12\347\211\210\346\234\254\345\206\205\346\240\270\345\217\221\345\270\203.md"
@@ -0,0 +1,55 @@
+大家好,Anolis8已发布新版本内核5.10.134-12,欢迎您下载体验。
+
+
+
+
+
+**使用该内核的方法:**
+
+[镜像地址](https://mirrors.openanolis.cn/anolis/8.6/isos/QU1/)
+1. 首先,下载并安装Anolis8:
+2. 然后,按照如下方法升级内核:
+ 1. yum install -y yum-utils anolis-experimental-release
+ 2. yum-config-manager --enable Experimental
+ 3. yum install -y kernel-5.10.134-12.an8
+
+
+
+
+
+**本次内核更新日志如下:**
+
+
+* 内核升级到5.10.134
+* 重要的缺陷及安全漏洞修复
+* 支持倚天710处理器
+* 支持磐久M物理机
+* 优化在倚天平台上的基础性能
+* ARM64支持mpam特性
+* 增加AMD SEV热迁移能力的guest支持
+* ARM64 crashkernel支持预留4G以上内存
+* ARM64支持对kernel module的hotfix
+* 支持ftrace osnoise tracer
+* 支持 ext4 fast commit 特性,该特性对于 fsync 比较频繁的应用如 MySQL/PostgreSQL 数据库有比较明显的性能优化。相应的 e2fsprogs 版本更新至 1.46.0。
+* 支持网讯10GB网卡
+
+
+**龙蜥自研:**
+
+
+* 支持datop监控NUMA跨node访问以及进程粒度内存冷热识别
+* 填充可执行二进制文件末尾2M未对齐部分,部分场景性能再提升2%
+* 支持 XFS 16k 原子写特性,相比默认打开双写,有至多 50% 的性能提升,同时显著减少磁盘 IO。相应的 xfsprogs 和 mariadb 也更新至龙蜥 yum repo。相比硬件原子写方案,该方案至少有着以下优点:
+ + 基于 CoW 机制;
+ + 不依赖硬件;
+ + 无运行时 IO 链路配置依赖。
+
+
+ 另外,该优化效果可以与代码段大页特性叠加。使用手册:
+
+
+* 支持 nydus + erofs over fscache 容器镜像加速。该特性由龙蜥社区贡献,于 5.19 合并到社区主线,并成为社区首个源生支持的容器镜像加速方案。相关技术博客:
+* 支持 fd passthrough 和 fd attach 增强特性。其中 fd passthrough 能将常用场景的 IO 延迟降低到先前的 10%;fd attach 支持无损恢复 fuse 挂载点连接,提升生产环境的稳定性。
+* kidled支持匿名页、文件页以及slab的扫描。
+* 新增memory.use\_priority\_swap接口,支持按cgroup优先级进行内存swap。
+* SMC 新增 1-RTT、RDMA DIM 支持,优化 CQ 中断处理逻辑,数据路径 QPS 提升 40%。引入 SMC 自动化测试能力,修复数十个稳定性问题;
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/2021.11.01~2021.11.14.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/2021.11.01~2021.11.14.md"
new file mode 100644
index 0000000000000000000000000000000000000000..8836ff2b507693190017a459eb94c992dad7b341
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/2021.11.01~2021.11.14.md"
@@ -0,0 +1,81 @@
+### 会议主题
+
+
+首次非正式会议, 自由讨论的形式, 聊聊龙蜥内核版本计划, 研发流程及后续双周会主题等
+
+
+### 会议时间
+
+
+2021.11.03 15:00-17:00
+
+
+### 与会人
+
+
+* 会议主持: Shiloong
+* 来自统信,龙芯, 阿里云的龙蜥社区爱好者
+
+
+### 会议纪要
+
+
+* 会议由 Shioong 发起主持, 开场简单介绍了龙蜥 ANCK 版本情况及当前基本研发流程.
+
+
+* 自由讨论中, 谢仲天提出如何尽快参与到内核社区共建的问题. 讨论认为,
+
+
+* + 1) 主动参与: 可通过向社区贡献开源特性参与社区内核研发; 可通过积极关注 kernel-sig bug 管理平台, 积极承担特性/bug 研发任务来参与;
+ + 2) 被动参考: 确定统一接口人, 由社区统一分派研发任务.
+
+
+* + 总之社区是极其开放的, 欢迎大家积极参与其中.
+
+
+* 卢彦表示关注内核性能测试相关 benchmark 评价与测试验收标准
+
+
+* + 阿里云在这一块有多年积累, 一些成熟经验计划在社区推广;
+ + 这块建议放到社区相应的 [QA Sig](https://openanolis.cn/sig/QA) 进一步深入交流.
+
+
+* 李雪峰介绍了龙芯内核同源异构相关进展:
+
+
+* + 表示龙芯内部已经有相关计划;
+ + 因这块工作量较大, 涉及内核及工具链; 且与架构相关的bug 一般难度较大.
+ + 龙芯内部还需要进一步讨论, 以确定排期等相关事项.
+
+
+* + 会上讨论认为这块可以在龙芯 sig 里进一步对齐.
+ + 当前ANCK 已经推出5.10内核, 希望能在这个内核尽快做起来.
+
+
+* 最后大家讨论了 kernel-sig 双周会的相关问题:
+
+
+* + 目前暂定双周会固定时间为第一周周三下午3:00-5:00; 下一次双周会时间 2021.11.17 15:00-17:00;
+ + 疫情期间以线上会议为主, 待国家放开后考虑线下会议;
+
+
+* + 会上头脑风暴了双周会话题:
+
+
+* + - 双周会会有一些例行事项: 1) kernel-sig 双周大事回顾; 2) kernel-sig 相关事项决策等等;
+ - 客户现场案例分享相关: 如在真实客户现场遇到的问题, 解决方案, 经验等分享交流;
+
+
+* + - 内核子系统相关: 如内核子系统相关新特性技术分享, 实例业务应用案例等;
+ - 内核相关业界软硬技术热点研讨: 如 eBPF 应用等等;
+
+
+* + - 客户解决方案相关话题: 如1)客户具体案例分享; 2) 应用软件生态适配相关话题;
+ - ANCK 内核历史经典问题,案例分享;
+
+
+* + - 软硬件协同, 跨平台支持技术等;
+ - 内核相关系列技术讲座;
+
+
+* + - 会上大家提议后面可以发起 ACK (Anolis Cloud Kernel 开发者大会); 待国内疫情放开后, 可以考虑先搞起线下 meetup.
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\344\273\243\347\240\201\345\244\247\351\241\265-mysql\346\200\247\350\203\275\346\265\213\350\257\225.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\344\273\243\347\240\201\345\244\247\351\241\265-mysql\346\200\247\350\203\275\346\265\213\350\257\225.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\344\273\243\347\240\201\345\244\247\351\241\265-mysql\346\200\247\350\203\275\346\265\213\350\257\225.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\351\276\231\350\234\245\345\206\205\346\240\270\347\232\204_Load_Averages_\345\211\226\346\236\220(\344\270\212).md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\351\276\231\350\234\245\345\206\205\346\240\270\347\232\204_Load_Averages_\345\211\226\346\236\220(\344\270\212).md"
new file mode 100644
index 0000000000000000000000000000000000000000..68caa548fbe3da879182beb14461ad4b49d4953e
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\351\276\231\350\234\245\345\206\205\346\240\270\347\232\204_Load_Averages_\345\211\226\346\236\220(\344\270\212).md"
@@ -0,0 +1,4 @@
+/img1.jpeg)
+
+点击[这里](https://www.bilibili.com/video/BV1R34y197Lw/)参看.
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\351\276\231\350\234\245\345\206\205\346\240\270\347\232\204_Load_Averages_\345\211\226\346\236\220(\344\270\213).md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\351\276\231\350\234\245\345\206\205\346\240\270\347\232\204_Load_Averages_\345\211\226\346\236\220(\344\270\213).md"
new file mode 100644
index 0000000000000000000000000000000000000000..e68954407328329fce3f3769179cae89ffbd8b1f
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\351\276\231\350\234\245\345\206\205\346\240\270\347\232\204_Load_Averages_\345\211\226\346\236\220(\344\270\213).md"
@@ -0,0 +1,4 @@
+/img1.jpeg)
+
+视频回放正在准备中, 敬请期待...
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2021.11.01~2021.11.14.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2021.11.01~2021.11.14.md"
new file mode 100644
index 0000000000000000000000000000000000000000..8836ff2b507693190017a459eb94c992dad7b341
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2021.11.01~2021.11.14.md"
@@ -0,0 +1,81 @@
+### 会议主题
+
+
+首次非正式会议, 自由讨论的形式, 聊聊龙蜥内核版本计划, 研发流程及后续双周会主题等
+
+
+### 会议时间
+
+
+2021.11.03 15:00-17:00
+
+
+### 与会人
+
+
+* 会议主持: Shiloong
+* 来自统信,龙芯, 阿里云的龙蜥社区爱好者
+
+
+### 会议纪要
+
+
+* 会议由 Shioong 发起主持, 开场简单介绍了龙蜥 ANCK 版本情况及当前基本研发流程.
+
+
+* 自由讨论中, 谢仲天提出如何尽快参与到内核社区共建的问题. 讨论认为,
+
+
+* + 1) 主动参与: 可通过向社区贡献开源特性参与社区内核研发; 可通过积极关注 kernel-sig bug 管理平台, 积极承担特性/bug 研发任务来参与;
+ + 2) 被动参考: 确定统一接口人, 由社区统一分派研发任务.
+
+
+* + 总之社区是极其开放的, 欢迎大家积极参与其中.
+
+
+* 卢彦表示关注内核性能测试相关 benchmark 评价与测试验收标准
+
+
+* + 阿里云在这一块有多年积累, 一些成熟经验计划在社区推广;
+ + 这块建议放到社区相应的 [QA Sig](https://openanolis.cn/sig/QA) 进一步深入交流.
+
+
+* 李雪峰介绍了龙芯内核同源异构相关进展:
+
+
+* + 表示龙芯内部已经有相关计划;
+ + 因这块工作量较大, 涉及内核及工具链; 且与架构相关的bug 一般难度较大.
+ + 龙芯内部还需要进一步讨论, 以确定排期等相关事项.
+
+
+* + 会上讨论认为这块可以在龙芯 sig 里进一步对齐.
+ + 当前ANCK 已经推出5.10内核, 希望能在这个内核尽快做起来.
+
+
+* 最后大家讨论了 kernel-sig 双周会的相关问题:
+
+
+* + 目前暂定双周会固定时间为第一周周三下午3:00-5:00; 下一次双周会时间 2021.11.17 15:00-17:00;
+ + 疫情期间以线上会议为主, 待国家放开后考虑线下会议;
+
+
+* + 会上头脑风暴了双周会话题:
+
+
+* + - 双周会会有一些例行事项: 1) kernel-sig 双周大事回顾; 2) kernel-sig 相关事项决策等等;
+ - 客户现场案例分享相关: 如在真实客户现场遇到的问题, 解决方案, 经验等分享交流;
+
+
+* + - 内核子系统相关: 如内核子系统相关新特性技术分享, 实例业务应用案例等;
+ - 内核相关业界软硬技术热点研讨: 如 eBPF 应用等等;
+
+
+* + - 客户解决方案相关话题: 如1)客户具体案例分享; 2) 应用软件生态适配相关话题;
+ - ANCK 内核历史经典问题,案例分享;
+
+
+* + - 软硬件协同, 跨平台支持技术等;
+ - 内核相关系列技术讲座;
+
+
+* + - 会上大家提议后面可以发起 ACK (Anolis Cloud Kernel 开发者大会); 待国内疫情放开后, 可以考虑先搞起线下 meetup.
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2021.11.15~2021.11.28.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2021.11.15~2021.11.28.md"
new file mode 100644
index 0000000000000000000000000000000000000000..c7c29a7bfe95059ba72fcf5fcd937c03c820ac6c
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2021.11.15~2021.11.28.md"
@@ -0,0 +1,52 @@
+## 会议主题
+
+
+技术分享:<龙蜥内核 load average 剖析(上)>及龙蜥内核自由讨论
+
+
+## 会议时间
+
+
+2021.11.17 15:00-17:00
+
+
+## 与会人
+
+
+会议主持: Shiloong
+
+
+技术分享人: xunlei
+
+
+参与人: 龙蜥社区
+
+
+## 会议纪要
+
+
+* 会议前1小时庞训磊带来了精彩的技术分享<龙蜥内核 load averages 剖析> 上半部分直播;
+
+
++ 感兴趣的社区爱好者可以到[这里](https://openanolis.cn/video/440158297192218780)(https://openanolis.cn/video/440158297192218780)观看回放.
+
+
+* 直播结束后, 大家就分享的内容及龙蜥内核相关话题自由讨论; 大家对这次技术分享反馈相当不错, 并积极互动讨论.
+
+
++ 社区爱好者陈国斌(音)提出希望技术分享能增加一些实操性的演示; 这部分会在下次分享中安排;
++ 社区爱好者耕深提到是否能搞几次虚拟化相关的技术分享; 这部分后续可以与龙蜥社区的"虚拟化 SIG"组合作推出. 也欢迎大家积极参加龙蜥社区共建中来;
+
+
++ 有社区爱好者提到对调度器及其优化感兴趣, 希望能安排分享龙蜥内核在调度器相关的优化; 这个后面会考虑安排;
++ 有社区爱好者对 eBPF 技术落地龙蜥内核感兴趣, 希望能有相关分享; 龙蜥内核在 eBPF 邻域是有一些创新与积累的, 后面计划安排;
+
+
+* 自由讨论时, 统信参与龙蜥 kernel-sig 研发的同学反馈目前的 Bug Tracker 状态更新不及时, 造成有些信息不对称.
+
+
++ 这个情况基本属实, 目前正在改进中, 后续会把 kernel-sig 相关的 bug 管理迁移至新的平台. 届时也会加强 bug 管理.
+
+
+感谢庞训磊为大家带来精彩讲解, 也感谢芹菜,邢秀帮忙筹划本次技术分享!
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2021.11.29~2021.12.12.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2021.11.29~2021.12.12.md"
new file mode 100644
index 0000000000000000000000000000000000000000..cc693bec33f50f25d178039e043baf9dabbf3c13
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2021.11.29~2021.12.12.md"
@@ -0,0 +1,21 @@
+## 会议主题
+技术分享:及龙蜥内核动态更新
+
+## 会议时间
+2021.12.1 15:00-17:00
+
+## 与会人
+会议主持: Shiloong
+技术分享人: Xunlei
+参与人: 龙蜥社区
+
+## 会议纪要
++ 前半段直播技术分享, 感谢庞训磊为大家带来精彩讲解, 感兴趣或错过的, 可以到观看[回放](https://www.bilibili.com/video/BV1R34y197Lw/).
++ 会议传达了龙蜥内核 cloud-kernel 基础设施迁移的最新情况:
+ + 代码托管平台已经迁移至Gitee: https://gitee.com/anolis/cloud-kernel;
+ + 缺陷与需求管理平台已经迁移到 Bugzilla: https://bugzilla.openanolis.cn;
+ + 相关的开发流程也已经更新;
++ 会议传达了最新龙蜥内核版本发布情况:
+ + ANCK-4.19 内核发布最新版本4.19.91-25, 已经同步到 yum 源支持更新安装;
+ + ANCK-5.10 内核最新版本研发中, 预计2022.1.17发布.
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2021.12.13~2021.12.26.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2021.12.13~2021.12.26.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e1ef7d82d40c50f34644b9c91acf1c1f25539500
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2021.12.13~2021.12.26.md"
@@ -0,0 +1,16 @@
+## 会议主题
++ 龙蜥内核新研发流程讲解
++ 龙蜥内核 kernel-sig 自由讨论
+## 会议时间
+2021.12.15 15:00-17:00
+## 与会人
++ 会议主持: Shiloong
++ 参与人: 龙蜥社区kernel-SIG
+## 会议记要
+1. 龙蜥内核新研发流程讲解.
+2. 龙蜥社区 kernel-sig 补丁规范答疑: 对首次通过龙蜥社区公开的补丁, 需要加上 anolis 标签, 以龙蜥自研补丁发布;
+3. 龙蜥内核社区公开征召技术分享, 以增加社区技术分享活跃度;
+4. 前期推广以技术分享为主, 后面增加技术 workshop, 技术讨论等形式, 丰富 kernel-sig 的技术研讨及新技术孵化.
+5. 鼓励更多内核相关的理事单位参加双周会.
+6. kernel-sig 技术分享主题征集.
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.01.10~2022.01.23.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.01.10~2022.01.23.md"
new file mode 100644
index 0000000000000000000000000000000000000000..3e4c0e6b49e9f47a71447d482a8a0baaf12fbb3d
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.01.10~2022.01.23.md"
@@ -0,0 +1,16 @@
+本期双周会为技术分享
+
+## 分享主题
+系统性能监控工具ssar使用介绍和案例分享
+
+## 直播内容
+ssar整机指标功能使用介绍,ssar进程级指标使用介绍,ssar的load特色指标使用介绍。ssar解决单机生产问题案例剖析。[直播回放](https://www.bilibili.com/video/BV19S4y157Xa?spm\_id\_from=333.999.0.0)
+## 听众收益
+了解ssar的基本功能和使用,初步学习用ssar解决单机OS问题的诊断。
+## 适合人群
+系统运维工程师、linux系统编程工程师、内核爱好者。
+## 讲师头衔
+闻茂泉(广成)龙蜥社区跟踪诊断SIG核心成员,阿里云运维专家。
+## 讲师介绍
+负责阿里云计算平台事业部的基础运维相关工作,目前是龙蜥社区ssar和iodump开源诊断工具的maintainer。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.03.07~2022.03.20.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.03.07~2022.03.20.md"
new file mode 100644
index 0000000000000000000000000000000000000000..534454b3eb62499e70db0418097ff860f30d6344
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.03.07~2022.03.20.md"
@@ -0,0 +1,4 @@
+本期技术分享《datop -- 轻量级靶向内存热点扫描工具介绍与入门》
+
+欢迎到 OpenAnolis Kernel SIG 钉群收看直播回放。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.03.21~2022.04.03.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.03.21~2022.04.03.md"
new file mode 100644
index 0000000000000000000000000000000000000000..976065ee9a2c3643867e712bb7b830f724c5dc46
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.03.21~2022.04.03.md"
@@ -0,0 +1,7 @@
+本期技术分享
+1. 《通过sealer实现整个集群Build&Share&Run》
+
+2. 《硬件兼容性 SIG 分享》
+
+欢迎到 OpenAnolis Kernel SIG 钉群收看直播回放。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.04.04~2022.04.17.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.04.04~2022.04.17.md"
new file mode 100644
index 0000000000000000000000000000000000000000..b7d2cce980ecfc4378940c4469cd2e24d7866014
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.04.04~2022.04.17.md"
@@ -0,0 +1,4 @@
+本期技术分享《内核内存被改和内存泄漏难题的线上解决方案》
+
+欢迎到 OpenAnolis Kernel SIG 钉群收看直播回放。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.04.18~2022.05.01.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.04.18~2022.05.01.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.07.20~2022.08.03.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.07.20~2022.08.03.md"
new file mode 100644
index 0000000000000000000000000000000000000000..b07d6e40219c62e1766ac42a351f41f0651a458d
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.07.20~2022.08.03.md"
@@ -0,0 +1,4 @@
+与会人: 卢彦 道引 落盘 子札
+
+主题:讨论了ANCK-5.10对ARMv9的支持情况,以及ANCK-5.10的分支管理和版本发布计划。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.08.04~2022.08.24.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.08.04~2022.08.24.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e4cd765f488d13c958d7efc53af68663d1da7ab4
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.08.04~2022.08.24.md"
@@ -0,0 +1,4 @@
+与会人:卢彦 王晓华 道引 落盘 行信 王帅
+
+主题:分享了ARMv9 MPAM的龙蜥内核方案,基于/sys/fs/resctrl/实现的LLC和MB的隔离方案,并做了实际案例分享和效果演示。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.08.25~2022.09.07.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.08.25~2022.09.07.md"
new file mode 100644
index 0000000000000000000000000000000000000000..fc4abb36858a52fae2da85021d9ff7db045af4ba
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.08.25~2022.09.07.md"
@@ -0,0 +1,18 @@
+与会人:卢彦 王晓华 道引 落盘 要麻 半叶
+
+主题:
+
+1)要麻分享了ARM64 RAS的龙蜥内核方案,并做了实际案例分享和测试用例建议。
+ - RAS错误处理流程
+
+ UE non fatal类型错误是不可纠正但可恢复的错误,例如出现错误的内存存储的非内核使用的数据结构,后续不再使用对应内存即可,或者是非关键数据在cache中,将对应cache内容丢弃即可,都不会也不必要导致crash。
+ - RAS错误注入流程
+ https://gitee.com/anolis/ras-tools 可用于错误注入的工具
+ - Rasdaemon工具解读日志方法
+
+2)半叶对OS Noise背景噪声检测机制及检测工具进行介绍
+ - ANCK 5.10 支持该功能,在进行benchmark跑分时可以先提前检测包括中断、软中断、NMI、硬件自身 干扰、其他任务干扰等噪声,避免噪声对benchmark跑分结果的准确性造成干扰
+ - OS Noise的trace机制在正常的生产环境中部署会有一定开销,可以使用用户态的检测工具(无法统 计硬件噪声),该工具开销低,可用于生产部署。同时,使用该工具对调度指标进行监控可分析
+ benchmark运行行为,排查干扰运行的因素。
+ - 硬件噪声主要包括会陷入BIOS的硬件中断,在新机型验证方面比较有用。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.09.08~2022.09.21.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.09.08~2022.09.21.md"
new file mode 100644
index 0000000000000000000000000000000000000000..2c04b50983c970d96b7dab2533807ce4b46d5a56
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.09.08~2022.09.21.md"
@@ -0,0 +1,12 @@
+与会人:卢彦 、焦芬芳、王毅博、苟浩、道引、行信、半叶、谷米、落盘
+
+主题:
+- datop工具介绍
+ - ANCK 5.10 已支持该功能,分析内存冷热和跨numa访问,工具开销低,可常态化部署
+ - 工具地址 https://gitee.com/anolis/data-profile-tools
+ - 跨numa访问统计准确性
+ 工具通过仿真统计跨numa访问,存在一定的定量误差,但是不存在定性误差
+- ancert-m工具介绍和演示
+- APP Noise用户态工具演示
+- 介绍了kdump可调可测能力的研发。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.09.22~2022.10.12.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.09.22~2022.10.12.md"
new file mode 100644
index 0000000000000000000000000000000000000000..648b6616934ffefaaa46b60836267aea0d2efec0
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.09.22~2022.10.12.md"
@@ -0,0 +1,11 @@
+# 与会人
+卢彦、焦芬芳、咸正、彧斌、云里、道引、落盘
+
+
+# 主题
+ARM64 PMU相关内容介绍,对ARM64 PMU进行了讲解,PMU从机制都进行了覆盖,并就perf使用问题,以及发生任务迁移时的场景进行了互动交流。
+- PMU的基本原理
+- ARM64 SPE 功能介绍
+- perf相关功能介绍
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.10.13~2022.10.26.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.10.13~2022.10.26.md"
new file mode 100644
index 0000000000000000000000000000000000000000..8f5f78b1a082d09c2c065216b929156cef3e05b6
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/2022.10.13~2022.10.26.md"
@@ -0,0 +1,9 @@
+# 与会人
+卢彦、焦芬芳、苟浩、道引、落盘
+
+
+# 主题
+- 交流了ARM baseos部分需要关注的包。
+- ras-tools是基于APEI的通用工具,服务器需要更新配套的BIOS版本才能使用。
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/\346\234\210\346\212\245\350\257\264\346\230\216.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/\346\234\210\346\212\245\350\257\264\346\230\216.md"
new file mode 100644
index 0000000000000000000000000000000000000000..30020428d41c0b35e0eb225c6a3b4a4a06f385a6
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\344\274\232/\346\234\210\346\212\245\350\257\264\346\230\216.md"
@@ -0,0 +1,7 @@
+- 每月的月初总结发出上月的报告,并更新到 SIG 页面,如 2022.12
+
+- 月报包含内容:
+ + 整体进展:SIG 该月的亮点特性汇总。
+ + 具体进展:SIG 该月项目的详细进展,分别展开细节。
+ + 重要议题: SIG 该月讨论的重要议题。
+ + 运营活动: SIG 该月发生的运营活动。
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\346\212\245/2021.10.18~2021.10.31.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\346\212\245/2021.10.18~2021.10.31.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ff1cb9a0546b95d630b6512bab635c0b33774ed2
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\346\212\245/2021.10.18~2021.10.31.md"
@@ -0,0 +1,27 @@
+
+**内核研发**
+
+
+* ANCK-4.19 CK25 代码本周(11.30)冻结, 新特性需求研发代码基本完成合入, 主要特性:
+
+
++ 支持商密特性更新及 bugfix;
++ 支持代码段大页优化;
+
+
++ 支持 SM2/SM3加密算法组合签名;
++ fs/buffer 性能优化;
+
+
++ 支持内核 SM4算法的 AVX/AVX2指令集优化;
+
+
+* ANCK-5.10 下一个版本开发中, 预计11.30代码冻结, 12.30日发布;
+
+
+**SIG运作**
+
+
+* 讨论决定下周三(暂定11.3下午3:00-5:00)召开第一次 kernel-sig 双周会, 主题暂定为;
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\346\212\245/2021.11.01~2021.11.14.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\346\212\245/2021.11.01~2021.11.14.md"
new file mode 100644
index 0000000000000000000000000000000000000000..b024c157bcbd7852404b4388babf1113afa979ae
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\346\212\245/2021.11.01~2021.11.14.md"
@@ -0,0 +1,14 @@
+**内核研发**
+
+
+* ANCK-4.19 下一个版本 4.19.91-25 rc1 已经开始发布测试;
+
+
+* ANCK-5.10 下一个版本开发路线图有调整, 代码冻结时间调整为2021.12.10, 发布日期调整为 2022.1.17;
+
+
+**SIG运作**
+
+
+* 顺利招开了龙蜥社区 kernel-SIG 第一期双周会, 统信, 龙芯及阿里云社区爱好者在一起自由畅谈龙蜥内核发展, 头脑风暴了内核相关的技术话题, 为后续双周会技术分享做准备.
+ + 详细周会纪要请参看[这里](https://openanolis.cn/sig/Cloud-Kernel/doc/426213132286165112).
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\346\212\245/2021.11.15~2021.11.28.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\346\212\245/2021.11.15~2021.11.28.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\346\212\245/2021.11.29~2021.12.12.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\346\212\245/2021.11.29~2021.12.12.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\346\212\245/2021.12.13~2021.12.26.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\346\212\245/2021.12.13~2021.12.26.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\346\212\245/2021.12.27~2022.1.9.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\346\212\245/2021.12.27~2022.1.9.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\346\212\245/2022.1.10~2022.1.23.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\346\212\245/2022.1.10~2022.1.23.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\346\212\245/2022.1.24~2022.2.6.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\217\214\345\221\250\346\212\245/2022.1.24~2022.2.6.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\346\211\213\345\206\214/ToneAgent\347\274\226\350\257\221\346\211\223\345\214\205\346\211\213\345\206\214.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\346\211\213\345\206\214/ToneAgent\347\274\226\350\257\221\346\211\223\345\214\205\346\211\213\345\206\214.md"
new file mode 100644
index 0000000000000000000000000000000000000000..0949b8e70e5300f1cf752ca0259c1d30317b932b
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\346\211\213\345\206\214/ToneAgent\347\274\226\350\257\221\346\211\223\345\214\205\346\211\213\345\206\214.md"
@@ -0,0 +1,63 @@
+# 1. ToneAgent编译
+
+## 1.1 环境准备
+Go 1.17 及以上版本([下载地址](https://go.dev/dl/))
+
+## 1.2 下载ToneAgent
+ git clone git@gitee.com:anolis/tone-agent.git
+ cd tone-agent
+
+## 1.3 编译
+`-o` 后面是二进制的名称
+
+### 1.3.1 编译 AMD64的二进制
+ GOOS=linux GOARCH=amd64 go build -o toneagent-amd64-v102
+
+### 1.3.2 编译 ARM 的二进制
+ GOOS=linux GOARCH=arm64 go build -o toneagent-amd64-v102
+
+# 2. Linux环境二进制打包
+
+## 2.1 RPM包制作
+
+### 2.1.1 RPM环境准备
+ sudo su -c bash # 使用bash
+ yum install rpmdevtools rpmdevtools # 安装rpm打包工具
+
+### 2.1.2 打包RPM包
+ rpmdev-setuptree # 创建目录,会在用户目录下创建rpmbuild文件夹 ~/rpmbuild
+ cd # 返回用户目录
+ vi rpmbuild/SPEC/toneagent.spec # 修改创建spec的模板文件
+ mkdir rpmbuild/BUILDROOT/toneagent-0.0.1-AMD
+ cp ${二进制路径} rpmbuild/BUILDROOT/toneagent-0.0.1-AMD/ # 拷贝二进制到RPM目录
+ cd rpmbuild/SPEC/
+ rpmbuild -bb toneagent.spec # 构建rpm包
+
+### 2.1.3 RPM安装及启动
+ sudo yum -y install ${toneagent包位置} # 安装
+ sudo systemctl start toneagent # 启动
+
+## 2.2 DEB包制作
+
+### 2.1.1 环境准备
+ sudo apt instsll -y dpkg # 使用二进制打包,只需要安装这个包
+ sudo apt install -y dpkg build-essential devscripts quilt dh-make git # 扩展安装
+
+### 2.1.2 打包DEB包
+ mkdir toneagent.work
+ cd toneagent.work
+ mkdir -pv toneagent_0.0.1_amd64/{DEBIAN,bin}
+ cp ${tone-agent二进制} toneagent_0.0.1_amd64/bin/
+ echo "Package: toneagent
+ Version: 1.0
+ Architecture: arm
+ Maintainer: alibaba
+ Installed-Size: 100
+ Depends:
+ Priority: optional
+ Description: toneagent for SUNXI devices (A10,A20 ...),example is Cubieboard.
+ " >> toneagent_0.0.1_amd64/DEBIAN/control
+ dpkg -b toneagent_0.0.1_amd64 toneagent_0.0.1_amd64.deb
+
+### 2.1.3 DEB安装
+ dpkg -i toneagent_0.0.1_amd64.deb
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\346\211\213\345\206\214/aest.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\346\211\213\345\206\214/aest.md"
new file mode 100644
index 0000000000000000000000000000000000000000..9dca95d406a94bcd351308487dead32fe19c01a1
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\346\211\213\345\206\214/aest.md"
@@ -0,0 +1,16 @@
+HCT密码计算套件的目录结构如下:
+阿斯顿法师打发斯蒂芬
+44444444444444444444444444444444444444444444444444444
+hygon-devkit/
+
+ ├─ hct
+ ├──pkg
+ │ ├── hct_1.0.0.20230224_rc
+ │ ├── hct_1.0.1.20230512_rc
+ │ └── hct_1.1.0.20230730_rc
+ │
+ └── README.md
+
+\* pkg目录:内含各版本hct密码计算套件。
+
+\* README.md文件:有关HCT的简单情况。
\ No newline at end of file
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\346\211\213\345\206\214/test.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\346\211\213\345\206\214/test.md"
new file mode 100644
index 0000000000000000000000000000000000000000..9dca95d406a94bcd351308487dead32fe19c01a1
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\346\211\213\345\206\214/test.md"
@@ -0,0 +1,16 @@
+HCT密码计算套件的目录结构如下:
+阿斯顿法师打发斯蒂芬
+44444444444444444444444444444444444444444444444444444
+hygon-devkit/
+
+ ├─ hct
+ ├──pkg
+ │ ├── hct_1.0.0.20230224_rc
+ │ ├── hct_1.0.1.20230512_rc
+ │ └── hct_1.1.0.20230730_rc
+ │
+ └── README.md
+
+\* pkg目录:内含各版本hct密码计算套件。
+
+\* README.md文件:有关HCT的简单情况。
\ No newline at end of file
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\346\211\213\345\206\214/test2.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\346\211\213\345\206\214/test2.md"
new file mode 100644
index 0000000000000000000000000000000000000000..9dca95d406a94bcd351308487dead32fe19c01a1
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\346\211\213\345\206\214/test2.md"
@@ -0,0 +1,16 @@
+HCT密码计算套件的目录结构如下:
+阿斯顿法师打发斯蒂芬
+44444444444444444444444444444444444444444444444444444
+hygon-devkit/
+
+ ├─ hct
+ ├──pkg
+ │ ├── hct_1.0.0.20230224_rc
+ │ ├── hct_1.0.1.20230512_rc
+ │ └── hct_1.1.0.20230730_rc
+ │
+ └── README.md
+
+\* pkg目录:内含各版本hct密码计算套件。
+
+\* README.md文件:有关HCT的简单情况。
\ No newline at end of file
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\346\211\213\345\206\214/\345\257\271\345\244\226\346\234\215\345\212\241API.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\346\211\213\345\206\214/\345\257\271\345\244\226\346\234\215\345\212\241API.md"
new file mode 100644
index 0000000000000000000000000000000000000000..6be2fe13cbb6e50e1bf41c425b239231eda209e8
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\346\211\213\345\206\214/\345\257\271\345\244\226\346\234\215\345\212\241API.md"
@@ -0,0 +1 @@
+参考文档:https://tone.openanolis.cn/help_doc/7
\ No newline at end of file
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\346\211\213\345\206\214/\346\265\213\350\257\225\345\245\227\344\273\266\351\233\206\346\210\220\346\211\213\345\206\214.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\346\211\213\345\206\214/\346\265\213\350\257\225\345\245\227\344\273\266\351\233\206\346\210\220\346\211\213\345\206\214.md"
new file mode 100644
index 0000000000000000000000000000000000000000..67b07c6d8e8470eef075cf75048ba3f4036edeaa
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\346\211\213\345\206\214/\346\265\213\350\257\225\345\245\227\344\273\266\351\233\206\346\210\220\346\211\213\345\206\214.md"
@@ -0,0 +1,282 @@
+# tone-cli介绍
+tone-cli主要用于测试套件(testsuite)的调度及运行。
+
+# 代码仓库
+https://gitee.com/anolis/tone-cli
+
+# 测试套件构成
+测试套件主要由套件本身和集成脚本构成,其中:
+
+- 测试套件可以存放于gitee或其他代码仓库,也可以是一个系统中已经包含的命令
+- 集成脚本由两部分构成:
+ - 适配脚本
+ - 测试套配置文件
+
+# 测试套件集成
+
+## 测试配置文件
+测试配置文件位于`$TONE_ROOT/conf`目录下,与适配脚本一起为测试套件服务。
+
+为了便于组织,当前根据测试类别分为`functional`,`performance`和`stress`。
+
+测试配置文件主要用于描述测试的参数,以netperf为例:
+
+ test IP runtime send_size
+ TCP_RR ipv4 60s Na
+ TCP_RR ipv4 60s 16K
+ TCP_CC ipv4 60s Na
+ TCP_CRR ipv4 60s Na
+ ...
+
+第一行描述为变量名,后续行描述的是变量的值。tone-cli会将测试套配置文件按照配置进行执行:
+
+ $ tone list netperf
+ test IP runtime send_size testconf
+ TCP_RR ipv4 60 None netperf:test=TCP_RR,IP=ipv4,runtime=60s
+ TCP_RR ipv4 60 16K netperf:test=TCP_RR,IP=ipv4,runtime=60s,send_size=16K
+ TCP_CC ipv4 60 None netperf:test=TCP_CC,IP=ipv4,runtime=60s
+ TCP_CRR ipv4 60 None netperf:test=TCP_CRR,IP=ipv4,runtime=60s
+在后续的脚本中,conf中的变量会以参数形式传递给适配脚本。
+
+> 注:
+>
+> - 没有任何变量的测试套,仍然需要创建对应名称的配置文件,保持内容为空
+> - 对于某个参数,如netperf的send_size,在某些状况下不需要传入参数,则可以置为NA
+
+## 适配脚本
+
+测试套件适配脚本需要存放于`$TONE_ROOT/tests`目录下,创建工具对应的目录,如`$TONE_ROOT/tests/netperf`。
+
+tone-cli将测试定义为以下几个阶段,可以根据需要来决定是否需要对应的阶段:
+
+- 测试套件获取
+- 测试套件编译安装
+- 测试执行
+- 结果处理
+- 测试套件卸载
+
+适配脚本需要最少包含`install.sh`,`run.sh`和`README.md`,其中:
+
+- install.sh: 定义测试套件获取、依赖包、测试套件编译及安装
+- run.sh: 定义测试执行过程,结果处理方式
+- README.md: 测试套件必要说明
+
+其他脚本可以根据需要决定,如:将结果处理脚本单独编写,在run.sh中加以引用
+
+### 测试套件获取
+
+当前支持通过URL下载或git方式获取对应的测试套:
+
+| 方式| 参数 | 说明 |举例 |
+| :--:| :---: | :---: |:---: |
+|URL下载 |WEB_URL |测试套下载地址 |WEB_URL=“https://gitee.com/anolis/tone-cli/repository/archive/master.zip”|
+|GIT仓库 |GIT_URL |git仓库地址 |GIT_URL="https://gitee.com/mirrors_HewlettPackard/netperf.git"|
+| |BRANCH |git分支| BRANCH="netperf-2.7.0"|
+
+tone-cli将根据提供的`WEB_URL`,`GIT_URL`,`BRANCH`等信息拉取对应的源代码
+
+### 举例:
+
+`netperf/install.sh`
+
+ GIT_URL="https://gitee.com/mirrors_HewlettPackard/netperf.git"
+ BRANCH="netperf-2.7.0"
+
+### 测试套件编译安装
+
+tone-cli提供的标准安装方式由以下几步:
+
+- 执行安装前额外的操作:extract_src
+- 安装依赖包:install_pkg
+- 编译:build
+- 安装:install
+
+**extract_src**
+
+用于在安装依赖包之前进行必要的准备,如centos安装epel源:
+
+ extract_src()
+ {
+ logger yum install -y epel-release
+ }
+
+**install_pkg**
+
+绝大部分状况下,不需要重写install_pkg的方法,而仅通过设置DEP_PKG_LIST的变量,tone-cli将自动进行依赖包安装。如netperf/install.sh:
+
+ DEP_PKG_LIST="automake gcc texinfo"
+
+**build和install**
+
+通常状况,build和install都需要根据测试套件进行重写。以netperf为例:
+
+ build()
+ {
+ local configure_flags=(
+ --prefix="$TONE_BM_RUN_DIR"
+ )
+ if [ "$(/usr/bin/arch)" = aarch64 ]; then
+ configure_flags+=('--build=aarch64-unknown-linux-gnu')
+ fi
+
+ export CFLAGS="-fno-strict-aliasing -fcommon"
+
+ ./autogen.sh
+ ./configure "${configure_flags[@]}"
+ make
+ }
+
+ install()
+ {
+ make install-exec
+ }
+### 测试执行
+
+测试执行被定义在`run.sh`中,主要的步骤有:
+
+- 测试准备:setup
+- 测试执行:run
+- 测试拆除:teardown
+
+以netperf为例,netperf测试可以划分为:
+
+- 启动netserver
+- 使用netperf命令进行测试
+- 拆除netserver
+
+**setup**
+
+netperf测试中,netserver启动主要逻辑为:
+
+- 判断是否设置了$SERVER,如果已设置,则认为netserver将在对应的server上执行
+- 启动netserver,启动netserver的主要逻辑在netserver.sh中体现
+
+ setup()
+ {
+ [ -n "$SERVER" ] && server=${SERVER%% *} || server=localhost
+ echo "Run netserver on host: $server"
+
+ if [ "$server" = localhost ]; then
+ source "$TONE_BM_SUITE_DIR"/netserver.sh
+ else
+ ssh $server "TONE_ROOT=$TONE_ROOT TONE_BM_RUN_DIR=$TONE_BM_RUN_DIR IP=$IP server=$server $TONE_BM_SUITE_DIR/netserver.sh"
+ fi
+ }
+
+**run**
+
+netperf测试套的执行逻辑,主要根据测试套件配置中的参数组合,设置netperf命令行参数以执行测试
+
+> 注:
+>
+> 在执行命令时,使用logger方法将netperf命令行输出写入对应的日志文件中,以备后续进行结果处理
+
+ run()
+ {
+ export PATH="$TONE_BM_RUN_DIR"/bin:$PATH
+
+ [ -n "$send_size" ] && test_options="-- -m $send_size"
+
+ opt_ip=
+ [ "$IP" = 'ipv4' ] && opt_ip='-4'
+ [ "$IP" = 'ipv6' ] && opt_ip='-6'
+ base_cmd="netperf $opt_ip -t $test -c -C -l $runtime -H $server $test_options"
+
+ # check online cpus with cpu_affinity set on multi-processor machine
+ if [ "$server" = localhost ] && [ "$(nproc)" -gt 1 ]; then
+ check_oneline_cpu
+ # the last cpu is reservered for netserver if test on single node
+ cpu_online_num=$((cpu_online_num - 1))
+ cpu_online_tpy=$(echo "$cpu_online_tpy" | awk '{$NF=""; print $0}')
+ cpu_x=$((1 % cpu_online_num))
+ [ "$cpu_x" -eq 0 ] && cpu_x=$cpu_online_num
+ mycpu=$(echo "$cpu_online_tpy" | awk -v n=$cpu_x '{print $n}')
+ test_cmd="taskset -c $(echo "$mycpu" | cut -d- -f3) $base_cmd"
+ echo "run netperf on cpu: $(echo "$mycpu" | cut -d- -f3),"\
+ "socket: $(echo "$mycpu" | cut -d- -f1),"\
+ "core_id: $(echo "$mycpu" | cut -d- -f2)"
+ else
+ test_cmd="$base_cmd"
+ fi
+
+ logger $test_cmd &
+ logger wait
+ }
+
+**teardown**
+
+netperf的teardown阶段,主要通过执行pkill命令杀死netserver进程
+
+ teardown()
+ {
+ pkill netserver
+ }
+
+**结果处理**
+tone-cli当前规定的结果规范为`key: value`,所以只要符合这个输出规范,对应的结果会被收集并存储。
+
+以netperf为例,其结果处理的`parse()`调用了一个awk脚本:
+
+ #!/usr/bin/awk -f
+
+ /^Size.*Okay.*Throughput.*Demand$/ {
+ unit = "Mbps1"
+ next
+ }
+
+ /^Size.*Throughput.*remote$/ {
+ unit = "Mbps2"
+ next
+ }
+
+ /^bytes.*secs.\s+per sec/ {
+ unit = "tps"
+ next
+ }
+
+ $8 && $0 ~ /^[ \t0-9.]+$/ {
+ if ( unit == "Mbps1" ) {
+ printf("Throughput_Mbps: %s\n",$(NF-2))
+ }
+ else if ( unit == "Mbps2" ) {
+ printf("Throughput_Mbps: %s\n",$5)
+ }
+ else{
+ printf("Throughput_%s: %s\n",unit,$6)
+ }
+ }
+
+执行完毕后会输出:
+
+ Throughput_tps: 91336.30
+
+# 公共变量
+tone-cli提供了多个公共变量用于在测试集成时使用
+
+## 测试套配置文件
+
+|变量名称| 用途| 举例|
+|:--:|:--:|:--:|
+|nr_task |设置使用的线程数,可以使用百分比形式表示,当设置为百分比时,框架会根据当前测试机CPU数量进行计算 |nr_task=1, nr_task=50%|
+|cpu_affinity |设置CPU绑定| cpupin|
+
+## 测试套适配脚本
+
+|变量名称| 用途| 举例|
+|:--:|:--:|:--:|
+|$TONE_BM_CACHE_DIR |测试套件cache目录| /tmp/tone/cache/netperf|
+|$TONE_BM_BUILD_DIR| 测试套件build目录| /tmp/tone/build/netperf|
+|$TONE_BM_RUN_DIR |测试套件run目录,可以将测试套件安装于该目录中,而不用安装到系统目录下| /tmp/tone/run/netperf|
+|$TONE_BM_RESULT_DIR |测试套件结果存放目录 |/tmp/tone/result/netperf|
+|$TONE_CURRENT_RESULT_DIR |当次运行时的结果存放目录| /tmp/tone/result/netperf/1|
+|$TONE_BM_SUITE_DIR |测试套件脚本目录| /tmp/tone/tests/netperf|
+
+# 公共函数
+
+tone-cli提供一些公共函数已方便脚本编写,公共函数主要归档于$TONE_ROOT/lib目录下,在编写脚本时可以按需引入。常用的函数有:
+
+|函数名| 文件 |用途 |举例|
+|:--:|:--:|:--:|:--:|
+|logger |lib/common.sh |记录日志 |logger netperf -t TCP_RR|
+|set_cpu_affinity_server |lib/cpu_affinity.sh |设置服务端CPU绑核,会将server绑定在最后一个CPU核上,注意,需要通过server_cmd变量进行传递 |server_cmd="netserver" [ -n "$cpu_affinity" ] && set_cpu_affinity_client logger ${server_cmd}|
+|set_cpu_affinity_client |lib/cpu_affinity.sh| 设置客户端CPU绑核,会将client绑定在第一个CPU核上,注意,需要通过client_cmd进行传递 |client_cmd="netperf -t TCP_RR" [ -n "$cpu_affinity" ] && set_cpu_affinity_client logger ${client_cmd}|
\ No newline at end of file
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2200\343\200\221\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227\347\233\256\345\275\225.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2200\343\200\221\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227\347\233\256\345\275\225.md"
new file mode 100644
index 0000000000000000000000000000000000000000..3e65665f4c7d72c4b9533d4b038c361d03adc62c
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2200\343\200\221\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227\347\233\256\345\275\225.md"
@@ -0,0 +1,31 @@
+
+### [【1】Anolis OS环境搭建教程](https://openanolis.cn/sig/Cloud-Kernel/doc/607571974230928479?preview=)
+
+
+### [【2】内核编译安装 - Make方式](https://openanolis.cn/sig/Cloud-Kernel/doc/607587039726485317?preview=)
+
+
+### [【3】内核编译安装 - RPM包方式](https://openanolis.cn/sig/Cloud-Kernel/doc/607593708787100770?preview=)
+
+
+### [【4】Cloud Kernel开发基本流程](https://openanolis.cn/sig/Cloud-Kernel/doc/607596680293474815?preview=)
+
+
+### [【4-1】向Cloud Kernel报告BUG](https://openanolis.cn/sig/Cloud-Kernel/doc/607601736106142822?preview=)
+
+
+### [【4-2】Cloud Kernel补丁规范](https://openanolis.cn/sig/Cloud-Kernel/doc/607603338330374166?preview=)
+
+
+### [【4-3】PR(Pull Request)规范](https://openanolis.cn/sig/Cloud-Kernel/doc/607605992881480196?preview=)
+
+
+### [【5】向Cloud Kernel报告CVE](https://openanolis.cn/sig/Cloud-Kernel/doc/607607272530076167?preview=)
+
+
+### [【6】订阅Cloud Kernel邮件列表](https://openanolis.cn/sig/Cloud-Kernel/doc/607613103206853741?preview=)
+
+
+### [【7】Cloud Kernel仓库代码管理](https://openanolis.cn/sig/Cloud-Kernel/doc/381448004602003761?preview=)
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ae47b98e47f3326d04df1542d6f5dec7bd5a9054
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213.md"
@@ -0,0 +1,407 @@
+# 写在前面
+
+
+Anolis OS 是 OpenAnolis 社区推出的完全开源、中立、开放的发行版,它支持多计算架构,也面向云端场景优化。
+
+
+在您使用Anolis OS之前,我们提供了一个预装Anolis OS的在线机器资源服务。我们**强烈建议**您访问[**龙蜥实验室**](https://lab.openanolis.cn/#/apply/home),使用Web页面及机器人等形式自动创建和管理机器资源,以此来对Anolis OS进行体验。
+
+
+您可以访问[龙蜥实验室使用指南](https://www.yuque.com/anolis-docs/community/peng85),来进行**一键申请**和**免费试用**。
+
+
+
+
+
+
+
+
+
+我们提供两种方式安装Anolis OS:
+
+
+* ISO镜像安装
+* qcow虚拟机镜像安装
+
+
+
+
+## 一、通过ISO进行安装
+
+
+### 1.1 ISO镜像下载
+
+
+登陆下载界面获取Anolis OS最新iso镜像文件
+
+
+
+
+
+
+
+
+
+
+
+### 1.2 镜像安装
+
+
+参考该文档,通过图形化安装接口部署Anolis8/7至目标平台:
+
+
+
+
+
+## 二、 通过qcow虚拟机镜像安装
+
+
+首先,验证CPU是否支持KVM;
+
+
+`egrep '(vmx|svm)' /proc/cpuinfo`
+
+
+如果结果中有vmx(Intel)或svm(AMD)字样,就说明CPU是支持的。
+
+
+如果您是买的ECS,或者已经开了虚拟机,那大概率没办法再通过KVM的方式进行安装。
+
+
+### 2.1 虚拟机镜像下载
+
+
+登陆下载界面获取Anolis OS最新qcow2镜像文件
+
+
+
+
+
+这里以7.9为例:点击网址中的下载按钮后,选择相应架构的文件夹进入,既可以看到对应的下载列表,请选择**AnolisOS-7.9-GA-x86\_64-ANCK.qcow2**文件进行下载。
+
+
+
+
+
+### 2.2 安装依赖包
+
+
+`sudo yum install -y qemu-kvm libvirt virt-install bridge-utils`
+
+
+### 2.3 启动前配置
+
+
+#### 2.3.1 libvirt服务
+
+
+开启libvirt服务
+
+
+`systemctl start libvirtd`
+
+
+设置开机启动
+
+
+`systemctl enable libvirtd`
+
+
+查看状态操作结果
+
+
+`systemctl status libvirtd`
+
+
+
+
+
+`systemctl is-enabled libvirtd`
+
+
+
+
+
+
+#### 2.3.2 打开虚拟化的网络支持
+
+
+`sudo virsh net-autostart default`
+
+
+`sudo virsh net-start default`
+
+
+`sudo sysctl -w net.ipv4.ip_forward=1` # 也可以写到配置文件里持久化
+
+
+
+
+
+**TIPS:**
+
+
+`sudo virsh net-autostart default` 执行过程中可能会卡住,此时将 `/etc/modprobe.d/blacklist.conf` 文件中的 "blacklist nf\_conntrack\_ipv4" 语句注释掉,例如
+
+
+
+```
+...
+#blacklist nf_conntrack_ipv4
+```
+
+之后再执行 `sudo virsh net-autostart default`
+
+
+#### 2.3.3 修改kvm权限
+
+
+直接设置成root启动
+
+
+
+```
+cat >> /etc/libvirt/qemu.conf << EOF
+user = "root"
+group = "root"
+EOF
+systemctl restart libvirtd.service
+```
+
+#### 2.3.4 建立链接
+
+
+查看qemu-kvm路径
+
+
+`whereis qemu-kvm`
+
+
+
+```
+qemu-kvm: /etc/qemu-kvm /usr/libexec/qemu-kvm /usr/share/qemu-kvm /usr/share/man/man1/qemu-kvm.1.gz
+```
+
+
+
+
+建立软连接
+
+
+`ln -s /usr/libexec/qemu-kvm /usr/bin/qemu-kvm`
+
+
+
+#### 2.3.5 创建xml配置文件
+
+
+示例文件的名称为anolis.xml,请根据提示修改您的镜像路径
+
+
+您可以按照注释自己酌情修改。
+
+
+
+```
+
+ anolis
+ 16777216
+ 8
+
+
+
+
+ hvm
+
+
+
+
+
+
+
+
+
+
+
+ destroy
+ restart
+ restart
+
+
+ /usr/bin/qemu-kvm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+
+
+
+### 2.4 虚拟机的启动与管理
+
+
+#### 2.4.1 使用virsh命令启动虚拟机
+
+
+
+新机器执行virsh命令可能会有setlocale: No such file or directory的警告,可安装语言包
+
+
+`yum install -y glibc-langpack-zh`
+
+
+
+`sudo virsh define 虚拟机名.xml`
+
+
+`sudo virsh start 虚拟机名` # 请修改为KVM虚拟机的真实名称。
+
+
+vm 默认的账户和密码为:
+
+
+* 用户名:`anuser`
+* 密码:`anolisos`
+
+
+
+
+
+
+
+
+
+
+
+
+
+#### 2.4.2 切换root用户并允许ssh root登录
+
+
+1. `sudo su`
+2. 输入密码`anolisos`
+3. 修改root密码:`passwd root`
+4. 修改`/etc/ssh/sshd_config`:
+
+
+
+
+```
+PasswordAuthentication yes
+
+PermitRootLogin yes
+```
+
+
+#### 2.4.3 虚拟机的访问
+
+
+可以通过下列方式访问VM:
+
+
+* 通过 vnc 访问宿主机的 IP,登录VM,查看 IP
+* 通过 `sudo virsh console 虚拟机名` 登录 VM(请注意可能会有一段时间的黑屏,VM启动过程没有输出到屏幕),查看 IP
+* 获取到 Guest IP 之后,通过 `ssh root@` 登录 VM.
+
+
+#### 2.4.3 查询虚拟机在宿主机对应串口设备
+
+
+`virsh ttyconsole 虚拟机名`
+
+
+
+#### 2.4.4 其余virsh命令
+
+
+`virsh list` #显示本地活动虚拟机
+
+
+`virsh list –-all` #显示本地所有的虚拟机(活动的+不活动的)
+
+
+`virsh define 虚拟机名.xml` #通过配置文件定义一个虚拟机(这个虚拟机还不是活动的)
+
+
+`virsh undefine 虚拟机名.xml` #删除虚拟机配置
+
+
+`virsh start 虚拟机名` #启动名字为ubuntu的非活动虚拟机
+
+
+`virsh create 虚拟机名.xml` # 创建虚拟机(创建后,虚拟机立即执行,成为活动主机)
+
+
+`virsh suspend 虚拟机名` # 暂停虚拟机
+
+
+`virsh resume 虚拟机名` # 启动暂停的虚拟机
+
+
+`virsh shutdown 虚拟机名` # 正常关闭虚拟机
+
+
+`virsh destroy 虚拟机名` # 强制关闭虚拟机
+
+
+`virsh dominfo 虚拟机名` #显示虚拟机的基本信息
+
+
+`virsh domname 2` # 显示id号为2的虚拟机名
+
+
+`virsh domid 虚拟机名` # 显示虚拟机id号
+
+
+`virsh domuuid 虚拟机名` # 显示虚拟机的uuid
+
+
+`virsh domstate 虚拟机名` # 显示虚拟机的当前状态
+
+
+`virsh dumpxml 虚拟机名` # 显示虚拟机的当前配置文件(可能和定义虚拟机时的配置不同,因为当虚拟机启动时,需要给虚拟机分配id号、uuid、vnc端口号等等)
+
+
+`virsh setmem 虚拟机名 512000` #给不活动虚拟机设置内存大小
+
+
+`virsh setvcpus 虚拟机名 4` # 给不活动虚拟机设置cpu个数
+
+
+`virsh edit 虚拟机名` # 编辑配置文件(一般是在刚定义完虚拟机之后)
+
+
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217.md"
new file mode 100644
index 0000000000000000000000000000000000000000..db8a3eed99bd77755d654f9e4bc81bc6258774f8
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217.md"
@@ -0,0 +1,410 @@
+# 写在前面
+
+
+**在进行本教程之前,我们****强烈建议****您:**
+
+
+1. **在****qemu虚拟机中进行操作****,防止安装内核的动作破坏您的现有环境**
+2. **虚拟机OS推荐选择****Anolis OS 8**
+3. **编译内核版本建议****5.10****,其他版本内核操作同理**
+
+
+**本篇教程将****以 Anolis OS 8环境+ 5.10内核编译 为例****。**
+
+
+
+## 1. 拉取内核代码仓库
+
+
+Cloud Kernel 是龙蜥操作系统(Anolis OS)内核,是基于Linux社区主线稳定版,访问以下地址可以查看详细信息。
+
+
+
+
+
+### 1.1 全量拉取
+
+
+首先,保证已经安装Git。
+
+
+
+`sudo yum install -y git`
+
+
+
+接着,复制内核代码仓库到本地,并选择需要编译的目标分支:
+
+
+
+1. 复制内核代码库到本地
+
+
+`git clone https://gitee.com/anolis/cloud-kernel.git`
+
+
+2. 切换到目标分支
+
+
+`cd cloud-kernel`
+
+
+`git checkout devel-5.10 -b devel-5.10`
+
+
+
+### 1.2 指定分支拉取
+
+
+注意到,git clone 默认是取回 master 分支,而Cloud Kernel分支量较大,commit较多,在网络状态不佳的情况下需要大量的下载时间。如果我们只需要特定分支进行编译,可以通过-b参数进行指定。
+
+
+
+
+
+
+
+如:拉取5.10版本内核分支
+
+
+`git clone https://gitee.com/anolis/cloud-kernel.git -b devel-5.10`
+
+
+实际上,如果我们指定的是branch,clone下来的仍然包含了该branch的完整历史,所以还是有较大的文件传输。如果想进一步缩减下载量,可以通过对commit depth进行限制。
+
+
+`git clone https://gitee.com/anolis/cloud-kernel.git -b devel-5.10 --depth 1`
+
+
+通过设置depth=1,这样只会clone最近一次commit。
+
+
+
+
+
+
+## 2. 安装依赖包
+
+
+### 2.1 Anolis OS、CentOS等
+
+
+
+安装开发工具包组
+
+
+`sudo yum groupinstall "development tools"`
+
+
+安装ncurse-devel包 (make menuconfig 文本界面窗口依赖包)
+
+
+`sudo yum install -y ncurses-devel`
+
+
+安装ssl依赖
+
+
+`sudo yum install -y openssl-devel`
+
+
+安装libelf依赖
+
+
+`sudo yum install -y elfutils-libelf-devel`
+
+
+安装dwarves
+
+
+`sudo yum install -y dwarves`
+
+
+
+## 3. 配置内核
+
+
+### 3.1 默认内核配置文件
+
+
+龙蜥操作系统内核提供默认内核配置文件, 常用x86架构和arm架构的配置文件如下:
+
+
+
+* arch/arm64/configs/anolis\_defconfig
+* arch/arm64/configs/anolis-debug\_defconfig
+* arch/x86/configs/anolis\_defconfig
+* arch/x86/configs/anolis-debug\_defconfig
+
+
+
+其中anolis\_defconfig为最常用的**默认配置**,anolis-debug\_defconfig为debug测试版本。
+
+
+
+
+
+您可以通过命令 `make help`列出支持的默认配置, 如下:
+
+
+
+
+
+
+### 3.2 make现有的内核配置文件
+
+
+进入到下载好的cloud-kernel目录下:
+
+
+
+`cd 你的工作目录/cloud-kernel`
+
+
+
+对于默认配置,我们可以直接进行make:
+
+
+
+`make anolis_defconfig`
+
+
+arch目录下包含了各种不同架构,更多config配置详见相应架构的configs文件夹,可以选择进行make
+
+
+
+在make完成后,我们可以在当前cloud-kernel目录下得到.config文件,作为我们之后内核编译使用的配置文件。
+
+
+
+
+
+## 4. 编译内核并运行
+
+
+### 4.1 内核编译
+
+
+这里需要您选择与您当前架构相同的kernel进行编译,我们此教程不涉及交叉编译,不考虑在x86进行arm版本编译,反之亦然。
+
+
+
+直接进行make即可开始内核编译,我们可以通过-j来指定CPU核心数来开启多线程编译以加快编译速度
+
+
+`make -j$(nproc)`
+
+
+
+如果看到以下提示,则代表内核编译成功。其中,bzImage是kernel镜像格式vmlinux经过压缩后得到。
+
+
+(在arm架构中,生成的kernel镜像压缩文件为arch/arm64/boot/Image.gz)
+
+
+
+
+
+### 4.2 内核安装
+
+
+内核编译完成后,我们可以通过执行以下命令对编译好的内核进行安装。
+
+
+
+编译完成后执行make modules\_install 安装内核模块
+
+
+`make modules_install`
+
+
+安装内核核心文件
+
+
+`make install`
+
+
+如需将新版本内核设置为默认启动内核,可以使用此命令
+
+
+`grub2-set-default 0`
+
+
+重启
+
+
+`reboot`
+
+
+
+重启进入系统后,查看内核版本
+
+
+`uname -a`
+
+
+成功安装。
+
+
+
+
+
+
+## 5 修改配置文件(可选)
+
+
+在对内核进行正式编译之前,我们可以对.config文件进行修改,来更改内核编译配置
+
+
+### 5.1 通过自带脚本进行更改
+
+
+为了方便对config进行管理,scripts文件夹中提供config脚本对.config进行修改
+
+
+
+```
+scripts/config的一些说明:
+commands:
+ --enable|-e option Enable option
+ --disable|-d option Disable option
+ --module|-m option Turn option into a module
+ --set-str option string Set option to "string"
+ --set-val option value Set option to value
+ --undefine|-u option Undefine option
+ --state|-s option Print state of option (n,y,m,undef)
+ --enable-after|-E beforeopt option Enable option directly after other option
+ --disable-after|-D beforeopt option Disable option directly after other option
+ --module-after|-M beforeopt option Turn option into module directly after other option
+
+ commands can be repeated multiple times
+
+options:
+ --file config-file .config file to change (default .config)
+ --keep-case|-k Keep next symbols' case (dont' upper-case it)
+```
+
+
+
+
+
+##
+
+
+
+举例:通过`scripts/config`开启/关闭/修改config选项
+
+
+
+创建config\_change.sh `chmod u+x config_change.sh`
+
+
+`./config_change.sh 你的工作目录/cloud-kernel/.config`
+
+
+
+```
+bash 你的工作目录/cloud-kernel/scripts/config --file $1 \
+-e CONFIG_XXX \ #开启CONFIG_XXX
+-d CONFIG_XXX \ #关闭CONFIG_XXX
+-m CONFIG_XXX \ #将CONFIG_XXX设置为module
+...
+```
+
+
+### 5.2 通过menuconfig进行修改
+
+
+在Linux里面我们所看到的menuconfig界面是通过配置内核顶层的Kconfig产生的,而当输入make menuconfig命令的时候系统会读取Makefile来解析Kconfig。
+
+
+
+`make menuconfig`
+
+
+
+
+
+
+在menuconfig图形界面,我们能够更加清晰地看到各个config相关的详细描述信息,来对各个config的管理的功能有进一步的了解。
+
+
+在对信息修改后,记住将修改保存到.config
+
+
+
+
+
+
+### 5.3 修改内核名称
+
+
+在menuconfig界面中,我们还能对编译的内核名称进行修改:
+
+
+
+General setup --->local version -append to kernel release
+
+
+此处修改内核名称为5.10.112-001.my\_test\_kernel.x86\_64
+
+
+
+
+
+
+
+
+
+
+## 6. 自动化脚本
+
+
+我们可以对内核编译过程编写自动化脚本来提高编译效率。(这里以x86为例,其他架构请自行更改)
+
+
+
+```
+bash 你的工作目录/cloud-kernel/scripts/config --file $1 \
+-e CONFIG_XXX \ #开启CONFIG_XXX
+-d CONFIG_XXX \ #关闭CONFIG_XXX
+-m CONFIG_XXX \ #将CONFIG_XXX设置为module
+...
+```
+
+
+```
+BUILD_DIR="你的工作目录/build/cloud-kernel/"
+SOURCE_DIR="你的工作目录/cloud-kernel/"
+
+mkdir $BUILD_DIR -p
+cd $SOURCE_DIR
+if ! [ -f "$BUILD_DIR/.config" ]; then
+ cp $SOURCE_DIR/arch/x86/configs/anolis_defconfig $BUILD_DIR/.config -f
+fi
+
+./config_change.sh $BUILD_DIR/.config
+make O=$BUILD_DIR -j$(nproc)
+
+```
+
+如需更改配置,我们只需要对config\_change.sh进行修改,并运行./build.sh即可一键执行对内核的编译。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217.md"
new file mode 100644
index 0000000000000000000000000000000000000000..6209f94c4abcd0858429125c6770ff0758f89cf1
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217.md"
@@ -0,0 +1,250 @@
+## 1. 前期准备
+
+
+### 1.1 准备Anolis OS环境
+
+
+如果您正在使用Anolis OS,请忽视这个步骤。
+
+
+如果您没有使用Anolis OS,我们**强烈建议在Anolis OS环境下进行操作**,以保证之后的打包流程能顺利进行。
+
+
+#### 1.1.1 镜像版本选择
+
+
+* 我们推荐根据想要编译的内核版本选择相应版本的Anolis OS。
+
+
++ kernel 5.10 -- Anolis OS 8
++ kernel 4.19 -- Anolis OS 7
+
+
+#### 1.1.2 本地镜像与docker镜像下载(二选一)
+
+
+* 您可以从龙蜥社区下ISO镜像或者qcow镜像以使用Anolis OS
+
+
+
+
+
+* 你也可以使用Anolis OS docker镜像
+
+
+
+
+
+
+
+| |
+| --- |
+|
+
+1. 根据tag拉取相应的系统版本(这里以8.6-x86\_64为例)
+
+
+`docker pull openanolis/anolisos:8.6-x86_64`
+2. 查看下载的镜像
+
+
+`docker images`
+示例结果如下:
+`REPOSITORY TAG IMAGE ID CREATED SIZE`
+`docker.io/openanolis/anolisos 8.6-x86_64 6b03ceb18d9c 9 days ago 211 MB`
+3. 运行镜像
+
+
+`docker run -it 6b03ceb18d9c /bin/bash`
+
+ |
+
+
+
+### 1.2 拉取内核代码仓库
+
+
+更多细节参见**内核编译**章节
+
+
+
+`git clone https://gitee.com/anolis/cloud-kernel.git -b devel-5.10`
+
+
+1.3 下载内核打包脚本
+
+
+
+仓库地址:
+
+
+需要根据当前的系统版本和需要打包的内核选择相应的分支。
+
+
+Anolis 8 编译kernel 5.10
+
+
+
+`git clone https://gitee.com/src-anolis-sig/ck-build.git -b an8-5.10`
+
+
+
+Anolis 7 编译kernel 4.19
+
+
+
+`git clone https://gitee.com/src-anolis-sig/ck-build.git -b an7-4.19`
+
+
+
+
+
+## 2. 安装依赖包
+
+
+
+1. 安装开发工具包组
+
+
+`sudo yum groupinstall "development tools" -y`
+
+
+2. 其他依赖
+
+
++ Anolis 8
+
+
+`sudo yum install -y audit-libs-devel binutils-devel java-devel ncurses-devel newt-devel numactl-devel openssl-devel pciutils-devel perl perl-devel xmlto python3-docutils dwarves bc elfutils-devel python3-devel rsync net-tools`
+
+
++ Anolis 7
+
+
+`sudo yum install -y xmlto asciidoc openssl-devel hmaccalc python-devel newt-devel perl pesign perl-ExtUtils-Embed elfutils-libelf-devel`
+
+
+
+## 3.修改代码
+
+
+在打包之前,如果需要的话,您可以对cloud kernel的代码进行一些修改。
+
+
+修改代码需要注意两个事情:
+
+
+1. 如果是要打开某些config的开关,请按照如下操作:
+ 1. 执行`make anolis_defconfig`,这一步会拷贝`arch/{x86,arm64}/configs/anolis_defconfig`的文件为`cloud-kernel/.config`
+ 2. 执行`make menuconfig`,修改某些config选项
+ 3. 根据对应的arch,将.config拷贝回`arch/{x86,arm64}/configs/anolis_defconfig`进行覆盖
+ 4. git add & git commit将修改后的config加入git中进行管理
+2. 任何代码和config的修改,都需要使用git add & git commit将修改加入到git中进行管理。这是因为该打包脚本,会以git HEAD对应的代码进行编译出包。
+
+
+## 4.内核打包
+
+
+进入到ck-bulid工作目录
+
+
+
+`cd 你的工作目录/ck-build`
+
+
+
+### 4.1 建立kernel源码链接
+
+
+
+`ln -s 你的工作目录/cloud-kernel cloud-kernel`
+
+
+
+注意:如果您在编译anolis8-4.19的rpm包时,发现有该报错信息:
+
+
+
+请使用该命令:
+
+
+`ln -s 你的工作目录/cloud-kernel ck.git`
+
+
+这是由于某些历史遗留原因导致的。
+
+
+### 4.2 执行打包命令
+
+
+这里提供基础包的打包命令,也可以根据自己需求进行更改,具体参数请参考FAQ
+
+
+
+`BUILD_NUMBER='自定义版本号' BUILD_VARIANT='default' BUILD_EXTRA='base' ./build.sh`
+
+
+
+### 4.3 输出路径
+
+
+rpm包输出路径:`你的工作目录/ck-build/outputs/自定义版本号`
+
+
+
+## FAQ
+
+
+### 打包选项
+
+
+在进行build之前,您可以对build的可执行选项进行了解,以方便您能更快的编译出自己所需要的rpm包
+
+
+一共有3个可填项BUILD\_VARIANT,BUILD\_EXTRA和BUILD\_NUMBER
+
+
+通过控制BUILD\_VARIANT和BUILD\_EXTRA,我们可以选择生成rpm包的种类,具体参照以下表格。
+
+
+
+
+| | | | |
+| --- | --- | --- | --- |
+| BUILD\_VARIANT
+BUILD\_EXTRA | default | only-debug | with-debug |
+| base | +headers
++default
+-debug | +headers
+-default
++debug | +headers
++default
++debug |
+| with-debuginfo | +debuginfo |
+| full | +tools +doc +perf |
+
+
+BUILD\_NUMBER则代表了包的版本号(默认为0),可以对这个参数定义进行更改(不限于数字)。
+
+
+比如,当我们使用参数
+
+
+`BUILD_NUMBER='test' BUILD_VARIANT='with-debug' BUILD_EXTRA='base'`
+
+
+生成的rpm包如下:
+
+
+
+
+
+
+
+
+
+
+
+###
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG.md"
new file mode 100644
index 0000000000000000000000000000000000000000..c008876d933d93c0849ef970c87202fe273e9469
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG.md"
@@ -0,0 +1,102 @@
+
+# 一、关于bugzilla
+
+
+龙蜥bugzilla平台是管理Cloud Kernel补丁的核心入口,其网址为。
+
+
+不管是您发现了任何**BUG、CVE**漏洞,还是想为Cloud Kernel贡献代码,都可以在bugzilla平台创建一个工单反馈相关信息给我们。
+
+
+
+# 二、bugzilla的使用
+
+
+## 1. 创建bugzilla账号
+
+
+bugzilla账号与龙蜥社区帐号是关联的:
+
+
++ 如果您已拥有龙蜥社区帐号,直接进入[bugzilla主页](https://bugzilla.openanolis.cn/)使用龙蜥社区帐号登陆即可。
++ 如果您还未拥有龙蜥社区帐号,可以先进入进行帐号申请,申请完毕之后再进入[bugzilla主页](https://bugzilla.openanolis.cn/)使用龙蜥社区帐号进行登陆。
+
+
+## 2. 创建bugzilla工单
+
+
+当您想创建一个bugzilla工单时,您可以直接在[bugzilla主页](https://bugzilla.openanolis.cn/)点击 **【 File a Bug 】** 按钮进行创建。创建流程如下:
+
+
+**step 1:**
+
+
+选择【**ANCK:龙蜥云内核 Anolis Cloud Kernel** 项目】
+
+
+
+
+
+**step 2:**
+
+
+选择bug所属版本
+
+
+PS: 如果在5.10和4.19上**都存在相应的Bug**,选择5.10并且在描述或者评论中说明相应情况即可。
+
+
+
+
+
+**step 3:**
+
+
+填写Bug详细信息,
+
+
+- 带红色星号(\*)的为**必填/选**内容
+- 点击每个字段的名称,即可跳转该字段的详细介绍
+- 请尽可能的按照bugzilla所提供的描述模版详细描述您的问题。
+
+
+
+
+
+
+
+
+**step 4:**
+
+
+在完成基本信息的填写之后,需要点击左上角的**【Show Advanced Fields】**,展开进阶选项,如图所示:
+
+
+
+
+
+然后在**keyword字段**选择您的工单类型:
+
+
+
+
+
+
+
+
+**step 5:**
+
+
+当您填写完相关信息之后,点击**【Submit Bug】**即可生成对应的bugzilla工单,每个bugzilla工单都有一个独一无二的ID。
+
+
+此ID会用于后续您提交patch的一系列流程中。
+
+
+
+
+
+
+#
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-2\343\200\221Cloud_Kernel\350\241\245\344\270\201\350\247\204\350\214\203.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-2\343\200\221Cloud_Kernel\350\241\245\344\270\201\350\247\204\350\214\203.md"
new file mode 100644
index 0000000000000000000000000000000000000000..b1c4b051ddd817f141e9664e69d3382d7de6a95a
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-2\343\200\221Cloud_Kernel\350\241\245\344\270\201\350\247\204\350\214\203.md"
@@ -0,0 +1,250 @@
+将代码合入cloud-kernel时,**请根据patch分类**,调整patch的subject、commit log、SOB(Signed-off-by)等内容:
+
+
+* **回合自upstream或第三方社区的补丁**,参考小节“回合自upstream或第三方社区的补丁”。
+* **自研补丁**,参考小节“自研补丁”
+* **CVE补丁**,参考小节“CVE补丁”
+
+
+注意:**所有补丁内容中均不能出现中文**
+
+
+
+## 1. 回合自upstream或第三方社区的补丁
+
+
+### 范例
+
+
+
+```
+sched/fair: Fix wrong cpu selecting from isolated domain
+
+ANBZ: #1468
+
+commit df3cb4ea1fb63ff326488efd671ba3c39034255e upstream.
+
+#commit body ......
+
+Signed-off-by: Andrew Morton
+Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx
+Reviewed-by: Linus Torvalds
+```
+
+### 规范细则
+
+
+* 补丁标题/subject: 保持原标题不变。
+* 补丁日志/commit log
+
+
++ 第一行
+
+
+- **附上**对应问题的**bugzilla ID**号。如果还没有bugzilla id,需要前往[bugzilla](https://bugzilla.openanolis.cn/)提交问题.
+
+
+* 格式:`**ANBZ +冒号+空格+#+bugzilla ID**`
+* 范例:`**ANBZ: #42**`
+* "ANBZ" 即是 "Anolis bugzilla"
+
+
++ 第二行
+
+
+- 空行
+
+
++ 第三行
+
+
+- 添加源补丁commit ID 及补丁来源信息。
+
+
+- 如果您的补丁**来自于upstream**
+
+
+* + - * 格式:`**commit <完整 hash 值> upstream.**`
+ * 范例:`commit 916e6d1a5ef17a6b3bffad0f086f173cde4240d8 upstream.`
+ - 如果您的补丁**来自于upstream,但尚未进入mainline**
+ * 格式:`**commit <完整 hash 值> .**`
+ * 范例:
+ + `commit b66eb3a6e427b059101c6c92ac2ddd899014634c net-next.`
+ + `commit 353f7988dd8413c47718f7ca79c030b6fb62cfe5 linux-block.`
+
+
+- 如果您的补丁**来自第三方社区补丁**
+
+
+* 格式:`**commit <完整 hash 值> <社区名>.**`
+* 范例:`commit 916e6d1a5ef17a6b3bffad0f086f173cde4240d8 openEuler.`
+
+
+- 如果您的补丁**来自社区邮件列表**中,尚未接收的补丁
+
+
+* 格式:`**cherry-picked from + <邮件链接>.**`
+* 范例: `cherry-picked from https://lore.kernel.org/linux-block/20210811142624.618598-1-ming.lei@redhat.com/`
+
+
+* 补丁签名/SOB
+
+
++ 保留原补丁的完整签名,在其后**追加****回合人的签名**
+
+
+- 格式:`**Signed-off-by: <名字> <邮箱地址>**`
+- 范例:`Signed-off-by: Andrew Morton `
+
+
+* PR链接(**由门禁自动添加**)
+
+
++ 在回合人签名后面追加**PR链接**
+
+
+- 格式:`**Link: **`
+- 范例:`Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx`
+
+
+* Reviewed-by(**由门禁自动添加**)
+
+
++ 在PR链接后追加评审人签名
+
+
+- 格式:`**Reviewed-by: <名字> <邮箱地址>**`
+- **范例:**`Reviewed-by: Linus Torvalds `
+
+
+### 回合补丁的修正
+
+
+如因下列原因需要修正的:
+
+
++ 如为解决合并冲突而做的代码适配改动;
++ 对源 commit log 添加新的描述改动;
++ ......
+
+
+都需要在 commit log 里特别注明, 并且**放在您的签名之上**。
+
+
+* 格式: **`[: comments]`**
+* 范例:
+
+
+
+```
+[fix up build warning - gregkh]
+Signed-off-by: Greg Kroah-Hartman
+```
+
+
+
+
+## 2. 自研补丁
+
+
+### 范例
+
+
+
+```
+anolis: scsi: target: tcmu: use new rw_semaphore to protect truncate
+
+ANBZ: #1310
+
+#commit body ......
+
+
+Signed-off-by: Andrew Morton
+Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx
+Reviewed-by: Linus Torvalds
+```
+
+### 规范细则
+
+
+* 补丁标题/subject
+
+
++ 对未被 Linux upstream及第三方开源社区接收的**自研补丁**, 标题前需要加 **`anolis:`** 标签
++ 格式:**`anolis: <标签>`**
+
+
++ 范例:`anolis: uio: Replace mutex info_lock with percpu_ref to improve performance`
+
+
+* 补丁日志/commit log
+
+
++ 附上对应问题的**bugzilla id号**。如果还没有bugzilla ID,需要前往[bugzilla](https://bugzilla.openanolis.cn/)提交问题。
++ 格式:**`ANBZ +冒号+空格+#+bugzilla ID.`**
++ 范例:`ANBZ: #1310`
++ 注:**ANBZ** —— **AN**olis **B**ug**Z**illa
+
+
+* 补丁签名/SOB(Signed-off-by)
+
+
++ 在commit log尾部附上作者签名,
++ 格式:**`Signed-off-by: <名字> <邮箱地址>`**
++ 范例:`Signed-off-by: Andrew Morton `
+
+
+* PR链接(**由门禁自动添加**)
+
+
++ 在回合人签名后面追加**PR链接**
+
+
+- 格式:**`Link: `**
+- 范例:`Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx`
+
+
+* Reviewed-by(**由门禁自动添加**)
+
+
++ 在PR链接后追加评审人签名
+
+
+- 格式:**`Reviewed-by: <名字> <邮箱地址>`**
+- **范例:**`Reviewed-by: Linus Torvalds `
+
+
+## 3. CVE补丁
+
+
+### 范例
+
+
+
+```
+tty: fix deadlock caused by calling printk() under tty_port->lock
+
+ANBZ: #1499
+
+commit 71a174b39f10b4b93223d374722aa894b5d8a82e upstream.
+
+#commit body ......
+
+Signed-off-by: Andrew Morton
+Fixes: CVE-2022-1462
+Signed-off-by: Greg Kroah-Hartman
+Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx
+Reviewed-by: Linus Torvalds
+```
+
+### 规范细则
+
+
+* 根据补丁的来源,参照上文的 **“回合自upstream或第三方社区的补丁规范”** 或 **“自研补丁规范”。**
+* 此外,**额外**在您的**补丁签名的上一行**加上**CVE-ID**
+
+
++ 格式:**`Fixes + 冒号 + 空格 + CVE-ID`**
++ 范例:`Fixes: CVE-2022-1462`
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-3\343\200\221PR(Pull_Request)\350\247\204\350\214\203.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-3\343\200\221PR(Pull_Request)\350\247\204\350\214\203.md"
new file mode 100644
index 0000000000000000000000000000000000000000..9493e467db9881c4303024cdbf8666cd2d74bf85
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-3\343\200\221PR(Pull_Request)\350\247\204\350\214\203.md"
@@ -0,0 +1,83 @@
+当您打算提交pr时,首先明确该pr所属的分类:
+
+
+* **BUG**
+* **CVE**
+* **Feature**
+
+
+**参考示例:**
+
+
+
+# PR标题
+
+
+PR标题不做强制要求,此处仅做建议。
+
+
++ bug类
+
+
+- 建议标题格式:`**[内核版本号] + [Bugfix] +描述**`
+- 范例:`[5.10] [Bugfix] Bug fix for kvm fpu`
+
+
++ CVE类
+
+
+- 建议标题格式:`**[内核版本号] + Bugfix for + CVE-ID**`
+- 范例:`[5.10] Bugfix for CVE-2022-1729`
+
+
++ Feature类
+
+
+- 建议标题格式:`**[内核版本号] + [Feature] + 冒号 + 描述**`
+- 范例:`[5.10] [Feature] : 海光CSV功能扩展`
+
+
+# PR正文
+
+
+正文部分强制要求如下,如果不符合规范,将被**门禁**拒绝:
+
+
+
+```
+bugzilla:
+
+
+
+
+```
+
+其中:
+
+
+* **第一行:bugzilla链接**
+* 第二行:空行
+* **第三行及以下:描述问题背景信息,不少于10个字**
+
+
+
++ 可以直接将bugzilla中的内容复制到描述部分
++ 如果回合自上游社区或者其他社区补丁,建议附上相应链接
++ 门禁将第三行及以下全部视为背景信息,可为中文或英文(英文每个单词视为一个字)。
+
+
+参考示例:
+
+
+
+```
+bugzilla: https://bugzilla.openanolis.cn/show_bug.cgi?id=1672
+
+To improve the code quality of iommu:SIOV - Sync IOMMU to upsteam 5.15
+
+- Merge some bugfixes related to iommu & intel vt-d
+- Align some basic functions related to SIOV
+- Merge iommu iopf framework
+```
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213.md"
new file mode 100644
index 0000000000000000000000000000000000000000..fefc2073257ba2c62031b7c45b85af4d25d82eb6
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213.md"
@@ -0,0 +1,153 @@
+
+为了让您的代码顺利进入Cloud Kernel中,您需要按照以下步骤进行:
+
+
+## 一、准备工作
+
+
+### 1. 注册账号/登陆
+
+
+参与龙蜥内核开发, 需要先注册龙蜥社区及 Gitee 平台账号, 并将两个账号关联.
+步骤如下:
+
+
+1. [注册龙蜥社区账号](https://gitee.com/link?target=https%3A%2F%2Fpassport.openanolis.cn%2Fregister), (已有账号的略过此步);
+2. [注册 Gitee 账号](https://gitee.com/signup), (已有账号的略过此步);
+3. 关联两个账号. 因涉及下节提到的 CLA 签署, 需要将两个账号关联. 直接登录龙蜥社区在 **【账号设置】 -> 【安全设置】** 里可以操作绑定 Gitee 账号.
+
+
+
+
+
+
+### 2. 签署CLA
+
+
+向龙蜥内核贡献代码, 必须先签署 CLA. 可以登录龙蜥社区后, 打开[CLA页面](https://openanolis.cn/pact/contributor) 进行 CLA 签署.
+
+
+注意:
+
+
+* 以人个名义贡献的, 可签署个人 CLA;
+* 以公司名义贡献的, 需要签署公司 CLA;
+* 详情请咨询贵公司相关法务.
+
+
+### 3. fork代码仓库
+
+
+龙蜥 Cloud Kernel 不允许开发者直接向官方代码仓库提交代码, 必须通过向官方代码仓库提交 **PR(Pull Request)** 的方式来合并代码。所以对长期代码贡献者(开发者), 建议先 fork 官方代码仓库到个人账号下, 先将待贡献的代码(补丁)提交到个人代码仓库。
+
+
+操作流程:
+
+
+1. 进入[anolis/cloud-kernel](https://gitee.com/anolis/cloud-kernel) ,点击右上角的 **【Forked】** 按钮,克隆cloud-kernel仓库至个人账号下。
+
+
+
+
+
+
+
+
+2. 克隆完毕之后,git clone 您个人账号下的内核代码库到您的开发环境,进行开发。
+
+
+
+
+
+
+## 二、[bugzilla](https://bugzilla.openanolis.cn/) 确认
+
+
+1. 提交代码前,根据[**bugzilla教程**](https://openanolis.cn/sig/Cloud-Kernel/doc/607601736106142822)进入bugzilla查看是否有对应的**bugzilla**,如果没有则需要根据教程创建新的bugzilla工单。
+2. 获取**bugzilla ID**。
+
+
+示例:图中 **1461** 即为bugzilla ID
+
+
+
+
+
+## 三、补丁制作
+
+
+1. 制作补丁,明确补丁分类(自研、回合、CVE)。
+
+
+2. 根据[**cloud-kernel补丁规范**](https://openanolis.cn/sig/Cloud-Kernel/doc/607603338330374166),确认**补丁标题、补丁日志、补丁签名、回合补丁修正**等部分符合规范。[参考范例](https://gitee.com/anolis/cloud-kernel/commit/dd884ad6baea91e9ea91824f31a5ee64bb58aab8)。
+
+
+3. push代码至个人账号下的内核代码库。
+
+
+
+## 四、提交Pull Request
+
+
+1. 登录 openAnolis 社区Gitee个人账号下的代码仓库页面;
+
+
+2. 点击 **【新建 Pull Request】** 创建合并请求;
+
+
+
+
+
+ 3. 填写PR信息:
+
+
++ 选择目标库为 **【kernel/cloud-kernel】**
++ 选取正确的**源及目标分支**
++ 选择合适的**评审人**。自动指定评审人的功能正在开发,目前您可以通过加入[Cloud Kernel Sig 钉钉群](https://openanolis.cn/sig/Cloud-Kernel)与我们取得联系。
+
+
+
+
+
+
+
+
+4. 根据[**Cloud-Kernel PR规范**](https://openanolis.cn/sig/Cloud-Kernel/doc/607603338330374166)中的要求,编辑好补丁描述,提交PR请求。[PR示例](https://gitee.com/anolis/cloud-kernel/pulls/449)。
+
+
+5. 当您提交完PR后,会有机器人自动帮您进行代码审核验证。
+
+
++ 代码**检测通过**,会有如下提示:
+
+
+
+
+
++ 代码**检测未通过**:
+
+ 1. 请自行修改代码后,使用 **`git push --force`** 重新push至个人仓库下
+ 2. 在pr链接下评论 **`/retest`** 重新触发代码检测。
+ 3. 若因为某些特殊原因导致无法通过检测,可联系maintainer回复 **`/skip-test`** 跳过检测。详见:
+
+
+
+
+
+6. 评审人回复通过并附上签名。
+
+
+
+
+
+
+7. 评审人评论 **`/merge`** 合入代码
+
+
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE.md"
new file mode 100644
index 0000000000000000000000000000000000000000..3904a43fab38397aa2603913bc40a3230bc2e856
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE.md"
@@ -0,0 +1,142 @@
+
+CVE是Cloud Kernel中很关注的部分,报告或修复CVE的流程,我们已经在【Cloud Kernel开发基本流程】一文中提及。
+
+
+但考虑到CVE的重要程度,我们再单独以一篇文档来详细描述报告和修复CVE的步骤。
+
+
+当您想报告或修复CVE时,请按照以下步骤进行:
+
+
+# 一、提交bugzilla
+
+
+1. 首先需要前往[**bugzilla**](https://openanolis.cn/sig/Cloud-Kernel/doc/607607272530076167)查看是否存在相应的bugzilla,如果不存在则需要根据教程创建新的bugzilla工单。
+
+
+* 创建bugzilla时,根据[**bugzilla教程**](https://openanolis.cn/sig/Cloud-Kernel/doc/607601736106142822)进行创建。但是需要注意以下几点:
+
+
+* **bugzilla的Summary必须带上CVE-ID**
+* **在keyword字段必须选择CVE**
+
+
+2. 获取**bugzilla ID**
+
+
+
+
+
+# 二、制作补丁
+
+
+1. 根据[**cloud-kernel补丁规范**](https://openanolis.cn/sig/Cloud-Kernel/doc/607603338330374166)中的CVE规范,确认**补丁标题、补丁日志、补丁签名、回合补丁修正**等部分符合规范。
+
+
+范例:
+
+
+> tty: fix deadlock caused by calling printk() under tty\_port->lock
+>
+> \
+> **ANBZ: #1499**
+>
+>
+> \
+> **commit 71a174b39f10b4b93223d374722aa894b5d8a82e upstream.**
+>
+>
+> \
+> #commit body ......
+>
+> \
+> Signed-off-by: Andrew Morton
+>
+> **Fixes: CVE-2022-1462**
+>
+> **Signed-off-by:Greg Kroah-Hartman **
+>
+> **Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx**
+>
+> **Reviewed-by: Linus Torvalds **
+>
+
+\
+**参考范例:`Fixes: CVE-2022-1462`**
+
+
+2. push代码至个人账号下的内核代码库。
+
+
+
+# 三、提交Pull Request
+
+
+1. 登录 openAnolis 社区Gitee个人账号下的代码仓库页面;
+
+
+2. 点击 **【新建 Pull Request】** 创建合并请求;
+
+
+
+
+
+3. 填写PR信息:
+
+
++ 选择目标库为 **【kernel/cloud-kernel】**
++ 选取正确的**源及目标分支**
++ 选择合适的**评审人**。目前自动指定评审人的功能正在开发,您现在可以通过加入[Cloud Kernel Sig 钉钉群](https://openanolis.cn/sig/Cloud-Kernel)与我们取得联系。
+
+
+
+
+
+4. 参考[**Cloud-Kernel PR规范**](https://openanolis.cn/sig/Cloud-Kernel/doc/607605992881480196)中对CVE的要求,编辑好补丁描述,提交PR请求。
+
+
++ **PR标题中必须带上CVE-ID**
+
+
+范例:**`[5.10] Bugfix for CVE-2022-1729`**
+
+
+5. 当您提交完PR后,会有机器人自动帮您进行代码审核验证。
+
+
++ 如果代码检测未通过:
+
+
+1. 请自行修改代码后,使用 **`git push --force`** 重新push至个人仓库下
+2. 在pr链接下评论 **`/retest`** 重新触发代码检测。
+3. 评审人回复通过并附上签名。
+4. 依次将**PR链接和评审人签名**添加到相应 **commit log 末尾处**,并且使用 **`git push --force`** 提交更新。
+
+
+格式:
+
+
+
+```
+Link:https://gitee.com/anolis/cloud-kernel/pulls/xxx.com
+Reviewed-by: xxx <邮箱>
+```
+
+范例:
+
+
+让最后10个 commit 都加上PR链接`Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx` 以及评审人签名`Reviewed-by: Linus Torvalds `的命令:
+
+
+
+```
+git filter-branch -f --msg-filter ' cat && echo "Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx" && echo "Reviewed-by: Linus Torvalds "' HEAD~10..HEAD
+```
+
+8. 在PR下评论,**`/check-sig`** 提交签名检查命令
+
+
+9. 联系maintainer评论 **`/merge`** 即可进入代码合入流程
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250.md"
new file mode 100644
index 0000000000000000000000000000000000000000..55461a2a9501b1b25449deaa75b6e069203aac3f
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250.md"
@@ -0,0 +1,41 @@
+
+Cloud Kernel邮件列表主要用于Sig消息推送和技术交流,您可以通过邮件列表与我们取得联系。
+
+
+## 订阅步骤:
+
+
+1. 打开[cloud-kernel@lists.openanolis.cn](https://lists.openanolis.cn/postorius/lists/cloud-kernel.lists.openanolis.cn)并且登陆您的龙蜥社区账号。
+2. 填写邮箱地址以及您的名称
+
+
+
+
+
+
+
+
+3. 点击 **【Subscribe】** 即可完成订阅,您将收到该邮件:
+
+
+
+
+
+4. 点击 **【Manage Subscription】** 进入订阅配置
+
+
+
+
+
+
+
+
+5. 根据提示个人喜好配置**Global Mailman Settings**。
+
+
+**注意:Delivery status需要Enable**,否则您无法收到我们的邮件。
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2207\343\200\221Cloud_Kernel_\344\273\223\345\272\223\344\273\243\347\240\201\347\256\241\347\220\206.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2207\343\200\221Cloud_Kernel_\344\273\223\345\272\223\344\273\243\347\240\201\347\256\241\347\220\206.md"
new file mode 100644
index 0000000000000000000000000000000000000000..479e5282441eca6fa84e05a51a3c4600d132d803
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2207\343\200\221Cloud_Kernel_\344\273\223\345\272\223\344\273\243\347\240\201\347\256\241\347\220\206.md"
@@ -0,0 +1,63 @@
+
+
+
+
+## 仓库地址
+
+
+https://gitee.com/anolis/cloud-kernel
+
+
+## 分支管理
+
+
+
+
+| | | |
+| --- | --- | --- |
+| **分支** | **说明** | **生命周期\*** |
+| master | 跟踪 Linux 主线 mainline, 每日自动同步. | 长期 |
+| devel-4.19 | 4.19内核开发分支 | 待定 |
+| release-4.19 | 4.19内核发布分支 | 待定 |
+| devel-5.10 | 5.10内核开发分支 | 待定 |
+| release-5.10 | 5.10内核发布分支 | 待定 |
+
+
+
+\*龙蜥内核各版本生命周期待规划后更新
+
+
+
+## Maintainer 管理机制
+
+
+龙蜥内核模块众多,目前还有很多重要的模块 Maintainer 虚位以待,如当前炙手可热的 BPF 等技术。我们欢迎广大社区同学参与进来,共同贡献,一起打造更多丰富功能,更加稳定可靠的龙蜥内核。
+
+
+### 申请成为龙蜥内核模块 Maintainer
+
+
+可以通过他人推荐或自荐来成为龙蜥内核模块的 Maintainer,方式如下:
+
+
+1、向 [cloud kernel 邮件列表](https://openanolis.cn/sig/Cloud-Kernel/doc/cloud-kernel@lists.openanolis.cn) 发送一封邮件,标题为:Add someone as somemodule's maintainer(他人推荐),或者 Add myself as somemodule's maintainer(自荐),并在邮件中阐述推荐理由,包括但不限于:在该模块实现的特性,修复的问题等,以此证明你在该模块的维护能力。其中,代码提交是重要的参考,可以是 Linux 内核上游的补丁,也可以是龙蜥内核主线的补丁。
+
+
+2、当前 Maintainer 成员针对邮件回复投票,重点参考相关领域 Maintainer 的投票结论,获得 3 位或以上 ACK,即可申请成功,将姓名和龙蜥社区 ID 更新到 Maintainer 列表当中。
+
+
+### 退出龙蜥内核模块 Maintainer
+
+
+因各种原因,不再参与社区活动维护相应模块,如提交补丁,Review 其他同学提交的补丁等,需要有相应的机制退出。退出方式如下:
+
+
+1、本人主动退出,向 [cloud kernel 邮件列表](https://openanolis.cn/sig/Cloud-Kernel/doc/cloud-kernel@lists.openanolis.cn) 发送一封邮件,标题为:Remove myself as somemodule's maintainer,并在邮件中阐述退出理由;社区 TC 在综合考虑后,确认退出,从当前 Maintainer 列表中移除。
+
+
+2、按月检视 Maintainer 的活跃程度,对于长时间没有参加社区活动的 Maintainer,如提交补丁,Review 其他同学提交的补丁等,视情况确认退出,并当前 Maintainer 列表中移除。
+
+
+3、维护历史 Maintainer 列表中,退出的 Maintainer 会在该表中列出曾经维护的模块和时间周期,作为社区历史 Credit 留存。
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\227/\347\224\250\346\210\267\350\201\206\345\220\254/\350\201\206\345\220\254.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\227/\347\224\250\346\210\267\350\201\206\345\220\254/\350\201\206\345\220\254.md"
deleted file mode 100644
index 22c2f1efb01fc56f05097dd7029af2ccfe3b2be0..0000000000000000000000000000000000000000
--- "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\227/\347\224\250\346\210\267\350\201\206\345\220\254/\350\201\206\345\220\254.md"
+++ /dev/null
@@ -1 +0,0 @@
-# hello, 欢迎来到聆听 .md
\ No newline at end of file
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\227/\350\247\243\345\206\263\346\226\271\346\241\210/migration_solution.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\227/\350\247\243\345\206\263\346\226\271\346\241\210/migration_solution.md"
new file mode 100644
index 0000000000000000000000000000000000000000..cd989b8bcfb4c322e1cc0b10fb431dd18a449004
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\227/\350\247\243\345\206\263\346\226\271\346\241\210/migration_solution.md"
@@ -0,0 +1,67 @@
+# CentOS停服替代场景的平滑迁移方案
+
+tags: CentOS迁移, Anolis8
+
+## 概述
+
+操作系统迁移是一个复杂的工程,而在云原生时代,IaaS与PaaS的迁移复杂度更高,且相互影响。因而操作系统迁移不再是一个单机维度的OS切换,而是系统性的迁移工程。针对这一痛点,龙蜥社区在支持用户进行操作系统迁移的过程中,逐步狠点了一套行之有效的迁移方法论,并为CentOS用户提供了迁移到 Anolis OS 的迁移系统 AOMS(Anolis OS Migration System)。
+
+## 场景挑战
+
+随着各种虚拟化技术,开发语言的繁荣发展,在进行操作系统迁移时会出现多种开发语言,中间件,数据库,虚拟化手段混杂在一起的情况,而平台,业务,产品等不同纬度的诉求也会产生叠加。在这些场景下,操作系统迁移不再是一个单机维度的OS切换,而是需要从集群迁移视角来看待,做好全局评估与实施方案,做好灾备,灰度,回滚方案,并结合上层业务调度来进行迁移的系统工程。
+
+## 方案特色
+
+迁移方法论:评估,决策,实施,优化四步迁移法。
+
+
+
+迁移评估的5个维度及其关键的决策信息:
+
+
+
+迁移实施也是业务迁移实现平稳交付的关键环节,其阶段详细的流程要经过实施方案制定、基础设施准备、业务适配改造、迁移试点、迁移批量实施、割接护航6大步骤,确保迁移的交付环节可靠和高效。
+
+## 实践验证
+
+AOMS迁移方案包含如下三个场景:
+
+- CentOS 8迁移Anolis OS 8
+- CentOS 7迁移Anolis OS 7
+- CentOS 7迁移Anolis OS 8
+
+### CentOS 8迁移Anolis OS 8及CentOS 7迁移Anolis OS 7场景
+
+Anolis OS 8在做出差异性开发的同时,在生态上和依赖管理上保持与CentOS 8的兼容,AOMS充分利用了兼容的特性,提供了一键 式迁移工具 : `centos2anolis.py`。
+
+CentOS 8迁移使用 Anolis release 相关的包替代 CentOS release ,通过 `yum distro-sync` 重装当前系统中所有的系统软件包。 软件重装的过程并不会修改当前系统基础配置,所以系统配置,业务配置,业务数据都不会被清除,迁移完成后这些数据无需重新设置。
+
+使用迁移脚本前需要注意如下事项:
+
+- 迁移过程涉及到访问Anolis OS的官方repo ,需要确保待迁移环境网络能够正常访问Anolis OS repo。
+- 需要使用root用户执行,当前只支持CentOS 8系统的迁移,不支持CentOS stream系统迁移。
+- 迁移过程依赖于yum/dnf ,需要确保组件能够正常运行。
+- 迁移脚本提供了Anolis OS repo访问加速的功能,如果访问Anolis OS官方repo速度较慢,可以通过-s选项进行加速访问。
+- 迁移日志保存在/var/log/centos2anolis.log。
+
+### CentOS 7迁移Anolis OS 8场景
+
+CentOS 7到Anolis OS 8,无论是内核,基础软件包,工具链都发生了较大的变化。迁移工具需要考虑这些变化带来的兼容性问题。 AOMS提供的迁移工具leapp包含了迁移评估,迁移实施,配置还原等步骤,用于实现CentOS 7到Anolis OS 8的就地迁移
+
+#### (一) 迁移评估
+
+leapp扫描待迁移系统,搜集内核,软件包,系统配置基础信息,同时与目标系统( Anolis OS 8 )进行对比分析,对于不兼容项给 出影响分析和解决方案。
+
+- 内核角度:给出Anolis OS 8中不再支持的内核特性,硬件驱动;
+- 软件角度:给出系统命令的变更项,提示用户适配业务程序。
+
+迁移评估报告会给出当前系统中所有可能影响到迁移的影响项目,当这些影响项目都被解决后,用户才能够继续做迁移实施。同时 业务程序可根据评估报告中的兼容性提示来适配迁移业务程序。
+
+#### (二) 迁移实施
+
+leapp首先搜集当前的系统信息,记录需要在重启后恢复的配置(如selinux状态)。迁移实施过程中,工具首先按照当前系统安装 的软件包列表,并根据CentOS 7到Anolis OS 8的软件包映射关系,从Anolis OS repo上提前下载迁移所需要的软件包,并基于 Anolis OS 8的软件包制作upgrade-initramfs ,在下一次重启后,系统自动进入 `upgrade-initramfs`,并触发所有软件包的就地升级。在所有的软件包就地升级完成后,自动重启进入系统配置还原阶段,待所有信息完成配置,系统重启进入新的OS ,完成OS的 就地迁移。
+
+
+## 总结
+
+基于龙蜥社区AOMS迁移工具,用户可以解决由于CentOS停服带来的软件供应链风险,同时大大降低由于操作系统迁移带来的高技 术要求、高复杂操作的工程难度,帮助用户快速完成操作系统迁移。
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/0-\345\256\211\345\205\250\345\212\237\350\203\275\351\205\215\347\275\256\350\246\201\346\261\202.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/0-\345\256\211\345\205\250\345\212\237\350\203\275\351\205\215\347\275\256\350\246\201\346\261\202.md"
new file mode 100644
index 0000000000000000000000000000000000000000..740f3adb1c356a111a8012589178d99caabda8e4
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/0-\345\256\211\345\205\250\345\212\237\350\203\275\351\205\215\347\275\256\350\246\201\346\261\202.md"
@@ -0,0 +1,124 @@
+# 安全功能配置要求
+
+## 硬件配置要求
+
+安全功能包括CSV、TPM2.0、TCM2.0、TPCM、TDM、TKM、HCT等,这些功能依赖CPU硬件、BIOS,表1是各种CPU型号所属的CPU代际信息,表2是各代际CPU使用安全功能的硬件配置版本要求。
+
+表 1 各CPU型号对应的海光CPU代际
+表 1 各CPU型号对应的海光CPU代际
+
+| CPU代际 | CPU型号 |
+| --- | --- |
+| 海光2号 | 32XX,52XX,72XX |
+| 海光C86-3G | 33XX,53XX,73XX |
+| 海光C86-4G | 343X,748X,749X,548X |
+
+表 2 安全功能的硬件配置版本要求
+
+| 配置 | CPU | BIOS |
+| --- | --- | --- |
+| 1 | 海光2号
| #**要求1**#:1.两种方法都可以确认bios是否支持相应的功能,方法如下
(1)PI版本为2.1.0.4或以上,通过机器型号和厂商沟通确认
(2)Bootloader 版本号为1.2.55 或以上,Bootloader 版本号可以通过bios 查看,方法在下面章节说明
2. 必须支持CSV、fTPM2.0、fTCM2.0、TPCM等安全功能
BIOS必须满足以上2点要求,如果不满足请直接联系整机厂商
|
+| 2 | 海光C86-3G
| 同 #**要求1**# |
+| 3 | 海光C86-4G | #**要求2**#:1. 两种方法都可以确认bios是否支持相应的功能,方法如下
(1)PI版本为4.2.0.0或以上,通过机器型号和厂商沟通确认
(2)Bootloader版本要求,lscpu \|grep Model 查看Model 对应的值,根据具体的值确认版本要求,版本要求如下
1)4: Bootloader版本为3.5.3.1或以上
2)6: Bootloader版本为 3.7.3.37或以上
Bootloader 版本号可以通过bios 查看,方法在下面章节说明
2. 必须支持CSV、fTPM2.0、fTCM2.0、TPCM等安全功能
BIOS必须满足以上2点要求,如果不满足请直接联系整机厂商
**注意:**
如果用户希望测试`CSV3`的kernel启动hash验证和秘密注入等功能(CSV3密钥封印,CSV3全磁盘加密,CSV3机密容器 等依赖于这些功能),要求安全固件的版本号(即build id)>= `2200`。如果版本号 < `2200`,用户需要联系OEM厂商获取指定PI版本的BIOS,以`PI4.6.x`为前缀的PI版本要求>=`PI4.6.0.5`,以`PI4.2.x`为前缀的PI版本要求>=`PI4.2.0.10`。 |
+
+## Bootloader 版本查看
+海光2号配置
+```
+Setup Utility -> Advanced -> PSP Firmware Versions
+```
+
+海光C86-4G配置
+```
+Chipset -> PSP Firmware Versions
+```
+如下图:
+
+
+## 国产OS安全功能支持情况
+
+> 您可根据表格中OS的版本,支持的CPU型号,及支持的安全功能;选择您需要的OS。推荐使用版本更高的OS,其支持的安全功能更为完善。
+>
+> 备注: 表格中,如果TPM2-TOOLS版本低于5.5(不包含5.5),则TCM有两个命令不支持:ecc encrypt/decrypt
+
+表 2 国产OS安全功能支持情况
+
+| 厂商 | OS版本
内核版本
| 支持的CPU型号 | 机密
计算
| 可信
计算
| 密码
技术
| 软件版本 |
+| :---------- | :------------------------------------------------- | :------------------------------------------- | :------------------- | :---------------------------------- | :------------------------------------------- | :----------------------------------------------------------- |
+| 龙蜥 | 8.8
kernel:5.10
| 海光2号
海光C86-3G
| CSV
1
| TPM
TPCM
TDM
| | qemu:6.2.0
edk2:20220126
tpm2-tools:4.1.1
tpm2-tss:2.3.2
grub2:2.02
tpm2-abrmd: 2.3.3
|
+| | 8.9
kernel:5.10
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2,3
| TPM
TPCM
TDM
TCM
| TKM
HCT
| 同上 |
+| | 23.1
kernel:5.10
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2,3
| TPM
TPCM
TDM
TCM
| TKM
HCT
| qemu: 8.2.0
edk2:202302
tpm2-tools:5.5
tpm2-tss:4.0.1
grub2:2.06
tpm2-abrmd: 3.0.0
|
+| | 23.1 GA
kernel:6.6
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2,3
| TPM
TPCM
TDM
TCM
| CCP
TKM
| qemu: 8.2
edk2:202402
tpm2-tools:5.5
tpm2-tss:4.0.1
grub2:2.12
tpm2-abrmd: 3.0.0
|
+| 麒麟 | 服务器V10
SP3 2303
kernel:4.19
| 海光2号
海光C86-3G
| CSV
1
| TPM
TPCM
TDM
| CCP | qemu: 4.1.0
edk2:202002
tpm2-tools:5.0
tpm2-tss:3.0.3
grub2:2.04
tpm2-abrmd: 2.3.3
|
+| | 服务器V10
SP3 2403
kernel:4.19
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2,3
| TPM
TPCM
TDM
TCM
| TKM
HCT
| 同上 |
+| | 服务器V11
kernel:6.6
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2,3
| TPM
TPCM
TDM
TCM
| TKM
HCT
| qemu: 8.2
edk2:202311
tpm2-tools:5.5.1
tpm2-tss:4.0.1
grub2:2.12
tpm2-abrmd: 3.0.0
|
+| | 桌面V10
SP1 2303
kernel:
5.4.18
| 海光2号
海光C86-3G
| CSV
1
| TPM
TPCM
TDM
| CCP
TKM
HCT
需update2以上
| qemu: 4.2.1
edk2:201911
|
+| | 桌面V10
SP1 2403
kernel:
5.4.18
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2
| TPM
TPCM
TDM
| TKM
HCT
| 同上 |
+| | 桌面V11
kernel:6.6
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2,3
| TPM
TPCM
TDM
TCM
| TKM
HCT
| qemu: 8.2
edk2:202402
tpm2-tools:5.6
tpm2-tss:4.0.1
grub2:2.12
tpm2-abrmd: 3.0.0
|
+| 统信 | 服务器
1060
kernel:
4.19.90
| 海光2号
海光C86-3G
| CSV
1
| TPM
TPCM
TDM
| CCP | qemu: 4.1.0
edk2:202002
tpm2-tools:5.0
tpm2-tss:3.0.3
grub2:2.04
tpm2-abrmd: 2.3.3
|
+| | 服务器
1070
kernel:
4.19.90
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2,3
| TPM
TPCM
TDM
TCM
| TKM
HCT
| qemu: 6.2.0
其他同上
|
+| | 桌面
1060
kernel:
4.19.90
| 海光2号
海光C86-3G
| CSV
1
| TPM
TPCM
TDM
| CCP | qemu: 3.1.3
edk2:201811
tpm2-tools:3.1.3
tpm2-tss:2.1.0
grub2:2.04
tpm2-abrmd: 2.1.0
|
+| | 桌面
1070
kernel:
4.19.90
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2
| TPM
TPCM
TDM
TCM
| TKM
HCT
| qemu: 3.1.3
edk2:201811
tpm2-tools:5.4
tpm2-tss:3.2.2
grub2:2.04
tpm2-abrmd: 3.0.0
|
+| 方德 | 服务器
V3.0
kernel:
4.19.113
| 海光2号
海光C86-3G
| CSV
1
| TPM
TPCM
TDM
| CCP | qemu: 2.12.0
edk2:201903
tpm2-tools:4.1.1
tpm2-tss:2.3.2
grub2:2.02
|
+| | 服务器
V4.0
kernel:
4.19.113
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2,3
| TPM
TPCM
TDM
TCM
| TKM
HCT
| qemu: 4.2.0/7.2
edk2:201903
tpm2-tools:5.6
tpm2-tss:4.0.1
grub2:2.04
tpm2-abrmd: 2.3.3
|
+| | 桌面
V5.0
kernel:
5.4.100
| 海光2号
海光C86-3G
| CSV
1
| TPM
TPCM
TDM
| CCP | grub2:2.04
tpm2-tools:4.1.1
tpm2-tss:2.3.2
|
+| 腾讯信创 | kernel:
4.19.278
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2,3
| TPM
TPCM
TDM
| TKM
HCT
| qemu: 6.2.0
edk2:202111
tpm2-tools:4.1.1
tpm2-tss:2.3.2
grub2:2.04
tpm2-abrmd: 2.3.3
|
+| 麒麟信安 | kernel:
4.19.90
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2,3
| TPM
TPCM
TDM
| TKM
HCT
| qemu: 4.1.0
edk2:202202
tpm2-tools:5.0
tpm2-tss:3.0.3
grub2:2.04
tpm2-abrmd: 2.3.3
|
+| OpenCloudOS | 9.2
kernel:
6.6
| 海光2号
海光C86-3G
海光C86-4G
| CSV
1,2,3
| TPM
TPCM
TDM
TCM
| TKM
HCT
| qemu: 8.2
edk2:20230524
tpm2-tools:5.5
tpm2-tss:4.0.1
grub2:2.12
tpm2-abrmd: 2.4.1
|
+| 浪潮云 | kernel:
4.19.91
| 海光2号
海光C86-3G
| | TPCM | | grub2:2.02 |
+| 曙光云 | kernel:
5.10.134
| 海光2号
海光C86-3G
| CSV
1,2
| | TKM
HCT
| qemu:3.1.1/7.2 |
+| BC-Linux | kernel:
5.10.0-182
| 海光2号
海光C86-3G
| CSV
1,2
| | | |
+| 新华三 | kernel:
5.10.0-136
| 海光2号
海光C86-3G
| CSV
1,2
| | | qemu: 5.0
libvirt: 6.3
|
+
+## BIOS安装及设置要求
+
+### 1. 加密虚拟化功能
+
+要使用HYGON加密虚拟化功能(CSV,CSV2,CSV3),必须进入BIOS设置,通过以下路径打开SMEE功能,并设置SEV-ES ASID Space Limit为1。
+*注:PI2104以上的版本,不需要设置SEV-ES ASID Space Limit为*
+
+#### CPU BIOS配置参考
+**BIOS界面因厂家不同各有区别,如果找不到对应选项请联系厂家确认**
+
+海光2号配置
+
+```
+HYGON CBS -> Moksha Common Options
+```
+```
+Setup Utility -> Advanced -> HYGON CBS -> Core Common Options
+```
+效果如下图:
+
+
+
+海光C86-4G配置
+```
+Advanced -> HYGON CBS -> Core Common Options
+```
+效果如下图:
+
+
+### 2. DCU直通功能
+
+要使用DCU直通功能,必须进入BIOS设置,通过以下路径打开IOMMU功能。
+
+#### CPU BIOS配置参考
+海光2号配置
+```
+HYGON CBS -> NBIO Common Options -> NB Configuration -> IOMMU
+```
+```
+Setup Utility -> Advanced -> HYGON CBS -> NBIO Common Options
+```
+
+效果如下图:
+
+
+
+海光C86-4G配置
+```
+Advanced -> HYGON CBS -> NBIO Common Options
+```
+效果如下图:
+
+
\ No newline at end of file
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/000000000130_anolis.jpg" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/000000000130_anolis.jpg"
new file mode 100644
index 0000000000000000000000000000000000000000..25e606c9c5d28fccaf9f6caa351e3720570e4162
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/000000000130_anolis.jpg" differ
diff --git "a/sig/CodeOneOne/content/\347\224\250\346\210\267\346\214\207\345\215\227/\346\214\207\345\215\227.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/T-One\346\246\202\350\277\260.md"
similarity index 98%
rename from "sig/CodeOneOne/content/\347\224\250\346\210\267\346\214\207\345\215\227/\346\214\207\345\215\227.md"
rename to "sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/T-One\346\246\202\350\277\260.md"
index eab771e0de695d9031232fd555398335e173f83a..74f3dbc4638e7e414a44eba81a927b219691bc3a 100644
--- "a/sig/CodeOneOne/content/\347\224\250\346\210\267\346\214\207\345\215\227/\346\214\207\345\215\227.md"
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/T-One\346\246\202\350\277\260.md"
@@ -3,7 +3,7 @@
### 平台架构
-
+
### 核心特点
- 一站式质量平台:平台打通了测试准备、测试执行、测试分析、测试计划、测试报告、覆盖率检测、智能Bisect、智能巡检等流程全闭环,为社区研发提供一站式测试支撑。
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/assets/Dingtalk_20240614165831.jpg" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/assets/Dingtalk_20240614165831.jpg"
new file mode 100644
index 0000000000000000000000000000000000000000..925bf2945891170613821e8e7dbc9e4206d17c8d
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/assets/Dingtalk_20240614165831.jpg" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\227/assets/jiagou.jpeg" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/assets/jiagou.jpeg"
similarity index 100%
rename from "sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\227/assets/jiagou.jpeg"
rename to "sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/assets/jiagou.jpeg"
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/atone\351\203\250\347\275\262.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/atone\351\203\250\347\275\262.md"
new file mode 100644
index 0000000000000000000000000000000000000000..12f85c9bb02d73ecf4fa31b8773d8b3743913cf7
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/atone\351\203\250\347\275\262.md"
@@ -0,0 +1,615 @@
+# 部署说明
+
+> 此文档以开源版本 T-One 最小单元部署举例说明,不保障系统的高可用及性能等
+>
+> 若期望大规模集群化部署可以联系SIG项目组进行具体讨论。
+> 若遇到问题请参照文未的 FAQ 文档,或进 SIG 群联系我们。
+
+**组件说明**: T-One 包含多个自研组件和几个开源组件,此文档以开源版本 T-One 最小单元部署举例说明。
+
+* 自研组件:tone-web、tone-agent-proxy、tone-agent、tone-runner等。
+* 开源组件:mysql、kafka、redis、zookeeper
+
+**机器要求**:
+
+* 硬件要求:推荐使用 8c16g 以上规格机器。
+* OS 要求:推荐使用 Anolis OS 系统进行部署( 暂不支持debian、ubuntu等)。
+
+**部署说明**:
+- 主要分为安装环境、项目构建、项目启动、数据初始化等几个步骤。
+- 该文档以x86_64机器为例, 如果您的部署机器为其他arch类型的机器,则需要将docker-compose.yaml中指定的第三方开源组件镜像更换成对应的镜像源。
+- 可以自己指定安装目录,该文档以 ~/tone目录为例(推荐)。
+
+# 部署步骤
+> 后续步骤以 Anolis OS 8.6 环境为示例进行行详细说明。
+
+## 1. 环境准备
+
+### a. 安装docker
+```
+ yum -y install yum-utils
+ yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
+ yum install -y docker-ce # 若出错:yum install -y docker-ce --nobest --allowerasing
+
+ # 启动docker
+ systemctl enable docker
+ systemctl start docker
+ systemctl status docker
+```
+### b. 配置docker源
+```
+ vim /etc/docker/daemon.json
+ {
+ "registry-mirrors": [
+ "https://6kx4zyno.mirror.aliyuncs.com",
+ "https://docker.mirrors.ustc.edu.cn",
+ "http://hub-mirror.c.163.com",
+ "https://registry.docker-cn.com"]
+ }
+ systemctl restart docker
+ # 建议使用国内镜像源。 阿里云: https://6kx4zyno.mirror.aliyuncs.com,网易: http://hub-mirror.c.163.com
+```
+### c. 安装docker-compose
+```
+ pip3 install --upgrade pip
+ pip3 install docker-compose
+ docker-compose --version
+```
+
+## 2. 项目构建
+
+### a. 下载项目源码
+```shell
+yum install -y git
+
+git clone --single-branch --branch master https://gitee.com/anolis/tone-web.git ~/tone/code/tone-web
+git clone --single-branch --branch master https://gitee.com/anolis/tone-runner.git ~/tone/code/tone-runner
+git clone --single-branch --branch master https://gitee.com/anolis/tone-agent-proxy.git ~/tone/code/tone-agent-proxy
+git clone --single-branch --branch master https://gitee.com/anolis/tone-storage.git ~/tone/code/tone-storage
+```
+下载后的目录结构:
+```
+~/tone/code/
+ ├── tone-web
+ ├── tone-runner
+ ├── tone-agent-proxy
+ └── tone-storage
+```
+
+### b. 集成前端代码
+```shell
+# 下载前端代码包:
+wget https://anolis-service-pub.oss-cn-zhangjiakou.aliyuncs.com/biz-resource/tone/deploy/front/tone-front-latest.zip
+wget https://anolis-service-pub.oss-cn-zhangjiakou.aliyuncs.com/biz-resource/tone/deploy/front/toneagent-front-latest.zip
+# 安装unzip命令
+yum install -y unzip
+# 解压到指定目录
+unzip -j -o tone-front-latest.zip -d ~/tone/code/tone-web/static/front/
+unzip -j -o toneagent-front-latest.zip -d ~/tone/code/tone-agent-proxy/static/front/
+```
+
+## 3. 项目配置
+### a. 下载 docker-compose.yaml
+```shell
+cd ~/tone
+wget https://anolis-service-pub.oss-cn-zhangjiakou.aliyuncs.com/biz-resource/tone/deploy/docker-compose.yaml
+```
+
+### b. 设置并替换变量
+执行以下脚本(需手动替换`必填的`变量):
+```shell
+# 部署机外网IP地址(必填)
+server_ip=
+
+# 账号密码(必填)
+db_password=
+redis_password=
+tone_storage_password=
+
+# 镜像版本标签(非必改、默认latest)
+version_tag=latest
+
+# token(非必改、可自动生成)
+toneagent_access_key=$(uuidgen)
+toneagent_secret_key=$(uuidgen)
+admin_urls_token=$(uuidgen)
+pub_api_token=$(uuidgen)
+
+sed -i "s/var_db_password/${db_password}/g" docker-compose.yaml
+sed -i "s/var_redis_password/${redis_password}/g" docker-compose.yaml
+sed -i "s/var_tone_storage/${tone_storage_password}/g" docker-compose.yaml
+sed -i "s/var_toneagent_access_key/${toneagent_access_key}/g" docker-compose.yaml
+sed -i "s/var_toneagent_secret_key/${toneagent_secret_key}/g" docker-compose.yaml
+sed -i "s/var_admin_urls_token/${admin_urls_token}/g" docker-compose.yaml
+sed -i "s/var_pub_api_token/${pub_api_token}/g" docker-compose.yaml
+sed -i "s/var_version_tag/${version_tag}/g" docker-compose.yaml
+sed -i "s/var_server_ip/${server_ip}/g" docker-compose.yaml
+```
+
+### c. 启动docker-compose
+```shell
+docker-compose -f ~/tone/docker-compose.yaml up --build -d
+# 注:如代码有更新或首次部署,需要加 --build 参数才会自动重新打包镜像
+```
+
+## 4. 数据初始化
+### a.初始化db
+* 进入`mysql` docker 镜像中,`docker exec -it {数据库容器ID} bash`
+* 连接数据库:`mysql -h 127.0.0.1 -P 3306 -u root -p`
+* 创建 `T-One` 数据库 `tone-db`,`ToneAgent` 数据库 `toneagent-db`
+ ```
+ CREATE DATABASE `tone-db` CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
+ CREATE DATABASE `toneagent-db` CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
+ ```
+ 也可以直接通过 mysql 可视化界面初始化数据库
+
+### b.初始化 `T-One` 数据
+浏览器或者curl命令请求接口($admin_urls_token可在docker-compose配置里查看或更改)
+```shell
+curl -s "http://${server_ip}:8080/admin/migrate/?token=${admin_urls_token}"
+curl -s "http://${server_ip}:8080/admin/init_data/?token=${admin_urls_token}"
+curl -s "http://${server_ip}:8080/admin/create_superuser/?token=${admin_urls_token}&username=admin&password=admin123."
+curl -s "http://${server_ip}:8081/admin/migrate/?token=${admin_urls_token}"
+curl -s "http://${server_ip}:8081/admin/create_superuser/?token=${admin_urls_token}&username=admin&password=admin123."
+curl -s "http://${server_ip}:8081/admin/import_access_token/?token=${admin_urls_token}"
+```
+
+### c. `T-One` 关联依赖配置
+**系统执行任务还需对以下配置进行设置**
+
+- 配置 `T-One` 测试用例
+- 配置`T-One` 测试机器
+- 配置 `ToneAgent` `token`
+ - 在 ToneAgent 系统-账号管理中增加一组 token
+ - 更改 docker-compose 配置中的toneagent_access_key和toneagent_secret_key
+
+## 5. 验证
+使用浏览器打开链接查看: `T-One` 页面:`http://{host}:8080` `ToneAgent` 管理页面:`http://{host}:8081`
+
+## 6. T-One 多生态使用
+`T-One` + `TestLib`
+### a. 创建 `TestLib` 数据库
+- 进入 mysql docker 镜像,docker exec -it {数据库容器ID} bash
+- 连接数据库:mysql -h 127.0.0.1 -P 3306 -u root -p
+- 创建 TestLib 数据库 testlib
+
+ CREATE DATABASE \`test-lib\` CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
+- 创建 TestLib 数据库表
+### testlib数据库初始化
+
+ 点击展开/折叠脚本
+
+```shell
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET NAMES utf8 */;
+/*!50503 SET NAMES utf8mb4 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+
+-- 表 test-lib.case 结构
+CREATE TABLE IF NOT EXISTS `case` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `name` varchar(64) NOT NULL COMMENT '测试用例名称',
+ `creator` varchar(64) NOT NULL COMMENT '负责人',
+ `type` enum('FUNCTIONAL','PERFORMANCE','STRESS','LOAD','SECURITY','COMPATIBILITY','OTHERS') NOT NULL COMMENT '测试用例类型',
+ `priority` enum('PRIORITY_0','PRIORITY_1','PRIORITY_2','PRIORITY_3') NOT NULL COMMENT '测试用例的优先级',
+ `suite_name` varchar(128) DEFAULT NULL COMMENT '测试套名称',
+ `run_method` enum('MANUAL','AUTO') NOT NULL COMMENT '测试用例执行方式,手动、自动',
+ `run_model` enum('SINGLE','CLUSTER') NOT NULL COMMENT '测试用例运行模式,单机、集群',
+ `is_available` tinyint(1) NOT NULL COMMENT '测试用例是否可用',
+ `tone_case` varchar(128) DEFAULT NULL COMMENT 'T-One测试用例,当run_method为自动的时候生效',
+ `device_type` varchar(128) DEFAULT 'unlimit' COMMENT '设备类型,可多选,默认支持所有设备',
+ `device_arch` varchar(256) NOT NULL COMMENT '设备架构类型,可多选,默认支撑所有类型',
+ `labels` varchar(256) DEFAULT NULL COMMENT '设备标签,多个用,隔开',
+ `desc` varchar(512) DEFAULT NULL COMMENT '用例描述',
+ `pre_condition` varchar(512) DEFAULT NULL COMMENT '前置条件',
+ `steps` json DEFAULT NULL COMMENT '操作步骤',
+ `custom_fields` json DEFAULT NULL COMMENT '测试用例扩展属性',
+ `parent` int(11) NOT NULL COMMENT '测试用例分类节点',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `name` (`name`),
+ KEY `ix_case_suite_name` (`suite_name`)
+) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.case_label 结构
+CREATE TABLE IF NOT EXISTS `case_label` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `name` varchar(64) NOT NULL COMMENT '用例标签',
+ `creator` varchar(64) NOT NULL COMMENT '标签创建人',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `name` (`name`)
+) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.case_label_map 结构
+CREATE TABLE IF NOT EXISTS `case_label_map` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `label_name` varchar(64) NOT NULL COMMENT '用例名称',
+ `case_id` int(11) NOT NULL COMMENT '用例ID',
+ PRIMARY KEY (`id`),
+ KEY `ix_case_label_map_label_name` (`label_name`)
+) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.case_tree 结构
+CREATE TABLE IF NOT EXISTS `case_tree` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `name` varchar(16) NOT NULL COMMENT '用例结构树节点名称',
+ `parent` int(11) NOT NULL COMMENT '父节点id',
+ `level` int(11) NOT NULL COMMENT '树结构的深度',
+ `path` varchar(128) NOT NULL COMMENT '模块完整路径',
+ `children_nums` int(11) NOT NULL COMMENT '子节点数量',
+ PRIMARY KEY (`id`),
+ KEY `ix_case_tree_path` (`path`)
+) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.device 结构
+CREATE TABLE IF NOT EXISTS `device` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `name` varchar(64) NOT NULL COMMENT '设备名称',
+ `arch` enum('X86','ARCH64','RISCV','LOONGARCH','NOARCH','OTHERS') NOT NULL COMMENT '设备架构',
+ `ip` varchar(16) NOT NULL COMMENT '设备ip',
+ `type` enum('UNLIMIT','VM','DOCKER','PHYSICS') NOT NULL COMMENT '设备类型',
+ `sn` varchar(16) DEFAULT NULL COMMENT '设备序号',
+ `status` tinyint(1) NOT NULL COMMENT '设备是否可用',
+ `label` json DEFAULT NULL COMMENT '设备标签列表数组',
+ `owner` varchar(256) NOT NULL COMMENT '设备负责人',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.device_label 结构
+CREATE TABLE IF NOT EXISTS `device_label` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `name` varchar(64) NOT NULL COMMENT '设备标签名称',
+ `color` varchar(32) NOT NULL COMMENT '设备标签颜色',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `ix_device_label_name` (`name`)
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.device_label_relationship 结构
+CREATE TABLE IF NOT EXISTS `device_label_relationship` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `label_id` int(11) NOT NULL COMMENT '机器Label id',
+ `device_id` int(11) NOT NULL COMMENT '机器Label id',
+ `is_delete` tinyint(1) DEFAULT NULL COMMENT '对应关系是否删除',
+ PRIMARY KEY (`id`),
+ KEY `ix_device_label_relationship_device_id` (`device_id`),
+ KEY `ix_device_label_relationship_label_id` (`label_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.func_result 结构
+CREATE TABLE IF NOT EXISTS `func_result` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `sub_case_name` varchar(128) NOT NULL COMMENT 'tone job名称',
+ `sub_case_result` enum('SUCCESS','FAIL','SKIP') NOT NULL COMMENT '功能结果',
+ `tone_suite_id` int(11) NOT NULL COMMENT 'suite id',
+ `tone_case_id` int(11) NOT NULL COMMENT 'tone case id',
+ `tone_job_id` int(11) NOT NULL COMMENT 'tone job id',
+ `task_id` int(11) NOT NULL COMMENT '测试方案id',
+ `current` json DEFAULT NULL,
+ `expect` json DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `ix_func_result_tone_suite_id` (`tone_suite_id`),
+ KEY `ix_func_result_task_id` (`task_id`),
+ KEY `ix_func_result_tone_case_id` (`tone_case_id`),
+ KEY `ix_func_result_tone_job_id` (`tone_job_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=479 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.outline 结构
+CREATE TABLE IF NOT EXISTS `outline` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `name` varchar(64) NOT NULL COMMENT '测试大纲文件名',
+ `title` varchar(128) NOT NULL COMMENT '测试大纲的标题',
+ `owner` varchar(16) NOT NULL COMMENT '测试大纲负责人',
+ `tid` varchar(256) NOT NULL COMMENT 'oss文件地址',
+ `remark` varchar(64) DEFAULT NULL COMMENT '测试大纲备注描述信息',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.perf_result 结构
+CREATE TABLE IF NOT EXISTS `perf_result` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `metric` varchar(128) NOT NULL COMMENT '指标名称',
+ `test_value` varchar(64) DEFAULT NULL COMMENT '测试值',
+ `cv_value` varchar(64) DEFAULT NULL COMMENT 'cv值',
+ `max_value` varchar(64) DEFAULT NULL COMMENT '最大值',
+ `min_value` varchar(64) DEFAULT NULL COMMENT '最小值',
+ `unit` varchar(64) DEFAULT NULL COMMENT '测试单位',
+ `track_result` enum('NA','INVALID','NORMAL','DECLINE','INCREASE') NOT NULL COMMENT '跟踪结果',
+ `tone_suite_id` int(11) NOT NULL COMMENT 'suite id',
+ `tone_case_id` int(11) NOT NULL COMMENT 'tone case id',
+ `tone_job_id` int(11) NOT NULL COMMENT 'tone job id',
+ `task_id` int(11) NOT NULL COMMENT '测试方案id',
+ PRIMARY KEY (`id`),
+ KEY `ix_perf_result_task_id` (`task_id`),
+ KEY `ix_perf_result_tone_case_id` (`tone_case_id`),
+ KEY `ix_perf_result_tone_suite_id` (`tone_suite_id`),
+ KEY `ix_perf_result_tone_job_id` (`tone_job_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.plan 结构
+CREATE TABLE IF NOT EXISTS `plan` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `title` varchar(64) NOT NULL COMMENT '测试方案名称',
+ `req_id` int(11) DEFAULT NULL COMMENT '测试需求id',
+ `req_title` varchar(128) DEFAULT NULL COMMENT '测试需求标题',
+ `content` json DEFAULT NULL COMMENT '测试方案内容',
+ `status` varchar(16) NOT NULL COMMENT '测试方案阶段状态',
+ `cases` varchar(256) DEFAULT NULL COMMENT '测试用例,多个使用","隔开',
+ `tasks` varchar(256) DEFAULT NULL COMMENT '测试任务,多个使用","隔开',
+ `reviewers` varchar(256) NOT NULL COMMENT '方案评审人列表',
+ `owner` varchar(256) NOT NULL COMMENT '测试需求的负责人,多个以,隔开',
+ `report` tinyint(1) NOT NULL COMMENT '测试报告是否已生成',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `title` (`title`)
+) ENGINE=InnoDB AUTO_INCREMENT=63 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.plan_review 结构
+CREATE TABLE IF NOT EXISTS `plan_review` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `plan_id` int(11) NOT NULL COMMENT '测试方案id',
+ `reviewer` varchar(32) NOT NULL COMMENT '测试需方案的评审人',
+ `status` varchar(16) NOT NULL COMMENT '评审状态',
+ `desc` varchar(512) DEFAULT NULL COMMENT '评审内容',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.product_category 结构
+CREATE TABLE IF NOT EXISTS `product_category` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `name` varchar(64) NOT NULL COMMENT '大类名称',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.product_plan 结构
+CREATE TABLE IF NOT EXISTS `product_plan` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `test_product_id` int(11) NOT NULL COMMENT '测试产品id',
+ `plan_id` int(11) NOT NULL COMMENT '测试产品实际复制执行的plan id',
+ `executor` varchar(256) NOT NULL COMMENT '测试产品执行人',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.requirement 结构
+CREATE TABLE IF NOT EXISTS `requirement` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `title` varchar(128) NOT NULL COMMENT '测试需求标题',
+ `outline_id` int(11) DEFAULT NULL COMMENT '测试大纲id',
+ `outline_title` varchar(64) DEFAULT NULL COMMENT '测试大纲标题',
+ `content` json NOT NULL COMMENT '测试需求的描述内容',
+ `status` varchar(16) NOT NULL COMMENT '测试需求阶段',
+ `owner` varchar(16) NOT NULL COMMENT '测试需求的创建人',
+ `assignee` varchar(256) NOT NULL COMMENT '测试需求的指派人,多个以,隔开',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.task 结构
+CREATE TABLE IF NOT EXISTS `task` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `name` varchar(64) NOT NULL COMMENT '任务名称',
+ `status` varchar(16) NOT NULL COMMENT '任务执行状态',
+ `run_method` enum('MANUAL','AUTO') NOT NULL COMMENT '测试任务执行方式',
+ `owner` varchar(256) NOT NULL COMMENT '任务执行人',
+ `plan_id` int(11) NOT NULL COMMENT '测试方案id',
+ `plan_title` varchar(256) NOT NULL COMMENT '测试方案标题',
+ `cases` varchar(256) NOT NULL COMMENT '测试用例,多个使用,隔开',
+ `desc` varchar(256) DEFAULT NULL COMMENT '备注',
+ `run_result` json DEFAULT NULL COMMENT '手动用例执行结果',
+ `config` json DEFAULT NULL COMMENT '测试任务配置',
+ `device_id` int(11) DEFAULT NULL COMMENT '测试设备ID',
+ `device_ip` varchar(256) DEFAULT NULL COMMENT '测试机器IP',
+ `workspace` varchar(128) NOT NULL COMMENT 'tone workspace',
+ `project` varchar(128) NOT NULL COMMENT 'tone project',
+ `job_type` varchar(128) NOT NULL COMMENT 'tone job type',
+ `test_type` varchar(32) DEFAULT 'others' COMMENT '测试任务类型',
+ `cluster` varchar(256) DEFAULT NULL COMMENT '测试机器集群名称',
+ `tags` varchar(256) DEFAULT NULL COMMENT '测试机器标签',
+ `tsn` varchar(256) DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `ix_task_plan_id` (`plan_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=90 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.test_product 结构
+CREATE TABLE IF NOT EXISTS `test_product` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `name` varchar(64) NOT NULL COMMENT '测试产品名称',
+ `category_id` int(11) NOT NULL COMMENT '大类id',
+ `origin_plan_id` int(11) NOT NULL COMMENT '测试产品对应的plan id',
+ `desc` varchar(256) DEFAULT NULL COMMENT '产品描述',
+ `test_method` varchar(256) DEFAULT NULL COMMENT '测试方法',
+ `test_requirement` varchar(256) DEFAULT NULL COMMENT '测试要求',
+ `need_config` tinyint(1) DEFAULT NULL COMMENT '是否扩展配置',
+ `owner` varchar(256) NOT NULL DEFAULT '' COMMENT '测试产品创建人',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.test_suite 结构
+CREATE TABLE IF NOT EXISTS `test_suite` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `name` varchar(128) NOT NULL COMMENT '测试套名称',
+ `creator` varchar(64) NOT NULL COMMENT '测试套的创建人员',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `name` (`name`)
+) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.tone_case 结构
+CREATE TABLE IF NOT EXISTS `tone_case` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `tone_case_id` int(11) NOT NULL COMMENT 'tone用例ID',
+ `tone_case_name` varchar(256) NOT NULL COMMENT 'tone用例名称',
+ `suite_id` int(11) NOT NULL COMMENT 'suite ID',
+ `suite_name` varchar(256) NOT NULL COMMENT 'suite用例名称',
+ `test_type` varchar(64) DEFAULT NULL COMMENT '测试类型',
+ PRIMARY KEY (`id`),
+ KEY `ix_tone_case_tone_case_name` (`tone_case_name`),
+ KEY `ix_tone_case_suite_id` (`suite_id`),
+ KEY `ix_tone_case_suite_name` (`suite_name`)
+) ENGINE=InnoDB AUTO_INCREMENT=603 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.tone_job 结构
+CREATE TABLE IF NOT EXISTS `tone_job` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `name` varchar(100) NOT NULL COMMENT 'tone job名称',
+ `state` enum('PENDING','RUNNING','SUCCESS','FAIL','STOP','SKIP') NOT NULL COMMENT 'tone job状态',
+ `test_type` enum('FUNCTIONAL','PERFORMANCE') NOT NULL COMMENT '测试类型',
+ `tone_job_id` int(11) NOT NULL COMMENT 'tone job id',
+ `tone_job_link` varchar(100) DEFAULT '' COMMENT 'tone job链接',
+ `task_id` int(11) NOT NULL COMMENT '测试方案id',
+ `server_info` json DEFAULT NULL COMMENT '存储tone job的机器信息',
+ PRIMARY KEY (`id`),
+ KEY `ix_tone_job_tone_job_id` (`tone_job_id`),
+ KEY `ix_tone_job_task_id` (`task_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=51 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.tone_sync_pull 结构
+CREATE TABLE IF NOT EXISTS `tone_sync_pull` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=76149 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.tone_sync_push 结构
+CREATE TABLE IF NOT EXISTS `tone_sync_push` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.user 结构
+CREATE TABLE IF NOT EXISTS `user` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `user_name` varchar(256) DEFAULT NULL COMMENT '用户名称',
+ `nick_name` varchar(64) DEFAULT NULL COMMENT '用户昵称,具有唯一性',
+ `email` varchar(64) NOT NULL COMMENT '用户邮箱',
+ `avatar_url` varchar(512) DEFAULT NULL COMMENT '用户头像地址',
+ `role` enum('ADMIN','SENIOR','JUNIOR','COMMON') NOT NULL DEFAULT 'COMMON',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `nick_name` (`nick_name`),
+ KEY `ix_user_user_name` (`user_name`)
+) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.user_open_source 结构
+CREATE TABLE IF NOT EXISTS `user_open_source` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `user_name` varchar(256) DEFAULT NULL COMMENT '用户名称',
+ `nick_name` varchar(64) NOT NULL COMMENT '用户昵称,具有唯一性',
+ `email` varchar(64) NOT NULL COMMENT '用户邮箱',
+ `password` varchar(64) NOT NULL COMMENT '用户密码,前端对密码md5加密后的值',
+ `avatar_url` varchar(512) DEFAULT NULL COMMENT '用户头像地址',
+ `role` enum('ADMIN','SENIOR','JUNIOR','COMMON') NOT NULL DEFAULT 'COMMON',
+ `token` varchar(256) NOT NULL COMMENT 'api访问凭证',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `nick_name` (`nick_name`),
+ UNIQUE KEY `email` (`email`),
+ KEY `ix_user_open_source_token` (`token`(255))
+) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.user_role_op_record 结构
+CREATE TABLE IF NOT EXISTS `user_role_op_record` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `applicant` varchar(64) NOT NULL COMMENT '申请人name',
+ `applicant_id` int(11) NOT NULL COMMENT '申请人ID',
+ `apply_reason` varchar(512) DEFAULT NULL COMMENT '申请理由',
+ `signer` varchar(64) DEFAULT NULL COMMENT '评审人name',
+ `has_review` tinyint(1) NOT NULL COMMENT '是否已经审核',
+ `review_result` enum('INIT','PASS','FAIL') NOT NULL COMMENT '审核结果',
+ `review_reason` varchar(512) DEFAULT NULL COMMENT '评审意见',
+ `method` enum('APPROVE','UPGRADE','DOWNGRADE','DELETE') NOT NULL COMMENT '操作方式',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
+
+/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
+/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+
+
+```
+
+
+### b.TestLib 服务依赖
+### c. clone test-lib代码到~/tone/code目录下
+```shell
+git clone --single-branch --branch master https://gitee.com/anolis/testlib.git ~/tone/code/testlib
+```
+### d.增加docker-compose配置
+```yaml
+# docker-compose.yaml service下增加test-lib
+ test-lib:
+ build:
+ context: code/testlib/
+ dockerfile: Dockerfile
+ args:
+ APP_NAME: test-lib
+ ENV: daily
+ image: test-lib:latest
+ ports:
+ - "8005:8005"
+ depends_on:
+ - mysql
+ - redis
+ environment:
+ <<: *common-variables
+ # db
+ db_url: mysql+aiomysql://${db_user}:{db_password}@mysql:3306/test-lib
+ # redis
+ redis_url: redis://:${redis_password}@redis:6379/10
+ # app
+ tone_host: http://${server_ip}:8080/
+ tone_token: tone_token
+ tone_user_name: tone_user_name
+ main_domain: http://${server_ip}:8005
+ oss_url: http://${server_ip}:8005
+```
+#### e.重启服务
+```shell
+docker-compose -f ~/tone/docker-compose.yaml up --build -d
+```
+## 7. 独立部署 FAQ
+https://tone.openanolis.cn/help_doc/12
\ No newline at end of file
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/a\347\224\250\346\210\267\350\201\206\345\220\254-copy/test.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/a\347\224\250\346\210\267\350\201\206\345\220\254-copy/test.md"
new file mode 100644
index 0000000000000000000000000000000000000000..b09df7d02fee342106c45e78485a992609d67bdb
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/a\347\224\250\346\210\267\350\201\206\345\220\254-copy/test.md"
@@ -0,0 +1,70 @@
+# 一级标题
+## 二级标题
+### 三级标题
+**粗体文本**
+
+__cuti__
+
+*斜体文本*
+
+_xieti_
+
+下划线
+
+~~删除线~~
+
+上标:Xy
+
+下标:An
+
+> 引用文本
+- 无序列表项1
+ - 第二层
+- 无序列表项2
+* * *
+1. 有序列表项1
+2. 有序列表项2
+---
+[链接文本](https://gitee.com/suli01/community/edit/master/sig/T-One/content/%E7%94%A8%E6%88%B7%E6%8C%87%E5%8D%97/%E7%94%A8%E6%88%B7%E8%81%86%E5%90%AC/test.md)
+
+链接名称
+
+'''python
+def hello_world():
+ print("Hello, world!")
+
+
+
+| 列1 | 列2 | 列3 |
+| --- | --- | --- |
+| 单元格1 | 单元格2 | 单元格3 |
+| 单元格4 | 单元格5 | 单元格6 |
+
+
+| 左对齐 | 居中对齐 | 右对齐 |
+|:-----|:------:|------:|
+| 文本 | 文本 | 文本 |
+
+
+
+
+
+ 值班人员 |
+ 星期一 |
+ 星期二 |
+ 星期三 |
+
+
+ 张三 |
+ 李四 |
+ 王五 |
+
+
+
+- [ ] :待完成事项
+
+- [x] :已完成事项
+
+
+

+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/a\347\224\250\346\210\267\350\201\206\345\220\254-copy/\346\265\213\350\257\225\345\244\226\351\223\276\345\233\276\347\211\207.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/a\347\224\250\346\210\267\350\201\206\345\220\254-copy/\346\265\213\350\257\225\345\244\226\351\223\276\345\233\276\347\211\207.md"
new file mode 100644
index 0000000000000000000000000000000000000000..d0a3a7f08baab2c20bc46fc52570530781997763
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/a\347\224\250\346\210\267\350\201\206\345\220\254-copy/\346\265\213\350\257\225\345\244\226\351\223\276\345\233\276\347\211\207.md"
@@ -0,0 +1,2 @@
+# hello
+
\ No newline at end of file
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/a\347\224\250\346\210\267\350\201\206\345\220\254-copy/\350\201\206\345\220\254.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/a\347\224\250\346\210\267\350\201\206\345\220\254-copy/\350\201\206\345\220\254.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e5d110a57b01266616a91010b0b0032dcff2c5c1
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/a\347\224\250\346\210\267\350\201\206\345\220\254-copy/\350\201\206\345\220\254.md"
@@ -0,0 +1,2 @@
+# hello, 欢迎来到聆听 .md
+## 阿斯顿发射点
\ No newline at end of file
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/test1.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/test1.md"
new file mode 100644
index 0000000000000000000000000000000000000000..bce7de8006c232d78a6c8052190ff0a3a60a8fa0
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/test1.md"
@@ -0,0 +1,73 @@
+*斜体文字*
+
+_斜体文字_
+
+**粗体文字**
+
+__粗体文字__
+
+***粗斜体文字***
+
+___粗斜体文字___
+
+***
+* * *
+******
+- - -
+------
+
+~~删除线~~
+
+带下划线文本
+
+# 一级标题
+
+## 二级标题
+
+### 三级标题
+
+#### 四级标题
+
+##### 五级标题
+
+###### 六级标题
+[链接](http://a.com)
+
+> 引用
+* 第一项
+* 第二项
+* 第三项
+
++ 第一项
++ 第二项
++ 第三项
+
+- 第一项
+- 第二项
+- 第三项
+1. 第一项
+2. 第二项
+3. 第三项
+
+1. 第一项:
+ - 第一项嵌套的第一个元素
+ - 第一项嵌套的第二个元素
+2. 第二项:
+ - 第二项嵌套的第一个元素
+ - 第二项嵌套的第二个元素
+水平线:
+
+---
+带反引号的“内联代码”
+```
+# 代码块
+print '3 个反引号或'
+print '缩进 4 个空格'
+```
+
+> 区块引用
+> Markdown教程
+> 学的不仅是技术更是梦想
+
+
+SDFGSDFGSDFGSDFG
\ No newline at end of file
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/tone\351\203\250\347\275\262.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/tone\351\203\250\347\275\262.md"
new file mode 100644
index 0000000000000000000000000000000000000000..12f85c9bb02d73ecf4fa31b8773d8b3743913cf7
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/tone\351\203\250\347\275\262.md"
@@ -0,0 +1,615 @@
+# 部署说明
+
+> 此文档以开源版本 T-One 最小单元部署举例说明,不保障系统的高可用及性能等
+>
+> 若期望大规模集群化部署可以联系SIG项目组进行具体讨论。
+> 若遇到问题请参照文未的 FAQ 文档,或进 SIG 群联系我们。
+
+**组件说明**: T-One 包含多个自研组件和几个开源组件,此文档以开源版本 T-One 最小单元部署举例说明。
+
+* 自研组件:tone-web、tone-agent-proxy、tone-agent、tone-runner等。
+* 开源组件:mysql、kafka、redis、zookeeper
+
+**机器要求**:
+
+* 硬件要求:推荐使用 8c16g 以上规格机器。
+* OS 要求:推荐使用 Anolis OS 系统进行部署( 暂不支持debian、ubuntu等)。
+
+**部署说明**:
+- 主要分为安装环境、项目构建、项目启动、数据初始化等几个步骤。
+- 该文档以x86_64机器为例, 如果您的部署机器为其他arch类型的机器,则需要将docker-compose.yaml中指定的第三方开源组件镜像更换成对应的镜像源。
+- 可以自己指定安装目录,该文档以 ~/tone目录为例(推荐)。
+
+# 部署步骤
+> 后续步骤以 Anolis OS 8.6 环境为示例进行行详细说明。
+
+## 1. 环境准备
+
+### a. 安装docker
+```
+ yum -y install yum-utils
+ yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
+ yum install -y docker-ce # 若出错:yum install -y docker-ce --nobest --allowerasing
+
+ # 启动docker
+ systemctl enable docker
+ systemctl start docker
+ systemctl status docker
+```
+### b. 配置docker源
+```
+ vim /etc/docker/daemon.json
+ {
+ "registry-mirrors": [
+ "https://6kx4zyno.mirror.aliyuncs.com",
+ "https://docker.mirrors.ustc.edu.cn",
+ "http://hub-mirror.c.163.com",
+ "https://registry.docker-cn.com"]
+ }
+ systemctl restart docker
+ # 建议使用国内镜像源。 阿里云: https://6kx4zyno.mirror.aliyuncs.com,网易: http://hub-mirror.c.163.com
+```
+### c. 安装docker-compose
+```
+ pip3 install --upgrade pip
+ pip3 install docker-compose
+ docker-compose --version
+```
+
+## 2. 项目构建
+
+### a. 下载项目源码
+```shell
+yum install -y git
+
+git clone --single-branch --branch master https://gitee.com/anolis/tone-web.git ~/tone/code/tone-web
+git clone --single-branch --branch master https://gitee.com/anolis/tone-runner.git ~/tone/code/tone-runner
+git clone --single-branch --branch master https://gitee.com/anolis/tone-agent-proxy.git ~/tone/code/tone-agent-proxy
+git clone --single-branch --branch master https://gitee.com/anolis/tone-storage.git ~/tone/code/tone-storage
+```
+下载后的目录结构:
+```
+~/tone/code/
+ ├── tone-web
+ ├── tone-runner
+ ├── tone-agent-proxy
+ └── tone-storage
+```
+
+### b. 集成前端代码
+```shell
+# 下载前端代码包:
+wget https://anolis-service-pub.oss-cn-zhangjiakou.aliyuncs.com/biz-resource/tone/deploy/front/tone-front-latest.zip
+wget https://anolis-service-pub.oss-cn-zhangjiakou.aliyuncs.com/biz-resource/tone/deploy/front/toneagent-front-latest.zip
+# 安装unzip命令
+yum install -y unzip
+# 解压到指定目录
+unzip -j -o tone-front-latest.zip -d ~/tone/code/tone-web/static/front/
+unzip -j -o toneagent-front-latest.zip -d ~/tone/code/tone-agent-proxy/static/front/
+```
+
+## 3. 项目配置
+### a. 下载 docker-compose.yaml
+```shell
+cd ~/tone
+wget https://anolis-service-pub.oss-cn-zhangjiakou.aliyuncs.com/biz-resource/tone/deploy/docker-compose.yaml
+```
+
+### b. 设置并替换变量
+执行以下脚本(需手动替换`必填的`变量):
+```shell
+# 部署机外网IP地址(必填)
+server_ip=
+
+# 账号密码(必填)
+db_password=
+redis_password=
+tone_storage_password=
+
+# 镜像版本标签(非必改、默认latest)
+version_tag=latest
+
+# token(非必改、可自动生成)
+toneagent_access_key=$(uuidgen)
+toneagent_secret_key=$(uuidgen)
+admin_urls_token=$(uuidgen)
+pub_api_token=$(uuidgen)
+
+sed -i "s/var_db_password/${db_password}/g" docker-compose.yaml
+sed -i "s/var_redis_password/${redis_password}/g" docker-compose.yaml
+sed -i "s/var_tone_storage/${tone_storage_password}/g" docker-compose.yaml
+sed -i "s/var_toneagent_access_key/${toneagent_access_key}/g" docker-compose.yaml
+sed -i "s/var_toneagent_secret_key/${toneagent_secret_key}/g" docker-compose.yaml
+sed -i "s/var_admin_urls_token/${admin_urls_token}/g" docker-compose.yaml
+sed -i "s/var_pub_api_token/${pub_api_token}/g" docker-compose.yaml
+sed -i "s/var_version_tag/${version_tag}/g" docker-compose.yaml
+sed -i "s/var_server_ip/${server_ip}/g" docker-compose.yaml
+```
+
+### c. 启动docker-compose
+```shell
+docker-compose -f ~/tone/docker-compose.yaml up --build -d
+# 注:如代码有更新或首次部署,需要加 --build 参数才会自动重新打包镜像
+```
+
+## 4. 数据初始化
+### a.初始化db
+* 进入`mysql` docker 镜像中,`docker exec -it {数据库容器ID} bash`
+* 连接数据库:`mysql -h 127.0.0.1 -P 3306 -u root -p`
+* 创建 `T-One` 数据库 `tone-db`,`ToneAgent` 数据库 `toneagent-db`
+ ```
+ CREATE DATABASE `tone-db` CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
+ CREATE DATABASE `toneagent-db` CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
+ ```
+ 也可以直接通过 mysql 可视化界面初始化数据库
+
+### b.初始化 `T-One` 数据
+浏览器或者curl命令请求接口($admin_urls_token可在docker-compose配置里查看或更改)
+```shell
+curl -s "http://${server_ip}:8080/admin/migrate/?token=${admin_urls_token}"
+curl -s "http://${server_ip}:8080/admin/init_data/?token=${admin_urls_token}"
+curl -s "http://${server_ip}:8080/admin/create_superuser/?token=${admin_urls_token}&username=admin&password=admin123."
+curl -s "http://${server_ip}:8081/admin/migrate/?token=${admin_urls_token}"
+curl -s "http://${server_ip}:8081/admin/create_superuser/?token=${admin_urls_token}&username=admin&password=admin123."
+curl -s "http://${server_ip}:8081/admin/import_access_token/?token=${admin_urls_token}"
+```
+
+### c. `T-One` 关联依赖配置
+**系统执行任务还需对以下配置进行设置**
+
+- 配置 `T-One` 测试用例
+- 配置`T-One` 测试机器
+- 配置 `ToneAgent` `token`
+ - 在 ToneAgent 系统-账号管理中增加一组 token
+ - 更改 docker-compose 配置中的toneagent_access_key和toneagent_secret_key
+
+## 5. 验证
+使用浏览器打开链接查看: `T-One` 页面:`http://{host}:8080` `ToneAgent` 管理页面:`http://{host}:8081`
+
+## 6. T-One 多生态使用
+`T-One` + `TestLib`
+### a. 创建 `TestLib` 数据库
+- 进入 mysql docker 镜像,docker exec -it {数据库容器ID} bash
+- 连接数据库:mysql -h 127.0.0.1 -P 3306 -u root -p
+- 创建 TestLib 数据库 testlib
+
+ CREATE DATABASE \`test-lib\` CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
+- 创建 TestLib 数据库表
+### testlib数据库初始化
+
+ 点击展开/折叠脚本
+
+```shell
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET NAMES utf8 */;
+/*!50503 SET NAMES utf8mb4 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+
+-- 表 test-lib.case 结构
+CREATE TABLE IF NOT EXISTS `case` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `name` varchar(64) NOT NULL COMMENT '测试用例名称',
+ `creator` varchar(64) NOT NULL COMMENT '负责人',
+ `type` enum('FUNCTIONAL','PERFORMANCE','STRESS','LOAD','SECURITY','COMPATIBILITY','OTHERS') NOT NULL COMMENT '测试用例类型',
+ `priority` enum('PRIORITY_0','PRIORITY_1','PRIORITY_2','PRIORITY_3') NOT NULL COMMENT '测试用例的优先级',
+ `suite_name` varchar(128) DEFAULT NULL COMMENT '测试套名称',
+ `run_method` enum('MANUAL','AUTO') NOT NULL COMMENT '测试用例执行方式,手动、自动',
+ `run_model` enum('SINGLE','CLUSTER') NOT NULL COMMENT '测试用例运行模式,单机、集群',
+ `is_available` tinyint(1) NOT NULL COMMENT '测试用例是否可用',
+ `tone_case` varchar(128) DEFAULT NULL COMMENT 'T-One测试用例,当run_method为自动的时候生效',
+ `device_type` varchar(128) DEFAULT 'unlimit' COMMENT '设备类型,可多选,默认支持所有设备',
+ `device_arch` varchar(256) NOT NULL COMMENT '设备架构类型,可多选,默认支撑所有类型',
+ `labels` varchar(256) DEFAULT NULL COMMENT '设备标签,多个用,隔开',
+ `desc` varchar(512) DEFAULT NULL COMMENT '用例描述',
+ `pre_condition` varchar(512) DEFAULT NULL COMMENT '前置条件',
+ `steps` json DEFAULT NULL COMMENT '操作步骤',
+ `custom_fields` json DEFAULT NULL COMMENT '测试用例扩展属性',
+ `parent` int(11) NOT NULL COMMENT '测试用例分类节点',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `name` (`name`),
+ KEY `ix_case_suite_name` (`suite_name`)
+) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.case_label 结构
+CREATE TABLE IF NOT EXISTS `case_label` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `name` varchar(64) NOT NULL COMMENT '用例标签',
+ `creator` varchar(64) NOT NULL COMMENT '标签创建人',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `name` (`name`)
+) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.case_label_map 结构
+CREATE TABLE IF NOT EXISTS `case_label_map` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `label_name` varchar(64) NOT NULL COMMENT '用例名称',
+ `case_id` int(11) NOT NULL COMMENT '用例ID',
+ PRIMARY KEY (`id`),
+ KEY `ix_case_label_map_label_name` (`label_name`)
+) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.case_tree 结构
+CREATE TABLE IF NOT EXISTS `case_tree` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `name` varchar(16) NOT NULL COMMENT '用例结构树节点名称',
+ `parent` int(11) NOT NULL COMMENT '父节点id',
+ `level` int(11) NOT NULL COMMENT '树结构的深度',
+ `path` varchar(128) NOT NULL COMMENT '模块完整路径',
+ `children_nums` int(11) NOT NULL COMMENT '子节点数量',
+ PRIMARY KEY (`id`),
+ KEY `ix_case_tree_path` (`path`)
+) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.device 结构
+CREATE TABLE IF NOT EXISTS `device` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `name` varchar(64) NOT NULL COMMENT '设备名称',
+ `arch` enum('X86','ARCH64','RISCV','LOONGARCH','NOARCH','OTHERS') NOT NULL COMMENT '设备架构',
+ `ip` varchar(16) NOT NULL COMMENT '设备ip',
+ `type` enum('UNLIMIT','VM','DOCKER','PHYSICS') NOT NULL COMMENT '设备类型',
+ `sn` varchar(16) DEFAULT NULL COMMENT '设备序号',
+ `status` tinyint(1) NOT NULL COMMENT '设备是否可用',
+ `label` json DEFAULT NULL COMMENT '设备标签列表数组',
+ `owner` varchar(256) NOT NULL COMMENT '设备负责人',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.device_label 结构
+CREATE TABLE IF NOT EXISTS `device_label` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `name` varchar(64) NOT NULL COMMENT '设备标签名称',
+ `color` varchar(32) NOT NULL COMMENT '设备标签颜色',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `ix_device_label_name` (`name`)
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.device_label_relationship 结构
+CREATE TABLE IF NOT EXISTS `device_label_relationship` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `label_id` int(11) NOT NULL COMMENT '机器Label id',
+ `device_id` int(11) NOT NULL COMMENT '机器Label id',
+ `is_delete` tinyint(1) DEFAULT NULL COMMENT '对应关系是否删除',
+ PRIMARY KEY (`id`),
+ KEY `ix_device_label_relationship_device_id` (`device_id`),
+ KEY `ix_device_label_relationship_label_id` (`label_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.func_result 结构
+CREATE TABLE IF NOT EXISTS `func_result` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `sub_case_name` varchar(128) NOT NULL COMMENT 'tone job名称',
+ `sub_case_result` enum('SUCCESS','FAIL','SKIP') NOT NULL COMMENT '功能结果',
+ `tone_suite_id` int(11) NOT NULL COMMENT 'suite id',
+ `tone_case_id` int(11) NOT NULL COMMENT 'tone case id',
+ `tone_job_id` int(11) NOT NULL COMMENT 'tone job id',
+ `task_id` int(11) NOT NULL COMMENT '测试方案id',
+ `current` json DEFAULT NULL,
+ `expect` json DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `ix_func_result_tone_suite_id` (`tone_suite_id`),
+ KEY `ix_func_result_task_id` (`task_id`),
+ KEY `ix_func_result_tone_case_id` (`tone_case_id`),
+ KEY `ix_func_result_tone_job_id` (`tone_job_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=479 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.outline 结构
+CREATE TABLE IF NOT EXISTS `outline` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `name` varchar(64) NOT NULL COMMENT '测试大纲文件名',
+ `title` varchar(128) NOT NULL COMMENT '测试大纲的标题',
+ `owner` varchar(16) NOT NULL COMMENT '测试大纲负责人',
+ `tid` varchar(256) NOT NULL COMMENT 'oss文件地址',
+ `remark` varchar(64) DEFAULT NULL COMMENT '测试大纲备注描述信息',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.perf_result 结构
+CREATE TABLE IF NOT EXISTS `perf_result` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `metric` varchar(128) NOT NULL COMMENT '指标名称',
+ `test_value` varchar(64) DEFAULT NULL COMMENT '测试值',
+ `cv_value` varchar(64) DEFAULT NULL COMMENT 'cv值',
+ `max_value` varchar(64) DEFAULT NULL COMMENT '最大值',
+ `min_value` varchar(64) DEFAULT NULL COMMENT '最小值',
+ `unit` varchar(64) DEFAULT NULL COMMENT '测试单位',
+ `track_result` enum('NA','INVALID','NORMAL','DECLINE','INCREASE') NOT NULL COMMENT '跟踪结果',
+ `tone_suite_id` int(11) NOT NULL COMMENT 'suite id',
+ `tone_case_id` int(11) NOT NULL COMMENT 'tone case id',
+ `tone_job_id` int(11) NOT NULL COMMENT 'tone job id',
+ `task_id` int(11) NOT NULL COMMENT '测试方案id',
+ PRIMARY KEY (`id`),
+ KEY `ix_perf_result_task_id` (`task_id`),
+ KEY `ix_perf_result_tone_case_id` (`tone_case_id`),
+ KEY `ix_perf_result_tone_suite_id` (`tone_suite_id`),
+ KEY `ix_perf_result_tone_job_id` (`tone_job_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.plan 结构
+CREATE TABLE IF NOT EXISTS `plan` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `title` varchar(64) NOT NULL COMMENT '测试方案名称',
+ `req_id` int(11) DEFAULT NULL COMMENT '测试需求id',
+ `req_title` varchar(128) DEFAULT NULL COMMENT '测试需求标题',
+ `content` json DEFAULT NULL COMMENT '测试方案内容',
+ `status` varchar(16) NOT NULL COMMENT '测试方案阶段状态',
+ `cases` varchar(256) DEFAULT NULL COMMENT '测试用例,多个使用","隔开',
+ `tasks` varchar(256) DEFAULT NULL COMMENT '测试任务,多个使用","隔开',
+ `reviewers` varchar(256) NOT NULL COMMENT '方案评审人列表',
+ `owner` varchar(256) NOT NULL COMMENT '测试需求的负责人,多个以,隔开',
+ `report` tinyint(1) NOT NULL COMMENT '测试报告是否已生成',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `title` (`title`)
+) ENGINE=InnoDB AUTO_INCREMENT=63 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.plan_review 结构
+CREATE TABLE IF NOT EXISTS `plan_review` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `plan_id` int(11) NOT NULL COMMENT '测试方案id',
+ `reviewer` varchar(32) NOT NULL COMMENT '测试需方案的评审人',
+ `status` varchar(16) NOT NULL COMMENT '评审状态',
+ `desc` varchar(512) DEFAULT NULL COMMENT '评审内容',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.product_category 结构
+CREATE TABLE IF NOT EXISTS `product_category` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `name` varchar(64) NOT NULL COMMENT '大类名称',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.product_plan 结构
+CREATE TABLE IF NOT EXISTS `product_plan` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `test_product_id` int(11) NOT NULL COMMENT '测试产品id',
+ `plan_id` int(11) NOT NULL COMMENT '测试产品实际复制执行的plan id',
+ `executor` varchar(256) NOT NULL COMMENT '测试产品执行人',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.requirement 结构
+CREATE TABLE IF NOT EXISTS `requirement` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `title` varchar(128) NOT NULL COMMENT '测试需求标题',
+ `outline_id` int(11) DEFAULT NULL COMMENT '测试大纲id',
+ `outline_title` varchar(64) DEFAULT NULL COMMENT '测试大纲标题',
+ `content` json NOT NULL COMMENT '测试需求的描述内容',
+ `status` varchar(16) NOT NULL COMMENT '测试需求阶段',
+ `owner` varchar(16) NOT NULL COMMENT '测试需求的创建人',
+ `assignee` varchar(256) NOT NULL COMMENT '测试需求的指派人,多个以,隔开',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.task 结构
+CREATE TABLE IF NOT EXISTS `task` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `name` varchar(64) NOT NULL COMMENT '任务名称',
+ `status` varchar(16) NOT NULL COMMENT '任务执行状态',
+ `run_method` enum('MANUAL','AUTO') NOT NULL COMMENT '测试任务执行方式',
+ `owner` varchar(256) NOT NULL COMMENT '任务执行人',
+ `plan_id` int(11) NOT NULL COMMENT '测试方案id',
+ `plan_title` varchar(256) NOT NULL COMMENT '测试方案标题',
+ `cases` varchar(256) NOT NULL COMMENT '测试用例,多个使用,隔开',
+ `desc` varchar(256) DEFAULT NULL COMMENT '备注',
+ `run_result` json DEFAULT NULL COMMENT '手动用例执行结果',
+ `config` json DEFAULT NULL COMMENT '测试任务配置',
+ `device_id` int(11) DEFAULT NULL COMMENT '测试设备ID',
+ `device_ip` varchar(256) DEFAULT NULL COMMENT '测试机器IP',
+ `workspace` varchar(128) NOT NULL COMMENT 'tone workspace',
+ `project` varchar(128) NOT NULL COMMENT 'tone project',
+ `job_type` varchar(128) NOT NULL COMMENT 'tone job type',
+ `test_type` varchar(32) DEFAULT 'others' COMMENT '测试任务类型',
+ `cluster` varchar(256) DEFAULT NULL COMMENT '测试机器集群名称',
+ `tags` varchar(256) DEFAULT NULL COMMENT '测试机器标签',
+ `tsn` varchar(256) DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `ix_task_plan_id` (`plan_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=90 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.test_product 结构
+CREATE TABLE IF NOT EXISTS `test_product` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `name` varchar(64) NOT NULL COMMENT '测试产品名称',
+ `category_id` int(11) NOT NULL COMMENT '大类id',
+ `origin_plan_id` int(11) NOT NULL COMMENT '测试产品对应的plan id',
+ `desc` varchar(256) DEFAULT NULL COMMENT '产品描述',
+ `test_method` varchar(256) DEFAULT NULL COMMENT '测试方法',
+ `test_requirement` varchar(256) DEFAULT NULL COMMENT '测试要求',
+ `need_config` tinyint(1) DEFAULT NULL COMMENT '是否扩展配置',
+ `owner` varchar(256) NOT NULL DEFAULT '' COMMENT '测试产品创建人',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.test_suite 结构
+CREATE TABLE IF NOT EXISTS `test_suite` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `name` varchar(128) NOT NULL COMMENT '测试套名称',
+ `creator` varchar(64) NOT NULL COMMENT '测试套的创建人员',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `name` (`name`)
+) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.tone_case 结构
+CREATE TABLE IF NOT EXISTS `tone_case` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `tone_case_id` int(11) NOT NULL COMMENT 'tone用例ID',
+ `tone_case_name` varchar(256) NOT NULL COMMENT 'tone用例名称',
+ `suite_id` int(11) NOT NULL COMMENT 'suite ID',
+ `suite_name` varchar(256) NOT NULL COMMENT 'suite用例名称',
+ `test_type` varchar(64) DEFAULT NULL COMMENT '测试类型',
+ PRIMARY KEY (`id`),
+ KEY `ix_tone_case_tone_case_name` (`tone_case_name`),
+ KEY `ix_tone_case_suite_id` (`suite_id`),
+ KEY `ix_tone_case_suite_name` (`suite_name`)
+) ENGINE=InnoDB AUTO_INCREMENT=603 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.tone_job 结构
+CREATE TABLE IF NOT EXISTS `tone_job` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `name` varchar(100) NOT NULL COMMENT 'tone job名称',
+ `state` enum('PENDING','RUNNING','SUCCESS','FAIL','STOP','SKIP') NOT NULL COMMENT 'tone job状态',
+ `test_type` enum('FUNCTIONAL','PERFORMANCE') NOT NULL COMMENT '测试类型',
+ `tone_job_id` int(11) NOT NULL COMMENT 'tone job id',
+ `tone_job_link` varchar(100) DEFAULT '' COMMENT 'tone job链接',
+ `task_id` int(11) NOT NULL COMMENT '测试方案id',
+ `server_info` json DEFAULT NULL COMMENT '存储tone job的机器信息',
+ PRIMARY KEY (`id`),
+ KEY `ix_tone_job_tone_job_id` (`tone_job_id`),
+ KEY `ix_tone_job_task_id` (`task_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=51 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.tone_sync_pull 结构
+CREATE TABLE IF NOT EXISTS `tone_sync_pull` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=76149 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.tone_sync_push 结构
+CREATE TABLE IF NOT EXISTS `tone_sync_push` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.user 结构
+CREATE TABLE IF NOT EXISTS `user` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `user_name` varchar(256) DEFAULT NULL COMMENT '用户名称',
+ `nick_name` varchar(64) DEFAULT NULL COMMENT '用户昵称,具有唯一性',
+ `email` varchar(64) NOT NULL COMMENT '用户邮箱',
+ `avatar_url` varchar(512) DEFAULT NULL COMMENT '用户头像地址',
+ `role` enum('ADMIN','SENIOR','JUNIOR','COMMON') NOT NULL DEFAULT 'COMMON',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `nick_name` (`nick_name`),
+ KEY `ix_user_user_name` (`user_name`)
+) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.user_open_source 结构
+CREATE TABLE IF NOT EXISTS `user_open_source` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `user_name` varchar(256) DEFAULT NULL COMMENT '用户名称',
+ `nick_name` varchar(64) NOT NULL COMMENT '用户昵称,具有唯一性',
+ `email` varchar(64) NOT NULL COMMENT '用户邮箱',
+ `password` varchar(64) NOT NULL COMMENT '用户密码,前端对密码md5加密后的值',
+ `avatar_url` varchar(512) DEFAULT NULL COMMENT '用户头像地址',
+ `role` enum('ADMIN','SENIOR','JUNIOR','COMMON') NOT NULL DEFAULT 'COMMON',
+ `token` varchar(256) NOT NULL COMMENT 'api访问凭证',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `nick_name` (`nick_name`),
+ UNIQUE KEY `email` (`email`),
+ KEY `ix_user_open_source_token` (`token`(255))
+) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8;
+
+-- 表 test-lib.user_role_op_record 结构
+CREATE TABLE IF NOT EXISTS `user_role_op_record` (
+ `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增id',
+ `gmt_created` datetime DEFAULT NULL COMMENT '创建时间',
+ `gmt_modified` datetime DEFAULT NULL COMMENT '修改时间',
+ `applicant` varchar(64) NOT NULL COMMENT '申请人name',
+ `applicant_id` int(11) NOT NULL COMMENT '申请人ID',
+ `apply_reason` varchar(512) DEFAULT NULL COMMENT '申请理由',
+ `signer` varchar(64) DEFAULT NULL COMMENT '评审人name',
+ `has_review` tinyint(1) NOT NULL COMMENT '是否已经审核',
+ `review_result` enum('INIT','PASS','FAIL') NOT NULL COMMENT '审核结果',
+ `review_reason` varchar(512) DEFAULT NULL COMMENT '评审意见',
+ `method` enum('APPROVE','UPGRADE','DOWNGRADE','DELETE') NOT NULL COMMENT '操作方式',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
+
+/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
+/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+
+
+```
+
+
+### b.TestLib 服务依赖
+### c. clone test-lib代码到~/tone/code目录下
+```shell
+git clone --single-branch --branch master https://gitee.com/anolis/testlib.git ~/tone/code/testlib
+```
+### d.增加docker-compose配置
+```yaml
+# docker-compose.yaml service下增加test-lib
+ test-lib:
+ build:
+ context: code/testlib/
+ dockerfile: Dockerfile
+ args:
+ APP_NAME: test-lib
+ ENV: daily
+ image: test-lib:latest
+ ports:
+ - "8005:8005"
+ depends_on:
+ - mysql
+ - redis
+ environment:
+ <<: *common-variables
+ # db
+ db_url: mysql+aiomysql://${db_user}:{db_password}@mysql:3306/test-lib
+ # redis
+ redis_url: redis://:${redis_password}@redis:6379/10
+ # app
+ tone_host: http://${server_ip}:8080/
+ tone_token: tone_token
+ tone_user_name: tone_user_name
+ main_domain: http://${server_ip}:8005
+ oss_url: http://${server_ip}:8005
+```
+#### e.重启服务
+```shell
+docker-compose -f ~/tone/docker-compose.yaml up --build -d
+```
+## 7. 独立部署 FAQ
+https://tone.openanolis.cn/help_doc/12
\ No newline at end of file
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/\347\224\250\346\210\267\350\201\206\345\220\254/test.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/\347\224\250\346\210\267\350\201\206\345\220\254/test.md"
new file mode 100644
index 0000000000000000000000000000000000000000..b09df7d02fee342106c45e78485a992609d67bdb
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/\347\224\250\346\210\267\350\201\206\345\220\254/test.md"
@@ -0,0 +1,70 @@
+# 一级标题
+## 二级标题
+### 三级标题
+**粗体文本**
+
+__cuti__
+
+*斜体文本*
+
+_xieti_
+
+下划线
+
+~~删除线~~
+
+上标:Xy
+
+下标:An
+
+> 引用文本
+- 无序列表项1
+ - 第二层
+- 无序列表项2
+* * *
+1. 有序列表项1
+2. 有序列表项2
+---
+[链接文本](https://gitee.com/suli01/community/edit/master/sig/T-One/content/%E7%94%A8%E6%88%B7%E6%8C%87%E5%8D%97/%E7%94%A8%E6%88%B7%E8%81%86%E5%90%AC/test.md)
+
+链接名称
+
+'''python
+def hello_world():
+ print("Hello, world!")
+
+
+
+| 列1 | 列2 | 列3 |
+| --- | --- | --- |
+| 单元格1 | 单元格2 | 单元格3 |
+| 单元格4 | 单元格5 | 单元格6 |
+
+
+| 左对齐 | 居中对齐 | 右对齐 |
+|:-----|:------:|------:|
+| 文本 | 文本 | 文本 |
+
+
+
+
+
+ 值班人员 |
+ 星期一 |
+ 星期二 |
+ 星期三 |
+
+
+ 张三 |
+ 李四 |
+ 王五 |
+
+
+
+- [ ] :待完成事项
+
+- [x] :已完成事项
+
+
+

+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/\347\224\250\346\210\267\350\201\206\345\220\254/test002.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/\347\224\250\346\210\267\350\201\206\345\220\254/test002.md"
new file mode 100644
index 0000000000000000000000000000000000000000..b72908564d0b1c392ec06a1882232260fdbd34ce
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/\347\224\250\346\210\267\350\201\206\345\220\254/test002.md"
@@ -0,0 +1,73 @@
+# 一级标题
+## 二级标题
+### 三级标题
+**粗体文本**
+
+__cuti__
+
+*斜体文本*
+
+_xieti_
+
+下划线
+
+~~删除线~~
+
+上标:Xy
+
+下标:An
+
+> 引用文本
+- 无序列表项1
+ - 第二层
+- 无序列表项2
+* * *
+1. 有序列表项1
+2. 有序列表项2
+---
+[链接文本](https://gitee.com/suli01/community/edit/master/sig/T-One/content/%E7%94%A8%E6%88%B7%E6%8C%87%E5%8D%97/%E7%94%A8%E6%88%B7%E8%81%86%E5%90%AC/test.md)
+
+链接名称
+
+'''python
+def hello_world():
+ print("Hello, world!")
+
+
+| 列1 | 列2 | 列3 |
+| --- | --- | --- |
+| 单元格1 | 单元格2 | 单元格3 |
+| 单元格4 | 单元格5 | 单元格6 |
+
+
+| 左对齐 | 居中对齐 | 右对齐 |
+|:-----|:------:|------:|
+| 文本 | 文本 | 文本 |
+
+
+
+
+
+ 值班人员 |
+ 星期一 |
+ 星期二 |
+ 星期三 |
+
+
+ 张三 |
+ 李四 |
+ 王五 |
+
+
+
+- [ ] :待完成事项
+| 列1 | 列2 | 列3 |
+| --- | --- | --- |
+| 单元格1 | 单元格2 | 单元格3 |
+| 单元格4 | 单元格5 | 单元格6 |
+
+- [x] :已完成事项
+
+
+

+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/\347\224\250\346\210\267\350\201\206\345\220\254/test003.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/\347\224\250\346\210\267\350\201\206\345\220\254/test003.md"
new file mode 100644
index 0000000000000000000000000000000000000000..41e1c3d0956cd79016fcfc77744fd6175e5a60ca
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/\347\224\250\346\210\267\350\201\206\345\220\254/test003.md"
@@ -0,0 +1,80 @@
+# 一级标题
+## 二级标题
+### 三级标题
+**粗体文本**
+
+__cuti__
+
+*斜体文本*
+
+_xieti_
+
+下划线
+
+~~删除线~~
+
+上标:Xy
+
+下标:An
+
+> 引用文本
+- 无序列表项1
+ - 第二层
+- 无序列表项2
+* * *
+1. 有序列表项1
+2. 有序列表项2
+---
+[链接文本](https://gitee.com/suli01/community/edit/master/sig/T-One/content/%E7%94%A8%E6%88%B7%E6%8C%87%E5%8D%97/%E7%94%A8%E6%88%B7%E8%81%86%E5%90%AC/test.md)
+
+链接名称
+
+'''python
+def hello_world():
+ print("Hello, world!")
+
+
+
+| 列1 | 列2 | 列3 |
+| --- | --- | --- |
+| 单元格1 | 单元格2 | 单元格3 |
+| 单元格4 | 单元格5 | 单元格6 |
+| 左对齐 | 居中对齐 | 右对齐 |
+|:-----|:------:|------:|
+| 文本 | 文本 | 文本 |
+
+
+
+
+
+ 值班人员 |
+ 星期一 |
+ 星期二 |
+ 星期三 |
+
+
+ 张三 |
+ 李四 |
+ 王五 |
+
+
+| 左对齐 | 居中对齐 | 右对齐 |
+|:-----|:------:|------:|
+| 文本 | 文本 | 文本 |
+
+- [ ] :待完成事项
+| 列1 | 列2 | 列3 |
+| --- | --- | --- |
+| 单元格1 | 单元格2 | 单元格3 |
+| 单元格4 | 单元格5 | 单元格6 |
+- [ ] :待完成事项2
+| 列1 | 列2 | 列3 |
+| --- | --- | --- |
+| 单元格1 | 单元格2 | 单元格3 |
+| 单元格4 | 单元格5 | 单元格6 |
+
+- [x] :已完成事项
+
+
+

+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/\347\224\250\346\210\267\350\201\206\345\220\254/test004.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/\347\224\250\346\210\267\350\201\206\345\220\254/test004.md"
new file mode 100644
index 0000000000000000000000000000000000000000..8cd3daee888105c0de2a4e97fd250125bad5c010
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/\347\224\250\346\210\267\350\201\206\345\220\254/test004.md"
@@ -0,0 +1,80 @@
+# 一级标题
+## 二级标题
+### 三级标题
+**粗体文本**
+
+__cuti__
+
+*斜体文本*
+
+_xieti_
+
+下划线
+
+~~删除线~~
+
+上标:Xy
+
+下标:An
+
+> 引用文本
+- 无序列表项1
+ - 第二层
+- 无序列表项2
+* * *
+1. 有序列表项1
+2. 有序列表项2
+---
+[链接文本](https://gitee.com/suli01/community/edit/master/sig/T-One/content/%E7%94%A8%E6%88%B7%E6%8C%87%E5%8D%97/%E7%94%A8%E6%88%B7%E8%81%86%E5%90%AC/test.md)
+
+链接名称
+
+'''python
+def hello_world():
+ print("Hello, world!")
+
+
+
+| 列1 | 列2 | 列3 |
+| --- | --- | --- |
+| 单元格1 | 单元格2 | 单元格3 |
+| 单元格4 | 单元格5 | 单元格6 |
+| 左对齐 | 居中对齐 | 右对齐 |
+|:-----|:------:|------:|
+| 文本 | 文本 | 文本 |
+
+
+
+
+
+ 值班人员 |
+ 星期一 |
+ 星期二 |
+ 星期三 |
+
+
+ 张三 |
+ 李四 |
+ 王五 |
+
+
+| 左对齐 | 居中对齐 | 右对齐 |
+|:-----|:------:|------:|
+| 文本 | 文本 | 文本 |
+
+- [ ] :待完成事项
+| 列1 | 列2 | 列3 |
+| --- | --- | --- |
+| 单元格1 | 单元格2 | 单元格3 |
+| 单元格4 | 单元格5 | 单元格6 |
+- [ ] :待完成事项2
+ | 列1 | 列2 | 列3 |
+ | --- | --- | --- |
+ | 单元格1 | 单元格2 | 单元格3 |
+ | 单元格4 | 单元格5 | 单元格6 |
+
+- [x] :已完成事项
+
+
+

+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/\347\224\250\346\210\267\350\201\206\345\220\254/test005.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/\347\224\250\346\210\267\350\201\206\345\220\254/test005.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ede9631c48e21f0c4e6677d1a5df93bce9fe4ae7
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/\347\224\250\346\210\267\350\201\206\345\220\254/test005.md"
@@ -0,0 +1,12 @@
+HCT密码计算套件的目录结构如下: 阿斯顿法师打发斯蒂芬 44444444444444444444444444444444444444444444444444444 hygon-devkit/
+
+├─ hct
+├──pkg
+│ ├── hct_1.0.0.20230224_rc
+│ ├── hct_1.0.1.20230512_rc
+│ └── hct_1.1.0.20230730_rc
+│
+└── README.md
+* pkg目录:内含各版本hct密码计算套件。
+
+* README.md文件:有关HCT的简单情况。
\ No newline at end of file
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/\347\224\250\346\210\267\350\201\206\345\220\254/\346\265\213\350\257\225\345\244\226\351\223\276\345\233\276\347\211\207.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/\347\224\250\346\210\267\350\201\206\345\220\254/\346\265\213\350\257\225\345\244\226\351\223\276\345\233\276\347\211\207.md"
new file mode 100644
index 0000000000000000000000000000000000000000..d0a3a7f08baab2c20bc46fc52570530781997763
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/\347\224\250\346\210\267\350\201\206\345\220\254/\346\265\213\350\257\225\345\244\226\351\223\276\345\233\276\347\211\207.md"
@@ -0,0 +1,2 @@
+# hello
+
\ No newline at end of file
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/\347\224\250\346\210\267\350\201\206\345\220\254/\350\201\206\345\220\254.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/\347\224\250\346\210\267\350\201\206\345\220\254/\350\201\206\345\220\254.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e5d110a57b01266616a91010b0b0032dcff2c5c1
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\224\250\346\210\267\346\214\207\345\215\2272/\347\224\250\346\210\267\350\201\206\345\220\254/\350\201\206\345\220\254.md"
@@ -0,0 +1,2 @@
+# hello, 欢迎来到聆听 .md
+## 阿斯顿发射点
\ No newline at end of file
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/Release_Notes/ANCK_4.19_ReleaseNote.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/Release_Notes/ANCK_4.19_ReleaseNote.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e7a1110583eb1bcdccd485388c302ca05fd330b6
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/Release_Notes/ANCK_4.19_ReleaseNote.md"
@@ -0,0 +1,130 @@
+# 4.19.91-26.y
+
+
+## 4.19.91-26
+
+
+发布时间:2022-05-24
+
+
+发布链接:
+
+
+*
+*
+
+
+内核更新:
+
+
+* 版本更新至 4.19.91-26
+* 重要内核缺陷及安全漏洞(CVE)修复
+* 龙蜥自研混部资源隔离特性Group Identity增加支持
+* 龙蜥自研多租户容器网络 QoS 隔离特性增强
+* 龙蜥自研冷 slab 内存监测与回收特性支持
+* 龙蜥自研 UKFEF 特性支持
+* Megaraid\_sas 设备驱动支持
+* virtio-net 支持 XDP Socket
+* 基于 EROFS 实现 RAFS v6 格式支持
+* livepatch 增加 static key 支持
+* SMR zoned 设备支持
+* ext4 delalloc buffer写性能优化
+* Kunit 测试框架支持
+* ARM 架构支持 kdump crashkernel 分配4G以上内存
+* ARM 架构 CMN PMU 特性支持
+* perf c2c 功能支持
+
+
+## 4.19.91-26.1
+
+
+发布时间:2022-08-02
+
+
+发布链接:
+
+
+* [https://anas.openanolis.cn/errata/detail/ANSA-2022:0602](https://anas.openanolis.cn/errata/detail/ANSA-2022:0603)
+*
+
+
+内核更新:
+
+
+* 修复CVE: CVE-2022-32250
+
+
+## 4.19.91-26.2
+
+
+发布时间:2022-08-26
+
+
+发布链接:
+
+
+*
+*
+
+
+内核更新:
+
+
+* 修复CVE: CVE-2022-2586
+
+
+## 4.19.91-26.3
+
+
+发布时间:2022-09-02
+
+
+发布链接:
+
+
+*
+*
+
+
+内核更新:
+
+
+* 修复CVE: CVE-2022-2978
+
+
+## 4.19.91-26.4
+
+
+发布时间:2022-09-16
+
+
+发布链接:
+
+
+*
+*
+
+
+内核更新:
+
+
+* 修复CVE: CVE-2022-2639
+
+
+## 4.19.91-26.5
+
+
+发布时间:2022-10-11
+
+
+发布链接:
+
+
+*
+*
+
+
+内核更新:
+
+
+* 修复CVE: CVE-2022-3176
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/Release_Notes/ANCK_5.10_ReleaseNote.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/Release_Notes/ANCK_5.10_ReleaseNote.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e5cb3fe247e6aa7cffc4dd4ea390bb0d01c1d85f
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/Release_Notes/ANCK_5.10_ReleaseNote.md"
@@ -0,0 +1,117 @@
+# 5.10.134-12.y
+
+
+## 5.10.134-12
+
+
+发布时间: 2022-09-06
+
+
+发布链接:
+
+
+内核更新:
+
+
+* 内核升级到5.10.134
+* 重要的缺陷及安全漏洞修复
+* 支持倚天710处理器
+* 支持磐久M物理机
+* 优化在倚天平台上的基础性能
+* ARM64支持mpam特性
+* 增加AMD SEV热迁移能力的guest支持
+* ARM64 crashkernel支持预留4G以上内存
+* ARM64支持对kernel module的hotfix
+* 支持ftrace osnoise tracer
+* 支持 ext4 fast commit 特性,该特性对于 fsync 比较频繁的应用如 MySQL/PostgreSQL 数据库有比较明显的性能优化。相应的 e2fsprogs 版本更新至 1.46.0。
+* 支持网讯10GB网卡
+
+
+**龙蜥自研:**
+
+
+* 支持datop监控NUMA跨node访问以及进程粒度内存冷热识别
+* 填充可执行二进制文件末尾2M未对齐部分,部分场景性能再提升2%
+* 支持 XFS 16k 原子写特性,相比默认打开双写,有至多 50% 的性能提升,同时显著减少磁盘 IO。相应的 xfsprogs 和 mariadb 也更新至龙蜥 yum repo。相比硬件原子写方案,该方案至少有着以下优点:
+
+
+a)基于 CoW 机制;
+
+
+b)不依赖硬件;
+
+
+c)无运行时 IO 链路配置依赖。
+
+
+另外,该优化效果可以与代码段大页特性叠加。
+
+
+使用手册:
+
+
+* 支持 nydus + erofs over fscache 容器镜像加速。该特性由龙蜥社区贡献,于 5.19 合并到社区主线,并成为社区首个源生支持的容器镜像加速方案。相关技术博客:
+* 支持 fd passthrough 和 fd attach 增强特性。其中 fd passthrough 能将常用场景的 IO 延迟降低到先前的 10%;fd attach 支持无损恢复 fuse 挂载点连接,提升生产环境的稳定性。
+* kidled支持匿名页、文件页以及slab的扫描。
+* 新增memory.use\_priority\_swap接口,支持按cgroup优先级进行内存swap。
+* SMC 新增 1-RTT、RDMA DIM 支持,优化 CQ 中断处理逻辑,数据路径 QPS 提升 40%。引入 SMC 自动化测试能力,修复数十个稳定性问题;
+
+
+# 5.10.112-11.y
+
+
+## 5.10.112-11
+
+
+发布时间: 2022-05-24
+
+
+内核更新:
+
+
+* 内核升级到5.10.112
+* 重要的缺陷及安全漏洞修复
+* Hygon CSV2 机密虚拟机特性支持
+* 龙蜥自研代码多副本特性支持
+* 龙蜥自研代码大页功能增强
+* Guest OS 256 CPU 支持
+* 龙蜥自研Kfence增加内存越界 UAF等问题定位能力
+* SMC 多场景下吞吐、时延性能提升,建联速度提升,多个稳定性、兼容问题修复;
+* Intel SPR 特性支持:AMX, vAMX, IPI虚拟化,Intel\_idle, TDX 等
+* AMD 特性支持:SEV-ES,ptdma,CPU frequency, k10temp, EDAC 等
+* 阿里倚天 710 特性支持:DDR PMU,PCIe PMU 驱动支持,CMN-700,RAS
+* coresight 特性支持
+* ARM 架构特性支持: ARM SPE perf memory profiling/c2c,
+* virtiofs: 支持文件级 DAX
+* smmu event polling 支持
+
+
+## 5.10.112-11.1
+
+
+发布时间: 2022-07-15
+
+
+发布链接:
+
+
+内核更新:
+
+
+* 修复CVE: CVE-2022-34918
+
+
+## 5.10.112-11.2
+
+
+发布时间: 2022-08-05
+
+
+内核更新:
+
+
+* 修复CVE:CVE-2022-32250
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270CVE\344\270\223\351\241\271/ANCK_CVE\344\277\256\345\244\215\350\256\260\345\275\225.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270CVE\344\270\223\351\241\271/ANCK_CVE\344\277\256\345\244\215\350\256\260\345\275\225.md"
new file mode 100644
index 0000000000000000000000000000000000000000..f07dbce6a1c9d5c7a709d1baf3d8924f9603654d
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270CVE\344\270\223\351\241\271/ANCK_CVE\344\277\256\345\244\215\350\256\260\345\275\225.md"
@@ -0,0 +1,76 @@
+
+# 4.19
+
+
+
+
+| | |
+| --- | --- |
+| 发布版本 | changelog |
+| 4.19.91-26.3 | CVE-2022-2978 |
+| 4.19.91-26.2 | CVE-2022-2586 |
+| 4.19.91-26.1 | CVE-2022-32250 |
+
+
+# 5.10
+
+
+
+
+| | |
+| --- | --- |
+| 发布版本 | changelog |
+| 5.10.112-11.2 | CVE-2022-32250 |
+| 5.10.112-11.1 | CVE-2022-34918 |
+| 5.10.134-12 | CVE-2021-33655
+CVE-2021-33656
+CVE-2022-0494
+CVE-2022-0500
+CVE-2022-1012
+CVE-2022-1184
+CVE-2022-1462
+CVE-2022-1652
+CVE-2022-1729
+CVE-2022-1734
+CVE-2022-1786
+CVE-2022-1789
+CVE-2022-1836
+CVE-2022-1966
+CVE-2022-1972
+CVE-2022-1974
+CVE-2022-1975
+CVE-2022-2078
+CVE-2022-21123
+CVE-2022-21125
+CVE-2022-21166
+CVE-2022-21499
+CVE-2022-21505
+CVE-2022-2153
+CVE-2022-2318
+CVE-2022-23816
+CVE-2022-2503
+CVE-2022-2586
+CVE-2022-2588
+CVE-2022-26365
+CVE-2022-2639
+CVE-2022-28893
+CVE-2022-29581
+CVE-2022-2959
+CVE-2022-2978
+CVE-2022-29900
+CVE-2022-29901
+CVE-2022-32250
+CVE-2022-32296
+CVE-2022-32981
+CVE-2022-33740
+CVE-2022-33741
+CVE-2022-33742
+CVE-2022-33743
+CVE-2022-33744
+CVE-2022-33981
+CVE-2022-34918
+CVE-2022-36123
+CVE-2022-36879
+CVE-2022-36946 |
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270CVE\344\270\223\351\241\271/\351\241\271\347\233\256\347\256\200\344\273\213.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270CVE\344\270\223\351\241\271/\351\241\271\347\233\256\347\256\200\344\273\213.md"
new file mode 100644
index 0000000000000000000000000000000000000000..7fe512a097fbcdbf1be0f66957c0653f2662729e
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270CVE\344\270\223\351\241\271/\351\241\271\347\233\256\347\256\200\344\273\213.md"
@@ -0,0 +1,4 @@
+本项目专注于:
+- 高危CVE的分析、POC和处理。
+- 龙蜥社区贡献的CVE案例分享。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220.md"
new file mode 100644
index 0000000000000000000000000000000000000000..b66bf0b7b6301cee323eacf33ae1b05836ebccda
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220.md"
@@ -0,0 +1,641 @@
+
+
+
+前面一篇文章中,我们简要的osnoise的相关信息,本篇文章主要针对其源代码进行分析阐述。
+
+
+
+# 一、数据结构:
+
+
+
+```
+/*
+ * NMI runtime info.
+ */
+struct osn_nmi {
+ u64 count;
+ u64 delta_start;
+};
+
+/*
+ * IRQ runtime info.
+ */
+struct osn_irq {
+ u64 count;
+ u64 arrival_time;
+ u64 delta_start;
+};
+
+#define IRQ_CONTEXT 0
+#define THREAD_CONTEXT 1
+/*
+ * sofirq runtime info.
+ */
+struct osn_softirq {
+ u64 count;
+ u64 arrival_time;
+ u64 delta_start;
+};
+
+/*
+ * thread runtime info.
+ */
+struct osn_thread {
+ u64 count;
+ u64 arrival_time;
+ u64 delta_start;
+};
+
+/*
+ * Runtime information: this structure saves the runtime information used by
+ * one sampling thread.
+ */
+struct osnoise_variables {
+ struct task_struct *kthread;
+ bool sampling;
+ pid_t pid;
+ struct osn_nmi nmi;
+ struct osn_irq irq;
+ struct osn_softirq softirq;
+ struct osn_thread thread;
+ local_t int_counter;
+};
+```
+
+
+osnoise用来记录结果的主要数据结构为`struct osnoise_variables`其中:
+
+
++ `struct task_struct *kthread`:采样线程的tcb。
++ `bool sampling`:采样开关
++ `pit_t pid`:采样线程的pid
++ `struct osn_nmi nmi`:保存nmi噪声的相关信息
++ `struct osn_irq irq`:保存irq噪声的相关信息
++ `struct osn_softiq softirq`:保存softirq噪声的相关信息
++ `struct osn_thread thread`:保存其他线程噪声的相关信息
++ `local_t int_counter`:保存噪声的总次数
+
+
+
+# 二、工作原理:
+
+
+## 2.1 注册trace\_point
+
+
+如第一篇,osnoise引入了一组trace\_point。通过这些trace\_point,开发人员可以获取噪声的详细信息。注册trace\_point的代码如下(以irq\_noise为例):
+
+
+
+```
+TRACE_EVENT(irq_noise,
+
+ TP_PROTO(int vector, const char *desc, u64 start, u64 duration),
+
+ TP_ARGS(vector, desc, start, duration),
+
+ TP_STRUCT__entry(
+ __field( u64, start )
+ __field( u64, duration)
+ __string( desc, desc )
+ __field( int, vector )
+
+ ),
+
+ TP_fast_assign(
+ __assign_str(desc, desc);
+ __entry->vector = vector;
+ __entry->start = start;
+ __entry->duration = duration;
+ ),
+
+ TP_printk("%s:%d start %llu.%09u duration %llu ns",
+ __get_str(desc),
+ __entry->vector,
+ __print_ns_to_secs(__entry->start),
+ __print_ns_without_secs(__entry->start),
+ __entry->duration)
+);
+```
+
+
+关于trace\_point这里我们不做过多介绍,感兴趣的读者可以去内核文件`include/trace/events/osnoise.h`下查看相应源代码。
+
+
+## 2.2 注册osnoise tracer
+
+
+这部分主要是涉及到osnoise的初始化过程,该过程主要就是将osnoise注册近ftrace中并且初始化相关的tracefs。注册的过程通过`register_tracer(&osnoise_tracer)`实现。
+
+
+
+```
+static struct tracer osnoise_tracer __read_mostly = {
+ .name = "osnoise",
+ .init = osnoise_tracer_init,
+ .reset = osnoise_tracer_reset,
+ .start = osnoise_tracer_start,
+ .stop = osnoise_tracer_stop,
+ .print_header = print_osnoise_headers,
+ .allow_instances = true,
+};
+```
+
+
+## 2.3 注册tracepoint钩子函数:
+
+
+osnoise 统计信息的方式就是通过在相应的tracepoint中注册钩子函数。因此这部分即是osnoise的核心部分,本篇文章将重点分析该模块。
+
+
+osnoise首先会将各种事件的钩子函数插入对应的tracepoint中,这一动作由`osnoise_hook_events()`函数执行,将该函数裁剪后如下:
+
+
+
+```
+static int osnoise_hook_events(void)
+{
+ ...
+ retval = hook_irq_events();
+ ...
+ retval = hook_softirq_events();
+ ...
+ retval = hook_thread_events();
+ ...
+}
+```
+
+
+该函数主要是针对irq、softirq、thread事件插入一些采样函数。
+
+
+### hook\_irq\_events
+
+
+hook\_irq\_events()主要是实现对irq事件的统计。如下:
+
+
+
+```
+static int hook_irq_events(void)
+{
+ ...
+ ret = register_trace_irq_handler_entry(trace_irqentry_callback, NULL);
+ ...
+ ret = register_trace_irq_handler_exit(trace_irqexit_callback, NULL);
+ ...
+}
+```
+
+
+主要是在irq\_handler\_entry 和 irq\_handler\_exit处插入相应的处理函数。最终插入的处理函数为osnoise\_trace\_irq\_entry() 和 osnoise\_trace\_irq\_exit()。
+
+
+
+```
+void osnoise_trace_irq_entry(int id)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+
+ if (!osn_var->sampling)
+ return;
+
+ osn_var->irq.arrival_time = time_get();
+ set_int_safe_time(osn_var, &osn_var->irq.delta_start);
+ osn_var->irq.count++;
+
+ local_inc(&osn_var->int_counter);
+}
+void osnoise_trace_irq_exit(int id, const char *desc)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+ int duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ duration = get_int_safe_duration(osn_var, &osn_var->irq.delta_start);
+ trace_irq_noise(id, desc, osn_var->irq.arrival_time, duration);
+ osn_var->irq.arrival_time = 0;
+ cond_move_softirq_delta_start(osn_var, duration);
+ cond_move_thread_delta_start(osn_var, duration);
+}
+```
+
+
+在irq handler的入口处插入的函数为osnoise\_trace\_irq\_entry,分析该函数:
+
+
++ 在irq.arrival\_time中记录本次irq事件的开始时间。
++ 在irq.delta\_start中记录本次irq事件的准确开始时间。
++ irq噪声事件的次数+1。
++ 噪声事件总体次数+1。
+
+
+在这里我们发现,除了在irq.arrival\_time中记录了一个irq开始时间之外,还通过set\_int\_safe\_time函数在 irq.delta\_start中都记录了一个开始时间。那么他们之间有什么区别呢?在这里我们先按下不表,后文会对其进行解释分析。
+
+
+在irq handler的出口处插入的函数为osnoise\_trace\_irq\_exit,该函数的主要作用:
+
+
++ 根据之前记录的osn\_var->irq.delta\_start计算出本次irq事件的持续时间。
++ 调用trace\_irq\_noise将本次irq事件的**中断号,中断名称、开始时间、持续时间**放到ftrace的ringbuffer中。
++ 清空osn\_var->irq.arrival\_time 表示此次irq事件结束。
+
+
+我们注意到在该函数的末尾处有cond\_move\_softirq\_delta\_start 以及 cond\_move\_thread\_delta\_start函数。其实形如此类的函数一共有三个:
+
+
++ cond\_move\_irq\_delta\_start
++ cond\_move\_softirq\_delta\_start
++ cond\_move\_thread\_delta\_start
+
+
+函数的形式都是一样的,我们以 cond\_move\_softirq\_delta\_start()为例:
+
+
+
+```
+static inline void
+cond_move_softirq_delta_start(struct osnoise_variables *osn_var, u64 duration)
+{
+ if (osn_var->softirq.delta_start)
+ osn_var->softirq.delta_start += duration;
+}
+```
+
+
++ 这个函数会在osnoise\_trace\_irq\_exit、trace\_osnoise\_callback中调用,前者我们知道是irq事件退出时的钩子函数,而后者则是nmi事件的钩子函数。
++ 可以看到该函数的主要功能是将softirq.delta\_start的开始时间推后一个duration。
+
+
+换句话说,这个函数是为了校准低优先级事件的开始时间。以下图为例:
+
+
++ 在t1时刻进入了softirq,此时记录**softirq.arrival\_time = t1**,**softirq.delta\_time = t1**。
++ 然后在t2时刻,来了一个irq抢占了softirq,进入irq的执行函数。
++ t3时刻离开irq执行完毕继续执行softirq。irq执行时间**duration = t3-t2**。同时调用cond\_move\_softirq\_delta\_start,更新softirq开始时间**softirq.delta\_start += duration;**
++ 在t4时刻softirq执行完毕退出。
+
+
+那么本次softirq的持续时间实际上应该是t4 - (t1 + duration) = t4 - **softirq.delta\_start。**
+
+
+
+
+因此,需要高优先级的对低优先级的事件的时间进行校准。
+
+
++ 对于nmi事件,需要调用
+
+
+- cond\_move\_irq\_delta\_start
+- cond\_move\_softirq\_delta\_start
+- cond\_move\_thread\_delta\_start
+
+
++ 对于irq事件,需要调用
+
+
+- cond\_move\_softirq\_delta\_start
+- cond\_move\_thread\_delta\_start
+
+
++ 对于softirq事件,需要调用
+
+
+- cond\_move\_thread\_delta\_start
+
+
+### hook\_softirq\_events
+
+
+与irq的钩子函数一样,需要注册tracepoint softirq\_entry、softirq\_exit的钩子函数。最终注册的钩子函数如下:
+
+
+
+```
+static void trace_softirq_entry_callback(void *data, unsigned int vec_nr)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+
+ if (!osn_var->sampling)
+ return;
+
+ osn_var->softirq.arrival_time = time_get();
+ set_int_safe_time(osn_var, &osn_var->softirq.delta_start);
+ osn_var->softirq.count++;
+
+ local_inc(&osn_var->int_counter);
+}
+static void trace_softirq_exit_callback(void *data, unsigned int vec_nr)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+ int duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ if (unlikely(timerlat_enabled()))
+ if (!timerlat_softirq_exit(osn_var))
+ return;
+
+ duration = get_int_safe_duration(osn_var, &osn_var->softirq.delta_start);
+ trace_softirq_noise(vec_nr, osn_var->softirq.arrival_time, duration);
+ cond_move_thread_delta_start(osn_var, duration);
+ osn_var->softirq.arrival_time = 0;
+}
+```
+
+
+可以发现对softirq的统计方式与对irq的统计方式一摸一样,在这里我们便不做详细分析,读者可以参考上面对hook\_irq\_events()的分析。
+
+
+### hook\_thread\_events
+
+
+osnoise通过在tracepoint sched\_switch注册钩子函数,来统计thread noise。函数如下所示:
+
+
+
+```
+static void
+trace_sched_switch_callback(void *data, bool preempt,
+ struct task_struct *p,
+ struct task_struct *n,
+ unsigned int prev_state)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+
+ if (p->pid != osn_var->pid)
+ thread_exit(osn_var, p);
+
+ if (n->pid != osn_var->pid)
+ thread_entry(osn_var, n);
+}
+static void
+thread_entry(struct osnoise_variables *osn_var, struct task_struct *t)
+{
+ if (!osn_var->sampling)
+ return;
+ /*
+ * The arrival time will be used in the report, but not to compute
+ * the execution time, so it is safe to get it unsafe.
+ */
+ osn_var->thread.arrival_time = time_get();
+
+ set_int_safe_time(osn_var, &osn_var->thread.delta_start);
+
+ osn_var->thread.count++;
+ local_inc(&osn_var->int_counter);
+}
+static void
+thread_exit(struct osnoise_variables *osn_var, struct task_struct *t)
+{
+ int duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ if (unlikely(timerlat_enabled()))
+ if (!timerlat_thread_exit(osn_var))
+ return;
+
+ duration = get_int_safe_duration(osn_var, &osn_var->thread.delta_start);
+
+ trace_thread_noise(t, osn_var->thread.arrival_time, duration);
+
+ osn_var->thread.arrival_time = 0;
+}
+```
+
+
+sched\_switch()为线程切换的核心函数,在该trace\_sched\_switch函数中的p表示前一个线程,n表示下一个要执行的线程,即从线程p切换到线程n。
+
+
+此时存在三种情况:
+
+
++ 从采样线程切换到其他线程
+
+
+- 执行thread\_entry()函数,标志一个噪声的进入
+
+
++ 从其他线程切换到采样线程
+
+
+- 执行thread\_exit()函数,标志上一个噪声的结束
+
+
++ 从其他线程切换到其他线程
+
+
+- 先执行thread\_exit()函数,标志上一个噪声的结束
+- 再执行thread\_entry()函数,标志下一个噪声的进入
+
+
+换句话说,该钩子函数会统计除了采样线程外其他所有线程执行的时间。其中thread\_entry()和thread\_exit()的具体实现与上面对irq事件统计的函数实现类似,此处不再过多赘述。
+
+
+### nmi\_events
+
+
+对于NMI事件的统计比较特殊,在ftrace\_nmi\_enter和ftrace\_nmi\_exit中直接调用trace\_osnoise\_callback获取nmi noise,并且调用trace\_nmi\_noise将duration放到ftrace的ringbuffer中。
+
+
+
+```
+static inline void ftrace_nmi_exit(void)
+{
+ ...
+ if (trace_osnoise_callback_enabled)
+ trace_osnoise_callback(false);
+ ...
+}
+static inline void ftrace_nmi_exit(void)
+{
+ ...
+ if (trace_osnoise_callback_enabled)
+ trace_osnoise_callback(false);
+ ...
+}
+void trace_osnoise_callback(bool enter)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+ u64 duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ /*
+ * Currently trace_clock_local() calls sched_clock() and the
+ * generic version is not NMI safe.
+ */
+ if (!IS_ENABLED(CONFIG_GENERIC_SCHED_CLOCK)) {
+ if (enter) {
+ osn_var->nmi.delta_start = time_get();
+ local_inc(&osn_var->int_counter);
+ } else {
+ duration = time_get() - osn_var->nmi.delta_start;
+
+ trace_nmi_noise(osn_var->nmi.delta_start, duration);
+
+ cond_move_irq_delta_start(osn_var, duration);
+ cond_move_softirq_delta_start(osn_var, duration);
+ cond_move_thread_delta_start(osn_var, duration);
+ }
+ }
+
+ if (enter)
+ osn_var->nmi.count++;
+}
+```
+
+
+主要函数为trace\_osnoise\_callback(bool enter),该函数通过一个bool值来判断当前是进入nmi中断还是退出nmi中断,进而进行相应的处理,统计方法和其他事件统计方法一直。可以看到在NMI的钩子函数中,会调用到
+
+
++ cond\_move\_irq\_delta\_start(osn\_var, duration);
++ cond\_move\_softirq\_delta\_start(osn\_var, duration);
++ cond\_move\_softirq\_delta\_start(osn\_var, duration);
+
+
+这三个函数去校准其他低优先级事件的统计。与我们之前的分析一致。
+
+
+## 2.4 采样
+
+
+上面介绍了osnoise对各类事件采样的方法,接下来,我们分析一下osnoise的采样流程。osnoise开始采样的函数调用流程为osnoise\_tracer\_start->osnoise\_workload\_start->start\_per\_cpu\_kthreads->start\_kthread->osnoise\_main->run\_osnoise。
+
+
+
+采样的核心函数为run\_osnoise,将代码裁剪后如下:
+
+
+
+```
+static int run_osnoise(void)
+{
+ ...
+
+ threshold = tracing_thresh ? : 5000;
+
+ osn_var->sampling = true;
+
+ runtime = osnoise_data.sample_runtime * NSEC_PER_USEC;
+
+ stop_in = osnoise_data.stop_tracing * NSEC_PER_USEC;
+
+ start = time_get();
+
+ last_int_count = set_int_safe_time(osn_var, &last_sample);
+
+ do {
+
+ int_count = set_int_safe_time(osn_var, &sample);
+
+ noise = time_sub(sample, last_sample);
+
+ total = time_sub(sample, start);
+
+ if (total < last_total) {
+ osnoise_taint("total overflow!");
+ break;
+ }
+
+ last_total = total;
+
+ if (noise >= threshold) {
+ int interference = int_count - last_int_count;
+
+ if (noise > max_noise)
+ max_noise = noise;
+
+ if (!interference)
+ hw_count++;
+
+ sum_noise += noise;
+
+ trace_sample_threshold(last_sample, noise, interference);
+
+ if (osnoise_data.stop_tracing)
+ if (noise > stop_in)
+ osnoise_stop_tracing();
+ }
+
+ last_sample = sample;
+ last_int_count = int_count;
+
+ } while (total < runtime && !kthread_should_stop());
+
+ osn_var->sampling = false;
+
+ ...
+}
+```
+
+
+
+分析采样函数的主体逻辑流程图如下所示:
+
+
+
+
+
+即通过不断的轮询TSC寄存器,将每次轮询的间隙与预设的threshold进行对比,判断是否发生噪声,如果发生了噪声且噪声不是由其他可测量事件所造成的,就认为发生了硬件噪声。
+
+
+其中:
+
+
+* threshold :两次轮询TSC寄存器时间之差,被认为是噪声的最小值,默认设为5us。
+* osn\_var->sampling:标志位,标志是否开启采样。
+* runtime:预设的本次采样时间。
+* start :记录本次采样开始的时间
+* last\_sample : 记录上次读取tsc寄存器的值
+* sample : 记录本次读取tsc寄存器的值
+* noise = time\_sub(sample, last\_sample) : 计算本次和上次轮询tsc寄存器的时间之差。
+* total :记录从采样开始到现在所经历的时间
+* 如果noise >= threshold,则视为发生了噪声,进行统计计算
+
+
++ max\_noise: 记录最大的单个噪声值
++ interference: 记录本次噪声内事件发生的次数,如果为0则代表是硬件噪声。
++ hw\_count: 记录硬件噪声的次数,当interference为0时,增加。
+
+
+* 轮询tsc寄存器,直到total>=runtime,结束本次采样。
+
+
+
+# 三、小结
+
+
+以上便是对osnoise的代码分析。osnoise就是站在一个普通进程的视角上,统计所有会打断他的事件,包含irq、softirq、nmi、thread、hw。
+
+
+对于前四种事件内核中都提供了相应的tracepoint,只需要注册相应的回掉函数到tracepoint中即可统计到相关的信息。而hw无法被直接统计测量,因此在osnoise中就通过不断的轮询tsc寄存器,将任意两次轮询的差值与threshold进行比较,如果大于threshold就认为发生了噪声,当发生噪声时如果其他四个事件都未发生就认为发生了硬件延迟。
+
+
+由于irq、softirq、nmi、thread都有相应的tracepoint可以供我们使用,在不考虑hw的情况下我们其实可以直接在用户态实现相关信息的采集。下篇文章我们会尝试在用户态,利用bcc通过动态插桩的方式来实现一个简单的osnoise背景噪声统计工具。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace_osnoise_\346\200\273\350\247\210.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace_osnoise_\346\200\273\350\247\210.md"
new file mode 100644
index 0000000000000000000000000000000000000000..782c9a33160ade07820bfa6300aa0fd6cc5779c9
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace_osnoise_\346\200\273\350\247\210.md"
@@ -0,0 +1,179 @@
+
+
+
+# Ftrace: osnoise 总览
+
+
+
+
+
+
+
+
+
+
+
+## 一、osnoise是什么?
+
+
+
+
+在linux系统中,一个普通线程在执行过程中会被各种各样的事件所干扰打断,如NMI、IRQ、SOFTIRQ、来自硬件的干扰以及来自其他线程的干扰。这些事件对于一个普通线程来说,就相当于噪声一样的存在。在Linux 5.14-rc1中,引入了一个新的tracer——osnoise tracer。osnoise从一个线程的视角出发,统计出所有对他有干扰的噪声,进而协助开发人员分析系统背景噪声情况。
+
+
+### 1.1 噪声分类
+
+
+在osnoise tracer中,将统计的噪声分为了以下五个大类:
+
+
++ IRQ:硬中断
++ SOFTIRQ:软中断
++ NMI:不可屏蔽中断
++ HW:来自硬件的噪声。
++ THREAD:来自其他线程的影响。
+
+
+其中,HW(hardware latency)表示某些底层硬件或者固件的行为引起的大型系统延迟。在Ftrace中,有一个名为hwlat\_detector的tracer,它的主要目的就是用来检测硬件噪声。osnoise的设计思想借鉴了hwlat\_detector。
+
+
+### 1.2 hwlat
+
+
+hwlat\_detector的工作原理简单来说就是在一段时间内,关闭irq、softirq以及抢占,然后不断的去轮询TSC(Time Stamp Counter)寄存器的值。由于关闭了中断及抢占,任意两次读取之间的间隙都是由于硬件噪声或者来自其他不可屏蔽中断的噪声(NMI)。
+
+
+如图所示:
+
+
+
+
+
+在一段时间内,采样线程不断的去循环读取TSC寄存器,在一个循环内会连续读取两次TSC寄存器。假设本次循环读取的时间分别为t1、t2,上次循环读取的时间为last\_t1、last\_t2。则:
+
+
++ t1与t2的时间之差,last\_t1、last\_t2的时间之差,称为inner\_latency。
++ t1与last\_t2的时间之差,称为outer\_latency。
++ tracing\_thresh为预设的阀值,如果观察到任何超过阀值的延迟就认为发生了噪声事件。
++ 在hwlat中,会不断的计算inner\_latency和outer\_latency。然后将其值与预设的tracing\_thresh值进行对比,如果大于tracing\_thresh,就认为发生了噪声事件。
++ 在hwlat采样期间,会同时追踪nmi中断事件。因此,观察到的任何超过阀值的延迟如果不是nmi造成的,那么就认为是hardware latency。
+
+
+### 1.3 osnoise实现
+
+
+前面我们介绍了hwlat的实现。简而言之,hwlat关闭irq、softirq、抢占等事件,通过不断的轮询TSC寄存器以及追踪NMI中断来探测延迟事件,观察到的任何延迟都是由NMI或者硬件造成的。
+
+
+osnoise的实现思想和hwlat类似,不过osnoise不会关闭irq、softirq、抢占等事件,而是在采样的同时追踪各类事件。在irq\_handler\_entry、irq\_handler\_exit、softirq\_entry、softirq\_exit、sched\_switch、nmi\_enter、nmi\_exit处也插入相应的钩子函数。进而统计出各类事件发生的次数以及持续时间。如果观测到的任意延迟不是由以上时间造成的,那么就认为是硬件噪声。
+
+
+## 二、osnoise tracer
+
+
+### 2.1 配置文件
+
+
+osnoise在`/sys/kernel/debug/tracing/` 目录下有一系列可配置文件, 含义如下:
+
+
+* **osnoise/cpus:** osnoise采样的目标cpu,默认是所有cpu。
+* **osnoise/period\_us:** osnoise线程的周期。默认是1000000ms,即1s。
+* **osnoise/runtime\_us:** osnoise线程在一个周期内的采样时间。默认是1000000ms,即1s。
+* **osnoise/stop\_tracing\_us:** 当单个噪声的最大值超过这个阀值时,停止采样。默认为0,即关闭该选项。
+* **osnoise/stop\_tracing\_total\_us:** 当总计噪声超过这个阀值时,停止采样。默认为0,即关闭该选项。
+* **tracing\_thresh**: 两次轮询TSC寄存器时间之差,被认为是噪声的最小值,单位为us。当配置为0时,默认设为5us。
+
+
+### 2.2 使用方法
+
+
+1. 将osnoise写入的current\_tracer:
+
+
+`echo osnoise > /sys/kernel/debug/tracing/current_tracer`
+
+
+2. 打开traceing\_on:
+
+
+`echo 1 > /sys/kernel/debug/tracing/tracing_on`
+
+
+3. 查看trace结果:
+
+
+`cat /sys/kernel/debug/tracing/trace`
+
+
+
+
+
+
+
+
+这里显示的是系统整体采样的结果各个字段的含义如下:
+
+
+* TASK-PID:采样线程的PID。
+* CPU:采样的CPU ID
+* TIMESTAMP:时间戳
+* RUNTIME IN US:采样时间,单位us
+* NOISE IN US:本次采样时间内的总计噪声时间,单位us。
+* %OF CPU AVAILABLE:在一个RUNTIME周期内,采样线程可以获得的cpu利用率。
+* HW、NMI、IRQ、SIRQ、THREAD:分别表示各类噪声事件发生的次数。
+
+
+## 三、osnoise trace\_point
+
+
+### 3.1 trace\_point
+
+
+osnoise除了提供tracer外,还提供了一组trace\_points,以协助开发人员对噪声进行进一步分析。可以在`/sys/kernel/debug/tracing/events/osnoise/`看到相关tracepoint:
+
+
+* **sample\_threshold:** 追踪任何高于阀值的噪声事件。阀值即为上文提到的tracing\_thresh,默认为5us。
+* **nmi\_noise:** nmi噪声,包含其持续时间。
+* **irq\_noise:** irq噪声,包含其持续时间。
+* **softirq\_noise:** softirq噪声,包含其持续时间
+* **thread\_noise:** 其他线程噪声,包含其持续时间
+
+
+### 3.2 使用方法
+
+
+前面我们已经介绍了osnoise tracer的使用,它可以让我们直观的看到整个系统级别的各种噪声事件的总和。如果我们像看到每种噪声或者是说指定噪声类型的事件的详细信息,就需要用到osnoise提供的trace\_point。
+
+
+打开trace\_point总开关:
+
+
+`echo 1 > /sys/kernel/debug/tracing/events/osnoise/enable`
+
+
+查看trace日志:
+
+
+`cat /sys/kernel/debug/tracing/trace`
+
+
+输出如下所示:
+
+
+
+
+
+
+日志中包含了所有噪声的详细信息,包括其名字,开始事件,持续时间等等。关于其输出的具体格式可以查看对应trace\_point文件夹下的format文件。
+
+
+trace\_ponit文件位置在`/sys/kernel/debug/tracing/events/osnoise/`下。
+
+
+除了总开关外,每个事件有自己单独的开关,在对应tracepoint目录下。如irq\_noise的开关为`/sys/kernel/debug/tracing/events/osnoise/irq_noise/enable`。用户可以根据自己的需求只追踪相应的事件,从而过滤掉其他不需要关注的信息。
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220.md"
new file mode 100644
index 0000000000000000000000000000000000000000..d8d8d5f7ea67371721d640d941991d8ea0ad4191
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220.md"
@@ -0,0 +1,641 @@
+
+
+
+前面一篇文章中,我们简要的介绍了一下osnoise的相关信息,本篇文章主要针对其源代码进行分析阐述。
+
+
+
+# 一、数据结构:
+
+
+
+```
+/*
+ * NMI runtime info.
+ */
+struct osn_nmi {
+ u64 count;
+ u64 delta_start;
+};
+
+/*
+ * IRQ runtime info.
+ */
+struct osn_irq {
+ u64 count;
+ u64 arrival_time;
+ u64 delta_start;
+};
+
+#define IRQ_CONTEXT 0
+#define THREAD_CONTEXT 1
+/*
+ * sofirq runtime info.
+ */
+struct osn_softirq {
+ u64 count;
+ u64 arrival_time;
+ u64 delta_start;
+};
+
+/*
+ * thread runtime info.
+ */
+struct osn_thread {
+ u64 count;
+ u64 arrival_time;
+ u64 delta_start;
+};
+
+/*
+ * Runtime information: this structure saves the runtime information used by
+ * one sampling thread.
+ */
+struct osnoise_variables {
+ struct task_struct *kthread;
+ bool sampling;
+ pid_t pid;
+ struct osn_nmi nmi;
+ struct osn_irq irq;
+ struct osn_softirq softirq;
+ struct osn_thread thread;
+ local_t int_counter;
+};
+```
+
+
+osnoise用来记录结果的主要数据结构为`struct osnoise_variables`其中:
+
+
++ `struct task_struct *kthread`:采样线程的tcb。
++ `bool sampling`:采样开关
++ `pit_t pid`:采样线程的pid
++ `struct osn_nmi nmi`:保存nmi噪声的相关信息
++ `struct osn_irq irq`:保存irq噪声的相关信息
++ `struct osn_softiq softirq`:保存softirq噪声的相关信息
++ `struct osn_thread thread`:保存其他线程噪声的相关信息
++ `local_t int_counter`:保存噪声的总次数
+
+
+
+# 二、工作原理:
+
+
+## 2.1 注册trace\_point
+
+
+如第一篇文章所述,osnoise引入了一组trace\_point。通过这些trace\_point,开发人员可以获取噪声的详细信息。注册trace\_point的代码如下(以irq\_noise为例):
+
+
+
+```
+TRACE_EVENT(irq_noise,
+
+ TP_PROTO(int vector, const char *desc, u64 start, u64 duration),
+
+ TP_ARGS(vector, desc, start, duration),
+
+ TP_STRUCT__entry(
+ __field( u64, start )
+ __field( u64, duration)
+ __string( desc, desc )
+ __field( int, vector )
+
+ ),
+
+ TP_fast_assign(
+ __assign_str(desc, desc);
+ __entry->vector = vector;
+ __entry->start = start;
+ __entry->duration = duration;
+ ),
+
+ TP_printk("%s:%d start %llu.%09u duration %llu ns",
+ __get_str(desc),
+ __entry->vector,
+ __print_ns_to_secs(__entry->start),
+ __print_ns_without_secs(__entry->start),
+ __entry->duration)
+);
+```
+
+
+关于trace\_point这里我们不做过多介绍,感兴趣的读者可以去内核文件`include/trace/events/osnoise.h`下查看相应源代码。
+
+
+## 2.2 注册osnoise tracer
+
+
+这部分主要是涉及到osnoise的初始化过程,该过程主要就是将osnoise注册近ftrace中并且初始化相关的tracefs。注册的过程通过`register_tracer(&osnoise_tracer)`实现。
+
+
+
+```
+static struct tracer osnoise_tracer __read_mostly = {
+ .name = "osnoise",
+ .init = osnoise_tracer_init,
+ .reset = osnoise_tracer_reset,
+ .start = osnoise_tracer_start,
+ .stop = osnoise_tracer_stop,
+ .print_header = print_osnoise_headers,
+ .allow_instances = true,
+};
+```
+
+
+## 2.3 注册tracepoint钩子函数:
+
+
+osnoise 统计信息的方式就是通过在相应的tracepoint中注册钩子函数。因此这部分即是osnoise的核心部分,本篇文章将重点分析该模块。
+
+
+osnoise首先会将各种事件的钩子函数插入对应的tracepoint中,这一动作由`osnoise_hook_events()`函数执行,将该函数裁剪后如下:
+
+
+
+```
+static int osnoise_hook_events(void)
+{
+ ...
+ retval = hook_irq_events();
+ ...
+ retval = hook_softirq_events();
+ ...
+ retval = hook_thread_events();
+ ...
+}
+```
+
+
+该函数主要是针对irq、softirq、thread事件插入一些采样函数。
+
+
+### hook\_irq\_events
+
+
+hook\_irq\_events()主要是实现对irq事件的统计。如下:
+
+
+
+```
+static int hook_irq_events(void)
+{
+ ...
+ ret = register_trace_irq_handler_entry(trace_irqentry_callback, NULL);
+ ...
+ ret = register_trace_irq_handler_exit(trace_irqexit_callback, NULL);
+ ...
+}
+```
+
+
+主要是在irq\_handler\_entry 和 irq\_handler\_exit处插入相应的处理函数。最终插入的处理函数为osnoise\_trace\_irq\_entry() 和 osnoise\_trace\_irq\_exit()。
+
+
+
+```
+void osnoise_trace_irq_entry(int id)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+
+ if (!osn_var->sampling)
+ return;
+
+ osn_var->irq.arrival_time = time_get();
+ set_int_safe_time(osn_var, &osn_var->irq.delta_start);
+ osn_var->irq.count++;
+
+ local_inc(&osn_var->int_counter);
+}
+void osnoise_trace_irq_exit(int id, const char *desc)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+ int duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ duration = get_int_safe_duration(osn_var, &osn_var->irq.delta_start);
+ trace_irq_noise(id, desc, osn_var->irq.arrival_time, duration);
+ osn_var->irq.arrival_time = 0;
+ cond_move_softirq_delta_start(osn_var, duration);
+ cond_move_thread_delta_start(osn_var, duration);
+}
+```
+
+
+在irq handler的入口处插入的函数为osnoise\_trace\_irq\_entry,分析该函数:
+
+
++ 在irq.arrival\_time中记录本次irq事件的开始时间。
++ 在irq.delta\_start中记录本次irq事件的准确开始时间。
++ irq噪声事件的次数+1。
++ 噪声事件总体次数+1。
+
+
+在这里我们发现,除了在irq.arrival\_time中记录了一个irq开始时间之外,还通过set\_int\_safe\_time函数在 irq.delta\_start中都记录了一个开始时间。那么他们之间有什么区别呢?在这里我们先按下不表,后文会对其进行解释分析。
+
+
+在irq handler的出口处插入的函数为osnoise\_trace\_irq\_exit,该函数的主要作用:
+
+
++ 根据之前记录的osn\_var->irq.delta\_start计算出本次irq事件的持续时间。
++ 调用trace\_irq\_noise将本次irq事件的**中断号,中断名称、开始时间、持续时间**放到ftrace的ringbuffer中。
++ 清空osn\_var->irq.arrival\_time 表示此次irq事件结束。
+
+
+我们注意到在该函数的末尾处有cond\_move\_softirq\_delta\_start 以及 cond\_move\_thread\_delta\_start函数。其实形如此类的函数一共有三个:
+
+
++ cond\_move\_irq\_delta\_start
++ cond\_move\_softirq\_delta\_start
++ cond\_move\_thread\_delta\_start
+
+
+函数的形式都是一样的,我们以 cond\_move\_softirq\_delta\_start()为例:
+
+
+
+```
+static inline void
+cond_move_softirq_delta_start(struct osnoise_variables *osn_var, u64 duration)
+{
+ if (osn_var->softirq.delta_start)
+ osn_var->softirq.delta_start += duration;
+}
+```
+
+
++ 这个函数会在osnoise\_trace\_irq\_exit、trace\_osnoise\_callback中调用,前者我们知道是irq事件退出时的钩子函数,而后者则是nmi事件的钩子函数。
++ 可以看到该函数的主要功能是将softirq.delta\_start的开始时间推后一个duration。
+
+
+换句话说,这个函数是为了校准低优先级事件的开始时间。以下图为例:
+
+
++ 在t1时刻进入了softirq,此时记录**softirq.arrival\_time = t1**,**softirq.delta\_time = t1**。
++ 然后在t2时刻,来了一个irq抢占了softirq,进入irq的执行函数。
++ t3时刻离开irq执行完毕继续执行softirq。irq执行时间**duration = t3-t2**。同时调用cond\_move\_softirq\_delta\_start,更新softirq开始时间**softirq.delta\_start += duration;**
++ 在t4时刻softirq执行完毕退出。
+
+
+那么本次softirq的持续时间实际上应该是t4 - (t1 + duration) = t4 - **softirq.delta\_start。**
+
+
+
+
+因此,需要高优先级的对低优先级的事件的时间进行校准。
+
+
++ 对于nmi事件,需要调用
+
+
+- cond\_move\_irq\_delta\_start
+- cond\_move\_softirq\_delta\_start
+- cond\_move\_thread\_delta\_start
+
+
++ 对于irq事件,需要调用
+
+
+- cond\_move\_softirq\_delta\_start
+- cond\_move\_thread\_delta\_start
+
+
++ 对于softirq事件,需要调用
+
+
+- cond\_move\_thread\_delta\_start
+
+
+### hook\_softirq\_events
+
+
+与irq的钩子函数一样,需要注册tracepoint softirq\_entry、softirq\_exit的钩子函数。最终注册的钩子函数如下:
+
+
+
+```
+static void trace_softirq_entry_callback(void *data, unsigned int vec_nr)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+
+ if (!osn_var->sampling)
+ return;
+
+ osn_var->softirq.arrival_time = time_get();
+ set_int_safe_time(osn_var, &osn_var->softirq.delta_start);
+ osn_var->softirq.count++;
+
+ local_inc(&osn_var->int_counter);
+}
+static void trace_softirq_exit_callback(void *data, unsigned int vec_nr)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+ int duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ if (unlikely(timerlat_enabled()))
+ if (!timerlat_softirq_exit(osn_var))
+ return;
+
+ duration = get_int_safe_duration(osn_var, &osn_var->softirq.delta_start);
+ trace_softirq_noise(vec_nr, osn_var->softirq.arrival_time, duration);
+ cond_move_thread_delta_start(osn_var, duration);
+ osn_var->softirq.arrival_time = 0;
+}
+```
+
+
+可以发现对softirq的统计方式与对irq的统计方式一摸一样,在这里我们便不做详细分析,读者可以参考上面对hook\_irq\_events()的分析。
+
+
+### hook\_thread\_events
+
+
+osnoise通过在tracepoint sched\_switch注册钩子函数,来统计thread noise。函数如下所示:
+
+
+
+```
+static void
+trace_sched_switch_callback(void *data, bool preempt,
+ struct task_struct *p,
+ struct task_struct *n,
+ unsigned int prev_state)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+
+ if (p->pid != osn_var->pid)
+ thread_exit(osn_var, p);
+
+ if (n->pid != osn_var->pid)
+ thread_entry(osn_var, n);
+}
+static void
+thread_entry(struct osnoise_variables *osn_var, struct task_struct *t)
+{
+ if (!osn_var->sampling)
+ return;
+ /*
+ * The arrival time will be used in the report, but not to compute
+ * the execution time, so it is safe to get it unsafe.
+ */
+ osn_var->thread.arrival_time = time_get();
+
+ set_int_safe_time(osn_var, &osn_var->thread.delta_start);
+
+ osn_var->thread.count++;
+ local_inc(&osn_var->int_counter);
+}
+static void
+thread_exit(struct osnoise_variables *osn_var, struct task_struct *t)
+{
+ int duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ if (unlikely(timerlat_enabled()))
+ if (!timerlat_thread_exit(osn_var))
+ return;
+
+ duration = get_int_safe_duration(osn_var, &osn_var->thread.delta_start);
+
+ trace_thread_noise(t, osn_var->thread.arrival_time, duration);
+
+ osn_var->thread.arrival_time = 0;
+}
+```
+
+
+sched\_switch()为线程切换的核心函数,在该trace\_sched\_switch函数中的p表示前一个线程,n表示下一个要执行的线程,即从线程p切换到线程n。
+
+
+此时存在三种情况:
+
+
++ 从采样线程切换到其他线程
+
+
+- 执行thread\_entry()函数,标志一个噪声的进入
+
+
++ 从其他线程切换到采样线程
+
+
+- 执行thread\_exit()函数,标志上一个噪声的结束
+
+
++ 从其他线程切换到其他线程
+
+
+- 先执行thread\_exit()函数,标志上一个噪声的结束
+- 再执行thread\_entry()函数,标志下一个噪声的进入
+
+
+换句话说,该钩子函数会统计除了采样线程外其他所有线程执行的时间。其中thread\_entry()和thread\_exit()的具体实现与上面对irq事件统计的函数实现类似,此处不再过多赘述。
+
+
+### nmi\_events
+
+
+对于NMI事件的统计比较特殊,在ftrace\_nmi\_enter和ftrace\_nmi\_exit中直接调用trace\_osnoise\_callback获取nmi noise,并且调用trace\_nmi\_noise将duration放到ftrace的ringbuffer中。
+
+
+
+```
+static inline void ftrace_nmi_exit(void)
+{
+ ...
+ if (trace_osnoise_callback_enabled)
+ trace_osnoise_callback(false);
+ ...
+}
+static inline void ftrace_nmi_exit(void)
+{
+ ...
+ if (trace_osnoise_callback_enabled)
+ trace_osnoise_callback(false);
+ ...
+}
+void trace_osnoise_callback(bool enter)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+ u64 duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ /*
+ * Currently trace_clock_local() calls sched_clock() and the
+ * generic version is not NMI safe.
+ */
+ if (!IS_ENABLED(CONFIG_GENERIC_SCHED_CLOCK)) {
+ if (enter) {
+ osn_var->nmi.delta_start = time_get();
+ local_inc(&osn_var->int_counter);
+ } else {
+ duration = time_get() - osn_var->nmi.delta_start;
+
+ trace_nmi_noise(osn_var->nmi.delta_start, duration);
+
+ cond_move_irq_delta_start(osn_var, duration);
+ cond_move_softirq_delta_start(osn_var, duration);
+ cond_move_thread_delta_start(osn_var, duration);
+ }
+ }
+
+ if (enter)
+ osn_var->nmi.count++;
+}
+```
+
+
+主要函数为trace\_osnoise\_callback(bool enter),该函数通过一个bool值来判断当前是进入nmi中断还是退出nmi中断,进而进行相应的处理,统计方法和其他事件统计方法一直。可以看到在NMI的钩子函数中,会调用到
+
+
++ cond\_move\_irq\_delta\_start(osn\_var, duration);
++ cond\_move\_softirq\_delta\_start(osn\_var, duration);
++ cond\_move\_softirq\_delta\_start(osn\_var, duration);
+
+
+这三个函数去校准其他低优先级事件的统计。与我们之前的分析一致。
+
+
+## 2.4 采样
+
+
+上面介绍了osnoise对各类事件采样的方法,接下来,我们分析一下osnoise的采样流程。osnoise开始采样的函数调用流程为osnoise\_tracer\_start->osnoise\_workload\_start->start\_per\_cpu\_kthreads->start\_kthread->osnoise\_main->run\_osnoise。
+
+
+
+采样的核心函数为run\_osnoise,将代码裁剪后如下:
+
+
+
+```
+static int run_osnoise(void)
+{
+ ...
+
+ threshold = tracing_thresh ? : 5000;
+
+ osn_var->sampling = true;
+
+ runtime = osnoise_data.sample_runtime * NSEC_PER_USEC;
+
+ stop_in = osnoise_data.stop_tracing * NSEC_PER_USEC;
+
+ start = time_get();
+
+ last_int_count = set_int_safe_time(osn_var, &last_sample);
+
+ do {
+
+ int_count = set_int_safe_time(osn_var, &sample);
+
+ noise = time_sub(sample, last_sample);
+
+ total = time_sub(sample, start);
+
+ if (total < last_total) {
+ osnoise_taint("total overflow!");
+ break;
+ }
+
+ last_total = total;
+
+ if (noise >= threshold) {
+ int interference = int_count - last_int_count;
+
+ if (noise > max_noise)
+ max_noise = noise;
+
+ if (!interference)
+ hw_count++;
+
+ sum_noise += noise;
+
+ trace_sample_threshold(last_sample, noise, interference);
+
+ if (osnoise_data.stop_tracing)
+ if (noise > stop_in)
+ osnoise_stop_tracing();
+ }
+
+ last_sample = sample;
+ last_int_count = int_count;
+
+ } while (total < runtime && !kthread_should_stop());
+
+ osn_var->sampling = false;
+
+ ...
+}
+```
+
+
+
+分析采样函数的主体逻辑流程图如下所示:
+
+
+
+
+
+即通过不断的轮询TSC寄存器,将每次轮询的间隙与预设的threshold进行对比,判断是否发生噪声,如果发生了噪声且噪声不是由其他可测量事件所造成的,就认为发生了硬件噪声。
+
+
+其中:
+
+
+* threshold :两次轮询TSC寄存器时间之差,被认为是噪声的最小值,默认设为5us。
+* osn\_var->sampling:标志位,标志是否开启采样。
+* runtime:预设的本次采样时间。
+* start :记录本次采样开始的时间
+* last\_sample : 记录上次读取tsc寄存器的值
+* sample : 记录本次读取tsc寄存器的值
+* noise = time\_sub(sample, last\_sample) : 计算本次和上次轮询tsc寄存器的时间之差。
+* total :记录从采样开始到现在所经历的时间
+* 如果noise >= threshold,则视为发生了噪声,进行统计计算
+
+
++ max\_noise: 记录最大的单个噪声值
++ interference: 记录本次噪声内事件发生的次数,如果为0则代表是硬件噪声。
++ hw\_count: 记录硬件噪声的次数,当interference为0时,增加。
+
+
+* 轮询tsc寄存器,直到total>=runtime,结束本次采样。
+
+
+
+# 三、小结
+
+
+以上便是对osnoise的代码分析。osnoise就是站在一个普通进程的视角上,统计所有会打断他的事件,包含irq、softirq、nmi、thread、hw。
+
+
+对于前四种事件内核中都提供了相应的tracepoint,只需要注册相应的回掉函数到tracepoint中即可统计到相关的信息。而hw无法被直接统计测量,因此在osnoise中就通过不断的轮询tsc寄存器,将任意两次轮询的差值与threshold进行比较,如果大于threshold就认为发生了噪声,当发生噪声时如果其他四个事件都未发生就认为发生了硬件延迟。
+
+
+由于irq、softirq、nmi、thread都有相应的tracepoint可以供我们使用,在不考虑hw的情况下我们其实可以直接在用户态实现相关信息的采集。下篇文章我们会尝试在用户态,利用bcc通过动态插桩的方式来实现一个简单的osnoise背景噪声统计工具。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210.md"
new file mode 100644
index 0000000000000000000000000000000000000000..782c9a33160ade07820bfa6300aa0fd6cc5779c9
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210.md"
@@ -0,0 +1,179 @@
+
+
+
+# Ftrace: osnoise 总览
+
+
+
+
+
+
+
+
+
+
+
+## 一、osnoise是什么?
+
+
+
+
+在linux系统中,一个普通线程在执行过程中会被各种各样的事件所干扰打断,如NMI、IRQ、SOFTIRQ、来自硬件的干扰以及来自其他线程的干扰。这些事件对于一个普通线程来说,就相当于噪声一样的存在。在Linux 5.14-rc1中,引入了一个新的tracer——osnoise tracer。osnoise从一个线程的视角出发,统计出所有对他有干扰的噪声,进而协助开发人员分析系统背景噪声情况。
+
+
+### 1.1 噪声分类
+
+
+在osnoise tracer中,将统计的噪声分为了以下五个大类:
+
+
++ IRQ:硬中断
++ SOFTIRQ:软中断
++ NMI:不可屏蔽中断
++ HW:来自硬件的噪声。
++ THREAD:来自其他线程的影响。
+
+
+其中,HW(hardware latency)表示某些底层硬件或者固件的行为引起的大型系统延迟。在Ftrace中,有一个名为hwlat\_detector的tracer,它的主要目的就是用来检测硬件噪声。osnoise的设计思想借鉴了hwlat\_detector。
+
+
+### 1.2 hwlat
+
+
+hwlat\_detector的工作原理简单来说就是在一段时间内,关闭irq、softirq以及抢占,然后不断的去轮询TSC(Time Stamp Counter)寄存器的值。由于关闭了中断及抢占,任意两次读取之间的间隙都是由于硬件噪声或者来自其他不可屏蔽中断的噪声(NMI)。
+
+
+如图所示:
+
+
+
+
+
+在一段时间内,采样线程不断的去循环读取TSC寄存器,在一个循环内会连续读取两次TSC寄存器。假设本次循环读取的时间分别为t1、t2,上次循环读取的时间为last\_t1、last\_t2。则:
+
+
++ t1与t2的时间之差,last\_t1、last\_t2的时间之差,称为inner\_latency。
++ t1与last\_t2的时间之差,称为outer\_latency。
++ tracing\_thresh为预设的阀值,如果观察到任何超过阀值的延迟就认为发生了噪声事件。
++ 在hwlat中,会不断的计算inner\_latency和outer\_latency。然后将其值与预设的tracing\_thresh值进行对比,如果大于tracing\_thresh,就认为发生了噪声事件。
++ 在hwlat采样期间,会同时追踪nmi中断事件。因此,观察到的任何超过阀值的延迟如果不是nmi造成的,那么就认为是hardware latency。
+
+
+### 1.3 osnoise实现
+
+
+前面我们介绍了hwlat的实现。简而言之,hwlat关闭irq、softirq、抢占等事件,通过不断的轮询TSC寄存器以及追踪NMI中断来探测延迟事件,观察到的任何延迟都是由NMI或者硬件造成的。
+
+
+osnoise的实现思想和hwlat类似,不过osnoise不会关闭irq、softirq、抢占等事件,而是在采样的同时追踪各类事件。在irq\_handler\_entry、irq\_handler\_exit、softirq\_entry、softirq\_exit、sched\_switch、nmi\_enter、nmi\_exit处也插入相应的钩子函数。进而统计出各类事件发生的次数以及持续时间。如果观测到的任意延迟不是由以上时间造成的,那么就认为是硬件噪声。
+
+
+## 二、osnoise tracer
+
+
+### 2.1 配置文件
+
+
+osnoise在`/sys/kernel/debug/tracing/` 目录下有一系列可配置文件, 含义如下:
+
+
+* **osnoise/cpus:** osnoise采样的目标cpu,默认是所有cpu。
+* **osnoise/period\_us:** osnoise线程的周期。默认是1000000ms,即1s。
+* **osnoise/runtime\_us:** osnoise线程在一个周期内的采样时间。默认是1000000ms,即1s。
+* **osnoise/stop\_tracing\_us:** 当单个噪声的最大值超过这个阀值时,停止采样。默认为0,即关闭该选项。
+* **osnoise/stop\_tracing\_total\_us:** 当总计噪声超过这个阀值时,停止采样。默认为0,即关闭该选项。
+* **tracing\_thresh**: 两次轮询TSC寄存器时间之差,被认为是噪声的最小值,单位为us。当配置为0时,默认设为5us。
+
+
+### 2.2 使用方法
+
+
+1. 将osnoise写入的current\_tracer:
+
+
+`echo osnoise > /sys/kernel/debug/tracing/current_tracer`
+
+
+2. 打开traceing\_on:
+
+
+`echo 1 > /sys/kernel/debug/tracing/tracing_on`
+
+
+3. 查看trace结果:
+
+
+`cat /sys/kernel/debug/tracing/trace`
+
+
+
+
+
+
+
+
+这里显示的是系统整体采样的结果各个字段的含义如下:
+
+
+* TASK-PID:采样线程的PID。
+* CPU:采样的CPU ID
+* TIMESTAMP:时间戳
+* RUNTIME IN US:采样时间,单位us
+* NOISE IN US:本次采样时间内的总计噪声时间,单位us。
+* %OF CPU AVAILABLE:在一个RUNTIME周期内,采样线程可以获得的cpu利用率。
+* HW、NMI、IRQ、SIRQ、THREAD:分别表示各类噪声事件发生的次数。
+
+
+## 三、osnoise trace\_point
+
+
+### 3.1 trace\_point
+
+
+osnoise除了提供tracer外,还提供了一组trace\_points,以协助开发人员对噪声进行进一步分析。可以在`/sys/kernel/debug/tracing/events/osnoise/`看到相关tracepoint:
+
+
+* **sample\_threshold:** 追踪任何高于阀值的噪声事件。阀值即为上文提到的tracing\_thresh,默认为5us。
+* **nmi\_noise:** nmi噪声,包含其持续时间。
+* **irq\_noise:** irq噪声,包含其持续时间。
+* **softirq\_noise:** softirq噪声,包含其持续时间
+* **thread\_noise:** 其他线程噪声,包含其持续时间
+
+
+### 3.2 使用方法
+
+
+前面我们已经介绍了osnoise tracer的使用,它可以让我们直观的看到整个系统级别的各种噪声事件的总和。如果我们像看到每种噪声或者是说指定噪声类型的事件的详细信息,就需要用到osnoise提供的trace\_point。
+
+
+打开trace\_point总开关:
+
+
+`echo 1 > /sys/kernel/debug/tracing/events/osnoise/enable`
+
+
+查看trace日志:
+
+
+`cat /sys/kernel/debug/tracing/trace`
+
+
+输出如下所示:
+
+
+
+
+
+
+日志中包含了所有噪声的详细信息,包括其名字,开始事件,持续时间等等。关于其输出的具体格式可以查看对应trace\_point文件夹下的format文件。
+
+
+trace\_ponit文件位置在`/sys/kernel/debug/tracing/events/osnoise/`下。
+
+
+除了总开关外,每个事件有自己单独的开关,在对应tracepoint目录下。如irq\_noise的开关为`/sys/kernel/debug/tracing/events/osnoise/irq_noise/enable`。用户可以根据自己的需求只追踪相应的事件,从而过滤掉其他不需要关注的信息。
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220.md"
new file mode 100644
index 0000000000000000000000000000000000000000..41ecbb17a91a745ddf9bfa70e2f998fafefc6a53
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220.md"
@@ -0,0 +1,558 @@
+
+
+
+作者:新绎
+
+
+
+# 写在前面
+
+
+pstore中提供了多种前端来实现捕获各种系统信息来加以调试。这篇文章中,我们会对pstore其中之一的前端`PSTORE\_CONSOLE`进行分析,从原理上分析pstore如何获取kernel printk的信息。
+
+
+# pstore console注册
+
+
+`pstore console`前端注册函数在`fs/pstore/platform.c`中被定义,通过后端初始化过程中被调用并注册,从而能够在系统执行`prink`时获取输出信息,并通过`write`方法将`prink`的输出写入到相应的后端当中。
+
+
+
+```
+static void pstore_console_write(struct console *con, const char *s, unsigned c)
+{
+ struct pstore_record record;
+
+ if (!c)
+ return;
+
+ pstore_record_init(&record, psinfo);
+ record.type = PSTORE_TYPE_CONSOLE;
+
+ record.buf = (char *)s;
+ record.size = c;
+ psinfo->write(&record);
+}
+
+static struct console pstore_console = {
+ .write = pstore_console_write,
+ .index = -1,
+};
+
+static void pstore_register_console(void)
+{
+ /* Show which backend is going to get console writes. */
+ strscpy(pstore_console.name, psinfo->name,
+ sizeof(pstore_console.name));
+ /*
+ * Always initialize flags here since prior unregister_console()
+ * calls may have changed settings (specifically CON_ENABLED).
+ */
+ pstore_console.flags = CON_PRINTBUFFER | CON_ENABLED | CON_ANYTIME;
+ register_console(&pstore_console);
+}
+```
+
+
+其中,pstore\_console的flag开启了3个选项:`CON\_PRINTBUFFER`,`CON\_ENABLED`和`CON\_ANYTIME`。
+
+
+`CON\_PRINTBUFFER`:只有开启了才会接受prink的输出
+
+
+`CON\_ENABLED`:console使能,如果没有开启这个flag需要手动使能(在cmdline中定义)
+
+
+`CON\_ANYTIME`:可以在cpu离线时进行调用
+
+
+
+```
+//console.h
+/*
+ * The interface for a console, or any other device that wants to capture
+ * console messages (printer driver?)
+ *
+ * If a console driver is marked CON_BOOT then it will be auto-unregistered
+ * when the first real console is registered. This is for early-printk drivers.
+ */
+
+#define CON_PRINTBUFFER (1)
+#define CON_CONSDEV (2) /* Last on the command line */
+#define CON_ENABLED (4)
+#define CON_BOOT (8)
+#define CON_ANYTIME (16) /* Safe to call when cpu is offline */
+#define CON_BRL (32) /* Used for a braille device */
+#define CON_EXTENDED (64) /* Use the extended output format a la /dev/kmsg */
+
+struct console {
+ char name[16];
+ void (*write)(struct console *, const char *, unsigned);
+ int (*read)(struct console *, char *, unsigned);
+ struct tty_driver *(*device)(struct console *, int *);
+ void (*unblank)(void);
+ int (*setup)(struct console *, char *);
+ int (*match)(struct console *, char *name, int idx, char *options);
+ short flags;
+ short index;
+ int cflag;
+ void *data;
+ struct console *next;
+};
+```
+
+
+# printk总览
+
+
+
+
+
+
+# printk向console输出过程分析
+
+
+pstore中注册好console之后,console会被动地获取printk的输出,接下来我们分析printk是对console进行输出。
+
+
+## cmdline解析
+
+
+如果console的flag中定义了`CON\_ENABLED`,那么console会默认使能。如果没有定义,则需要在cmdline中手动使能。
+
+
+`kernel/printk.c`中将`'console='`的解析函数`console\_setup`注册到`obs\_kernel\_param`,在kernel启动过程中会遍历所有`obs\_kernel\_param`,接着会调用`console\_setup`来解析。
+
+
+我们通过在cmdline中定义`console=xxx`则能够被`console\_setup`所解析并使能相应的console。
+
+
+
+参数是`'console='`的值字符串,如“ttyS0,115200”,`console\_setup`对`console=`参数值做解析,以ttyS0,115200为例,`buf=“ttyS”`,`idx=0`,`options="115200"`,`brl\_options=NULL`。
+
+
+
+```
+//printk.c 解析cmdline
+/*
+ * Set up a console. Called via do_early_param() in init/main.c
+ * for each "console=" parameter in the boot command line.
+ */
+static int __init console_setup(char *str)
+{
+ char buf[sizeof(console_cmdline[0].name) + 4]; /* 4 for "ttyS" */
+ char *s, *options, *brl_options = NULL;
+ int idx;
+
+ if (_braille_console_setup(&str, &brl_options))
+ return 1;
+
+ /*
+ * Decode str into name, index, options.
+ */
+ if (str[0] >= '0' && str[0] <= '9') {
+ strcpy(buf, "ttyS");
+ strncpy(buf + 4, str, sizeof(buf) - 5);
+ } else {
+ strncpy(buf, str, sizeof(buf) - 1);
+ }
+ buf[sizeof(buf) - 1] = 0;
+ options = strchr(str, ',');
+ if (options)
+ *(options++) = 0;
+#ifdef __sparc__
+ if (!strcmp(str, "ttya"))
+ strcpy(buf, "ttyS0");
+ if (!strcmp(str, "ttyb"))
+ strcpy(buf, "ttyS1");
+#endif
+ for (s = buf; *s; s++)
+ if (isdigit(*s) || *s == ',')
+ break;
+ idx = simple_strtoul(s, NULL, 10);
+ *s = 0;
+
+ __add_preferred_console(buf, idx, options, brl_options);
+ console_set_on_cmdline = 1;
+ return 1;
+}
+__setup("console=", console_setup);
+```
+
+
+`console\_setup`最后调用`\_\_add\_preferred\_console`:
+
+
+kernel利用结构体数组`console\_cmdline[8]`,最多可支持8个cmdline传入的console参数。
+
+
+`\_\_add\_preferred\_console`将name,idx,options保存到数组下一个成员`console\_cmdline`结构体中,如果数组中已有重名,则不添加,并置`selected\_console`为最新添加的`console\_cmdline`的下标。
+
+
+
+**一个例子:**
+
+
+如cmdline中有“console=ttyS0,115200 console=ttyS1,9600”
+
+
+则在`console\_cmdline[8]`数组中`console\_cmdline[0]`代表ttyS0,`console\_cmdline[1]`代表ttyS1,而`preferred\_console=1`。
+
+
+
+```
+//printk.c __add_preferred_console
+static int __add_preferred_console(char *name, int idx, char *options,
+ char *brl_options)
+{
+ struct console_cmdline *c;
+ int i;
+
+ /*
+ * See if this tty is not yet registered, and
+ * if we have a slot free.
+ */
+ for (i = 0, c = console_cmdline;
+ i < MAX_CMDLINECONSOLES && c->name[0];
+ i++, c++) {
+ if (strcmp(c->name, name) == 0 && c->index == idx) {
+ if (!brl_options)
+ preferred_console = i;
+ return 0;
+ }
+ }
+ if (i == MAX_CMDLINECONSOLES)
+ return -E2BIG;
+ if (!brl_options)
+ preferred_console = i;
+ strlcpy(c->name, name, sizeof(c->name));
+ c->options = options;
+ braille_set_options(c, brl_options);
+
+ c->index = idx;
+ return 0;
+}
+```
+
+
+## printk console选择
+
+
+printk内容会一直存在log\_buf中,log\_buf满了之后则会从头在开始存,覆盖掉原来的数据。
+
+
+log\_buf的大小由kernel `menuconfig`中的`CONFIG\_LOG\_BUF\_SHIFT`配置。
+
+
+根据printk的实现原理,printk最后调用`console\_unlock`实现log\_buf数据刷出到设备。
+
+
+kernel下每次printk打印,首先存log\_buf,然后遍历console\_drivers,找到合适console(如果有`execlusive\_console`,则往`execlusive\_console`写,如果没有,则为所有使能的console),刷出log。
+
+
+**默认情况下**`**execlusive\_console=NULL**`,所以printk默认是向所有enable的console写
+
+
+只有一种情况是指定`execlusive\_console`,就是在console注册时
+
+
+
+```
+//printk.c call_console_drivers
+/*
+ * Call the console drivers, asking them to write out
+ * log_buf[start] to log_buf[end - 1].
+ * The console_lock must be held.
+ */
+static void call_console_drivers(const char *ext_text, size_t ext_len,
+ const char *text, size_t len)
+{
+ struct console *con;
+
+ trace_console_rcuidle(text, len);
+
+ if (!console_drivers)
+ return;
+
+ for_each_console(con) {
+ if (exclusive_console && con != exclusive_console)
+ continue;
+ if (!(con->flags & CON_ENABLED))
+ continue;
+ if (!con->write)
+ continue;
+ if (!cpu_online(smp_processor_id()) &&
+ !(con->flags & CON_ANYTIME))
+ continue;
+ if (con->flags & CON_EXTENDED)
+ con->write(con, ext_text, ext_len);
+ else
+ con->write(con, text, len);
+ }
+}
+```
+
+
+## printk console注册
+
+
+注意:linux提供了early console机制(通过`CONFIG\_EARLY\_PRINTK`进行使能),用于实现为设备注册console之前的早期log的输出,对应console也称为boot console,简称bcon。这个console在kernel启动的早期阶段就会被注册,主要通过输出设备(比如串口设备)的简单的write方法直接进行数据打印。而这个write方法也就是平台实现。这时候作为输出的串口设备是基于bootloader中已经初始化完成的。
+
+
+
+1. 如果注册的是bootconsole(kernel早期启动打印),需要检查console\_drivers中没有real console,也就是说bootconsole必须是第一个注册的console。
+2. 检查new console是否是cmdline指定的console,如果是,则使能(`CON\_ENABLE`)并初始化该console
+3. 如果该new console没有使能,退出
+4. 如果new console为bootconsole,则newcon不需要输出register之前的log(`newcon->flags &= ~CON\_PRINTBUFFER`),因为如果bootconsole和new console是同一个设备则会之前的log就输出2次
+5. 把new console加入`console\_drivers`链表,对于置位`CON\_CONSDEV`的console,放在链表首
+6. 加锁
+7. 如果new console置位`CON\_PRINTBUFFER`,则将log全部刷出(暂时修改printk输出的指定唯一`exclusive\_console`为new console,保证将之前的log只输出到new console)
+8. 解锁(console\_unlock()会重新把`exclusive\_console`设置为NULL)
+9. 如果有bootconsole并且不是作为real console继续使用,则unregister bootconsole(从`console\_drivers`中删掉)
+
+```
+//printk.c register_console
+/*
+ * The console driver calls this routine during kernel initialization
+ * to register the console printing procedure with printk() and to
+ * print any messages that were printed by the kernel before the
+ * console driver was initialized.
+ *
+ * This can happen pretty early during the boot process (because of
+ * early_printk) - sometimes before setup_arch() completes - be careful
+ * of what kernel features are used - they may not be initialised yet.
+ *
+ * There are two types of consoles - bootconsoles (early_printk) and
+ * "real" consoles (everything which is not a bootconsole) which are
+ * handled differently.
+ * - Any number of bootconsoles can be registered at any time.
+ * - As soon as a "real" console is registered, all bootconsoles
+ * will be unregistered automatically.
+ * - Once a "real" console is registered, any attempt to register a
+ * bootconsoles will be rejected
+ */
+void register_console(struct console *newcon)
+{
+ int i;
+ unsigned long flags;
+ struct console *bcon = NULL;
+ struct console_cmdline *c;
+ static bool has_preferred;
+
+ if (console_drivers)
+ for_each_console(bcon)
+ if (WARN(bcon == newcon,
+ "console '%s%d' already registered\n",
+ bcon->name, bcon->index))
+ return;
+
+ /*
+ * before we register a new CON_BOOT console, make sure we don't
+ * already have a valid console
+ */
+ if (console_drivers && newcon->flags & CON_BOOT) {
+ /* find the last or real console */
+ for_each_console(bcon) {
+ if (!(bcon->flags & CON_BOOT)) {
+ pr_info("Too late to register bootconsole %s%d\n",
+ newcon->name, newcon->index);
+ return;
+ }
+ }
+ }
+
+ if (console_drivers && console_drivers->flags & CON_BOOT)
+ bcon = console_drivers;
+
+ if (!has_preferred || bcon || !console_drivers)
+ has_preferred = preferred_console >= 0;
+
+ /*
+ * See if we want to use this console driver. If we
+ * didn't select a console we take the first one
+ * that registers here.
+ */
+ if (!has_preferred) {
+ if (newcon->index < 0)
+ newcon->index = 0;
+ if (newcon->setup == NULL ||
+ newcon->setup(newcon, NULL) == 0) {
+ newcon->flags |= CON_ENABLED;
+ if (newcon->device) {
+ newcon->flags |= CON_CONSDEV;
+ has_preferred = true;
+ }
+ }
+ }
+
+ /*
+ * See if this console matches one we selected on
+ * the command line.
+ */
+ for (i = 0, c = console_cmdline;
+ i < MAX_CMDLINECONSOLES && c->name[0];
+ i++, c++) {
+ if (!newcon->match ||
+ newcon->match(newcon, c->name, c->index, c->options) != 0) {
+ /* default matching */
+ BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name));
+ if (strcmp(c->name, newcon->name) != 0)
+ continue;
+ if (newcon->index >= 0 &&
+ newcon->index != c->index)
+ continue;
+ if (newcon->index < 0)
+ newcon->index = c->index;
+
+ if (_braille_register_console(newcon, c))
+ return;
+
+ if (newcon->setup &&
+ newcon->setup(newcon, c->options) != 0)
+ break;
+ }
+
+ newcon->flags |= CON_ENABLED;
+ if (i == preferred_console) {
+ newcon->flags |= CON_CONSDEV;
+ has_preferred = true;
+ }
+ break;
+ }
+
+ if (!(newcon->flags & CON_ENABLED))
+ return;
+
+ /*
+ * If we have a bootconsole, and are switching to a real console,
+ * don't print everything out again, since when the boot console, and
+ * the real console are the same physical device, it's annoying to
+ * see the beginning boot messages twice
+ */
+ if (bcon && ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV))
+ newcon->flags &= ~CON_PRINTBUFFER;
+
+ /*
+ * Put this console in the list - keep the
+ * preferred driver at the head of the list.
+ */
+ console_lock();
+ if ((newcon->flags & CON_CONSDEV) || console_drivers == NULL) {
+ newcon->next = console_drivers;
+ console_drivers = newcon;
+ if (newcon->next)
+ newcon->next->flags &= ~CON_CONSDEV;
+ } else {
+ newcon->next = console_drivers->next;
+ console_drivers->next = newcon;
+ }
+
+ if (newcon->flags & CON_EXTENDED)
+ if (!nr_ext_console_drivers++)
+ pr_info("printk: continuation disabled due to ext consoles, expect more fragments in /dev/kmsg\n");
+
+ if (newcon->flags & CON_PRINTBUFFER) {
+ /*
+ * console_unlock(); will print out the buffered messages
+ * for us.
+ */
+ logbuf_lock_irqsave(flags);
+ console_seq = syslog_seq;
+ console_idx = syslog_idx;
+ /*
+ * We're about to replay the log buffer. Only do this to the
+ * just-registered console to avoid excessive message spam to
+ * the already-registered consoles.
+ *
+ * Set exclusive_console with disabled interrupts to reduce
+ * race window with eventual console_flush_on_panic() that
+ * ignores console_lock.
+ */
+ exclusive_console = newcon;
+ exclusive_console_stop_seq = console_seq;
+ logbuf_unlock_irqrestore(flags);
+ }
+ console_unlock();
+ console_sysfs_notify();
+
+ /*
+ * By unregistering the bootconsoles after we enable the real console
+ * we get the "console xxx enabled" message on all the consoles -
+ * boot consoles, real consoles, etc - this is to ensure that end
+ * users know there might be something in the kernel's log buffer that
+ * went to the bootconsole (that they do not see on the real console)
+ */
+ pr_info("%sconsole [%s%d] enabled\n",
+ (newcon->flags & CON_BOOT) ? "boot" : "" ,
+ newcon->name, newcon->index);
+ if (bcon &&
+ ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV) &&
+ !keep_bootcon) {
+ /* We need to iterate through all boot consoles, to make
+ * sure we print everything out, before we unregister them.
+ */
+ for_each_console(bcon)
+ if (bcon->flags & CON_BOOT)
+ unregister_console(bcon);
+ }
+}
+
+EXPORT_SYMBOL(register_console);
+```
+
+
+## printk打印级别
+
+
+printk可以根据设置的日志级别来确定这个语句最后是否能够打印出来。
+
+
+查看此文件:`cat /proc/sys/kernel/printk`
+
+
+该文件有四个数字值,它们根据日志记录消息的重要性,定义将其发送到何处。
+
+
+
+ 1. 控制台日志级别:优先级高于该值的消息将被打印至控制台
+ 2. 默认的消息日志级别:将用该优先级来打印没有优先级的消息
+ 3. 最低的控制台日志级别:控制台日志级别可被设置的最小值(最高优先级)
+ 4. 默认的控制台日志级别:控制台日志级别的缺省值
+
+内核中共提供了八种不同的日志级别,在 `linux/kernel.h` 中有相应的宏对应。
+
+
+
+```
+#define KERN_EMERG "<0>" /* systemis unusable */
+#define KERN_ALERT "<1>" /* actionmust be taken immediately */
+#define KERN_CRIT "<2>" /*critical conditions */
+#define KERN_ERR "<3>" /* errorconditions */
+#define KERN_WARNING "<4>" /* warning conditions */
+#define KERN_NOTICE "<5>" /* normalbut significant */
+#define KERN_INFO "<6>" /*informational */
+#define KERN_DEBUG "<7>" /*debug-level messages */
+```
+
+
+**可以通过在cmdline中加入“loglevel=X”的语句,来调整日志输入级别。**其中X就是我们想要设置的console\_loglevel的值。
+
+
+# 总结
+
+
+pstore实现console前端的方式很简单:通过注册一个console并且使能即可实现。
+
+
+默认情况下,printk会对所有使能的console进行输出,将log\_buf中的数据写入到使能的console当中。
+
+
+当对pstore的console进行输出时,会触发pstore console的write,将数据写入到相应后端。
+
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257DMESG_\344\273\243\347\240\201\345\210\206\346\236\220.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257DMESG_\344\273\243\347\240\201\345\210\206\346\236\220.md"
new file mode 100644
index 0000000000000000000000000000000000000000..d00e1b42c34c3055a84dfdfe4e134dbab1df1f6d
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257DMESG_\344\273\243\347\240\201\345\210\206\346\236\220.md"
@@ -0,0 +1,210 @@
+
+
+
+作者:新绎
+
+
+
+## 写在前面
+
+
+pstore中提供了多种前端来实现捕获各种系统信息从而加以调试。这篇文章中,我们会对pstore其中之一的前端PSTORE\_DMESG进行分析,从原理上分析pstore如何获取当内核发生panic时kmsg信息。
+
+
+## Pstore注册kmsg\_dumper
+
+
+kmsg\_dumper结构体有两个重要成员:回调函数`dump()`以及相应的`kmsg_dump_reason`。通过对`dump()`进行实现,我们就可以将相应的log信息保存到我们希望保存的地方,并且可以通过`kmsg_dump_reason`来对需要保存的信息进行筛选。
+
+
+
+```
+//kmsg_dump.h
+/**
+* struct kmsg_dumper - kernel crash message dumper structure
+* @list: Entry in the dumper list (private)
+* @dump: Call into dumping code which will retrieve the data with
+* through the record iterator
+* @max_reason: filter for highest reason number that should be dumped
+* @registered: Flag that specifies if this is already registered
+*/
+struct kmsg_dumper {
+ struct list_head list;
+ void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason);
+ enum kmsg_dump_reason max_reason;
+ bool active;
+ bool registered;
+
+ /* private state of the kmsg iterator */
+ u32 cur_idx;
+ u32 next_idx;
+ u64 cur_seq;
+ u64 next_seq;
+};
+
+/*
+ * Keep this list arranged in rough order of priority. Anything listed after
+ * KMSG_DUMP_OOPS will not be logged by default unless printk.always_kmsg_dump
+ * is passed to the kernel.
+ */
+enum kmsg_dump_reason {
+ KMSG_DUMP_UNDEF,
+ KMSG_DUMP_PANIC,
+ KMSG_DUMP_OOPS,
+ KMSG_DUMP_EMERG,
+ KMSG_DUMP_RESTART,
+ KMSG_DUMP_HALT,
+ KMSG_DUMP_POWEROFF,
+};
+```
+
+
+我们可以看到,目前有7种定义的`kmsg\_dump\_reason`,而pstore则关心在系统出现panic时的log信息。在pstore的实现中,pstore通过`pstore\_cannot\_block\_path()`函数对相应的信息进行过滤。
+
+
+
+```
+//pstore_cannot_block_path()
+/*
+ * Should pstore_dump() wait for a concurrent pstore_dump()? If
+ * not, the current pstore_dump() will report a failure to dump
+ * and return.
+ */
+static bool pstore_cannot_block_path(enum kmsg_dump_reason reason)
+{
+ /* In NMI path, pstore shouldn't block regardless of reason. */
+ if (in_nmi())
+ return true;
+
+ switch (reason) {
+ /* In panic case, other cpus are stopped by smp_send_stop(). */
+ case KMSG_DUMP_PANIC:
+ /* Emergency restart shouldn't be blocked. */
+ case KMSG_DUMP_EMERG:
+ return true;
+ default:
+ return false;
+ }
+}
+```
+
+
+其中dmesg前端的主要工作就是为其实现一个`dump()`函数,该函数将从log buffer中读取log信息,然后将其封装为recored之后写入对应的后端设备,其主要定义如下:
+
+
+
+```
+//pstore_dump()
+static struct kmsg_dumper pstore_dumper = {
+ .dump = pstore_dump,
+}
+
+static void pstore_dump(struct kmsg_dumper *dumper,
+ enum kmsg_dump_reason reason)
+{
+ …
+ while (total < kmsg_bytes) {
+ …
+ pstore_record_init(&record, psinfo);
+ …
+ header_size = snprintf(dst, dst_size, "%s#%d Part%u\n", why,
+ oopscount, part);
+ dst_size -= header_size;
+
+ if (!kmsg_dump_get_buffer(&iter, true, dst + header_size,
+ dst_size, &dump_size))
+ break;
+
+ if (big_oops_buf) {
+ zipped_len = pstore_compress(dst, psinfo->buf,
+ header_size + dump_size,
+ psinfo->bufsize);
+ …
+ } else {
+ record.size = header_size + dump_size;
+ }
+
+ ret = psinfo->write(&record);
+ …
+ }
+ …
+}
+
+```
+
+
+## kmsg\_dump实现
+
+
+printk实现了一个`kmsg\_dump()`函数,用于方便其它模块dump内核的log buffer,当内核发生oops、panic或重启等事件时,都会调用该函数dump log信息。其代码实现如下:
+
+
+
+```
+void kmsg_dump(enum kmsg_dump_reason reason)
+{
+ …
+ list_for_each_entry_rcu(dumper, &dump_list, list) {
+ enum kmsg_dump_reason max_reason = dumper->max_reason;
+
+ if (max_reason == KMSG_DUMP_UNDEF) {
+ max_reason = always_kmsg_dump ? KMSG_DUMP_MAX :
+ KMSG_DUMP_OOPS;
+ }
+ if (reason > max_reason)
+ continue;
+
+ dumper->dump(dumper, reason);
+ }
+ rcu_read_unlock();
+}
+```
+
+
+使用`kmsg\_dump()`之前要先使用`kmsg\_dump\_register()`来注册一个dumper,用于实际的log写操作。
+
+
+我们先来看看`kmsg\_dump\_register`的定义,只定义了一个dump\_list,将系统中所有注册的dump都挂在同一个list下,这就说明系统可以注册多个dumper。
+
+
+
+```
+int kmsg_dump_register(struct kmsg_dumper *dumper)
+{
+ …
+ if (!dumper->registered) {
+ dumper->registered = 1;
+ list_add_tail_rcu(&dumper->list, &dump_list);
+ err = 0;
+ }
+ …
+}
+```
+
+
+## 总结
+
+
+pstore dmesg主要工作流程如下:
+
+
+(1)初始化一个record结构体
+
+
+(2)先向其写入pstore头信息,如dmesg reason、oops发生次数等
+
+
+(3)从log buffer中读取一行log信息
+
+
+(4)若需要压缩信息,则执行压缩操作
+
+
+(5)调用后端的写函数,将record写入相应的后端设备
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220.md"
new file mode 100644
index 0000000000000000000000000000000000000000..41ecbb17a91a745ddf9bfa70e2f998fafefc6a53
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220.md"
@@ -0,0 +1,558 @@
+
+
+
+作者:新绎
+
+
+
+# 写在前面
+
+
+pstore中提供了多种前端来实现捕获各种系统信息来加以调试。这篇文章中,我们会对pstore其中之一的前端`PSTORE\_CONSOLE`进行分析,从原理上分析pstore如何获取kernel printk的信息。
+
+
+# pstore console注册
+
+
+`pstore console`前端注册函数在`fs/pstore/platform.c`中被定义,通过后端初始化过程中被调用并注册,从而能够在系统执行`prink`时获取输出信息,并通过`write`方法将`prink`的输出写入到相应的后端当中。
+
+
+
+```
+static void pstore_console_write(struct console *con, const char *s, unsigned c)
+{
+ struct pstore_record record;
+
+ if (!c)
+ return;
+
+ pstore_record_init(&record, psinfo);
+ record.type = PSTORE_TYPE_CONSOLE;
+
+ record.buf = (char *)s;
+ record.size = c;
+ psinfo->write(&record);
+}
+
+static struct console pstore_console = {
+ .write = pstore_console_write,
+ .index = -1,
+};
+
+static void pstore_register_console(void)
+{
+ /* Show which backend is going to get console writes. */
+ strscpy(pstore_console.name, psinfo->name,
+ sizeof(pstore_console.name));
+ /*
+ * Always initialize flags here since prior unregister_console()
+ * calls may have changed settings (specifically CON_ENABLED).
+ */
+ pstore_console.flags = CON_PRINTBUFFER | CON_ENABLED | CON_ANYTIME;
+ register_console(&pstore_console);
+}
+```
+
+
+其中,pstore\_console的flag开启了3个选项:`CON\_PRINTBUFFER`,`CON\_ENABLED`和`CON\_ANYTIME`。
+
+
+`CON\_PRINTBUFFER`:只有开启了才会接受prink的输出
+
+
+`CON\_ENABLED`:console使能,如果没有开启这个flag需要手动使能(在cmdline中定义)
+
+
+`CON\_ANYTIME`:可以在cpu离线时进行调用
+
+
+
+```
+//console.h
+/*
+ * The interface for a console, or any other device that wants to capture
+ * console messages (printer driver?)
+ *
+ * If a console driver is marked CON_BOOT then it will be auto-unregistered
+ * when the first real console is registered. This is for early-printk drivers.
+ */
+
+#define CON_PRINTBUFFER (1)
+#define CON_CONSDEV (2) /* Last on the command line */
+#define CON_ENABLED (4)
+#define CON_BOOT (8)
+#define CON_ANYTIME (16) /* Safe to call when cpu is offline */
+#define CON_BRL (32) /* Used for a braille device */
+#define CON_EXTENDED (64) /* Use the extended output format a la /dev/kmsg */
+
+struct console {
+ char name[16];
+ void (*write)(struct console *, const char *, unsigned);
+ int (*read)(struct console *, char *, unsigned);
+ struct tty_driver *(*device)(struct console *, int *);
+ void (*unblank)(void);
+ int (*setup)(struct console *, char *);
+ int (*match)(struct console *, char *name, int idx, char *options);
+ short flags;
+ short index;
+ int cflag;
+ void *data;
+ struct console *next;
+};
+```
+
+
+# printk总览
+
+
+
+
+
+
+# printk向console输出过程分析
+
+
+pstore中注册好console之后,console会被动地获取printk的输出,接下来我们分析printk是对console进行输出。
+
+
+## cmdline解析
+
+
+如果console的flag中定义了`CON\_ENABLED`,那么console会默认使能。如果没有定义,则需要在cmdline中手动使能。
+
+
+`kernel/printk.c`中将`'console='`的解析函数`console\_setup`注册到`obs\_kernel\_param`,在kernel启动过程中会遍历所有`obs\_kernel\_param`,接着会调用`console\_setup`来解析。
+
+
+我们通过在cmdline中定义`console=xxx`则能够被`console\_setup`所解析并使能相应的console。
+
+
+
+参数是`'console='`的值字符串,如“ttyS0,115200”,`console\_setup`对`console=`参数值做解析,以ttyS0,115200为例,`buf=“ttyS”`,`idx=0`,`options="115200"`,`brl\_options=NULL`。
+
+
+
+```
+//printk.c 解析cmdline
+/*
+ * Set up a console. Called via do_early_param() in init/main.c
+ * for each "console=" parameter in the boot command line.
+ */
+static int __init console_setup(char *str)
+{
+ char buf[sizeof(console_cmdline[0].name) + 4]; /* 4 for "ttyS" */
+ char *s, *options, *brl_options = NULL;
+ int idx;
+
+ if (_braille_console_setup(&str, &brl_options))
+ return 1;
+
+ /*
+ * Decode str into name, index, options.
+ */
+ if (str[0] >= '0' && str[0] <= '9') {
+ strcpy(buf, "ttyS");
+ strncpy(buf + 4, str, sizeof(buf) - 5);
+ } else {
+ strncpy(buf, str, sizeof(buf) - 1);
+ }
+ buf[sizeof(buf) - 1] = 0;
+ options = strchr(str, ',');
+ if (options)
+ *(options++) = 0;
+#ifdef __sparc__
+ if (!strcmp(str, "ttya"))
+ strcpy(buf, "ttyS0");
+ if (!strcmp(str, "ttyb"))
+ strcpy(buf, "ttyS1");
+#endif
+ for (s = buf; *s; s++)
+ if (isdigit(*s) || *s == ',')
+ break;
+ idx = simple_strtoul(s, NULL, 10);
+ *s = 0;
+
+ __add_preferred_console(buf, idx, options, brl_options);
+ console_set_on_cmdline = 1;
+ return 1;
+}
+__setup("console=", console_setup);
+```
+
+
+`console\_setup`最后调用`\_\_add\_preferred\_console`:
+
+
+kernel利用结构体数组`console\_cmdline[8]`,最多可支持8个cmdline传入的console参数。
+
+
+`\_\_add\_preferred\_console`将name,idx,options保存到数组下一个成员`console\_cmdline`结构体中,如果数组中已有重名,则不添加,并置`selected\_console`为最新添加的`console\_cmdline`的下标。
+
+
+
+**一个例子:**
+
+
+如cmdline中有“console=ttyS0,115200 console=ttyS1,9600”
+
+
+则在`console\_cmdline[8]`数组中`console\_cmdline[0]`代表ttyS0,`console\_cmdline[1]`代表ttyS1,而`preferred\_console=1`。
+
+
+
+```
+//printk.c __add_preferred_console
+static int __add_preferred_console(char *name, int idx, char *options,
+ char *brl_options)
+{
+ struct console_cmdline *c;
+ int i;
+
+ /*
+ * See if this tty is not yet registered, and
+ * if we have a slot free.
+ */
+ for (i = 0, c = console_cmdline;
+ i < MAX_CMDLINECONSOLES && c->name[0];
+ i++, c++) {
+ if (strcmp(c->name, name) == 0 && c->index == idx) {
+ if (!brl_options)
+ preferred_console = i;
+ return 0;
+ }
+ }
+ if (i == MAX_CMDLINECONSOLES)
+ return -E2BIG;
+ if (!brl_options)
+ preferred_console = i;
+ strlcpy(c->name, name, sizeof(c->name));
+ c->options = options;
+ braille_set_options(c, brl_options);
+
+ c->index = idx;
+ return 0;
+}
+```
+
+
+## printk console选择
+
+
+printk内容会一直存在log\_buf中,log\_buf满了之后则会从头在开始存,覆盖掉原来的数据。
+
+
+log\_buf的大小由kernel `menuconfig`中的`CONFIG\_LOG\_BUF\_SHIFT`配置。
+
+
+根据printk的实现原理,printk最后调用`console\_unlock`实现log\_buf数据刷出到设备。
+
+
+kernel下每次printk打印,首先存log\_buf,然后遍历console\_drivers,找到合适console(如果有`execlusive\_console`,则往`execlusive\_console`写,如果没有,则为所有使能的console),刷出log。
+
+
+**默认情况下**`**execlusive\_console=NULL**`,所以printk默认是向所有enable的console写
+
+
+只有一种情况是指定`execlusive\_console`,就是在console注册时
+
+
+
+```
+//printk.c call_console_drivers
+/*
+ * Call the console drivers, asking them to write out
+ * log_buf[start] to log_buf[end - 1].
+ * The console_lock must be held.
+ */
+static void call_console_drivers(const char *ext_text, size_t ext_len,
+ const char *text, size_t len)
+{
+ struct console *con;
+
+ trace_console_rcuidle(text, len);
+
+ if (!console_drivers)
+ return;
+
+ for_each_console(con) {
+ if (exclusive_console && con != exclusive_console)
+ continue;
+ if (!(con->flags & CON_ENABLED))
+ continue;
+ if (!con->write)
+ continue;
+ if (!cpu_online(smp_processor_id()) &&
+ !(con->flags & CON_ANYTIME))
+ continue;
+ if (con->flags & CON_EXTENDED)
+ con->write(con, ext_text, ext_len);
+ else
+ con->write(con, text, len);
+ }
+}
+```
+
+
+## printk console注册
+
+
+注意:linux提供了early console机制(通过`CONFIG\_EARLY\_PRINTK`进行使能),用于实现为设备注册console之前的早期log的输出,对应console也称为boot console,简称bcon。这个console在kernel启动的早期阶段就会被注册,主要通过输出设备(比如串口设备)的简单的write方法直接进行数据打印。而这个write方法也就是平台实现。这时候作为输出的串口设备是基于bootloader中已经初始化完成的。
+
+
+
+1. 如果注册的是bootconsole(kernel早期启动打印),需要检查console\_drivers中没有real console,也就是说bootconsole必须是第一个注册的console。
+2. 检查new console是否是cmdline指定的console,如果是,则使能(`CON\_ENABLE`)并初始化该console
+3. 如果该new console没有使能,退出
+4. 如果new console为bootconsole,则newcon不需要输出register之前的log(`newcon->flags &= ~CON\_PRINTBUFFER`),因为如果bootconsole和new console是同一个设备则会之前的log就输出2次
+5. 把new console加入`console\_drivers`链表,对于置位`CON\_CONSDEV`的console,放在链表首
+6. 加锁
+7. 如果new console置位`CON\_PRINTBUFFER`,则将log全部刷出(暂时修改printk输出的指定唯一`exclusive\_console`为new console,保证将之前的log只输出到new console)
+8. 解锁(console\_unlock()会重新把`exclusive\_console`设置为NULL)
+9. 如果有bootconsole并且不是作为real console继续使用,则unregister bootconsole(从`console\_drivers`中删掉)
+
+```
+//printk.c register_console
+/*
+ * The console driver calls this routine during kernel initialization
+ * to register the console printing procedure with printk() and to
+ * print any messages that were printed by the kernel before the
+ * console driver was initialized.
+ *
+ * This can happen pretty early during the boot process (because of
+ * early_printk) - sometimes before setup_arch() completes - be careful
+ * of what kernel features are used - they may not be initialised yet.
+ *
+ * There are two types of consoles - bootconsoles (early_printk) and
+ * "real" consoles (everything which is not a bootconsole) which are
+ * handled differently.
+ * - Any number of bootconsoles can be registered at any time.
+ * - As soon as a "real" console is registered, all bootconsoles
+ * will be unregistered automatically.
+ * - Once a "real" console is registered, any attempt to register a
+ * bootconsoles will be rejected
+ */
+void register_console(struct console *newcon)
+{
+ int i;
+ unsigned long flags;
+ struct console *bcon = NULL;
+ struct console_cmdline *c;
+ static bool has_preferred;
+
+ if (console_drivers)
+ for_each_console(bcon)
+ if (WARN(bcon == newcon,
+ "console '%s%d' already registered\n",
+ bcon->name, bcon->index))
+ return;
+
+ /*
+ * before we register a new CON_BOOT console, make sure we don't
+ * already have a valid console
+ */
+ if (console_drivers && newcon->flags & CON_BOOT) {
+ /* find the last or real console */
+ for_each_console(bcon) {
+ if (!(bcon->flags & CON_BOOT)) {
+ pr_info("Too late to register bootconsole %s%d\n",
+ newcon->name, newcon->index);
+ return;
+ }
+ }
+ }
+
+ if (console_drivers && console_drivers->flags & CON_BOOT)
+ bcon = console_drivers;
+
+ if (!has_preferred || bcon || !console_drivers)
+ has_preferred = preferred_console >= 0;
+
+ /*
+ * See if we want to use this console driver. If we
+ * didn't select a console we take the first one
+ * that registers here.
+ */
+ if (!has_preferred) {
+ if (newcon->index < 0)
+ newcon->index = 0;
+ if (newcon->setup == NULL ||
+ newcon->setup(newcon, NULL) == 0) {
+ newcon->flags |= CON_ENABLED;
+ if (newcon->device) {
+ newcon->flags |= CON_CONSDEV;
+ has_preferred = true;
+ }
+ }
+ }
+
+ /*
+ * See if this console matches one we selected on
+ * the command line.
+ */
+ for (i = 0, c = console_cmdline;
+ i < MAX_CMDLINECONSOLES && c->name[0];
+ i++, c++) {
+ if (!newcon->match ||
+ newcon->match(newcon, c->name, c->index, c->options) != 0) {
+ /* default matching */
+ BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name));
+ if (strcmp(c->name, newcon->name) != 0)
+ continue;
+ if (newcon->index >= 0 &&
+ newcon->index != c->index)
+ continue;
+ if (newcon->index < 0)
+ newcon->index = c->index;
+
+ if (_braille_register_console(newcon, c))
+ return;
+
+ if (newcon->setup &&
+ newcon->setup(newcon, c->options) != 0)
+ break;
+ }
+
+ newcon->flags |= CON_ENABLED;
+ if (i == preferred_console) {
+ newcon->flags |= CON_CONSDEV;
+ has_preferred = true;
+ }
+ break;
+ }
+
+ if (!(newcon->flags & CON_ENABLED))
+ return;
+
+ /*
+ * If we have a bootconsole, and are switching to a real console,
+ * don't print everything out again, since when the boot console, and
+ * the real console are the same physical device, it's annoying to
+ * see the beginning boot messages twice
+ */
+ if (bcon && ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV))
+ newcon->flags &= ~CON_PRINTBUFFER;
+
+ /*
+ * Put this console in the list - keep the
+ * preferred driver at the head of the list.
+ */
+ console_lock();
+ if ((newcon->flags & CON_CONSDEV) || console_drivers == NULL) {
+ newcon->next = console_drivers;
+ console_drivers = newcon;
+ if (newcon->next)
+ newcon->next->flags &= ~CON_CONSDEV;
+ } else {
+ newcon->next = console_drivers->next;
+ console_drivers->next = newcon;
+ }
+
+ if (newcon->flags & CON_EXTENDED)
+ if (!nr_ext_console_drivers++)
+ pr_info("printk: continuation disabled due to ext consoles, expect more fragments in /dev/kmsg\n");
+
+ if (newcon->flags & CON_PRINTBUFFER) {
+ /*
+ * console_unlock(); will print out the buffered messages
+ * for us.
+ */
+ logbuf_lock_irqsave(flags);
+ console_seq = syslog_seq;
+ console_idx = syslog_idx;
+ /*
+ * We're about to replay the log buffer. Only do this to the
+ * just-registered console to avoid excessive message spam to
+ * the already-registered consoles.
+ *
+ * Set exclusive_console with disabled interrupts to reduce
+ * race window with eventual console_flush_on_panic() that
+ * ignores console_lock.
+ */
+ exclusive_console = newcon;
+ exclusive_console_stop_seq = console_seq;
+ logbuf_unlock_irqrestore(flags);
+ }
+ console_unlock();
+ console_sysfs_notify();
+
+ /*
+ * By unregistering the bootconsoles after we enable the real console
+ * we get the "console xxx enabled" message on all the consoles -
+ * boot consoles, real consoles, etc - this is to ensure that end
+ * users know there might be something in the kernel's log buffer that
+ * went to the bootconsole (that they do not see on the real console)
+ */
+ pr_info("%sconsole [%s%d] enabled\n",
+ (newcon->flags & CON_BOOT) ? "boot" : "" ,
+ newcon->name, newcon->index);
+ if (bcon &&
+ ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV) &&
+ !keep_bootcon) {
+ /* We need to iterate through all boot consoles, to make
+ * sure we print everything out, before we unregister them.
+ */
+ for_each_console(bcon)
+ if (bcon->flags & CON_BOOT)
+ unregister_console(bcon);
+ }
+}
+
+EXPORT_SYMBOL(register_console);
+```
+
+
+## printk打印级别
+
+
+printk可以根据设置的日志级别来确定这个语句最后是否能够打印出来。
+
+
+查看此文件:`cat /proc/sys/kernel/printk`
+
+
+该文件有四个数字值,它们根据日志记录消息的重要性,定义将其发送到何处。
+
+
+
+ 1. 控制台日志级别:优先级高于该值的消息将被打印至控制台
+ 2. 默认的消息日志级别:将用该优先级来打印没有优先级的消息
+ 3. 最低的控制台日志级别:控制台日志级别可被设置的最小值(最高优先级)
+ 4. 默认的控制台日志级别:控制台日志级别的缺省值
+
+内核中共提供了八种不同的日志级别,在 `linux/kernel.h` 中有相应的宏对应。
+
+
+
+```
+#define KERN_EMERG "<0>" /* systemis unusable */
+#define KERN_ALERT "<1>" /* actionmust be taken immediately */
+#define KERN_CRIT "<2>" /*critical conditions */
+#define KERN_ERR "<3>" /* errorconditions */
+#define KERN_WARNING "<4>" /* warning conditions */
+#define KERN_NOTICE "<5>" /* normalbut significant */
+#define KERN_INFO "<6>" /*informational */
+#define KERN_DEBUG "<7>" /*debug-level messages */
+```
+
+
+**可以通过在cmdline中加入“loglevel=X”的语句,来调整日志输入级别。**其中X就是我们想要设置的console\_loglevel的值。
+
+
+# 总结
+
+
+pstore实现console前端的方式很简单:通过注册一个console并且使能即可实现。
+
+
+默认情况下,printk会对所有使能的console进行输出,将log\_buf中的数据写入到使能的console当中。
+
+
+当对pstore的console进行输出时,会触发pstore console的write,将数据写入到相应后端。
+
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232DMESG_\344\273\243\347\240\201\345\210\206\346\236\220.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232DMESG_\344\273\243\347\240\201\345\210\206\346\236\220.md"
new file mode 100644
index 0000000000000000000000000000000000000000..d00e1b42c34c3055a84dfdfe4e134dbab1df1f6d
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232DMESG_\344\273\243\347\240\201\345\210\206\346\236\220.md"
@@ -0,0 +1,210 @@
+
+
+
+作者:新绎
+
+
+
+## 写在前面
+
+
+pstore中提供了多种前端来实现捕获各种系统信息从而加以调试。这篇文章中,我们会对pstore其中之一的前端PSTORE\_DMESG进行分析,从原理上分析pstore如何获取当内核发生panic时kmsg信息。
+
+
+## Pstore注册kmsg\_dumper
+
+
+kmsg\_dumper结构体有两个重要成员:回调函数`dump()`以及相应的`kmsg_dump_reason`。通过对`dump()`进行实现,我们就可以将相应的log信息保存到我们希望保存的地方,并且可以通过`kmsg_dump_reason`来对需要保存的信息进行筛选。
+
+
+
+```
+//kmsg_dump.h
+/**
+* struct kmsg_dumper - kernel crash message dumper structure
+* @list: Entry in the dumper list (private)
+* @dump: Call into dumping code which will retrieve the data with
+* through the record iterator
+* @max_reason: filter for highest reason number that should be dumped
+* @registered: Flag that specifies if this is already registered
+*/
+struct kmsg_dumper {
+ struct list_head list;
+ void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason);
+ enum kmsg_dump_reason max_reason;
+ bool active;
+ bool registered;
+
+ /* private state of the kmsg iterator */
+ u32 cur_idx;
+ u32 next_idx;
+ u64 cur_seq;
+ u64 next_seq;
+};
+
+/*
+ * Keep this list arranged in rough order of priority. Anything listed after
+ * KMSG_DUMP_OOPS will not be logged by default unless printk.always_kmsg_dump
+ * is passed to the kernel.
+ */
+enum kmsg_dump_reason {
+ KMSG_DUMP_UNDEF,
+ KMSG_DUMP_PANIC,
+ KMSG_DUMP_OOPS,
+ KMSG_DUMP_EMERG,
+ KMSG_DUMP_RESTART,
+ KMSG_DUMP_HALT,
+ KMSG_DUMP_POWEROFF,
+};
+```
+
+
+我们可以看到,目前有7种定义的`kmsg\_dump\_reason`,而pstore则关心在系统出现panic时的log信息。在pstore的实现中,pstore通过`pstore\_cannot\_block\_path()`函数对相应的信息进行过滤。
+
+
+
+```
+//pstore_cannot_block_path()
+/*
+ * Should pstore_dump() wait for a concurrent pstore_dump()? If
+ * not, the current pstore_dump() will report a failure to dump
+ * and return.
+ */
+static bool pstore_cannot_block_path(enum kmsg_dump_reason reason)
+{
+ /* In NMI path, pstore shouldn't block regardless of reason. */
+ if (in_nmi())
+ return true;
+
+ switch (reason) {
+ /* In panic case, other cpus are stopped by smp_send_stop(). */
+ case KMSG_DUMP_PANIC:
+ /* Emergency restart shouldn't be blocked. */
+ case KMSG_DUMP_EMERG:
+ return true;
+ default:
+ return false;
+ }
+}
+```
+
+
+其中dmesg前端的主要工作就是为其实现一个`dump()`函数,该函数将从log buffer中读取log信息,然后将其封装为recored之后写入对应的后端设备,其主要定义如下:
+
+
+
+```
+//pstore_dump()
+static struct kmsg_dumper pstore_dumper = {
+ .dump = pstore_dump,
+}
+
+static void pstore_dump(struct kmsg_dumper *dumper,
+ enum kmsg_dump_reason reason)
+{
+ …
+ while (total < kmsg_bytes) {
+ …
+ pstore_record_init(&record, psinfo);
+ …
+ header_size = snprintf(dst, dst_size, "%s#%d Part%u\n", why,
+ oopscount, part);
+ dst_size -= header_size;
+
+ if (!kmsg_dump_get_buffer(&iter, true, dst + header_size,
+ dst_size, &dump_size))
+ break;
+
+ if (big_oops_buf) {
+ zipped_len = pstore_compress(dst, psinfo->buf,
+ header_size + dump_size,
+ psinfo->bufsize);
+ …
+ } else {
+ record.size = header_size + dump_size;
+ }
+
+ ret = psinfo->write(&record);
+ …
+ }
+ …
+}
+
+```
+
+
+## kmsg\_dump实现
+
+
+printk实现了一个`kmsg\_dump()`函数,用于方便其它模块dump内核的log buffer,当内核发生oops、panic或重启等事件时,都会调用该函数dump log信息。其代码实现如下:
+
+
+
+```
+void kmsg_dump(enum kmsg_dump_reason reason)
+{
+ …
+ list_for_each_entry_rcu(dumper, &dump_list, list) {
+ enum kmsg_dump_reason max_reason = dumper->max_reason;
+
+ if (max_reason == KMSG_DUMP_UNDEF) {
+ max_reason = always_kmsg_dump ? KMSG_DUMP_MAX :
+ KMSG_DUMP_OOPS;
+ }
+ if (reason > max_reason)
+ continue;
+
+ dumper->dump(dumper, reason);
+ }
+ rcu_read_unlock();
+}
+```
+
+
+使用`kmsg\_dump()`之前要先使用`kmsg\_dump\_register()`来注册一个dumper,用于实际的log写操作。
+
+
+我们先来看看`kmsg\_dump\_register`的定义,只定义了一个dump\_list,将系统中所有注册的dump都挂在同一个list下,这就说明系统可以注册多个dumper。
+
+
+
+```
+int kmsg_dump_register(struct kmsg_dumper *dumper)
+{
+ …
+ if (!dumper->registered) {
+ dumper->registered = 1;
+ list_add_tail_rcu(&dumper->list, &dump_list);
+ err = 0;
+ }
+ …
+}
+```
+
+
+## 总结
+
+
+pstore dmesg主要工作流程如下:
+
+
+(1)初始化一个record结构体
+
+
+(2)先向其写入pstore头信息,如dmesg reason、oops发生次数等
+
+
+(3)从log buffer中读取一行log信息
+
+
+(4)若需要压缩信息,则执行压缩操作
+
+
+(5)调用后端的写函数,将record写入相应的后端设备
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ae0745cbba745886ad0ace066854f42eb9dc8834
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201.md"
@@ -0,0 +1,197 @@
+
+
+
+
+作者:新绎
+
+
+## 写在前面
+
+
+目前,pstore一次只支持打开一个后端。 如果一个新的后端想稍后注册, pstore将拒绝这个请求并返回一个错误。这个设计迫使我们关闭现有后端以使用新后端。
+
+
+内核支持某些类型的后端,例如ramoops和blk。在实际使用当中,我们还可以自行实现多种类型的后端。不同的后端根据不同的场景或业务进行信息收集。因此,他们需要同时工作,以满足各种需求。
+
+
+## 原始实现
+
+
+具体来说,由于全局变量`psinfo`的存在, pstore只接受第一个注册后端。如果一个新的后端想稍后注册, pstore将拒绝这个请求并返回一个错误。
+
+
+
+```
+int pstore_register(struct pstore_info *psi)
+{
+ if (backend && strcmp(backend, psi->name)) {
+ pr_warn("ignoring unexpected backend '%s'\n", psi->name);
+ return -EPERM;
+ }
+
+ /* Sanity check flags. */
+ if (!psi->flags) {
+ pr_warn("backend '%s' must support at least one frontend\n",
+ psi->name);
+ return -EINVAL;
+ }
+
+ /* Check for required functions. */
+ if (!psi->read || !psi->write) {
+ pr_warn("backend '%s' must implement read() and write()\n",
+ psi->name);
+ return -EINVAL;
+ }
+
+ mutex_lock(&psinfo_lock);
+ if (psinfo) {
+ pr_warn("backend '%s' already loaded: ignoring '%s'\n",
+ psinfo->name, psi->name);
+ mutex_unlock(&psinfo_lock);
+ return -EBUSY;
+ }
+ ...
+}
+```
+
+
+psinfo作为后端信息的存储结构体,一个psinfo只能保存一个后端。
+
+
+
+```
+struct pstore_info {
+ struct module *owner;
+ const char *name;
+
+ spinlock_t buf_lock;
+ char *buf;
+ size_t bufsize;
+
+ struct mutex read_mutex;
+
+ int flags;
+ int max_reason;
+ void *data;
+
+ int (*open)(struct pstore_info *psi);
+ int (*close)(struct pstore_info *psi);
+ ssize_t (*read)(struct pstore_record *record);
+ int (*write)(struct pstore_record *record);
+ int (*write_user)(struct pstore_record *record,
+ const char __user *buf);
+ int (*erase)(struct pstore_record *record);
+};
+```
+
+
+## 多后端实现
+
+
+### 修改全局变量
+
+
+在原始`fs/pstore/internal.h`中定义了全局变量`psinfo`
+
+
+`extern struct pstore\_info \*psinfo;`
+
+
+psinfo为后端信息的存储结构体,一个psinfo只能保存一个后端
+
+
+修改后:
+
+
+`extern struct pstore\_backends \*psback;`
+
+
+`psback`保存了所有使能`psinfo`的双向链表头节点。
+
+
+启动`psback`以及双向链表的定义如下:
+
+
+
+```
+struct pstore_info_list {
+ struct pstore_info *psi;
+ struct list_head list;
+ int index;
+};
+
+/**
+ * struct pstore_backends - management of pstore backends
+ * @list_entry: entry of pstore backend driver information list
+ * @front_cnt: count of each enabled frontend
+ * @flag: bitmap of enabled pstore backend
+ * @fs_ready: whether the pstore filesystem is ready
+ *
+ */
+
+struct pstore_backends {
+ struct list_head list_entry;
+ int front_cnt[PSTORE_TYPE_MAX];
+ u16 flag;
+ bool fs_ready;
+};
+```
+
+
+### 前端复用
+
+
+为了防止每注册一个后端就要注册相应的前端造成过多开销,我们选择对已经注册好的前端进行复用。如果当多个后端同时使能了同一前端,那么这个前端将会把自己收集的信息多写到这几个后端当中。
+
+
+
+
+
+
+代码实现:
+
+
+
+```
+static void pstore_dump(struct kmsg_dumper *dumper,
+ enum kmsg_dump_reason reason)
+{
+ struct pstore_info_list *entry;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(entry, &psback->list_entry, list)
+ if (entry->psi->flags & PSTORE_FLAGS_DMESG)
+ pstore_do_dump(dumper, reason, entry->psi, entry->index);
+ rcu_read_unlock();
+}
+```
+
+
+通过rcu锁以及对双向链表遍历的方式,前端可以线程安全地获取所有使能的后端,并且根据后端的使能情况执行写操作。
+
+
+### 让文件系统更直观
+
+
+由于多后端的存在,不同后端的输出文件将显得格外混乱,所以通过文件夹对不同后端进行分类的想法是自然而然产生的。
+
+
+通过修改`inode.c`,在`sys/fs/pstore`下建立相应后端的子文件夹,实现文件归类
+
+
+
+
+
+
+## 总结
+
+
+多后端支持的引入让pstore的使用更加灵活,可以根据不同后端功能以及业务场景同时使能多个后端,实现互不干扰,和谐共存。
+
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210.md"
new file mode 100644
index 0000000000000000000000000000000000000000..fa9fdd8e4bf09b7a262d3bd3720ddccaa753fd61
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210.md"
@@ -0,0 +1,366 @@
+
+
+
+作者:新绎
+
+
+## pstore概述
+
+
+### 定义
+
+
+pstore文件系统,是Persistent Storage的缩写,最早设计的目的是在内核Panic/Oops时能自动转存内核日志(log\_buf)到持久化内存(Persistent Ram),在Panic重启后,把转存的日志以文件形式呈现到用户空间以分析内核崩溃问题。随着版本的不断演进,pstore开始支持console,ftrace等一系列信息获取,提供多方位的日志抓捕功能,来帮助维护人员快速定位问题。
+
+
+### 对比kdump
+
+
+kdump作为一个重量级的问题分析工具,在发生panic时通过kexec加载crash kernel,该kernel会收集内存所有信息到dump core文件中予以保存。kdump的方案适用于服务器这种有大量资源的设备,功能也非常强大,但对嵌入式设备非常不友好。而pstore是个轻量级的内核崩溃日志转存的方案,虽然不能保存所有完整的寄存器等信息,但是不需要大量的内存空间进行部署,功能简洁轻量,在移动端和嵌入式设备的调试中被广泛地使用。
+
+
+
+
+
+
+## pstore配置方法
+
+
+### config选项(基于kernel version 5.10)
+
+
+pstore的各个模块需要在内核编译时通过config进行使能。
+
+
+
+pstore的各个模块需要在内核编译时通过config进行使能。
+
+
+
+
+| | |
+| --- | --- |
+| `CONFIG_PSTORE` | pstore文件系统使能 |
+
+
+* 前端
+
+
+
+
+| | |
+| --- | --- |
+| `CONFIG_PSTORE_PMSG` | 用户空间信息,/dev/pmsg0 |
+| `CONFIG_PSTORE_CONSOLE` | 控制台输出,所有内核信息 |
+| `CONFIG_PSTORE_FTRACE` | 函数调用序列, ftrace 信息 |
+
+
+* 后端
+
+
+
+
+| | |
+| --- | --- |
+| `CONFIG_PSTORE_RAM` | 持久化内存(重启后不会丢失数据的内存) |
+| `CONFIG_PSTORE_ZONE` | 实现存储空间的分配和管理 |
+| `CONFIG_PSTORE_BLK` | 所有可写的块设备 |
+
+
+* 压缩算法(**只针对DMESG前端数据**)
+
+
+
+
+| | |
+| --- | --- |
+| `CONFIG_PSTORE_COMPRESS` | 压缩算法使能 |
+| `CONFIG_PSTORE_DEFLATE_COMPRESS` | 默认压缩算法(deflate) |
+| `CONFIG_PSTORE_LZO_COMPRESS` | LZO压缩 |
+| `CONFIG_PSTORE_LZ4_COMPRESS` | LZ4压缩 |
+| `CONFIG_PSTORE_LZ4HC_COMPRESS` | LZHC(high compression)压缩 |
+| `CONFIG_PSTORE_842_COMPRESS` | 842压缩 |
+| `CONFIG_PSTORE_ZSTD_COMPRESS` | zstd压缩 |
+
+
+#### RAM后端(ramoops)配置方式
+
+
+
+**cmdline方式**
+
+
+example:
+
+
+`ramoops.mem_address=0x800000 ramoops.mem_size=0x10000 ramoops.console_size=0x4000`
+
+
+提供选项:
+
+
+`mem_address`,`mem_size`,`mem_type`,`record_size`,`console_size`,`pmsg_size`
+
+
+`max_reason`,`ramoops_ecc`,`dump_oops`
+
+
+**Platform Data方式**
+
+
+
+```
+#include
+ [...]
+
+ static struct ramoops_platform_data ramoops_data = {
+ .mem_size = <...>,
+ .mem_address = <...>,
+ .mem_type = <...>,
+ .record_size = <...>,
+ .max_reason = <...>,
+ .ecc = <...>,
+ };
+
+ static struct platform_device ramoops_dev = {
+ .name = "ramoops",
+ .dev = {
+ .platform_data = &ramoops_data,
+ },
+ };
+
+ [... inside a function ...]
+ int ret;
+
+ ret = platform_device_register(&ramoops_dev);
+ if (ret) {
+ printk(KERN_ERR "unable to register platform device\n");
+ return ret;
+ }
+
+```
+
+**设备树方式**
+
+
+
+``Documentation/devicetree/bindings/reserved-memory/ramoops.yaml``.
+
+
+
+```
+ For example::
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ ramoops@8f000000 {
+ compatible = "ramoops";
+ reg = <0 0x8f000000 0 0x100000>;
+ record-size = <0x4000>;
+ console-size = <0x4000>;
+ };
+ };
+```
+
+#### BLK后端配置方式
+
+
+**cmdline方式**
+
+
+example:
+
+
+`pstore_blk.blkdev=/dev/mmcblk0p7 pstore_blk.kmsg_size=64 best_effort=y`
+
+
+提供选项:
+
+
+`blkdev`,`kmsg_size`,`pmsg_size`,`console_size`,`ftrace_size`,`max_reason`
+
+
+
+
+
+**Kconfig方式**
+
+
+在编译时设置config
+
+
+`CONFIG_PSTORE_BLK_BLKDEV`
+
+
+`CONFIG_PSTORE_BLK_KMSG_SIZE`
+
+
+`CONFIG_PSTORE_BLK_MAX_REASON`
+
+
+`CONFIG_PSTORE_BLK_PMSG_SIZE`
+
+
+`CONFIG_PSTORE_BLK_CONSOLE_SIZE`
+
+
+`CONFIG_PSTORE_BLK_FTRACE_SIZE`
+
+
+### 配置查看
+
+
+检查 pstore 配置成功与否。
+`cat /sys/module/pstore/parameters/*`
+
+
+
+
+
+
+如图配置,backend = ramoops,compress = deflate,update\_ms = -1
+
+
+检查相关预留 size 是否配置成功(这里以ramoops后端为例)
+`ls /sys/module/ramoops/parameters`
+`cat /sys/module/ramoops/parameters/*`
+
+
+
+
+
+## pstore使用
+
+
+pstore使用十分简单,只要我们使能成功,并且检查各项配置都正确,那么pstore已经可以正常工作了。
+
+
+我们可以通过手动触发crash来查看pstore捕获的日志。
+
+
+`echo c > /proc/sysrq-trigger`
+
+
+在重启之后,我们可以在`/sys/fs/pstore/*` 看到加载的 pstore 数据
+
+
+`ls /sys/fs/pstore/`
+
+
+
+
+
+## pstore框架梳理
+
+
+这里后端以ramoops为例,kernel version = 5.10
+
+
+**【右键-在新标签页中打开图片】[查看原图](https://oss.openanolis.cn/fragment/uqbmggfmkvyziugluctq)**
+
+
+
+
+
+
+### pstore初始化
+
+
+pstore的初始化分为两步,首先是pstore前端和后端的初始化,接着是pstore文件系统的初始化
+
+
+pstore前后端:`postcore_initcall(ramoops_init);`
+
+
+pstore文件系统:`late_initcall(pstore_init);`
+
+
+
+
+
+通过查看相关模块初始化定义,我们发现pstore前后端位于`postcore_initcall`(优先级2)被初始化,而pstore文件系统则在`late_initcall`(优先级7)才会被初始化
+
+
+#### pstore前后端初始化
+
+
+**主要函数**
+
+
+fs/pstore/ram.c:
+
+
+`static int __init ramoops_init(void)`
+
+
+`static int ramoops_probe(struct platform_device *pdev)`
+
+
+fs/pstore/platform.c:
+
+
+`int pstore_register(struct pstore_info *psi)`
+
+
+**流程**
+
+
+1、解析并初始化前后端各种配置参数
+
+
+2、根据参数为每一个使能的前端申请持久化内存空间
+
+
+3、检测到内存中已经存在合法数据:开辟临时内存空间old\_log,将数据写入到old\_log,并刷新持久化内存
+
+
+4、根据flag以此判断是否注册前端,如果使能则对前端进行注册
+
+
+#### pstore文件系统初始化
+
+
+**主要函数**
+
+
+fs/pstore/inode.c:
+
+
+`pstore_init_fs()`
+
+
+`register_filesystem(&pstore_fs_type);`
+
+
+**流程**
+
+
+1、选择压缩函数
+
+
+2、文件系统初始化,读取old\_log数据并在/sys/fs/pstore下挂载
+
+
+
+
+
+### pstore写入数据
+
+
+pstore根据前端的不同,各个前端会分别调用pstore后端的写方法向自己的空间写入数据。
+
+
+具体各个前端的工作模式将会在“Pstore:前端”各章节文档介绍。
+
+
+
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267.md"
new file mode 100644
index 0000000000000000000000000000000000000000..4236a6963503e0e0f11d62ae24994315c5b0c621
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267.md"
@@ -0,0 +1,88 @@
+## 简介
+
+
+基于pstore的kdump调测工具是一个用于收集并存储crash kernel启动并执行vmcore转储过程中串口打印信息的工具,为kdump提供新的feature。
+方便对crash kernel启动并执行dump过程中所遇到的问题进行定位,能够覆盖crash kernel启动的绝大部分时间点。
+目前支持内核态以及用户态信息的全收集。
+
+
+仓库链接:
+
+
+\*目前对于内核pstore的改动已完成,正在进行用户态kdumpctl的整合
+
+
+## 背景
+
+
+目前kdump服务在使用过程中难免会遇到各种问题,导致vmcore无法正常生成。而在各种使用环境和因素的情况下,可能存在问题定位没有串口可用或者需要较高权限和复杂的流程来申请CN串口,那么我们需要一个机制来对crash kernel的打印信息进行转储,方便我们后续进行查看。
+
+
+当前新版的kdump支持在vmcore转储过程中对crash kernel的dmesg顺带进行保存,如下图所示:
+
+
+
+
+
+但是,这样的dmesg信息存储需要在crash kernel成功进入用户态并执行相应的脚本进行实现,如果crash kernel在内核态启动的过程中出现panic,亦或是kdump相关脚本没有正常工作,那么dmesg将无法进行保存。所以目前的crash kernel的dmesg保存机制能覆盖问题的点比较少,我们需要一个能够cover更多问题的调测工具。
+
+
+## 原理
+
+
+### pstore相关原理及修改
+
+
+pstore相关介绍和对应的补丁修改参见:
+
+
+[Pstore总览 - OpenAnolis 龙蜥操作系统开源社区](https://openanolis.cn/sig/Cloud-Kernel/doc/623611346526568454)
+
+
+[Pstore多后端支持补丁](https://openanolis.cn/sig/Cloud-Kernel/doc/646804783491448879)
+
+
+当前的pstore的内核态与用户态的log存储逻辑如下:
+
+
+
+
+
+对于用户态信息,pmsg只会接受用户对其的输入信息,而不会主动获取。而可以产生用户态输出的程序和服务有许多,包括各种service以及dump相关脚本,如果想采用这样一个方案进行用户态信息的收集,我们需要对用户态的输出进行重定向到pmsg。这样的操作有两个比较大的问题:
+
+
+1、重定向后原有的串口将不显示输出
+
+
+2、如果想cover所有用户态输出,需要在用户态进行大量的修改
+
+
+所以,我们希望从根源上高效地解决问题。我们注意到所以用户态向串口输出都会走tty驱动,那么我们可以实现一个新的pstore前端,该前端在tty驱动前有一个hook点,我们可以直接获取到用户态向tty驱动的输出,从而获取相关的log信息。
+
+
+
+
+
+## 工具流程
+
+
+基于pstore的kdump调测工具主要工作在crash kernel中,在crash kernel中配置好pstore后端ramoops相应的参数(内存地址,预留空间大小等),在crash kernel启动过程中会使能pstore并且获取内核态以及用户态的信息,实时输出到ramoops配置好的持久化内存当中。
+
+
+由于机器重启不会掉电(正常情况下),当我们重回第一个kernel的之后,我们对那块内存进行解析,就可以获取crash kernel相应的log输出。
+
+
+
+
+
+## 使用
+
+
+我们对工具进行了包装,与kdump进行融合,pstore相关的配置将由相应的脚本自动实现,使用者无需进行配置。在正常使用过程中,我们将工具包装进了kdumpctl命令。
+
+
+只需要在crash kernel执行过后输入kdumpctl showdebug,就可以很方便地对crash kernel的log输出进行查看。
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/\351\241\271\347\233\256\347\256\200\344\273\213.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/\351\241\271\347\233\256\347\256\200\344\273\213.md"
new file mode 100644
index 0000000000000000000000000000000000000000..8f8b3d07e9fa873033a1f1dcc81e30e3c39ddcb5
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/\351\241\271\347\233\256\347\256\200\344\273\213.md"
@@ -0,0 +1,2 @@
+致力于各种内核调测技术的研发和产品化,包括但不限于kdump/pvdump, pstore, ftrace, 各种probes, perf/pmu, ebpf等技术。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/Anolis_OS\346\224\257\346\214\201\347\232\204\351\251\261\345\212\250\345\210\227\350\241\250.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/Anolis_OS\346\224\257\346\214\201\347\232\204\351\251\261\345\212\250\345\210\227\350\241\250.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250spec\350\247\204\350\214\203.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250spec\350\247\204\350\214\203.md"
new file mode 100644
index 0000000000000000000000000000000000000000..540c85ff72f062433beba350151d0c95f2c53dfc
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250spec\350\247\204\350\214\203.md"
@@ -0,0 +1,104 @@
+### spec文件命名
+
+
+驱动名、仓库名保持一致,因此spec文件的命名方式为「驱动名.spec」。
+
+
+### spec内容规范
+
+
+下面提供了spec文件的通用模板,在合入驱动时需根据实际的驱动修改pkg等字段,需修改的字段如下:
+
+
+1)「pkg」,需修改成驱动名。
+
+
+2)「Summary」,需修改为该驱动的描述。
+
+
+3)「License」,需按照实际的license修改。
+
+
+4)「URL」,可修改为驱动官网链接。
+
+
+5)「%description」,需修改成该驱动的描述。
+
+
+6)「%build」,需根据实际的编译方式修改。
+
+
+7)「%install」,需根据实际的安装路径修改。
+
+
+
+```
+%global pkg ast
+%global pkgversion 1.0
+%global kernel kernel version
+%define anolis_release 1
+
+Name: kmod-%{pkg}
+Version: %(echo %{kernel} | sed -E 's/-/~/g; s/\.(el|al|alios)[0-9]+$//g')
+Release: %{pkgversion}.%{anolis_release}%{?dist}
+Summary: ASPEED Graphics DRM Driver
+License: LBPLv2+ and MIT
+URL: https://www.aspeedtech.com/support_driver/
+Patch0: source-git.patch
+
+# 安装依赖, 和内核版本对应
+Requires: kernel = %{kernel}
+Requires(post): kmod
+Requires(post): dracut
+
+# 构建依赖, 和内核版本对应
+BuildRequires: kernel-devel = %{kernel}
+BuildRequires: kernel-headers = %{kernel}
+BuildRequires: elfutils-libelf-devel
+BuildRequires: gcc
+BuildRequires: kernel-rpm-macros
+BuildRequires: kmod
+BuildRequires: make
+BuildRequires: redhat-rpm-config
+BuildRequires: xz
+
+%description
+RPM Package for ASPEED Graphics DRM Driver
+
+%prep
+%autosetup -p1 -c -T
+
+%build
+pushd src
+%{__make} -C /usr/src/kernels/%{kernel}.%{_arch} %{?_smp_mflags} M=$PWD modules
+popd
+
+%install
+mkdir -p %{buildroot}/lib/modules/%{kernel}.%{_arch}/extra/drivers/gpu/drm/ast
+%{__install} -D -t %{buildroot}/lib/modules/%{kernel}.%{_arch}/extra/drivers/gpu/drm/ast src/ast.ko
+
+# Make .ko objects temporarily executable for automatic stripping
+find %{buildroot}/lib/modules -type f -name \*.ko -exec chmod u+x \{\} \+
+
+# Generate depmod.conf
+%{__install} -d %{buildroot}/%{_sysconfdir}/depmod.d/
+for kmod in $(find %{buildroot}/lib/modules/%{kernel}.%{_arch}/extra -type f -name \*.ko -printf "%%P\n" | sort)
+do
+ echo "override $(basename $kmod .ko) * extra/$(dirname $kmod)" >> %{buildroot}/%{_sysconfdir}/depmod.d/%{pkg}.conf
+done
+
+%clean
+%{__rm} -rf %{buildroot}
+
+%post
+depmod -a %{kernel}.%{_arch}
+dracut -v -f /boot/initramfs-%{kernel}.%{_arch}.img %{kernel}.%{_arch}
+
+%files
+%defattr(644,root,root,755)
+%license licenses
+/lib/modules/%{kernel}.%{_arch}
+%config(noreplace) %{_sysconfdir}/depmod.d/%{pkg}.conf
+
+%changelog
+```
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227.md"
new file mode 100644
index 0000000000000000000000000000000000000000..f8053a0c625e8d9bdfec29cf31ae5213c2a64c0e
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227.md"
@@ -0,0 +1,185 @@
+### 简介
+
+
+龙蜥社区采用Out-of-tree(OOT)的方式管理部分第三方驱动,这部分驱动的版本可以在已发布的内核版本的基础上迭代小版本。一个驱动对应着两个仓库,一个source tree仓库用于管理源码,一个rpm tree仓库用于管理编译打包RPM包。
+
+
+#### 代码管理
+
+
+Source tree仓库的代码组织形式为「src目录」+ 「licenses目录」+ 「spec文件」,「src目录」用于存放驱动源码,「licenses目录」用于存放license,「spec文件」用于编译打包RPM包。
+
+
+#### 版本管理
+
+
+当前[Cloud Kernel](https://gitee.com/anolis/cloud-kernel)有devel-4.19和devel-5.10两个分支对应两个版本,因此source tree仓库也分有devel-4.19和devel-5.10两个分支用于分别适配Cloud Kernel的两个版本。
+
+
+**Cloud Kernel发布版本:**
+
+
+当Cloud Kernel发布版本时会基于OOT驱动source tree仓库的devel-xxx分支拉取release分支,例如要发布4.19.91-27版本,拉取的分支为release-4.19.91-27,然后构建系统将代码和spec文件传到rpm tree仓库编译出包,打包的RPM包会随着Cloud Kernel的版本一起发布。
+
+
+**OOT单独迭代小版本:**
+
+
+当Cloud Kernel的下一个版本还未发布时,OOT驱动可以单独在已经发布的大版本的基础上迭代小版本,例如在4.19.91-27的版本基础上发布4.19.91-27-1版本。
+
+
+### 如何向OOT合入新的驱动
+
+
+下文将以ast为实际例子进行流程说明。
+
+
+#### 创建source tree仓库和rpm tree仓库
+
+
+Maintainer会为驱动创建source tree仓库和rpm tree仓库,然后**将创建好的仓库地址同步到bugzilla**,仓库地址例如:https://gitee.com/anolis/ast 和 https://gitee.com/src-anolis-sig/ast。
+
+
+#### 注册账号/登录
+
+
+参与龙蜥OOT开发,需要先注册龙蜥社区及 Gitee 平台账号,并将两个账号关联。
+步骤如下:
+
+
+* [注册龙蜥社区账号](https://gitee.com/link?target=https%3A%2F%2Fpassport.openanolis.cn%2Fregister)(已有账号的略过此步);
+* [注册 Gitee 账号](https://gitee.com/signup)(已有账号的略过此步);
+* 关联两个账号:因涉及下节提到的 CLA 签署,需要将两个账号关联,直接登录龙蜥社区在【账号设置】 -> 【安全设置】里可以操作绑定 Gitee 账号。
+
+
+ 
+
+
+签署CLA
+向龙蜥OOT贡献代码,必须先签署 CLA。 可以登录龙蜥社区后, 打开[CLA页面](https://openanolis.cn/pact/contributor) 进行 CLA 签署。
+
+
+注意:
+
+
+* 以人个名义贡献的,可签署个人 CLA;
+* 以公司名义贡献的,需要签署公司 CLA;
+* 详情请咨询贵公司相关法务。
+
+
+#### fork代码仓库
+
+
+1、将maintainer创建好的source tree仓库fork到自己的账户,龙蜥采用PR(Pull Request)的方式合并源码。
+
+
+ 
+
+
+2、将fork到个人账号的source tree仓库clone到本地的开发环境。
+
+
+
+
+
+#### 补丁制作
+
+
+1、根据[OOT驱动补丁规范](https://openanolis.cn/sig/Cloud-Kernel/doc/695239829190715269),并且按照「src目录」+ 「licenses目录」+「spec文件」的格式(「src目录」存放源码,「licenses目录」用于存放license,spec文件为编译RPM包所需的文件)制作补丁,spec文件的命名和格式需按照[OOT驱动spec规范](https://openanolis.cn/sig/Cloud-Kernel/doc/684402508139285258??preview=null)上传。
+
+
+2、将commit push到个人账号下的source tree仓库。
+
+
+#### 提交PR(Pull Request)
+
+
+1、登录gitee,进入个人账户下的仓库页面。
+
+
+
+
+
+2、在「Pull Request栏」点击「新建Pull Request」,创建PR。
+
+
+
+
+
+3、填写PR信息:
+
+
+* 选择目标仓库为被fork的source tree仓库。
+* 选择正确的**源及目标分支**。
+* 选择合适的评审人即maintainer,maintainer会将他的账号同步到bugzilla或者钉钉群。
+* 「标题」和「说明」请参考[PR(Pull Request)规范](https://openanolis.cn/sig/Cloud-Kernel/doc/607605992881480196)填写。
+
+
+
+
+
+4、当您提交完PR后,会有机器人自动帮您进行代码审核验证。
+
+
+* 代码**检测通过**,会有如下提示:
+
+
+
+
+
+* 代码**检测未通过**:
+ + 请自行修改代码后,使用**git push --force**重新push至个人仓库下。
+ + 在pr链接下评论 **/retest** 重新触发代码检测。
+ + 若因为某些特殊原因导致无法通过检测,可联系maintainer回复**/skip-test**跳过检测。详见:[龙蜥内核代码门禁系统](https://openanolis.cn/sig/SIG-Infra/doc/594387296754325258)。
+
+
+
+
+
+5、评审人(maintainer)回复通过并附上签名。
+
+
+
+
+
+6、依次将PR链接和评审人签名添加到相应 commit log 末尾处,并且使用git push --force 提交更新。
+
+
+注意:PR链接放在评审人签名前面
+
+
+格式:
+
+
+Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx Reviewed-by: xxx <邮箱>
+
+
+
+
+
+让最后10个 commit 都加上PR链接Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx 以及评审人签名Reviewed-by: Linus Torvalds 的命令:
+
+
+git filter-branch -f --msg-filter ' cat && echo "Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx" && echo "Reviewed-by: Linus Torvalds "' HEAD~10..HEAD
+
+
+
+
+
+7、在PR下评论 **/check-sig**提交签名及PR链接检查命令。
+
+
+
+
+
+8、联系maintainer评论**/merge** 即可进入代码合入流程。
+
+
+
+
+
+9、(可选)最后还需指定一人作为source tree仓库的maintainer,社区maintainer会为该maintainer添加仓库权限,新maintainer负责后续source tree仓库的维护。
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\350\241\245\344\270\201\350\247\204\350\214\203.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\350\241\245\344\270\201\350\247\204\350\214\203.md"
new file mode 100644
index 0000000000000000000000000000000000000000..8522a7f0c86127e085c25b4a2a2112dd0aacf0b7
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\350\241\245\344\270\201\350\247\204\350\214\203.md"
@@ -0,0 +1,48 @@
+将代码合入OOT驱动仓库时,请根据如下规范制作补丁。
+
+
+注意:**所有补丁内容均不能出现中文**
+
+
+## 范例
+
+
+
+```
+sched/fair: Fix wrong cpu selecting from isolated domain
+
+ANBZ: #1468
+
+#commit body ......
+
+Signed-off-by: Andrew Morton
+Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx
+Reviewed-by: Linus Torvalds
+```
+
+## 范例细则
+
+
+* 补丁标题/subject:保持原标题不变。
+* 补丁日志/commit log
+ + 第一行
+ - 附上对应问题的bugzilla ID号。如果还没有bugzilla ID,需要前往[bugzilla](https://bugzilla.openanolis.cn/)提交问题。
+ * 格式:**ANBZ +冒号+空格+#+bugzilla ID**
+ * 范例:**ANBZ: #42**
+ * "ANBZ" 即是 "Anolis bugzilla"
+ + 第二行
+ - 空行。
+ + 第三行及其之后
+ - 具体的commit 内容。
+* 补丁签名/SOB
+ + 保留原补丁的完整签名,在其后追加合入人的签名
+ - 格式:**Signed-off-by: <名字> <邮箱地址>**
+ - 范例:Signed-off-by: Andrew Morton
+* PR链接(初次提交不需要,评审通过后再追加至commit log尾部)
+ + 在回合人签名后面追加PR链接
+ - 格式:**Link: **
+ - 范例:Link:
+* Reviewed-by(初次提交不需要,评审通过后再追加至commit log尾部)
+ + 在PR链接后追加评审人签名
+ - 格式:**Reviewed-by: <名字> <邮箱地址>**
+ - 范例:Reviewed-by: Linus Torvalds
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\345\246\202\344\275\225\346\217\220\344\272\244\347\241\254\344\273\266\345\205\274\345\256\271\346\200\247\346\265\213\350\257\225\347\224\263\350\257\267.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\345\246\202\344\275\225\346\217\220\344\272\244\347\241\254\344\273\266\345\205\274\345\256\271\346\200\247\346\265\213\350\257\225\347\224\263\350\257\267.md"
new file mode 100644
index 0000000000000000000000000000000000000000..0ba118fa1a49e233cab33c2263af1e55172a5e97
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\345\246\202\344\275\225\346\217\220\344\272\244\347\241\254\344\273\266\345\205\274\345\256\271\346\200\247\346\265\213\350\257\225\347\224\263\350\257\267.md"
@@ -0,0 +1,6 @@
+请按照硬件兼容测试申请流程: https://openanolis.cn/sig/HCT/doc/423293128473364249 ,
+
+下载安装ancert,ancert快速开始手册:https://openanolis.cn/sig/HCT/doc/515463617816101039
+
+针对第三方驱动设备执行硬件兼容性测试,审核通过之后,同步测试结果到bugzilla。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\345\246\202\344\275\225\346\217\220\344\272\244\347\254\254\344\270\211\346\226\271\351\251\261\345\212\250\351\233\206\346\210\220\347\224\263\350\257\267.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\345\246\202\344\275\225\346\217\220\344\272\244\347\254\254\344\270\211\346\226\271\351\251\261\345\212\250\351\233\206\346\210\220\347\224\263\350\257\267.md"
new file mode 100644
index 0000000000000000000000000000000000000000..a404159259fcede41aee30466d053dcd40ae2f46
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\345\246\202\344\275\225\346\217\220\344\272\244\347\254\254\344\270\211\346\226\271\351\251\261\345\212\250\351\233\206\346\210\220\347\224\263\350\257\267.md"
@@ -0,0 +1,6 @@
+如果您有意向往Anolis OS中集成您的第三方驱动,请首先提一个龙蜥社区bugzilla用于跟踪合入流程。
+
+具体操作步骤详见"[向CloudKernel报告BUG](https://openanolis.cn/sig/Cloud-Kernel/doc/607601736106142822)",其中「Component」选择「drivers」以保证社区能够第一时间看到。
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\347\254\254\344\270\211\346\226\271\351\251\261\345\212\250\345\246\202\344\275\225\350\277\233\345\205\245Anolis_OS.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\347\254\254\344\270\211\346\226\271\351\251\261\345\212\250\345\246\202\344\275\225\350\277\233\345\205\245Anolis_OS.md"
new file mode 100644
index 0000000000000000000000000000000000000000..50466a9d6029b13d74b528f738847efd2aa1c6e1
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\347\254\254\344\270\211\346\226\271\351\251\261\345\212\250\345\246\202\344\275\225\350\277\233\345\205\245Anolis_OS.md"
@@ -0,0 +1,53 @@
+### 第三方驱动集成形式(Intree 或 Out-of-tree)
+
+
+第三方驱动分为两种集成形式:第一种是集成到[Cloud Kernel](https://gitee.com/anolis/cloud-kernel)里面,与内核版本同步迭代,称为intree;第二种是采用单独的仓库管理,可以在大版本的基础上快速迭代小版本,称为out-of-tree(OOT)。
+
+
+两种集成形式的判定原则为:
+
+
+* 使用较广泛的驱动,在其他主流OS intree支持,则Anolis OS也优先考虑intree支持。
+* 综合厂商意愿和多方意见决定是否intree。
+* 如果第三方驱动与Anolis内核中的相关代码有冲突,则选择out-of-tree。
+* 如果第三方驱动处于开发活跃期,版本节奏与Anolis OS不匹配,则选择out-of-tree。
+
+
+### 第三方驱动集成流程
+
+
+1、第三方厂商提交第三方驱动集成申请,具体操作请点击 [如何提交第三方驱动集成申请](https://openanolis.cn/sig/Cloud-Kernel/doc/658176089664054811) 。
+
+
+2、如果是外设驱动相关,第三方厂商还需要提交硬件兼容性测试申请,具体操作请点击 [如何硬件兼容性测试申请](https://openanolis.cn/sig/Cloud-Kernel/doc/658195172967044331) 。
+
+
+3、强烈建议你加入 [Cloud Kernel SIG](https://openanolis.cn/sig/Cloud-Kernel) 钉钉交流群,可用群号「**35675176」**或扫 [这里](https://openanolis.cn/sig/Cloud-Kernel) 末尾的二维码入群,入群后请查看群公告。
+
+
+
+
+
+通过bugzilla或钉钉群决策出来该第三方驱动是intree还是out-of-tree后,分别走不同的合入流程:
+
+
+#### Intree流程
+
+
+1、第三方厂商提PR(Pull Request)将驱动合入到Anolis kernel中, 具体操作请点击 [内核开发者指南](https://openanolis.cn/sig/Cloud-Kernel/doc/657676881630727957) 。
+
+
+2、根据上述指南完成提交后,第三方厂商更新信息关闭bugzilla。
+
+
+#### Out-of-tree流程
+
+
+社区maintainer会创建source tree仓库和rpm tree仓库,将仓库信息同步至bugzilla中。
+
+
+1、第三方厂商提交PR(Pull Request)将源码 + spec文件合入到source tree仓库,具体操作请点击 [OOT驱动开发者指南](https://openanolis.cn/sig/Cloud-Kernel/doc/660356858711892913?preview=null) 。
+
+
+2、根据上述指南完成提交后,第三方厂商更新信息关闭bugzilla。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\351\241\271\347\233\256\347\256\200\344\273\213.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\351\241\271\347\233\256\347\256\200\344\273\213.md"
new file mode 100644
index 0000000000000000000000000000000000000000..98854f24cfab9915e81a716bcdbe31f57b194ef4
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\351\241\271\347\233\256\347\256\200\344\273\213.md"
@@ -0,0 +1,14 @@
+本项目致力于维护Anolis OS各个版本的第三方驱动,例如适配支持最新的硬件型号,但不限于硬件外设驱动。
+
+
+
+
+
+相关文档:
+
+
+#### [第三方驱动如何进入Anolis OS](https://openanolis.cn/sig/Cloud-Kernel/doc/657632139127603555?preview=)
+
+
+#### [Anolis OS支持的驱动列表](https://openanolis.cn/sig/Cloud-Kernel/doc/657632317528069334?preview=)
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213.md"
new file mode 100644
index 0000000000000000000000000000000000000000..c3c53de12d0105c4ec0b9895ac7ded0a11993e7f
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213.md"
@@ -0,0 +1,340 @@
+# 1. RAS机制简介
+
+
+为了提高系统的容错能力及可用性, 面向服务器的处理器芯片都需要支持 RAS 机制。RAS是可靠性(Reliability)、可用性(Availability)和可服务性(Serviceability)的简称,分别代表下面的意义:
+
+
+**Reliability**:指的是系统尽可能最大化运行时间,不会意外崩溃,重启甚至系统物理损坏,即对于某些错误能做到自动修复,无法自修复的也尽可能进行隔离,保证系统正常运转。
+
+
+**Availability**:指的是系统最大限度减少非预期宕机的时间,当出现问题也不会影响整个系统的正常运行,在某些情况下甚至可以进行替换组件操作,严格确保系统宕机时间在一定范围内。
+
+
+**Serviceability**:指的是系统提供诊断功能,例如系统日志,动态检测等手段方便管理人员进行系统诊断和维护操作,尽早发现并修复错误。
+
+
+RAS是评估服务器系统容错能力及可用性评测的一项关键指标。错误等级可分为三级分别是可纠正错误(Corrected Error, CE)、可恢复错误(Uncorrected Error, UE)以及致命错误(Fatal),RAS机制实现对错误的分级处理。
+
+
+# 2. RAS机制错误处理流程
+
+
+RAS机制需要硬件、固件、OS内核协同工作才能得以支持,因此需要一个统一高效的接口来进行硬件错误的上报与处理。ACPI Platform Error Interfaces(APEI)正是为解决这一问题而出现,APEI规范统一了软硬件接口。它通过提供BOOT Error Record Table (BERT)、Error Record Serialization Table (ERST)、Error Injection Table (EINJ)以及Hardware Error Source Table (HEST)这四张表来实现OS内核与固件、硬件之间的协同工作,其中,HEST用于错误上报,EINJ用于错误注入。
+
+
+RAS机制错误处理流程如下,当硬件(如CPU、内存、PCIe总线)产生错误时,中断信号会首先交由运行在Secure World的固件处理,固件首先调用CPER库产生规范化的错误信息记录并填入CPER表中,然后将中断信号交由linux内核处理。linux内核中SDEI驱动接收该中断并调用ghes\_proc\_in\_irq函数从ACPI Table中读取错误信息,然后调用ghes\_do\_proc对错误进行处理,并且调用ghes\_print\_estatus打印错误信息。ghes\_do\_proc函数会最终调用memory\_failure函数对内存以及Cache的UE错误进行处理,对于CPU错误进行记录,对于fatal错误则会产生kernel panic。
+
+
+
+
+
+# 3. RAS机制评测流程
+
+
+RAS提供的EINJ机制可以在系统发布之前评测系统的可靠性、容错性以及完备性。EINJ 可以注入各种类型的硬件错误,这些注入的错误通过 EINJ 和底层 firmware 以及硬件共同配合产生的,对于软件来说和硬件真实发生的错误没有差别。
+
+
+APEI按照错误等级以及错误类型进行组合,总共支持以下12种错误注入,需要以实际系统支持的错误注入类型为准。
+
+
+从表中可以看到,错误类型分别有Processor错误、Memory错误、PCIe错误以及Platform错误。典型的Processor错误有L1-Cache/L2-Cache/TLB中出现数据一位或多位翻转;典型的Memory错误有内存中出现数据一位或多位翻转;在ARM架构中,典型的Platform错误有LLC(last level cache)中出现一位或多位位翻转。
+
+
+如果仅一位翻转,那么硬件(比如通过ECC)可以检测到并且纠正,像这样的错误就是Correctable Error,在软件层面则只需要进行记录发生此类错误的次数,在次数未达阀值前不需要进一步处理。如果有一位以上的数据翻转,那么硬件只能检测到发生错误没有能力进行纠正,这就是Uncorrectable Error,需要软件层面根据错误等级提供处理逻辑:如果产生的错误是Uncorrectable Non-Fatal Error,可将该数据直接丢弃;如果产生的错误是Uncorrectable Fatal Error,触发kernel panic重启系统。
+
+
+
+
+| |
+| --- |
+| 0 Processor Correctable
+1 Processor Uncorrectable non-fatal
+2 Processor Uncorrectable fatal |
+| 3 Memory Correctable
+4 Memory Uncorrectable non-fatal
+5 Memory Uncorrectable fatal |
+| 6 PCI Express Correctable
+7 PCI Express Uncorrectable non-fatal
+8 PCI Express Uncorrectable fatal |
+| 9 Platform Correctable
+10 Platform Uncorrectable non-fatal
+11 Platform Uncorrectable fatal |
+
+
+Linux内核进行错误注入的流程如下。EINJ.ko模块封装了APEI进行错误注入的操作细节(具体操作细节可参考ACPI SPEC 18.6.5节),在/apei/einj目录下为用户提供了便于操作的接口。这些参数的意义如下,available\_error\_type展示系统支持注入哪些错误;error\_type是当前注入的错误类型;flags取值与当前错误类型相关;参数param1~param4可传递注入错误的地址、掩码、CPU编号等,也与当前注入的错误类型相关;向error\_inject写1表示开始注入错误。EINJ.ko模块接受到这些参数后,调用EINJ Table中相应的action,由固件进行错误注入。EINJ.ko模块等待错误注入成功后,可继续调用EINJ Table中的action触发该错误,或者直接返回由用户自行触发(参数notrigger置1表示由用户自行触发)。
+
+
+
+
+
+上述流程比较简要地介绍了APEI错误注入机制,linux内核中的APEI Error INJection support模块已经完整地支持了错误注入机制,可调用EINJ.ko模块的接口或者使用封装了该模块接口的ras-tools进行错误注入。
+
+
+错误注入是为了验证系统RAS机制的正确性,因此**RAS评测流程**可分为如下三步:
+
+
+1**.使用ras-tools工具注入错误**,比如,内存、CPU的错误。
+
+
+2.**触发错误**。ras-tools工具默认注入错误后即进行触发。
+
+
+3.**观测系统对错误的处理是否符合预期**,比如,上报的错误信息是否准确,系统对各类错误的处理逻辑是否合理等。
+
+
+# 4. CPU及内存错误注入演示
+
+
+CPU和内存在计算机系统中的具有十分重要地位,它们出现错误有可能导致系统宕机甚至程序执行出错,对于服务器系统来说是不可接受的。因此,本节演示CPU与内存的错误注入。
+
+
+## 4.1 环境准备
+
+
+### 1. 安装EINJ模块
+
+
+使用命令modprobe einj进行模块加载,如果无法加载,则需要配置内核重新编译,可参考文档 :https://docs.kernel.org/firmware-guide/acpi/apei/einj.html
+
+
+此外,由于RAS机制需要固件的支持,如果后续的测试未看到上报的错误信息,那么需要检查固件(BIOS)是否支持RAS,或者将固件更新到最新。
+
+
+### 2. 安装RAS测试工具
+
+
+直接使用EINJ接口进行错误注入比较繁琐,可安装ras-tools工具进行错误注入,该工具由C语言编写,直接编译即可,链接:https://gitee.com/anolis/ras-tools.git
+
+
+### 3. 安装rasdaemon
+
+
+先安装依赖包yum install sqlite perl-DBD-SQLite
+
+
+使用如下命令编译安装rasdaemon,链接:https://github.com/mchehab/rasdaemon.git
+
+
+
+```
+autoreconf -vfi && ./configure --enable-sqlite3 --enable-arm && make
+make install
+```
+
+在命令行中输入rasdaemon -r 即可开启rasdaemon守护进程,rasdaemon支持如下参数。
+
+
+
+```
+ -d, --disable 禁用RAS事件并退出
+ -e, --enable 使能RAS事件并退出
+ -f, --foreground 前台运行
+ -r, --record 通过sqlite3记录事件
+```
+
+rasdaemon用户态守护进程能将捕获系统events并将错误信息输出到log、database或console。
+
+
+查看系统详细的错误处理信息可以通过dmesg命令查看,或者从BMC串口查看。
+
+
+本次测试需要使用rasdaemon -r命令开启该进程,并在跳板机上使用BMC串口连接到目标机。
+
+
+## 4.2 CPU错误注入
+
+
+本文主要使用einj\_mem\_uc工具,该工具可注入内存错误以及CPU错误,可使用命令./einj\_mem\_uc -h查看使用说明。
+
+
+使用./einj\_mem\_uc core\_non\_fatal命令注入一个UE类型的CPU错误。
+
+
+
+```
+./einj_mem_uc core_non_fatal
+0: core_non_fatal vaddr = 0xffff88f22400 paddr = 8a878e400
+injecting ...
+triggering ...
+Manually take page offline
+Test passed
+```
+
+使用BMC串口错误处理详细信息如下,没有时间戳的信息是由固件输出的,有时间戳的信息则是由内核输出的(如果使用dmesg则只能查看到下述带时间戳的信息)。可以看到硬件产生了17号中断,并首先由固件接管。17号中断的意义如下,它是一个CPU错误信号。
+
+
+
+
+| | | | |
+| --- | --- | --- | --- |
+| 17 | nFaultIRQ | Core fault interrupt | Generated from CORE and connect to nFAULTIRQ pins; nFAULTIRQ pins are connected to GIC components; this CPU or other CPUs handle the faults in firmware, firmware behavior is implementation-defined. |
+
+
+可以看到,这个错误是来自L2 Cache的错误,它是不可纠正但可恢复的。恢复手段应该是硬件层面CPU丢弃Cache中的数据,软件层面通过memory\_failure函数删除Cache数据对应的内存页面。
+
+
+
+```
+->Core[8](0x81080000) received intr=17(core), cnt=0xd
+INFO: RAS reg:
+INFO: fr = 10a9a2
+INFO: status = 44800007
+INFO: addr = 8007e0e95fffb7ff
+INFO: misc0 = 4
+INFO: misc1 = 0
+RTC: 2000-01-06 09:32:09
+ core[8] mm(17) return: 0
+--handler(17) end
+[40858.417829] [Firmware Warn]: GHES: Unhandled processor error type: cache error
+[40858.427894] {42}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 4
+[40858.436229] {42}[Hardware Error]: event severity: recoverable
+[40858.441961] {42}[Hardware Error]: precise tstamp: 2000-01-06 09:32:09
+[40858.448473] {42}[Hardware Error]: Error 0, type: recoverable
+[40858.454204] {42}[Hardware Error]: section_type: ARM processor error
+[40858.460629] {42}[Hardware Error]: MIDR: 0x00000000410fd490
+[40858.466272] {42}[Hardware Error]: Multiprocessor Affinity Register (MPIDR): 0x0000000081080000
+[40858.475041] {42}[Hardware Error]: running state: 0x1
+[40858.480163] {42}[Hardware Error]: Power State Coordination Interface state: 0
+[40858.487456] {42}[Hardware Error]: Error info structure 0:
+[40858.493013] {42}[Hardware Error]: num errors: 1
+[40858.497702] {42}[Hardware Error]: error_type: 0, cache error
+[40858.503606] {42}[Hardware Error]: error_info: 0x0000000000800015
+[40858.509857] {42}[Hardware Error]: transaction type: Instruction
+[40858.516109] {42}[Hardware Error]: cache level: 2
+[40858.521058] {42}[Hardware Error]: the error has not been corrected
+[40858.528062] Memory failure: 0x89b78f: recovery action for dirty LRU page: Recovered
+```
+
+## 4.3 内存错误注入
+
+
+使用命令./einj\_mem\_uc single注入一个UE类型的内存错误。该命令首先向一个内存地址注入一个UE类型的内存错误,然后通过读取该地址的数据触发该错误。
+
+
+
+```
+./einj_mem_uc single
+0: single vaddr = 0xffffabcb3400 paddr = 8aaf74400
+injecting ...
+triggering ...
+SIGBUS: addr = 0xffffabcb3400
+page not present
+Test passed
+```
+
+BMC串口中显示详细的错误处理详细信息如下(如果使用dmesg则只能查看到下述带时间戳的信息),硬件产生了一个中断号为0的中断,这代表产生的是一个同步异常。接下来的信息指出该错误是一个可恢复的内存错误,并且展示了产生该错误的内存地址以及ECC寄存器的状态。最后调用memory\_failure函数删除该地址对应的内存页面。
+
+
+
+```
+->Core[8](0x81080000) received intr=0(exception), cnt=0xa
+MM Mem RAS handle,Intr:0
+Ch = 25810000
+ |-ECCERRCNT:10000, ECCSTAT:0, ADVECCSTAT:8000002 ECCSYMBOL:760000
+ |-ECCERRCNTSTAT:0 ECCERRCNT0:0 ECCERRCNT1:0
+ |-ECCCADDR0:0 ECCCADDR1:0 ECCCDATA0~1:0,0
+ |-ECCCSYN0~2:0,0,0 ECCAPSTAT:0
+ |-ECCUADDR0:176D ECCUADDR1:2010480 ECCUDATA0~1:1FF,0
+ |-ECCUSYN0~2:1FF,0,76
+ |-SBRCTL:1C01591B,SBRSTS:0
+RasData->ExceptionEl: 0, UeCnt:0x1
+RTC: 2000-01-06 09:27:58
+Get SystemAddrss through mAddrTransProtocol start
+Get SystemAddrss through mAddrTransProtocol end
+s:0 d:0 ctl:2 ch:0 rank:0 bg:2 b:1 row:176D col:480 DeAddr:DDB599400
+Locate error dimm, Socket:0, Channel:2 Dimm:0
+ core[8] mm(0) return: 0
+--handler(0) end
+[40606.624019] EDAC MC0: 1 UE multi-symbol chipkill ECC on unknown memory (node:0 card:2 module:0 rank:0 bank_group:2 bank_address:1 device:0 row:5997 column:1152 chip_id:0 page:0xddb599 offset:0x400 grain:1 - APEI location: node:0 card:2 module:0 rank:0 bank_group:2 bank_address:1 device:0 row:5997 column:1152 chip_id:0 status(0x0000000000000400): Storage error in DRAM memory)
+[40606.660031] {41}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 2
+[40606.668367] {41}[Hardware Error]: event severity: recoverable
+[40606.674098] {41}[Hardware Error]: precise tstamp: 2000-01-06 09:27:58
+[40606.680611] {41}[Hardware Error]: Error 0, type: recoverable
+[40606.686342] {41}[Hardware Error]: section_type: memory error
+[40606.692159] {41}[Hardware Error]: error_status: Storage error in DRAM memory (0x0000000000000400)
+[40606.701275] {41}[Hardware Error]: physical_address: 0x0000000ddb599400
+[40606.707961] {41}[Hardware Error]: node:0 card:2 module:0 rank:0 bank_group:2 bank_address:1 device:0 row:5997 column:1152 chip_id:0
+[40606.720028] {41}[Hardware Error]: error_type: 5, multi-symbol chipkill ECC
+[40606.727781] Memory failure: 0xddb599: recovery action for dirty LRU page: Recovered
+```
+
+## 4.4 rasdaemon日志读取
+
+
+rasdaemon日志存储在数据库中,可通过ras-mc-ctl --errors读取日志。可以看到rasdaemon简要地记录了系统中的错误信息。
+
+
+
+```
+[root@localhost ras-tools]# ras-mc-ctl --errors
+Memory controller events:
+1 2022-09-01 10:29:28 +0800 1 Uncorrected error(s): multi-symbol chipkill ECC at unknown memory location: 0:-1:-1:-1, addr 4434626552832, grain 0, syndrome 0 APEI location: node:0 card:6 module:0 rank:0 bank_group:6 bank_address:2 device:0 row:529 column:256 chip_id:0 status(0x0000000000000400): Storage error in DRAM memory
+2 2022-09-01 11:25:11 +0800 1 Uncorrected error(s): multi-symbol chipkill ECC at unknown memory location: 0:-1:-1:-1, addr 4434626552832, grain 0, syndrome 0 APEI location: node:0 card:6 module:0 rank:0 bank_group:6 bank_address:2 device:0 row:529 column:256 chip_id:0 status(0x0000000000000400): Storage error in DRAM memory
+3 2022-09-01 11:55:11 +0800 1 Uncorrected error(s): multi-symbol chipkill ECC at unknown memory location: 0:-1:-1:-1, addr 4434626552832, grain 0, syndrome 0 APEI location: node:0 card:6 module:0 rank:0 bank_group:6 bank_address:2 device:0 row:529 column:256 chip_id:0 status(0x0000000000000400): Storage error in DRAM memory
+```
+
+# 5. Q&A
+
+
+Q:RAS机制是否需要BIOS支持?
+
+
+A:需要BIOS支持,并且由于BIOS对RAS支持的更新较快,最好将BIOS更新到最新版本。
+
+
+
+
+
+Q: x86和ARM64的APEI是否一致?
+
+
+A: x86与ARM64的芯片只要都遵循同一套ACPI协议,那么APEI是一致的。
+
+
+
+
+
+Q: RAS注入的错误是真实的错误吗?
+
+
+A: 错误中断是真实触发的;关于内存中的数据,是通过写入ECC相关寄存器模拟的。
+
+
+
+
+
+Q: rasdaemon日志查看是否有更易用的方法?
+
+
+A: 首先安装rasdaemon依赖的库yum install sqlite perl-DBD-SQLite;使用rasdaemon -r 命令启动;
+
+
+ 最后使用 ras-mc-ctl --errors 命令可以查看rasdaemon日志。
+
+
+
+
+
+Q: 可否使用mcelog?
+
+
+A: mcelog的原理是通过读取并解析x86的machine check机制的寄存器信息来捕获硬件错误,因此它是x86专用的,不适用于ARM64。
+
+
+
+
+
+Q:einj\_mem\_uc是否覆盖所有case,例如向用户进程地址空间注入UE,是否kill掉用户进程而让系统保持正常?向内核注入UE,系统是否crash?
+
+
+A:ras-tools工具提供的测试用例比较丰富,可满足RAS机制测试与研发的需求。比如,./einj\_mem\_uc single用例实现用户进程访问UE数据,einj\_mem\_uc程序对SIGBUS信号进行了处理,否则会被直接kill;而./einj\_mem\_uc copyin用例实现内核访问UE数据,系统会crash。
+
+
+
+
+
+Q:由于RAS错误导致内核crash,对应记录未被记录在rasdaemon中,是否合理?
+
+
+A:需要检查是否是rasdaemon某些选项未开启。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220.md"
new file mode 100644
index 0000000000000000000000000000000000000000..2afffe558eb929d14d756b06611e15d90e3fc163
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220.md"
@@ -0,0 +1,182 @@
+## cgroup.memory=nokmem
+
+
+### kmem 是什么
+
+
+kmem 是cgroup 的一个扩展,全称CONFIG\_MEMCG\_KMEM
+
+
+内核内存:专用于Linux内核系统服务使用,是不可swap的,因而这部分内存非常宝贵的。但现实中存在很多针对内核内存资源的攻击,如不断地fork新进程从而耗尽系统资源,即所谓的“fork bomb”。
+
+
+为了防止这种攻击,社区中提议通过linux内核限制cgroup中的kmem容量,从而限制恶意进程的行为,即kernel memory accounting机制。
+
+
+内核内存统计对所有内存控制组默认使能,在启动时传递cgroup.memory=nokmem参数可以禁用该功能,在禁用后,内核内存就不会被统计。
+
+
+### 带来的性能影响
+
+
+#### 相关代码
+
+
+通过解析cmdline,是否传入nokmem会控制cgroup\_memory\_nokmem的值。
+
+
+
+```
+static int __init cgroup_memory(char *s)
+{
+ char *token;
+
+ while ((token = strsep(&s, ",")) != NULL) {
+ if (!*token)
+ continue;
+ if (!strcmp(token, "nosocket"))
+ cgroup_memory_nosocket = true;
+ if (!strcmp(token, "nokmem"))
+ cgroup_memory_nokmem = true;
+ }
+ return 0;
+}
+__setup("cgroup.memory=", cgroup_memory);
+```
+
+cgroup\_memory\_nokmem涉及到的相关函数如下:
+
+
+each slab object pointer to an memcg respectively when kmem account enable, slab page can be used by root mem\_cgroup and children memcg. slab object age is recorded in slab\_age of page when kmem account disable. Otherwise, an special obj\_cgroups pointer will store the value.
+
+
+int kidled\_alloc\_slab\_age(struct page \*page, struct kmem\_cache \*s, gfp\_t flags)
+
+
+static unsigned short \*kidled\_get\_slab\_age\_array(void \*object)
+
+
+static int memcg\_online\_kmem(struct mem\_cgroup \*memcg)
+
+
+意味着使能该参数后,会在slab管理的page分配和释放流程上增加额外的处理逻辑,下面通过实际对比测试来直观的感受一下对应的开销。
+
+
+#### 数据测试
+
+
+通过lmbench对cgroup.memory=nokmem是否使能进行内存测试(5次取平均):
+
+
+
+
+| | | |
+| --- | --- | --- |
+| 测试环境 | 开启cgroup\_memory\_nokmem | Communication bandwidths (Pipe,越大越好) |
+| an8-4.19, memory cgroup 500M | 是 | 4234 |
+| 否 | 3705 |
+| an8-5.10, memory cgroup 500M | 是 | 4125 |
+| 否 | 3659 |
+
+
+### 其他问题
+
+
+#### kmem.slabinfo造成cpu使用率异常
+
+
+该问题只存在于4.19内核,5.10内核实现逻辑改变无此问题,参见mm/slab\_common.c
+
+
+通过CONFIG\_SLAB或CONFIG\_SLUB\_DEBUG会使能kmem.slabinfo,目前anolis默认开启CONFIG\_SLUB\_DEBUG
+
+
+
+```
+#if defined(CONFIG_SLAB) || defined(CONFIG_SLUB_DEBUG)
+ {
+ .name = "kmem.slabinfo",
+ .seq_start = memcg_slab_start,
+ .seq_next = memcg_slab_next,
+ .seq_stop = memcg_slab_stop,
+ .seq_show = memcg_slab_show,
+ },
+#endif
+```
+
+slabinfo通过链表的方式进行组织,意味着访问的时间复杂度为O(n),通过读取相应cgroup下的memory.kmem.slabinfo,可以查看相应的slabinfo信息。
+
+
+
+```
+void *memcg_slab_start(struct seq_file *m, loff_t *pos)
+{
+ struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(m));
+
+ mutex_lock(&slab_mutex);
+ return seq_list_start(&memcg->kmem_caches, *pos);
+}
+
+void *memcg_slab_next(struct seq_file *m, void *p, loff_t *pos)
+{
+ struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(m));
+
+ return seq_list_next(p, &memcg->kmem_caches, pos);
+}
+
+void memcg_slab_stop(struct seq_file *m, void *p)
+{
+ mutex_unlock(&slab_mutex);
+}
+
+int memcg_slab_show(struct seq_file *m, void *p)
+{
+ struct kmem_cache *s = list_entry(p, struct kmem_cache,
+ memcg_params.kmem_caches_node);
+ struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(m));
+
+ if (p == memcg->kmem_caches.next)
+ print_slabinfo_header(m);
+ cache_show(s, m);
+ return 0;
+}
+```
+
+通过特定操作cgroup,可以让memory cgroup产生泄漏,复现方法如下:
+
+
+通过不断创建新的memory cgroup,执行文件操作,并删除memory cgroup,我们可以看到,/sys/fs/cgroup/memory中的cgroup并没有增加,而/proc/cgroup显示存在大量的memory cgroup。
+
+
+
+```
+for ((i=0;i<100000;++i)); do
+ mkdir -p /sys/fs/cgroup/memory/test/test$i
+ echo $$ > /sys/fs/cgroup/memory/test/test$i/tasks
+ mkdir -p /tmp/test/
+ echo 'date' > /tmp/test/test$i
+ echo $$ > /sys/fs/cgroup/memory/test/tasks
+ rmdir /sys/fs/cgroup/memory/test/test$i
+done
+```
+
+脚本执行前:
+
+
+
+
+
+脚本执行后:
+
+
+
+
+
+但是在执行脚本后,查看/sys/fs/cgroup/memory,并不存在对应数量的memory cgroup,产生泄漏。这样,大量的memory cgroup会造成访问slabinfo链表的执行时间大量增加,造成不必要的cpu访问开销。
+
+
+### 结论
+
+
+基于性能测试以及存在的潜在问题,存量的版本建议通过 boot cmdline cgroup.memory=nokmem 来关闭 kmem ,并保证用户习惯的兼容性。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215.md"
new file mode 100644
index 0000000000000000000000000000000000000000..5e0b929172b7964295fa721ac409f93606b5e52d
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215.md"
@@ -0,0 +1,1028 @@
+本文介绍龙蜥内核已支持的内核功能与接口。
+
+
+# Group Identity
+
+
+Group Identity功能可以对每一个CPU cgroup设置身份标识,以区分cgroup中的任务优先级。Group Identity核心是双红黑树设计,在CFS(Completely Fair Scheduler)调度队列的单红黑树基础上,新增了一颗低优先级的红黑树,用于存放低优先级任务。系统内核在调度包含具有身份标识的任务时,会根据不同的优先级做相应处理。
+
+
+在业务的混合部署(延迟敏感型和计算型任务混合部署在同一台实例)场景中,Linux内核调度器需要为高优先级任务赋予更多的调度机会以最小化调度延迟,并需要把低优先级任务对内核调度带来的影响降到最低。
+
+
+基于该场景,ANCK提供了Group Identity功能,为CPU cgroup新增了配置调度优先级的接口,且不同优先级的任务具有以下特点:
+* 高优先级任务的唤醒延迟最小化。
+* 低优先级任务不对高优先级任务造成性能影响。主要体现在:
+ + 低优先级任务的唤醒不会对高优先级任务造成性能影响。
+ + 低优先级任务不会通过共享硬件unit而对高优先级任务造成性能影响。
+
+
+
+
+| | |
+| --- | --- |
+| 接口 | 说明 |
+| `cpu.identity` | 默认取值为0,表示身份标识为`ID_NORMAL`。
+该接口是一个位段,一共有5个比特位,该接口各个比特位的取值说明如下:
+* 空值:表示身份标识为`ID_NORMAL`。
+* 比特位0:表示身份标识为`ID_UNDERCLASS`。
+* 比特位1:表示身份标识为`ID_HIGHCLASS`。
+* 比特位2:表示身份标识为`ID_SMT_EXPELLER`。
+* 比特位3:表示身份标识为`ID_IDLE_SAVER`。
+* 比特位4:表示身份标识为`ID_IDLE_SEEKER`。
+
+
+
+例如,如果设置一个cgroup的身份标识为`ID_HIGHCLASS`和`ID_IDLE_SEEKER`,那么将比特位1和4置为1,其他比特位置为0,得到的二进制表示为:10010,转化为十进制为:18,则执行`echo 18 > /sys/fs/cgroup/cpu/$cg/cpu.identity`即可完成写入。 |
+| `cpu.bvt_warp_ns` | 默认取值为0,表示身份标识为`ID_NORMAL`。该接口的取值说明如下:
+* 2:表示同时具有身份标识`ID_SMT_EXPELLER`、`ID_IDLE_SEEKER`、`ID_HIGHCLASS`,对应的identity值为22。
+* 1:表示同时具有身份标识`ID_HIGHCLASS`、`ID_IDLE_SEEKER`,对应的identity值为18。
+* 0:表示身份标识为`ID_NORMAL`,对应的identity值为0。
+* -1:表示同时具有身份标识`ID_UNDERCLASS`、`ID_IDLE_SAVER`,对应的identity值为9。
+* -2:表示同时具有身份标识`ID_UNDERCLASS`、`ID_IDLE_SAVER`,对应的identity值为9。
+ |
+
+
+
+
+
+# 在cgroup v1接口开启CPU Burst功能
+
+
+
+在容器服务中,容器允许使用的CPU资源被内核的CFS Bandwidth Controller(带宽控制器)限流。当您在cgroup v1接口开启CPU Burst功能后,CPU Burst功能允许容器突发使用限流之外的CPU资源。该功能既可以保证容器运行的服务质量,又不降低容器部署密度。
+
+
+
+
+
+CPU Burst功能允许突发使用的CPU资源依赖于日常的资源积累。比如,容器在日常运行中使用的CPU资源未超过CPU限流,则空余的CPU资源将会被积累。后续当容器运行需要大量CPU资源时,将通过CPU Burst功能突发使用CPU资源,这部分突发使用的资源来源于已积累的资源。以休假体系作为类比:
+
+
+假如您每年休假时间为4天(CPU限流),未休的假期可以存放起来后续使用,但存放上限为4天(CPU Burst)。当您第一年、第二年各只休了1天的假期,那么没有休息的6天假期可以存放起来。当第三年的时候,理论上您可以休息共计10天的假期,但因为有存放上限(CPU Burst),则实际可以休息至多8天的假期。
+
+
+## 开启CPU Burst功能
+
+
+1. 检查cgroup v1接口中的CPU Burst功能的全局开关是否已打开。
+
+
+
+
+```
+cat /proc/sys/kernel/sched_cfs_bw_burst_enabled
+```
+
+
+
+返回结果说明:
+
+ * 如果返回结果为`1`,则表示CPU Burst功能的全局开关已打开。
+
+
+ **说明** 默认情况下,cgroup v1接口中的CPU Burst功能的全局开关为打开状态。
+ * 如果返回结果不为`1`,则表示CPU Burst功能的全局开关已关闭。您可以运行以下命令打开全局开关:
+
+
+
+ ```
+ echo 1 > /proc/sys/kernel/sched_cfs_bw_burst_enabled
+ ```
+2. 在具体的子cgroup中开启CPU Burst功能。
+默认情况下,cgroup v1接口中的CPU Burst功能在各个子cgroup中均未开启。具体的开启方式如下:
+ 1. 进入子cgroup路径下,检查CFS Bandwidth Controller限流是否处于生效状态。
+
+
+
+
+ ```
+ cd /sys/fs/cgroup/cpu/子cgroup目录名称/
+ cat cpu.cfs_period_us
+ cat cpu.cfs_quota_us
+ ```
+
+
+
+ 如果`cpu.cfs_quota_us`对应的返回结果为正整数,则表示CFS Bandwidth Controller限流处于生效状态,进而在启用CPU Burst功能后,容器才可以获得超出CPU限流的CPU资源。
+ 2. 检查当前默认的CPU Burst设置。
+
+
+
+
+ ```
+ cat cpu.cfs_burst_us
+ ```
+
+
+
+ 返回结果的默认值为`0`,表示CPU Burst功能未开启。
+ 3. 设置`cpu.cfs_burst_us`的值以开启CPU Burst功能。
+ 您可以设置一个适用的正整数启用CPU Burst功能,且这个正整数表示子cgroup突发额外使用的CPU资源的上限。本文通过以下示例场景,介绍如何开启CPU Burst功能。
+
+ 1. 配置CFS Bandwidth Controller带宽控制器默认的`cpu.cfs_quota_us`与`cpu.cfs_period_us`。
+ 以下配置,将CPU资源的使用周期(`cpu.cfs_period_us`)设置为100ms,每个周期中的CPU限流(`cpu.cfs_quota_us`)设置为400ms,则子cgroup将会持续获得4个CPU资源(`cpu.cfs_quota_us`/`cpu.cfs_period_us`)。
+
+
+
+ ```
+ echo 400000 > cpu.cfs_quota_us
+ echo 100000 > cpu.cfs_period_us
+ ```
+ 2. 配置`cpu.cfs_burst_us`以开启CPU Burst功能。
+ 以下配置,将CPU Burst的值设置为600ms,表示开启了CPU Burst功能,且允许子cgroup可以突发额外使用最多6个CPU资源(`cpu.cfs_burst_us`/`cpu.cfs_period_us`)。
+
+
+
+ ```
+ echo 600000 > cpu.cfs_burst_us
+ ```
+
+
+## 查询CPU Burst的统计数据
+
+
+1. 进入待查询数据的子cgroup路径下。
+
+
+
+
+```
+cd /sys/fs/cgroup/cpu/子cgroup目录名称/
+```
+2. 查看统计数据。
+
+
+
+
+```
+cat cpu.stat
+```
+
+
+返回结果中,主要的信息说明如下:
+
+ * `nr_burst`数据:当前子cgroup触发CPU Burst的次数。
+ * `burst_time`数据:当前子cgroup突发使用CPU资源的时间。
+
+
+
+
+
+
+
+# 在cgroup v1接口开启PSI功能
+
+
+
+PSI(Pressure Stall Information)是一个可以监控CPU、内存及IO性能异常的内核功能。有关PSI功能的详细信息,您可以通过内核文档`Documentation/accounting/psi.txt`了解。
+
+## 为cgroup v1接口开启PSI功能
+
+
+默认情况下cgroup v1接口的PSI功能为关闭状态。按照以下步骤开启PSI功能。
+
+
+1. 运行`grubby`命令,修改启动参数。
+参数`args`中默认为`"psi=1"`,表示cgroup v2启用PSI功能。将参数修改为`"psi=1 psi_v1=1"`,表示为cgroup v1接口开启PSI功能。 本示例中内核版本为`4.19.81-17.an7.x86_64`,您在操作中需要更换为实际的内核版本,内核版本的查看命令为`uname -a`。
+
+
+
+```
+sudo grubby --update-kernel="/boot/vmlinuz-4.19.81-17.an7.x86_64" --args="psi=1 psi_v1=1"
+```
+2. 重启系统使该功能生效。
+
+
+
+
+```
+sudo reboot
+```
+
+
+## 确认cgroup v1接口的PSI功能已启用
+
+
+系统重启后,您可以执行命令,确认内核`/proc/cmdline`中已启用cgroup v1接口的PSI功能。
+
+
+
+```
+cat /proc/cmdline | grep "psi=1 psi_v1=1"
+```
+
+
+
+## 查询CPU、内存及IO的监控数据
+
+
+当您开启cgroup v1接口的PSI功能时,CPU、内存及IO的PSI监控数据均会输出到cpuacct控制器下,您可以通过以下命令查看详细的监控数据。
+
+
+
+```
+cat /sys/fs/cgroup/cpuacct/cpu.pressure
+cat /sys/fs/cgroup/cpuacct/memory.pressure
+cat /sys/fs/cgroup/cpuacct/io.pressure
+```
+
+
+
+
+
+
+
+
+# Memcg后台异步回收
+
+
+
+
+在社区内核系统中,系统分配内存并在相应memcg中的统计达到memcg设定的内存上限时,会触发memcg级别的直接内存回收。直接内存回收是发生在内存分配上下文的同步回收,因此会影响当前进程的性能。
+
+
+为了解决这个问题,ANCK增加了memcg粒度的后台异步回收功能。该功能的实现不同于全局kswapd内核线程的实现,并没有创建对应的memcg kswapd内核线程,而是采用了workqueue机制来实现,并在cgroup v1和cgroup v2两个接口中,均新增了4个memcg控制接口。
+
+
+注意事项:
+* 当前memcg的内存分配,可能会递归触发父组的后台异步回收。
+* 触发memcg后台异步回收时,会从当前被触发的memcg开始,自上而下做层级回收。
+* 当memory.high接口被配置,并且memory.high的值比memory.limit\_in\_bytes接口的值小的时候,接口memory.wmark\_high和memory.wmark\_low水位线的计算将基于memory.high而不是memory.limit\_in\_bytes。
+
+
+
+
+| 接口 | 说明 |
+| --- | --- |
+| memory.wmark\_ratio | 该接口用于设置是否启用memcg后台异步回收功能,以及设置异步回收功能开始工作的memcg内存水位线。单位是相对于memcg limit的百分之几。取值范围:0~100
+* 默认值为0,该值也表示禁用memcg后台异步回收功能。
+* 取值为非0时,表示开启memcg后台异步回收功能并设置对应的水位线。
+ |
+| memory.wmark\_high | 只读接口,说明如下:
+* 当memcg内存使用超过该接口的值时,后台异步回收功能启动。
+* 该接口的值由`(memory.limit_in_bytes * memory.wmark_ratio / 100)`计算获得。
+* memcg后台异步回收功能被禁用时,memory.wmark\_high默认为一个极大值,从而达到永不触发后台异步回收功能的目的。
+* memcg根组目录下不存在该接口文件。
+ |
+| memory.wmark\_low | 只读接口,说明如下:
+* 当memcg内存使用低于该接口的值时,后台异步回收结束。
+* 该接口的值由`memory.wmark_high - memory.limit_in_bytes * memory.wmark_scale_factor / 10000`计算得出。
+* memcg根组目录下不存在该接口文件。
+ |
+| memory.wmark\_scale\_factor | 该接口用于控制memory.wmark\_high和memory.wmark\_low之间的间隔。单位是相对于memcg limit的万分之几。取值范围:1~1000
+* 该接口在创建时,会继承父组的值(该值为50),该值也是默认值,即memcg limit的千分之五。
+* memcg根组目录不存在该接口文件。
+ |
+
+
+
+
+
+# Memcg全局最低水位线分级
+
+
+
+
+在Linux内核中,全局内存回收对系统性能影响很大。当时延敏感型业务和资源消耗型任务共同部署时,资源消耗型任务时常会瞬间申请大量的内存,使得系统的空闲内存触及全局最低水位线(global wmark\_min),引发系统所有任务进入直接内存回收的慢速路径,引发时延敏感型业务的性能抖动。在此场景下,无论是全局kswapd后台回收还是memcg后台回收,都将无法处理该问题。
+
+
+基于上述场景下的问题,ANCK新增了memcg全局最低水位线分级功能。在global wmark\_min的基础上,将资源消耗型任务的global wmark\_min上移,使其提前进入直接内存回收。将时延敏感型业务的global wmark\_min下移,使其尽量避免直接内存回收。这样当资源消耗型任务瞬间申请大量内存的时候,会通过上移的global wmark\_min将其短时间抑制,避免时延敏感型业务发生直接内存回收。等待全局kswapd回收一定量的内存后,再解除资源消耗型任务的短时间抑制。
+
+
+
+
+
+## 功能接口说明
+
+
+实现memcg全局最低水位线分级功能的接口为memory.wmark\_min\_adj。该接口的值,表示基于全局最低水位线(global wmark\_min)所作出的调整(adjustment)百分比。取值范围:-25 ~ 50,取值范围说明如下:
+* 该接口创建时,继承父组的值(值为0),即默认值为0。
+* 取值范围中的负值是基于调整范围`[0, WMARK_MIN]`的百分比,其中`WMARK_MIN`表示global wmark\_min的值,例如:
+
+
+
+```
+memory.wmark_min_adj=-25, memcg WMARK_MIN is "WMARK_MIN + (WMARK_MIN - 0) * (-25%)"
+```
+
+
+
+
+**说明** 负值也表示global wmark\_min下移,即提高时延敏感型业务的内存子系统服务质量(memcg QoS)。
+* 取值范围中的正值是基于调整范围`[WMARK_MIN, WMARK_LOW]`的百分比,其中`WMARK_MIN`和`WMARK_LOW`分别表示global wmark\_min和global wmark\_low的值,例如:
+
+
+
+```
+memory.wmark_min_adj=50, memcg WMARK_MIN is "WMARK_MIN + (WMARK_LOW - WMARK_MIN) * 50%"
+```
+
+
+
+
+**说明** 正值也表示global wmark\_min上移,即降低资源消耗型任务的内存子系统服务质量(memcg QoS)。
+* 当偏移后的global wmark\_min被触发后,会执行抑制操作,抑制操作的时间和超出的内存使用为线性比例关系。抑制时间的取值范围:1ms ~ 1000ms。
+
+
+
+
+**说明** memcg根组目录下不存在该接口文件。
+
+
+## 接口注意事项
+
+
+在多层级目录的memcg中,有一个`effective memory.wmark_min_adj`的概念,即最终生效的memory.wmark\_min\_adj值。具体规则是在memcg层级路径上遍历取最大值(中间节点的默认值0除外)。例如,有以下层级关系示例。
+
+
+
+```
+ root
+ / \
+ A D
+ / \
+ B C
+ / \
+ E F
+```
+
+
+则各层级设置的接口值与最终生效的接口值,对应关系如下所示。
+
+
+ | 层级 | 各层级设置的接口值 | 最终生效的接口值 |
+| --- | --- | --- |
+| A | -10 | -10 |
+| B | -25 | -10 |
+| C | 0 | 0 |
+| D | 50 | 50 |
+| E | -25 | -10 |
+| F | 50 | 50 |
+
+
+
+
+**说明**
+* 运行命令`cat /sys/fs/cgroup/memory//memory.wmark_min_adj`输出的值为最终生效的值,其中变量``是memcg的根路径。
+* 本功能建议配合较高的全局最低水位线(global wmark\_min)来使用,例如将global wmark\_min值设置为2 GB或更高,您可以通过/proc/sys/vm/min\_free\_kbytes进行设置。
+
+
+
+
+
+## 功能配置示例
+
+
+示例一:为时延敏感型业务所在memcg配置全局最低水位线分级。
+
+
+1. 运行命令`mkdir /sys/fs/cgroup/memory/test-lc`创建测试文件。
+2. 运行命令`echo -25 > /sys/fs/cgroup/memory/test-lc/memory.wmark_min_adj`向接口写入值`-25`,提高时延敏感型业务的memcg QoS。
+
+
+示例二:为资源消耗型任务所在memcg配置全局最低水位线分级。
+
+
+1. 运行命令`mkdir /sys/fs/cgroup/memory/test-be`创建测试文件。
+2. 运行命令`echo 25 > /sys/fs/cgroup/memory/test-be/memory.wmark_min_adj`向接口写入值`25`,降低资源消耗型任务的memcg QoS。
+
+
+
+
+
+
+# Memcg OOM优先级策略功能
+
+
+
+
+在现有内核系统中,内存紧张情况下内核会遍历cgroup,选择耗用内存较多的cgroup进行内存回收,甚至在回收失败的情况下直接OOM,并停止当前cgroup下的所有任务。这对于当前cgroup包含的核心业务来说,会造成很大的影响。为此我们希望这类包含核心业务的cgroup占有的内存不被回收,或者cgroup下的任务在OOM中可以存活下来,以便让内核去选择其他的cgroup进行内存回收或者OOM。
+
+
+为了解决这个问题,ANCK增加了memcg OOM优先级配置功能。该功能在进行OOM操作时,会首先判定cgroup的优先级,选择低优先级的cgroup进行OOM操作。
+
+
+## memcg OOM优先级接口功能说明
+
+
+
+
+ | 接口 | 说明 |
+| --- | --- |
+| `memory.use_priority_oom` | 该接口用于设置是否启用memcg OOM优先级策略功能,取值为0或者1。该接口不会继承,默认值为0。
+* 取值为0时,表示禁用memcg OOM优先级策略功能。
+* 取值为1时,表示开启memcgOOM优先级策略功能。
+ |
+| `memory.priority` | 该接口提供13个级别的memcg优先级以支持不同重要程度的业务。取值范围为0~12,数值越大表示优先级越高。该接口不会继承,默认值为0。
+* 实现一定程度的内存QoS,此处需要说明的优先级值非全局变量,只能在同父cgroup下的兄弟节点进行比较。
+* 对于优先级相等的兄弟节点来说,会按照组的内存使用量来排序选择内存使用最大的进行OOM操作。
+ |
+
+
+## 接口配置示例
+
+
+按如下所示创建6个cgroup子节点A、 B、 C、 D、 E、 F,开启`memory.use_priority_oom`接口,并通过`memory.priority`接口设置OOM的优先级。
+
+
+
+```
+ root
+ / \
+ A B
+ / \ / \
+ C D E F
+```
+
+
+则各层级设置的接口值,对应关系如下所示:
+* A:10
+* B:8
+* C:5
+* D:6
+* E:7
+* F:8
+
+
+
+当在root中进行OOM操作时,它首先迭代查找它的两个子节点A和B,由于B的优先级值低于A,所以会选择B节点作为下一个迭代cgroup继续进行迭代,最终会在子节点E上进行OOM操作,因为它的优先级比其他的兄弟节点低。
+
+
+
+
+
+# THP reclaim功能
+
+
+
+
+
+
+
+Linux操作系统的内存采用分页管理模式,其中的THP(Transparent Huge Page)是指内核中2 MiB或1 GiB大小的大页面(普通的小页面大小为4 KiB),一般被称为透明大页。基于应用程序使用到的内存范围越来越大,地址转换产生的开销变得不可忽视。因此,当服务器上的应用程序申请内存时,内核会根据进程的实际情况动态分配透明大页,透明大页可以减少TLB(Translation Lookaside Buffer) Miss的出现概率,从而提升应用程序的性能。
+
+
+THP在带来性能提升的同时,也产生了一定副作用,即可能产生Memory bloating(内存膨胀)问题。该问题产生的原因说明:透明大页申请释放的粒度为2 MiB(即512个小页面),相较于小页面,透明大页更容易产生内存碎片,进而导致内核分配的内存容量大于实际需要的内存容量。
+
+
+Memory bloating可能引发OOM(Out Of Memory)。例如,一个应用程序实际需要使用2个小页面,即8 KiB内存,但是内核分配了1个透明大页。此时,除去应用程序实际需要的内存(2个小页面),透明大页剩下的内存(510个小页面)大小均为0。最终可能会因RSS(Resident Set Size)内存用量增加而导致OOM。
+
+
+为解决THP可能引发的内存问题。ANCK增加了memcg粒度的THP reclaim功能。在内核回收内存时,该功能会把透明大页拆分为小页面,并将其中的全零页面(zero subpage)回收,从而避免内存的快速膨胀引发OOM。但您需要注意,由于THP reclaim功能会将透明大页拆分为小页面,所以相较于2 MiB大小的透明大页,THP reclaim功能会在一定程度上造成内存性能的回退。
+
+
+## 接口说明
+
+
+实现THP reclaim功能的接口说明,如下表所述:
+
+
+ | 接口 | 说明 |
+| --- | --- |
+| `memory.thp_reclaim` | 开启或关闭THP reclaim功能。支持以下配置项:
+* reclaim:开启THP reclaim功能。
+* swap:预留配置项,目前暂无实际功能。
+* disable:关闭THP reclaim功能。
+
+
+THP reclaim功能默认为关闭状态,即接口默认值为disable。 |
+| `memory.thp_reclaim_stat` | 查看THP reclaim功能当前的状态。接口内的参数说明如下:
+* queue\_length:当前被THP reclaim管理的透明大页数量。
+* split\_hugepage:累计拆分的透明大页数量。
+* reclaim\_subpage:累计回收的全零页面(zero subpage)数量。
+
+
+该接口的参数值按照NUMA node的顺序(node0、node1)从左到右排列。 |
+| `memory.thp_reclaim_ctrl` | 控制THP reclaim功能的触发机制。目前支持以下配置项:
+* threshold:默认值为16。表示当透明大页中的全零页面(zero subpage)数量超过该值时,会触发THP reclaim功能。
+* reclaim:用于主动触发THP reclaim功能。
+ |
+| `/sys/kernel/mm/transparent_hugepage/reclaim` | THP reclaim功能的全局配置接口。支持以下配置项:
+* memcg:该接口的默认配置项。表示每个memory cgroup按照各自的配置开启或关闭THP reclaim,即以每个memory cgroup中的`memory.thp_reclaim`接口配置为准。
+* reclaim:强制开启所有memory cgroup的THP reclaim功能。
+* swap:预留配置项,目前暂无实际功能。
+* disable:强制关闭所有memory cgroup的THP reclaim功能。
+ |
+
+
+
+## 接口配置的操作说明
+
+
+本示例操作中,将创建一个名为test的memory cgroup,以test为例介绍THP reclaim接口的操作说明。
+
+
+1. 运行以下命令,创建一个名为test的memory cgroup。
+
+
+
+
+```
+mkdir /sys/fs/cgroup/memory/test/
+```
+2. 运行以下命令,开启test的THP reclaim功能。
+
+
+
+
+```
+echo reclaim > /sys/fs/cgroup/memory/test/memory.thp_reclaim
+```
+3. 运行以下命令,确认test的THP reclaim功能成功开启。
+
+
+
+
+```
+cat /sys/fs/cgroup/memory/test/memory.thp_reclaim
+```
+
+
+
+返回结果如下图所示,被`[]`包裹的配置项为生效配置项,`[reclaim]`表示test的THP reclaim功能已开启。
+4. 运行以下命令,通过THP reclaim功能的全局配置接口强制开启THP reclaim功能。
+
+
+
+
+```
+echo reclaim > /sys/kernel/mm/transparent_hugepage/reclaim
+```
+
+
+如果您想强制关闭THP reclaim功能,可运行以下命令:
+
+
+
+```
+echo disable > /sys/kernel/mm/transparent_hugepage/reclaim
+```
+
+
+
+
+**说明** THP reclaim功能的全局配置接口`/sys/kernel/mm/transparent_hugepage/reclaim`在设置为强制开启(`reclaim`)或强制关闭(`disable`)时,接口生效的优先级会高于各个memory cgroup中的`memory.thp_reclaim`接口,但不会影响各个memory cgroup中`memory.thp_reclaim`接口的配置。
+5. 运行以下命令,配置test的`memory.thp_reclaim_ctrl`接口的`threshold`配置项。
+
+
+
+
+```
+echo "threshold 32" > /sys/fs/cgroup/memory/test/memory.thp_reclaim_ctrl
+```
+
+
+
+此时,如果透明大页中的全零页面数量超过32,则会触发THP reclaim的全零页面回收功能。
+6. 主动触发THP reclaim的全零页面回收功能。
+主动触发后,THP reclaim会把所有超过`threshold`配置的全零页面回收。配置项`reclaim`存在以下配置方式:
+
+
+**说明** 该配置项的调用方式为同步调用,并且为只写配置项,即您只能向`memory.thp_reclaim_ctrl`接口写入`reclaim`以主动触发THP reclaim的全零页面回收功能,但不能通过cat命令查看到`reclaim`配置项。
+
+
+ * 运行以下命令,会主动触发当前memory cgroup的THP reclaim的全零页面回收功能。
+
+
+
+ ```
+ echo "reclaim 1" > /sys/fs/cgroup/memory/test/memory.thp_reclaim_ctrl
+ ```
+ * 运行以下命令,会主动递归触发当前memory cgroup以及该cgroup下所有子cgroup的THP reclaim的全零页面回收功能。
+
+
+
+ ```
+ echo "reclaim 2" > /sys/fs/cgroup/memory/test/memory.thp_reclaim_ctrl
+ ```
+
+
+ 除了通过`reclaim`主动触发THP reclaim的全零页面回收功能。THP reclaim还会伴随内存回收而触发:
+ + 内存出现OOM时,会触发THP reclaim的全零页面回收功能。
+ + 当memory cgroup触发memory后台异步回收时,会触发THP reclaim的全零页面回收功能。关于memory后台异步回收的更多信息,请参见"Memcg后台异步回收"。
+7. 运行以下命令,查看test的THP reclaim功能状态。
+
+
+
+
+```
+cat /sys/fs/cgroup/memory/test/memory.thp_reclaim_stat
+```
+
+
+
+返回结果示例如下:
+
+
+
+```
+queue_length 14
+split_hugepage 523
+reclaim_subpage 256207
+```
+
+
+## C语言代码测试样例
+
+
+本章节基于C语言提供了进程申请透明大页的代码测试样例。您可以通过以下测试样例,查看到THP reclaim功能在开启与关闭时的区别。
+
+
+1. 运行以下命令,为内存使用量限制接口`memory.limit_in_bytes`设置1 GiB的限制。
+
+
+
+
+```
+echo 1G > /sys/fs/cgroup/memory/test/memory.limit_in_bytes
+```
+
+
+
+设置后,您可以运行以下命令查看`memory.limit_in_bytes`接口的值。
+
+
+
+```
+cat /sys/fs/cgroup/memory/test/memory.limit_in_bytes
+```
+
+
+查看结果如下图所示:
+2. 运行以下命令,关闭memcg后台异步回收功能。
+关于memory后台异步回收的更多信息,请参见"Memcg后台异步回收"。
+
+
+
+```
+echo 0 > /sys/fs/cgroup/memory/test/memory.wmark_ratio
+```
+3. 分别在开启或关闭THP reclaim功能的前提下,运行以下C语言代码进行测试,并查看测试结果。
+
+
+
+
+```
+// 申请1 G内存(即512个透明大页),其中10个透明大页包含部分全零页面。
+#define HUGEPAGE_SIZE 4096 * 512
+int main()
+{
+ int i, thp = 512;
+ char *addr;
+ posix_memalign((void **)&addr, HUGEPAGE_SIZE, HUGEPAGE_SIZE * thp);
+
+ for (i = 0; i < 10; i++) {
+ memset(addr, 0xc, HUGEPAGE_SIZE >> 1);
+ addr += HUGEPAGE_SIZE;
+ }
+
+ for (; i < thp; i++) {
+ memset(addr, 0xc, HUGEPAGE_SIZE);
+ addr += HUGEPAGE_SIZE;
+ }
+
+ pause();
+ return 0;
+}
+```
+
+
+
+测试结果根据THP reclaim功能的开启状态有所不同:
+
+ * 在THP reclaim功能关闭时,进程申请最后一个透明大页会发生OOM。
+ * 在THP reclaim功能开启时,进程申请透明大页过程中,THP reclaim会把前序申请的透明大页拆分为小页,并回收其中的全零页面,最终不会发生OOM。
+
+
+
+
+
+
+
+# 启用cgroup writeback功能
+
+
+
+
+
+## 背景信息
+
+
+
+控制群组(control group)简称为cgroup,分为v1和v2两个版本。本文介绍如何启用cgroup v1的cgroup writeback功能,并对进程进行Buffered I/O限速。
+
+
+## 使用限制
+
+
+在启用cgroup writeback功能之后,您可以先确认内存子系统(memcg)和IO子系统(blkcg)的映射关系是否符合下文所述的规则,再对进程进行Buffered I/O限速。
+
+
+cgroup writeback功能需要memcg和blkcg协同工作,完成Buffered I/O的限速,但是内核接口cgroup v1的各个控制子系统间默认不协同工作。因此需要通过一定的规则把memcg和blkcg连接起来,规则为:通过任意一个memcg必须可以找到与之唯一对应的blkcg。即memcg和blkcg的映射关系可以是一对一或多对一,不可以是一对多或多对多。
+
+
+例如,存在进程A和B,对它们进行Buffered I/O限速,需要遵循以下约束。
+* 如果A和B分属不同的memcg,它们可以映射到不同的blkcg,只需各自一一对应。例如:A属于`memcg1`,`blkcg1`;B属于`memcg2`,`blkcg0`。
+* 如果A和B分属不同的memcg,它们也可以映射到同一个blkcg。例如:A属于`memcg1`,B属于`memcg2`,A和B都属于`blkcg2`。
+* 如果A和B属于相同的memcg,那么它们只能映射到同一个blkcg。例如:A和B均属于`memcg0`,它们同时属于`blkcg3`。
+
+
+为了避免出现意外情况,建议您在启用cgroup writeback功能后,对进程进行Buffered I/O限速前,优先设置blkcg的`cgroup.procs`接口,向该接口写入一个进程ID来保证blkcg映射的唯一性。同时您也可以通过工具查看memcg和blkcg的映射关系,详情请参见确认memcg和blkcg的映射关系。
+
+在实际运维中,可能出现进程移动到其它cgroup的情况。根据上述规则,如果进程在memcg之间移动,不会出现问题,但如果进程在blkcg之间移动,将会出现异常情况。为了避免产生异常,该功能的代码中定义了规则:一旦工作中的blkcg内的进程发生blkcg间的移动,则将映射关系直接指向root blkcg。由于一般情况是不在root blkcg设置限流阈值,所以当映射关系直接指向root blkcg时,限速功能会失效。
+
+
+**注意** 内核代码虽定义了规则避免出现意外,但您需要在实际操作中尽量避免将进程在blkcg间移动。
+
+
+## 开启cgroup writeback功能
+
+
+cgroup v1接口中的cgroup writeback功能默认是关闭的,按照以下步骤开启该功能。
+
+
+1. 通过命令`grubby`内添加`cgwb_v1`字段开启该功能。
+本示例中内核版本为`4.19.36-12.an7.x86_64`,您在操作中需要更换为实际的内核版本,内核版本的查看命令为`uname -a`。
+
+
+
+```
+sudo grubby --update-kernel="/boot/vmlinuz-4.19.36-12.an7.x86_64" --args="cgwb_v1"
+```
+2. 重启系统使功能生效。
+
+
+
+
+```
+sudo reboot
+```
+3. 使用以下命令读取内核文件`/proc/cmdline`,确认内核命令行参数中带有`cgwb_v1`字段。此时,blkcg下的`blkio.throttle.write_bps_device`及`blkio.throttle.write_iops_device`接口能够对Buffered I/O进行限速。
+
+
+
+
+```
+cat /proc/cmdline | grep cgwb_v1
+```
+
+
+## 确认memcg和blkcg的映射关系
+
+
+当您对进程进行Buffered I/O限速之前,您可以使用以下任意一种方式诊断memcg和blkcg的映射关系是否为一对一或多对一。
+
+
+* 查看memcg与blkcg映射关系。
+
+
+
+```
+sudo cat /sys/kernel/debug/bdi/bdi_wb_link
+```
+
+
+返回结果示例如下,该示例表示memcg和blkcg符合一对一的映射规则。
+
+
+
+```
+memory <---> blkio
+memcg1: 35 <---> blkcg1: 48
+```
+* 使用ftrace内核监测工具。
+ 1. 开启ftrace工具。
+
+
+
+ ```
+ sudo bash -c "echo 1 > /sys/kernel/debug/tracing/events/writeback/insert_memcg_blkcg_link/enable"
+ ```
+ 2. 查看信息输出接口。
+
+
+
+ ```
+ sudo cat /sys/kernel/debug/tracing/trace_pipe
+ ```
+
+
+ 输出内容示例如下,其中`memcg_ino=35 blkcg_ino=48`表示memcg和blkcg符合一对一的映射规则。
+
+
+
+ ```
+ <...>-1537 [006] .... 99.511327: insert_memcg_blkcg_link: memcg_ino=35 blkcg_ino=48 old_blkcg_ino=0
+ ```
+
+
+## 验证cgroup writeback是否生效
+
+
+本示例将模拟出两个产生I/O的进程,用于验证cgroup writeback功能是否有效。
+
+
+
+
+**说明**
+* 由于`dd`命令的反馈速度较快,结果使用`iostat`命令查看。
+* 由于`dd`命令为顺序写入,顺序IO回刷时,会生成1 MB数据再回刷,因此设置阈值时,`blkio.throttle.write_bps_device`不得小于1 MB(1048576)。如果设置值小于1 MB,可能会引发IO hang。
+
+
+
+
+1. 模拟出两个产生I/O的进程,并按照限制条件优先设置blkcg的`cgroup.procs`接口。
+
+
+
+
+```
+sudo mkdir /sys/fs/cgroup/blkio/blkcg1
+sudo mkdir /sys/fs/cgroup/memory/memcg1
+sudo bash -c "echo $$ > /sys/fs/cgroup/blkio/blkcg1/cgroup.procs" # $$为您的进程ID
+sudo bash -c "echo $$ > /sys/fs/cgroup/memory/memcg1/cgroup.procs" # $$为您的进程ID
+```
+2. 使用blkcg下的`blkio.throttle.write_bps_device`接口对Buffered I/O进行限速。
+
+
+
+
+```
+sudo bash -c "echo 254:48 10485760 > /sys/fs/cgroup/blkio/blkcg1/blkio.throttle.write_bps_device" # 通过设备号配置磁盘的回写限流bps为10 M
+```
+3. 使用不带参数`oflag=sync`的`dd`命令产生缓存异步I/O。
+
+
+
+
+```
+sudo dd if=/dev/zero of=/mnt/vdd/testfile bs=4k count=10000
+```
+4. 使用iostat工具查询结果。查看输出列`wMB/s`,如果被限制到10 MB/s,则表示cgroup writeback功能已生效。
+
+
+
+
+```
+iostat -xdm 1 vdd
+```
+
+
+
+
+
+
+# 增强容器资源可见性
+
+
+
+
+
+
+
+标准Linux的容器资源视图功能接口默认状态下是未启动的,当您在启动该功能后,如果在容器中使用top、free等命令,让容器读取以下接口的数据时,将直接获取容器资源信息,而不是获取容器所在的宿主机(即ECS实例)资源信息。
+* /proc/cpuinfo
+* /proc/meminfo
+* /sys/devices/system/cpu/online
+
+
+
+## 接口说明
+
+
+
+
+ | 接口 | 说明 |
+| --- | --- |
+| /proc/sys/kernel/rich\_container\_enable | 该接口控制容器资源视图功能是否开启。取值范围:
+* 0:关闭容器资源视图功能。
+* 1:开启容器资源视图功能。
+
+
+默认值:0 |
+| /proc/sys/kernel/rich\_container\_source | 该接口控制cgroup接口的数据源。取值范围:
+* 0:使用指针current所在的cgroup接口作为数据源。
+* 1:使用child reaper(即当前PID Namespace的1号进程)所在的cgroup作为数据源。
+
+
+默认值:0 |
+| /proc/sys/kernel/rich\_container\_cpuinfo\_source | 该接口控制/proc/cpuinfo接口以及/sys/devices/system/cpu/online接口显示的CPU数量。取值范围:
+* 0:使用Kubernetes的Request和Limit数据的比值(`Request/Limit`),即`quota`与`period`的比值(`quota/period`)。
+* 1:使用cpuset.cpus接口中的CPU数据源。
+* 2:使用`cpu.shares` 值除以 `/proc/sys/kernel/rich_container_cpuinfo_sharesbase`值的向上取整后的数据(原始数据如果包含小数,则整数位加1后,只取整数作为最终数据,例如:原始数据为1.1,则最终数据为2)。最终数据最多不超过实际在线CPU的数量。
+
+
+默认值:0 |
+| /proc/sys/kernel/rich\_container\_cpuinfo\_sharesbase | 当/proc/sys/kernel/rich\_container\_cpuinfo\_source接口的取值为2时,需要使用该接口作为计算公式的一部分获取最终数据。取值范围:大于等于2的整数值。
+默认值:1024 |
+
+
+## 接口使用示例
+
+
+本示例中,已在一台Linux实例中部署Docker,并创建了一个内存大小为1 GB的容器。
+
+
+* 如果您未开启容器资源视图功能,即/proc/sys/kernel/rich\_container\_enable接口的值为0。当您在容器中运行free -m命令时,查看到的资源信息如下图所示,该信息为容器所在的宿主机(Linux实例)资源信息。
+* 如果您在宿主机(Linux实例)中运行命令echo 1 > /proc/sys/kernel/rich\_container\_enable开启了容器资源视图功能,当您在容器中运行free -m命令时,查看到的资源信息如下图所示,该信息为容器资源信息。
+
+
+## 特殊场景说明
+
+
+一般情况下,开启容器资源视图功能后,使用相关接口的默认值即可满足常规需求,但您需要注意以下特殊场景的接口配置:
+
+
+对于非共享PID Namespace的Pod,其中的每一个容器都是独立的PID Namespace,如果使用systemd启动某个特权容器,容器的进程号为1号,则采集监控数据的任务可能位于容器的某个子cgroup中,而不是根cgroup。
+
+
+例如,当您通过SSH登录容器并运行cat /proc/cpuinfo命令后:
+* 如果/proc/sys/kernel/rich\_container\_source取值为默认值0,则指针current实际是位于容器的sshd.service所创建的子cgroup中,此时查看的结果为错误数据。
+* 如果您运行echo 1 > /proc/sys/kernel/rich\_container\_source命令,使用child reaper(即当前PID Namespace的1号进程)所在的cgroup作为数据源,即可查看到正确的数据。
+
+
+
+
+
+
+
+# 修改TCP TIME-WAIT超时时间
+
+
+
+
+在Linux的内核中,TCP/IP协议的TIME-WAIT状态持续60秒且无法修改。但在某些场景下,例如TCP负载过高时,适当调小该值有助于提升网络性能。ANCK新增内核接口用于修改TCP TIME-WAIT超时时间,本文主要介绍该接口的使用方法。
+
+
+
+## 背景信息
+
+
+
+TCP/IP协议的TIME-WAIT状态是指应用关闭用于通信的套接口(socket)之后,TCP/IP协议栈保持socket处于打开状态。该状态默认持续60秒,用来保证完成服务器和客户端的数据传输。当处于TIME-WAIT状态的连接数过多时,可能会影响到网络性能。因此ANCK提供了可修改TIME-WAIT超时时间的接口,用于在特定场景提高网络性能。例如,高并发业务场景。该接口的取值范围为[1, 600],单位为秒。如果不修改该接口,TIME-WAIT超时时间的默认值保持60秒不变。
+
+
+## 注意事项
+
+
+将TCP TIME-WAIT超时时间修改为小于60秒与TCP/IP协议quiet time概念相违背,可能导致您的系统将旧数据当做新数据接收,或者复制的新数据当做旧数据拒绝。因此请在网络专家建议下调整。了解TCP/IP协议quiet time的相关概念,请参见[IETF RFC 793标准](https://tools.ietf.org/html/rfc793)。
+
+
+## 配置方法
+
+
+您可以通过以下两种方式修改TIME-WAIT超时时间,其中参数[$TIME\_VALUE]为您修改的TIME-WAIT超时时间。
+
+
+* 通过`sysctl`命令修改TIME-WAIT超时时间。
+
+
+
+```
+sysctl -w "net.ipv4.tcp_tw_timeout=[$TIME_VALUE]"
+```
+* 以root权限使用`echo`命令,将值修改到`/proc/sys/net/ipv4/tcp_tw_timeout`接口中。
+
+
+
+```
+echo [$TIME_VALUE] > /proc/sys/net/ipv4/tcp_tw_timeout
+```
+
+
+例如,在Nginx配置7层代理等存在大量短连接的场景下,阿里云推荐您将TIME-WAIT超时时间修改为5s。运行以下任一命令修改超时时间:
+
+
+**说明** 服务器中是否存在大量短连接,您可以运行`netstat -ant | grep TIME_WAIT | wc -l`命令进行判断。
+
+
+
+
+```
+sysctl -w "net.ipv4.tcp_tw_timeout=5"
+```
+
+
+
+
+
+```
+echo 5 > /proc/sys/net/ipv4/tcp_tw_timeout
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210.md"
new file mode 100644
index 0000000000000000000000000000000000000000..f3563b40c6a0ec9514aeab101e06fdf089fa06df
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210.md"
@@ -0,0 +1,444 @@
+
+# 概述
+
+
+在本文中,我们基于社区DAMON设计用于跟踪实时内存热点数据的工具DATOP, 采用划分内存区域采样的方式,并自适应区域构建技术来获取极低的开销损耗,在此基础上,还增加了numa 仿真功能,用于收集任务跨numa访存情况,为了评估其准确性和低开销能力,我们选取和测试了多个benchmark,并与基线进行比较, 结果表明:**DATOP工具运行时开销非常小(保持在不到4%左右),此外开销不受负载大小的影响,仍然保持出色的监控质量,通过多方面测试,我们得出结论:DATOP工具在识别冷热内存以及跨numa访存方面具备优秀的表现能力。**
+
+
+# 背景:云计算大规模复杂场景下内存面临的挑战
+
+
+云计算领域场景下,海量用户数据的增长,对计算机软件和硬件设计都带来了巨大的挑战,尤其是内存设备如DRAM的速率提升并没有跟上这种高速增长趋势,在数据中心中,海量数据的处理,常常让服务器饱受内存不足之苦。
+
+
+为克服低内存容量,混合内存使用如DRAM搭配PMEM成为未来数据中心的主流方案,但是如何快速识别热点数据并让其准确保持在DRAM中运行是影响性能的关键因素,这就要求系统具备快速识别热点数据的能力,并能动态跟踪捕获热点数据的变化,让其处于高性能的DRAM中,但是不幸的是,现有工具为达到一定的准确度,通常会耗费大量的时间,并引入额外的overhead,造成性能回退。
+
+
+此外服务器硬件架构的快速迭代,cpu核数越来越多,numa节点也越来越多,例如amd服务器numa node数目达到8个,arm服务器飞腾s2500 numa节点达到16个,跨numa节点访存带来的性能影响日益突出,如何低开销高效的识别出跨numa热点数据,并优化之,对于提升系统服务质量,有着重要的意义。
+
+
+# datop:轻量级靶向热点内存扫描工具
+
+
+## 热点扫描原理及策略
+
+
+在内存领域,对内存进行优化其实依靠预测内存的行为而做的决策,但是能够高效准确的预测内存的走势,其实是非常困难的,此外内存的策略优化对于用户来说,是不透明的,因此现有内存领域的各种策略机制,在实际生产环境中,并未取得很好的效果,也正是基于这些原因,社区推出了一种新的内存调控机制DAMON(Data Access Monitor),它试图让向用户展示内存的动作行为,让用户可根据这些行为相应的调整内存管理策略。
+
+
+### 三大chunks
+
+
+服务器现有硬件能支持非常巨大的地址空间,内存容量动不动达到几个T的大小,工作负载耗用内存几个G也是很普遍的事,随机毫无规律的划分地址空间可肯定是不可取的,并且在实际使用中,只有小部分区域被实际映射到内存并被访问,DAMON通过分析和论证,先将地址分为三大chunks,这三个chunks区域之间的空隙是给定地址空间中两个最大的未映射区域。
+
+
+**图1:**
+
+
+
+
+
+在大多数情况下,两个最大的未映射区域是堆与最上层mmap() ed区域之间的空隙,以及最下层mmap() ed区域与堆栈之间的空隙, 因为这些间隙在通常的地址空间中是非常大的,排除这些就足够了,所以针对一个工作负载而言,DAMON只需要监控一下这些区域就足够了, 此外,随着工作负载的运行,映射区域发生变化,例如部分最大ummaped区域易主,所以damon设置了一个update周期,去周期性检测这些三大chunks的有效性,重新查找有效的三大chunks,并和现有监测得区域进行对比,删减或者增加。
+
+
+### region拆分与合并
+
+
+在获取三大chunks后,damon会按照设定规则,去将这三个chuns划分为不均等的若干分regions, 如下图2所示:
+
+
+**图2:**
+
+
+
+
+
+这些regions后面会随着热点频率去动态调整,进行拆分或者合并操作,其算法原理大致如下:
+
+
+**拆分原则:**
+
+
+1. 大于等于2倍 DAMON\_MIN\_REGION才能拆分;
+2. 才分region的size不能小于DAMON\_MIN\_REGION;
+3. region可以拆分为3个,当regions个数大于max\_nr\_regions的2/3后,降低拆分个数,由3变2;
+4. region个数必须保持在min\_nr\_regions和max\_nr\_regions范围内;
+
+
+**合并原则:**
+
+
+1. 两合并的regions必须收尾地址相等;
+2. 两者热点统计值之差必须小于设定阈值范围内;
+
+
+### region采样与热点统计
+
+
+“trace page access bit”技术作为跟踪热点内存通用那就的技术手段,被业界广泛使用,但是该技术有一个固有的缺陷,那就是随着工作负载耗用内存增加,自身带来的开销和跟踪质量都会变糟,而damon通过region划分, 再结合空间采样方式良好的解决了该缺陷:假设一个region中,所有page都有相同的访问模式,这样的话,只需要监控一个page就够了。这样一来,在每个region里面,会随机选择一个page,在bitmap中把它对应的“accessed(访问过)”bit先清零,然后时不时地检查一下,如果这个page被访问过了,那么就算作这个region都被访问过了,它不是监视所有的页面,而是只监视reigon里面随机抽取的一个页面,该页面在某个采样时刻代表着这个region, 并将该值记录下来, 随着采样的不断进行,该region的热点就被统计下来了。
+
+
+
+```
+void check_access(region ∗ r) {
+ if (!r−>sampled_page)
+ goto next ;
+ if (accessed(r−>sampled_page) )
+ r−>nr_accesses++;
+ next:
+ r−>sampled_page = rand_page(r->sampled_page);
+ clear_accessed(r−>sampled_page);
+}
+```
+
+上述伪代码只是介绍其采样和统计实现方法,其更复杂的逻辑处理关系,例如region合并和拆分后nr\_access的值处理,以及nr\_access周期性清零等本文不再介绍,有兴趣的读者可以依据damon实现源码自行分析。
+
+
+### numa仿真实现
+
+
+社区damon能有有效的识别工作负载内存的冷热情况,但是对于工作负载内存跨numa访存这块,是无法做出判断的, 然而在实际业务中,跨numa访问造成的性能衰退问题真实存在,尤其是现今服务硬件多numa架构numa数目越来越多,正式基于以上原因,我们丰富了damon kernel部分代码,增加了内存numa访存情况。
+
+
+和热点统计一样,numa仿真不会统计region中所有page的跨numa访问情况,而是利用damon空间采样方式,将damon获取的page在clear了access bit后,将其设置为pte none.
+
+
+
+```
+void check_numa(region ∗ r) {
+ if (!r−>sampled_page)
+ goto next ;
+ if (local_numa_node(r−>sampled_page) )
+ r−>nr_local++;
+ else
+ r->nr_remote++;
+ next:
+ r−>sampled_page = rand_page(r->sampled_page);
+ set_page_none(r−>sampled_page);
+}
+```
+
+同样该部分伪代码只是介绍其numa基本实现,在实际中我们需要考虑pte处于swap,和page属于大页的情况,此外在pte设置为none后,会造成再次访问该page时发生page\_fault和tlb miss的情况,我们测试发现,在某些频繁访问某块内存的工作负载中,造成一定的性能损耗,所以在实际使用中,我们增加了numa仿真开关,需要的时候去开启该功能。
+
+
+### 小结
+
+
+基于上述几小节对damon以及numa仿真在kernel部分的实现机制的介绍,让我们对datop工具的实现原理有了清楚的认识,datop包括内核态部分和用户态部分,用户态可以通过perf调用功能,将内核态通过trace统计的热点信息捕获,并排序显示出来,详细调用流程入下图3显示。
+
+
+**图3:**
+
+
+
+
+
+在用户态,DATOP通过trace\_event、damon dbgfs、以及numa switch接口和内核进行交互:
+
+
+**蓝色**绘制线部分:该部分是和用户态显示的核心, 通过内核kdamond线程将采样统计的相关值传递给trace接口, 用户态通过trace\_event方式获取region区域热点信息,包括区域大小,access统计,进程信息以及跨numa统计等,最终通过窗口向用户展示。
+
+
+**黑色**绘制线部分:该部分用于控制内核态线程kdamond的相关行为,通过damon dbfs接口,用于设置采样频率,更新周期,region个数划分,监控进程配置,kdamond线程的开启和关闭等。
+
+
+**绿色**绘制线部分用于设定numa仿真功能的开启和关闭,此功能针对支持多numa的场景。
+
+
+**红色**绘制线部分是热点工具的核心执行单元,用户态通过dbgfs接口开启监控后,kdamond线程被创建, 首先会查找被监控进程的三大chunks, 找到后,按照damon dbgfs接口设定的region个数方范围,对其进行拆分,此后按照设定好的采样频率进入周期性循环工作,直到被监控进程停止运行或用户操作dbgfs接口,停止监控,在周期性循环中,会对region热点进行随机采样并统计,此外还判定用户是否开启numa仿真功能,若开启还会对region跨numa情况进行统计,处理完成后,会更新采样结果,并通过trace event传递给用户,以上操作完成后,会依据kdamond线程运行时间,并在指定周期内,通过热点统计值对region进行拆分和合并操作,此外在更长的周期到来后,还会从新检查chunks的准确性,并按多加少减原则,修改region,以此保证热点内存跟踪的实时性和准确性。
+
+
+至此DATOP技术实现原理介绍完毕,后面会进入介绍使用和数据测试方面的介绍。
+
+
+## 使用
+
+
+在龙蜥社区 5.10版本内核支持damon代码以及自研的numa仿真部分代码,结合开源的用户态工具datop: 工具就可以运行起来了,datop工具支持单、多进程以及cgroup粒度内存热点监控以及跨numa访存监控 两种方式,详细使用可以参考源码readme部分。
+
+
+**注:**cgroup粒度监控功能会在近期开源。
+
+
+## DATOP工具对部分关联性能指标影响说明
+
+
+为评估了DATOP工具在使用中对系统造成的影响,此处采用lmbench作为作为被监控进程进行了测试。
+
+
+
+
+| | | |
+| --- | --- | --- |
+| 测试情况 | 虚拟机 32vCPU 4 node | 物理机 96cpu 4node |
+| | 被监控进程个数 | 未开numa仿真
+和base对比 | 开numa仿真功能 | base对比 | 未开numa仿真 | base对比 | 开numa仿真 | base对比 |
+|
+用户态overhead | 1 | 最高0.4%, | 稳定后0.1%不到 | 最高0.4% | 稳定后0.1%不到 | 最高0.2% | 稳定后不到0.1% | 0.2% | 稳定后不到0.1% |
+| 4 | 最高0.7% | 0.2% | 最高0.8% | 稳定后0.2% | 最高0.2% | 稳定后不到0.1% | 最高0.3 | 稳定后不到0.1% |
+|
+kernel overhead | 1 | 最高2% | 0.1% | 2.3% | 0.2% | 最高0.4% | 稳定后不到0.1% | 最高0.6% | 稳定后不到0.1% |
+| 4 | 最高2.5% | 0.2% | 2.8% | 0.2% | 最高0.6% | 稳定后不到0.1 | 最高0.7% | 稳定后不到0.2% |
+
+
+以上测试可能会存在一定的误差的,测试目主要是为了充分验证热点工具内核态代码引入,对内核以及应用程序的影响,通过测试,可以看出datop工具以及kernel部分,造成系统整机cpu使用率增加不超过1%。
+
+
+## 关于numa仿真测试统计正确性验证说明
+
+
+### 测试方法一
+
+
+构造一个执行程序,并创建两个线程a和b,这两个线程将会共享代码段部分代码,进行反复性读测试
+
+
+在测试前,将线程1和程序绑定在同一个numa节点,将线程2绑定在不同numa节点。
+
+
+在测试前先通过/proc/pid/smaps确认下代码段映射地址,如下图4所示。
+
+
+**图4:**
+
+
+
+
+
+通过perf工具在不通时刻抓取numa仿真统计相关值,如下所示:
+
+
+
+```
+kdamond.0 target_id=18446462601994805632 nr_regions=10 400000-402000: 12 5243 0
+kdamond.0 target_id=18446462601994805376 nr_regions=10 400000-402000: 8 0 5427
+...
+kdamond.0 target_id=18446462601994805632 nr_regions=10 400000-402000: 9 7669 0
+kdamond.0 target_id=18446462601994805376 nr_regions=10 400000-402000: 7 0 7913
+```
+
+从测试来看,虚拟地址0x400000-0x402000为属于代码段, 两线程共享该部分内存,通过perf采样统计可以看出, 本地线程1访问这块地址次数为5243次, 远端线程访问次数为5427次,隔一段时间后第二次统计本地线程1为7669,远端线程为7913,基本一致,说明numa仿真功能统计正确。
+
+
+### 测试方法二
+
+
+构造一个应用程序,申请1G左右大小的空间MSIZE,通过设置numa\_alloc等版本操作,将MSIZE绑定在node0和node1, 通过交叉访问,统计其跨numa的情况。
+
+
+下图是datop工具显示程序跨numa的情况,按照预定设置,两者访问占比50%,结果满足预期。
+
+
+
+```
+ INDEX TYPE START END SIZE(KiB) ACCESS AGE LOCAL REMOTE
+ 1 rw-p ffff49a34000 ffff515aa000 126424 2 0 50.02% 49.98%
+ 2 rw-p ffff4a636000 ffff52662000 131248 1 0 50.01% 49.99%
+ 3 rw-p ffff4f31d000 ffff52cb3000 58968 1 1 49.98% 50.02%
+ 4 rw-p ffff5704f000 ffff586f9000 23208 1 1 49.77% 50.23%
+ 5 rw-p ffff5b5a5000 ffff5cbd1000 22704 1 1 49.78% 50.22%
+ 6 rw-p ffff5cbd1000 ffff5ff58000 52764 2 0 49.71% 50.29%
+ 7 rw-p ffff5ff58000 ffff64ca4000 79152 1 0 49.71% 50.29%
+```
+
+同样采用numastat正是下该程序node访问情况,如下图所示:
+
+
+
+```
+Per-node process memory usage (in MBs) for PID 111676 (lt-numademo)
+ Node 0 Node 1 Node 2
+ --------------- --------------- ---------------
+Huge 0.00 0.00 0.00
+Heap 0.02 0.00 0.00
+Stack 0.01 0.00 0.00
+Private 565.24 564.00 0.00
+---------------- --------------- --------------- ---------------
+Total 565.27 564.00 0.00
+```
+
+从测试结果来看,node0和node1这块两者各自占比50%左右,复合预期,说明numa仿真统计这块正确性没有问题。
+
+
+## benchmark测试结果
+
+
+此处我们选取了几款常用的benchmark作为其测试,评估datop监控对其测试结果造成的影响。
+
+
+### unixbench
+
+
+选取unixbench中fstime和context1两者耗用内存较多的作为测试参考。
+
+
+
+
+| | | |
+| --- | --- | --- |
+| | 虚拟机 | 物理机 |
+| 测试类 | 关numa仿真 | 开numa仿真 | 关numa仿真 | 开numa仿真 |
+|
+
+fstime | 1573.6 | 1589.4 | 1955.6 | 1960.0 |
+| 1591.4 | 1574.2 | 1966.1 | 1960.7 |
+| 1575.6 | 1592.3 | 1963.5 | 1977.4 |
+|
+
+context1 | 475.4 | 473.3 | 556.5 | 557.4 |
+| 471.2 | 472.1 | 555.3 | 560.0 |
+| 473.4 | 474.6 | 557.6 | 558.2 |
+
+
+从以上测试数据来看,将unixbench作为被监控对象,在开和不开numa仿真功能下,不会造成其性能衰退。
+
+
+### stream
+
+
+stream通常用于内存带宽测试,会按照多种形式频繁访问内存,正好基于这一特性验证datop工具对其影响。
+
+
+测试指令:numactl -m 0 -C 5 ./stream
+
+
+
+
+| | | |
+| --- | --- | --- |
+| | 虚拟机 | 物理机 |
+| 测试项 | 关numa仿真 | 开numa仿真 | 关numa仿真 | 开numa仿真 |
+|
+Copy | 1499.4 | 1487.2 | 1678.0 | 1673.1 |
+| 1495.5 | 1493.5 | 1674.3 | 1665.5 |
+| 1473.0 | 1479.1 | 1675.2 | 1680.7 |
+|
+Scale | 1459.1 | 1483.9 | 1585.9 | 1588.5 |
+| 1490.9 | 1451.3 | 1590.0 | 1597.3 |
+| 1475.1 | 1472.1 | 1588.8 | 1595.6 |
+|
+Add | 1960.3 | 1937.0 | 1983.7 | 1974.6 |
+| 1962.2 | 1955.6 | 1991.9 | 1991.4 |
+| 1957.3 | 1944.9 | 1992.3 | 1996.2 |
+|
+Triad | 1867.8 | 1860.2 | 1976.6 | 2017.5 |
+| 1862.5 | 1873.1 | 2035.0 | 2025.3 |
+| 1852.1 | 1859.5 | 2011.9 | 1997.0 |
+
+
+从以上测试数据来看,将stream作为被监控对象,在开和不开numa仿真功能下,不会造成其性能衰退。
+
+
+### mbw
+
+
+测试指令:numactl -m 0 -C 5 ./mbw
+
+
+
+
+| | | |
+| --- | --- | --- |
+| | 虚拟机 | 物理机 |
+| 测试项 | 关numa仿真 | 开numa仿真 | 关numa仿真 | 开numa仿真 |
+|
+MEMCPY
+MiB/s | 2714.146 | 2627.115 | 2645.083 | 2621.095 |
+| 2713.336 | 2634.099 | 2643.614 | 2616.979 |
+| 2718.278 | 2625.363 | 2646.133 | 2629.780 |
+|
+DUMB
+MiB/s | 1019.456 | 1019.602 | 751.405 | 745.045 |
+| 1018.745 | 1018.746 | 768.279 | 763.038 |
+| 1018.080 | 1020.929 | 773.796 | 746.797 |
+|
+MCBLOCK
+MiB/s | 5139.354 | 5151.532 | 2668.374 | 2649.498 |
+| 5155.516 | 5150.471 | 2666.596 | 2650.973 |
+| 5148.191 | 5149.887 | 2667.449 | 2645.573 |
+
+
+通过测试发现mbw:
+
+
+在虚拟机测试时memcopy项时候存在3%左右性能衰退,其他测试项未见明显差异。
+
+
+在物理机测试时,三类测试项都存稍微的性能衰退, 其中MEMCPY衰退不到1%,DUMB衰退2.6%,MCBLOCK不到1%。
+
+
+
+
+
+### 小结
+
+
+在对比mbw和stream测试时,有个较为奇怪的问题了,steam测试copy并没有发生性能衰退,而mbw发生了3%的性能衰退,笔者通过分析其各自源码发现,发现stream copy测试过程中,每一次copy大小是小于4K的,而stream memcopy测试过程中每一次copy远大于4K,一个页的大小,这就导致stream memcpoy测试过程中会应为numa仿真设置pte表为空被命中的概率相比stream copy要大的多, 会造成更多的page fault问题,通过perf抓取分析也正好论证了这一点,所以mbw memcopy出现了性能衰退。
+
+
+这也充分说明,针对频繁访问一次超过4K大小的内存区域的应用程序,datop工具会造成一定的性能衰退影响,这也是numa仿真设置开关的原因,可根据实际情况按需打开。
+
+
+# 热点数据扫描试用
+
+
+我们可以对那些**内存访问密集模型进行简单的测试,获取到较稳定的热点**。例如redis get操作(测试命令:redis-benchmark -r 20000000 -n 20000000 -t get -d 1024 -c 32 -P 8)。
+
+
+**图5:**
+
+
+
+
+
+图5中INDEX:表示region索引,TYPE表示region的虚拟地址类型,START表示region的起始地址,END表示reigon结束地址,SIZE表示region大小为多少,单位KiB, ACCESS表示热点程度,值越大表示越热,AGE表示热点波动情况,值越大表示冷热状态稳定,波动小,LOCAL表示这段region区域本地numa访问占比,REMOTE表示远端numa访问占比。
+
+
+图5是按采集的ACCESS进行排序获取的热点较高的14个regions。目前测试,可以确定在一段时间内这些regions的统计基本稳定,并且存在大量的匿名页热点, 此外通过刻意numa本地绑定测试,也正确的统计numa访存情况。
+
+
+
+
+
+另外,我们以mysql为例,验证下跨代码端部分存在跨numa的情况。
+
+
+**图6:**
+
+
+
+
+
+上图6的热点监控命令为:datop -p 168368 -r 100,400。mysql中的热点显示与redis有些不同,存在大量属于"r-xp"的热点,并且存在跨numa访问的情况,我们之前测试中同样发现mysql的代码段热点高于匿名页,所以针对不同的场景,需要具体分析热点以及跨numa的内存段属性,然后做相应的优化措施。
+
+
+以上的测试数据表明:**该热点工具可以用于反映进程代码段、匿名段的相对热点,以及跨numa访存情况,用于判断进程使用大页,页迁移,冷内存回收等方面提供测试量化手段,进而达到有针对性优化的目的。**
+
+
+# 参考
+
+
+
+
+
+[Memory-management optimization with DAMON](https://lwn.net/Articles/812707/)
+
+
+[Using DAMON for proactive reclaim](https://lwn.net/Articles/863753/)
+
+
+[DAMON Extended To Offer Physical Memory Address Space Monitoring](https://www.phoronix.com/scan.php?page=news_item&px=DAMON-Physical-Monitoring)
+
+
+[Proactively reclaiming idle memory](https://lwn.net/Articles/787611/)
+
+
+[Intel® Optane™ Memory](https://www.intel.com/content/www/us/en/products/details/memory-storage/optane-memory.html)
+
+
+[damon用户态工具damo](https://github.com/awslabs/damo)
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/\351\241\271\347\233\256\347\256\200\344\273\213.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/\351\241\271\347\233\256\347\256\200\344\273\213.md"
new file mode 100644
index 0000000000000000000000000000000000000000..2c784154e3c39f8fc10ffd5e29d8a0c9fe98e7ff
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/\351\241\271\347\233\256\347\256\200\344\273\213.md"
@@ -0,0 +1,4 @@
+本项目聚焦于:
+- 龙蜥内核的基础能力建设,包括基础功能、兼容性、稳定性和性能,建立相关基线。
+- 跟踪行业和upstream发展动态,负责下一代龙蜥内核版本演进。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212.md"
new file mode 100644
index 0000000000000000000000000000000000000000..4ff5c36d16da8225d0a52c4ebf7bfdd7187d62e1
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212.md"
@@ -0,0 +1,449 @@
+from arm-sig:
+
+
+# 一、测试总结
+
+
+针对龙蜥 OS MPAM 特性的整体测试情况如下:
+
+
+* 经过对 MPAM 的功能性验证,目前 L3 cache 资源隔离和监控功能均正常,内存带宽隔离效果甚微,监控功能可用。
+* 测试用例覆盖 MPAM 接口读写测试、并发压力测试等多种类型,测试结果未发现问题。
+* 针对 MPAM ESR 中断,验证了 PARTID、PMG、monitor 相关异常能否触发中断、告知错误类型,中断监测功能正常可用。
+
+
+# 二、MPAM 功能验证
+
+
+## 2.1 cache 隔离功能验证
+
+
+### 2.1.1 不同配置对实际 cache 占有量的影响
+
+
+L3 cache 资源隔离以 ways 的方式进行配置。倚天机器共有 16 ways,测试对不同 ways 的隔离效果进行了验证。
+
+
+
+```
+numactl -m 0 -C 16 memhog -r10000000 100000m > /mnt/log
+```
+
+程序和资源隔离 group 绑定分别采用了 pid 绑定(tasks)和 cpu 绑定(cpus)两种方式。通过 schemata 接口设置程序所能够使用的 ways 数目,通过 mon\_data/mon\_L3\_0\*/llc\_occupancy 接口读取程序的 L3 cache 占用。多次读取取平均值,并与理想的 cache ways 大小进行对比。
+
+
+测试结果显示,L3 cache 隔离功能**效果显著**,无论是通过 tasks 绑定还是 cpus 绑定,均可以得到与理想值相接近的隔离效果。
+
+
+
+
+
+### 2.1.2 不同配置对 mem latency 的影响
+
+
+latency 作为一个重要的性能指标,在一些对时延敏感的场景来说,有很重要的参考作用,此处使用 lat\_mem\_rd 测试 cache 在不同的 ways 下,内存 latency 的分布情况,也从侧面验证 MPAM 对 cache 的隔离功能。
+
+
+
+```
+#设置步长为512字节
+numactl -C 10 -m 0 ./lat_mem_rd -N 1 -P 1 145M 512
+```
+
+测试结果显示,随着 cache way 数目的增加,加载相同内存的 latency 逐渐减小。
+
+
+
+
+
+### 2.1.3 L3 cache 抗干扰测试
+
+
+
+```
+# workload
+numactl -m 1 -C 64-127 memhog -r10000000 100000m > /mnt/log
+# distractor
+numactl -m 1 -C 64-127 memhog -r10000000 100000m > /mnt/log
+```
+
+workload:保持 L3:1=fff0 配置无变化
+
+
+distractor: 测试 L3:1=,mask 值分别为 0-f(无干扰)、0010-fff0(有干扰)
+
+
+测试结果显示:
+
+
+在无干扰情况下,workload 的 L3 cache 占用量基本无变化;
+
+
+随着干扰 way 数逐渐变多,workload 和 distractor 两者的 L3 cache占比逐渐趋同,总量不变。
+
+
+
+
+
+### 2.1.4 模拟混部 L3 cache 隔离测试
+
+
+分别以 SPECjbb 2015 和 stress-ng 程序模拟在线环境和离线环境,对L3 cache隔离功能进行测试。两个环境均运行在 NUMA node 1 上。
+
+
+在前 40s 的时间内,两个程序共享 L3 cache 资源。在约 40s 后,开始隔离在线和离线L3 cache资源的使用,在离线任务 L3 cache 的配比分别为 0xffff 和 0xf。
+
+
+
+
+
+通过实验结果可以看到,在 L3 cache 资源共享的情况下,离线资源对在线资源干扰和压制明显,L3 cache 竞争激烈,波动幅度很大;在对 L3 cache 资源进行隔离后,一方面离线得到了持续有效的压制,L3 cache 占有率大幅下降,另一方面在线性能提升明显,而且波动幅度变小。
+
+
+## 2.2 MB 隔离功能验证
+
+
+### 2.2.1 不同配置对内存带宽的影响
+
+
+
+```
+gcc -O3 -fopenmp -DSTREAM_ARRAY_SIZE=100000000 -DNTIMES=1000 stream.c -o stream
+# 单node测试
+numactl -m 1 -C 64-127 ./stream
+# 单CPU测试
+numactl -m 1 -C 72 ./stream
+```
+
+MB 资源隔离以百分比的方式进行配置。测试以 5% 为粒度,通过设置 schemata 接口让内存带宽从 5% 逐次递增到 100%,通过读取 mon\_data/mon\_MB\_0\*/mbm\_local\_bytes 接口读取带宽值,最终取多次测量的平均值。
+
+
+通过测试结果可以发现,不同百分比下的测试MB带宽值和100%带宽下的MB带宽值基本相等,倚天机器的 MB 带宽隔离**效果甚微**。
+
+
+#### 单 node(64 CPU) MB 配置结果
+
+
+
+
+| | | |
+| --- | --- | --- |
+| **percent** | **stream测试值[Copy] (MB/s)** | **mbm\_local\_bytes接口值 (MB/s)** |
+| 5 | 104808.5 | 104800.0 |
+| 10 | 105028.3 | 105730.5 |
+| 20 | 104459.3 | 104915.1 |
+| 40 | 105077.6 | 105852.0 |
+| 60 | 104980.6 | 105178.7 |
+| 80 | 104924.8 | 105182.8 |
+| 100 | 104828.1 | 105855.8 |
+
+
+#### 单 CPU MB 配置结果
+
+
+
+
+| | | |
+| --- | --- | --- |
+| **percent** | **stream测试值[Copy] (MB/s)** | **mbm\_local\_bytes接口值 (MB/s)** |
+| 5 | 25948.7 | 24147.7 |
+| 10 | 25934.0 | 24433.1 |
+| 20 | 25913.5 | 22771.2 |
+| 40 | 25897.9 | 24559.4 |
+| 60 | 25952.9 | 24079.7 |
+| 80 | 25866.5 | 24246.4 |
+| 100 | 25952.1 | 24171.9 |
+
+
+# 三、MPAM稳定性测试
+
+
+## 3.1 resctrl mount/umount
+
+
+**测试方法**
+
+
+挂载 resctrl 文件系统,设置 schemata 资源隔离接口,随机写 cpus/cpus\_list、tasks 接口,读取mon\_data 资源监控接口,最后卸载 resctrl 文件系统。重复 1000000 次。
+
+
+**测试结果**
+
+
+resctrl 文件系统相关接口仍可正常使用。
+
+
+## 3.2 接口写入测试
+
+
+### 3.2.1 schemata 写入
+
+
+**测试方法**
+
+
+创建两个 group,生成随机 L3 cache mask 和 MB 内存带宽值,并分别写入两个 group 的 schemata 接口,之后读取 schemata 接口,验证当前值是否与写入值相同。重复测试 1000000 次。
+
+
+**测试结果**
+
+
+schemata 均可正常写入。
+
+
+### 3.2.2 schemata 错误写入
+
+
+对 schemata 接口写入多种错误参数,验证 schemata 是否可以正确识别处理。
+
+
+验证的错误类型及验证结果如下:
+
+
+
+
+| | | |
+| --- | --- | --- |
+| **错误写入示例** | **last\_cmd\_status输出** | **测试结果** |
+| L3:0=10000 | Mask out of range | PASS |
+| L3:2=ff;3=ff | Unknown domain | PASS |
+| L3 | Missing ':' | PASS |
+| L3: | Missing 'L3' value | PASS |
+| L3:0 | Missing '=' or non-numeric domain | PASS |
+| L30:0=fff | Unknown or unsupported resource name 'L30' | PASS |
+| L3:0=fghi | Non-hex character in the mask fghi | PASS |
+| L3:1=ff;1=f4 | Duplicate domain 1 | PASS |
+| MB:0=150 | MB value 150 out of range 5-100 | PASS |
+| MB:0=4 | MB value 4 out of range 5-100 | PASS |
+| MB:0=FOO | Non-decimal digit in MB | PASS |
+| MB | Missing ':' | PASS |
+| MB:0 | Missing 'MB' value | PASS |
+| MB:2=55 | Unknown domain | PASS |
+| MB:1=23;1=56 | Duplicate domain 1 | PASS |
+| L3:0=ff (with cdp) | Unknown or unsupported resource name 'L3' | PASS |
+
+
+### 3.2.3 cpus/cpus\_list 写入
+
+
+测试方法
+
+
+随机写入 cpus/cpus\_list 接口 1000000 次,验证是否写入成功,并且 cpus 接口和 cpus\_list 接口的值是否相对应。
+
+
+测试结果
+
+
+cpus/cpus\_list 均可正常写入,并保持值的相等。
+
+
+### 3.2.4 cpus/cpus\_list 错误写入
+
+
+
+
+| | | |
+| --- | --- | --- |
+| **错误写入示例** | **last\_cmd\_status输出** | **测试结果** |
+| echo 156 > cpus\_list | Can only assign online CPUs | PASS |
+| echo 4096 > cpus\_list | Bad CPU list/mask | PASS |
+| echo ffff > cpus\_list | Bad CPU list/mask | PASS |
+| echo 3-12 > cpus | Bad CPU list/mask | PASS |
+
+
+### 3.2.5 tasks 写入
+
+
+**测试方法**
+
+
+创建 500 个进程,并将其 pid 写入 tasks 接口,验证进程对应 pid 是否存在。之后 kill 掉所有进程,验证其 pid 是否已从 tasks 文件中移除。重复 1000000 次。
+
+
+**测试结果**
+
+
+tasks 接口均可正常写入和移除。
+
+
+### 3.2.6 tasks 错误写入
+
+
+
+
+| | | |
+| --- | --- | --- |
+| **错误示例** | **stderr** | **测试结果** |
+| 将不存在pid写入tasks | echo: write error: No such process | PASS |
+| echo hello > tasks | echo: write error: Invalid argument | PASS |
+
+
+### 3.2.7 mode 写入
+
+
+mode 接口默认值为 shareable,当前MPAM接口暂不支持 mode 接口值的修改。
+
+
+
+
+| | |
+| --- | --- |
+| **Mode** | **支持情况** |
+| shareable | 支持 |
+| exclusive | 不支持 |
+| pseudo-locksetup | 不支持 |
+| pseudo-locked | 不支持 |
+
+
+## 3.3 group mkdir/rmdir 测试
+
+
+### 3.3.1 max group 创建
+
+
+**测试方法**
+
+
+以 info/\*/num\_closids 为基准,创建所能达到的最多 group。重复 1000000 次。
+
+
+**测试结果**
+
+
+倚天 PARTID 数目为 64 个,因此除了 default group 外,最多能够创建 63 个 group。一般情况下均可达到最大值。但在部分 group 被使用过的情况下,由于其对应的 PARTID 在 L3 cache中占用量可能超过 /sys/fs/resctrl/info/L3\_MON/max\_threshold\_occupancy,从而导致该 PARTID 在一定时间内不可用。
+
+
+### 3.3.2 group 随机创建/删除
+
+
+**测试方法**
+
+
+随机创建/删除 group 共计 2000\*(num\_closids-1),验证 group 分配和回收功能是否正常。
+
+
+**测试结果**
+
+
+group 随机创建和删除,group 分配/回收接口仍可正常运作。
+
+
+### 3.3.3 mon\_group 创建/删除
+
+
+当前社区版本MPAM代码下 num\_rmids 均为 1,暂不支持 mon\_groups 目录下 mon group 的创建和删除。
+
+
+## 3.4 并发读写测试
+
+
+### 3.4.1 L3 cache 监控接口并发读取
+
+
+**测试方法**
+
+
+创建 5 个 group,每个 group 中写入 10 个进程:memhog -r1000000000 1m > /mnt/log
+
+
+同时 10 个进程并发读 mon\_data/L3\_MON/llc\_occupancy,持续时间 60 min。
+
+
+**测试结果**
+
+
+测试过程中未出现resctrl接口崩溃或不可用问题。
+
+
+### 3.4.2 MB 监控接口并发读取
+
+
+**测试方法**
+
+
+创建 5 个 group,每个 group 中写入 10 个进程:memhog -r1000000000 1m > /mnt/log
+
+
+同时 10 个进程并发读 mon\_data/mon\_MB\_\*/mbm\_local\_bytes,持续时间 60 min。
+
+
+**测试结果**
+
+
+测试过程中未出现 resctrl 接口崩溃或不可用问题。
+
+
+### 3.4.3 schemata 接口并发写入
+
+
+**测试方法**
+
+
+创建 5 个 group,每个 group 中写入 10 个进程:memhog -r1000000000 1m > /mnt/log
+
+
+同时 10 个进程并发随机写入 schemata,持续时间 60 min。
+
+
+**测试结果**
+
+
+测试过程中未出现 resctrl 接口崩溃或不可用问题。
+
+
+### 3.4.4 cpus/cpus\_list 接口并发写入
+
+
+**测试方法**
+
+
+创建 1 个 group,10 个进程并发写入随机 cpus/cpus\_list,持续时间 60 min。
+
+
+**测试结果**
+
+
+测试过程未出现接口崩溃或不可用问题。
+
+
+### 3.4.5 tasks 接口并发写入
+
+
+**测试方法**
+
+
+创建 1 个 group,10 个进程并发创建 300 个 task 并写入 tasks 接口。
+
+
+**测试结果**
+
+
+测试过程未出现接口崩溃或不可用问题。
+
+
+# 四、MPAM 错误中断验证
+
+
+## 4.1 L3 cache 资源错误中断验证
+
+
+
+
+| | | | |
+| --- | --- | --- | --- |
+| 错误码 | 描述 | 结果 | 备注 |
+| 0 | No error captured in MPAMF\_ESR | 无 | 非异常情况 |
+| 1 | MPAMCFG\_PART\_SEL out of range | 可触发 | |
+| 2 | Request PARTID out of range | 可触发 | |
+| 3 | MSMON out of range PARTID/PMG | 可触发 | |
+| 4 | Request PMG out of range | 不可触发 | PMG>1时无法写入 |
+| 5 | MSMON\_CFG\_MON\_SEL out of range | 可触发 | |
+| 6 | MPAMCFG\_INTPARTID out of range | 未测试 | 暂不支持PARTID narrowing |
+| 7 | INTERNAL unexpected | 未测试 | 暂不支持PARTID narrowing |
+| 8 | MPAMCFG\_PART\_SEL.RIS unimplemented | 不可触发 | RIS>1时无法写入 |
+| 9 | MPAMCFG\_PART\_SEL.RIS no control | 不可触发 | RIS>1时无法写入 |
+| 10 | MSMON\_CFG\_MON\_SEL.RIS unimplemented | 不可触发 | RIS>1时无法写入 |
+| 11 | MSMON\_CFG\_MON\_SEL.RIS no monitor | 不可触发 | RIS>1时无法写入 |
+| 12:18 | Reserved |
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214.md"
new file mode 100644
index 0000000000000000000000000000000000000000..917ca23cdee68096e992a6be8ba697c009e4c010
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214.md"
@@ -0,0 +1,374 @@
+from arm-sig:
+
+
+# 一、引言
+
+
+MPAM(Memory System Resource Partitioning and Monitoring)是 ARM v8 引入的新特性,对标 x86 的 RDT 特性,可以实现对 Cache、内存带宽、SMMU 等资源的分配及监控功能。该特性可以从硬件层面减少不同工作负载之间的性能干扰,确保高优先级任务性能的稳定性,在虚拟化、混部等业务中取得了良好的效果。
+
+
+# 二、MPAM特性简介
+
+
+## 2.1 MPAM整体框架
+
+
+MPAM 特性的整体框架如图1所示。其中,MPAM 硬件上是通过 MSC(Memory System Component)实现的。MPAM 将提供资源管理功能组件称为 MSC,可以对资源请求进行处理。完整的系统模型中一般拥有多个 MSC,分别负责管理不同资源。MPAM 为资源访问请求添加了 PARTID 和 PMG 标识,MSC 可以对该标识进行区分处理,进而实现资源的隔离和监控功能。
+
+
+根据 MPAM 手册的介绍,除了基本的 Cache 和内存带宽资源隔离和监控外,MPAM 可以实现比 Intel RDT 更为丰富的资源隔离和监控特性,包括:
+
+
+* 提供对 SMMU 资源的支持
+* 提供对 Cache 和内存带宽资源进行最大最小值限制
+* 提供基于优先级的资源隔离支持
+
+
+
+
+
+MPAM 驱动作为核心部分,对下完成了 MPAM 硬件功能的访问和设置,包括 MPAM 资源的获取和初始化、MPAM 中断初始化以及对 MPAM 相关寄存器的读写,对上则与 resctrl fs 用户态接口层进行交互。
+
+
+resctrl fs 接口层以资源调配 group 为单位提供了资源隔离和监控的用户态接口,并通过 info 接口暴露 MPAM 硬件相关信息。此外,其底层还完成了 PARTID 和 PMG 的分配和回收。
+
+
+## 2.2 MPAM资源隔离特性
+
+
+MPAM 资源隔离特性的关键是由 MSC 组件维护的资源配置表。资源配置表中包含了不同 PARTID 和对应资源分配方案的映射。
+
+
+
+
+
+对于每一次资源请求,该资源对应的 MSC 会通过请求中的 PARTID 查找自身的配置表,然后按照表中与该 PARTID 相对应的方案进行资源分配。这样,通过将不同业务应用或VM与不同PARTID相绑定,就可以达到资源隔离的目的。
+
+
+通过图2左侧部分可以看到,不同资源分配方案的表示方法是有所区别的,这与资源的拆分方式不同有关。Cache 资源使用了 Bit Map,每一bit表示了对应的 Cache way 是否能够被分配;内存带宽资源则使用了百分比,表示该方案能够分配的内存带宽比例。
+
+
+## 2.3 MPAM资源监控特性
+
+
+资源监控可以看做是 MPAM 在支持资源隔离功能后的附加功能。MPAM 除了拥有资源隔离组件外,还拥有一定数目的资源 monitor。资源 monitor 可以实现对特定标识的资源使用情况的监控。
+
+
+为了实现对使用同一个 PARTID 的不同 task 分别进行资源监控,MPAM引入了PMG(Performance Monitoring Group)的概念。资源监控接口通过选取对应的 PARTID 和 PMG,即可获取到对应的资源使用情况。
+
+
+
+
+
+## 2.4 龙蜥 OS 对倚天 MPAM 特性的支持
+
+
+龙蜥 OS 5.10.134-12.al8 版本基于 resctrl 文件系统实现了对倚天芯片的 MPAM 特性的支持,同时保证了对 x86 RDT 特性和鲲鹏的 MPAM 特性的兼容。对应的代码仓库在 中。其中,MPAM 支持相关代码路径包括:
+
+
+* drivers/platform/mpam —— MPAM 驱动代码
+* drivers/acpi/arm64 —— MPAM ACPI 解析代码
+* fs/resctrl —— 用户态接口实现代码
+* arch/x86/kernel/cpu/resctrl —— x86 RDT 特性架构相关代码
+* drivers/staging/kunpeng/mpam —— 鲲鹏 MPAM 特性相关代码
+
+
+目前,龙蜥 OS 针对倚天芯片提供了 L3 Cache 和内存带宽两种资源的资源隔离和监控接口。接口的主要特性如下:
+
+
+* 提供最大 64 个 PARTID 支持
+* 提供 4 个 monitor 支持
+* 支持 per-numa 的 16 way L3 CAT(Cache Allocation Technology)特性
+* 支持 per-numa 的 16 way L3 CDP(Code and Data Prioritization)特性
+* 支持 per-numa 的 L3 Cache 资源监控特性
+* 支持 per-numa 的粒度为 5% 的 MBA(Memory Bandwidth Allocation)特性(受硬件限制,该特性目前效果较差)
+* 支持 per-numa 的内存带宽资源监控特性
+* 支持 MPAM 寄存器错误中断检测
+
+
+对应测试文档在。
+
+
+# 三、MPAM的使用
+
+
+## 3.1 开启MPAM
+
+
+1. 首先需要确保当前内核支持 MPAM 功能,需要设置`CONFIG_ARM64_MPAM`和`CONFIG_RESCTRL`;
+2. 在 cmdline 或 grub.cfg 文件中添加`mpam=acpi`,使能 MPAM 功能;
+3. 系统启动后,需要手动挂载 resctrl 文件系统到 /sys/fs/resctrl 目录。
+
+
+
+```
+mount -t resctrl resctrl /sys/fs/resctrl
+```
+
+## 3.2 MPAM 用户态接口
+
+
+MPAM 的用户态接口复用了 Intel RDT 功能的 resctrl 文件系统。resctrl 文件系统的目录结构如下图。
+
+
+
+
+
+### 3.2.1 资源调配 group
+
+
+开启 MPAM 功能后,操作系统中的每个进程(线程)都会与 resctrl 文件系统中的一个资源调配 group 相绑定。每个资源调配 group 在 MPAM 中对应着一个 PARTID。在 /sys/fs/resctrl 下新创建的每个目录将分别对应一个新的资源调配 group,每个资源调配 group 中会自动添加以下文件和目录:
+
+
+
+```
+|-- cpus
+|-- cpus_list
+|-- id
+|-- mode
+|-- mon_data
+|-- mon_groups
+|-- schemata
+|-- size
+`-- tasks
+```
+
+其中各文件和目录的作用为:
+
+
+**schemata**:表示该 group 对各个资源的分配方案,可读写。
+
+
+**mon\_data**:该目录中各个文件包含了对各个资源的监控值,只读。
+
+
+**cpus**:以 bitmask 的形式表示该 group 所控制的逻辑 CPU,可读写。
+
+
+**cpus\_list**: 与 cpus 含义一致,但以 range 的形式(如0-63)表示该 group 所控制的逻辑 CPU,可读写。
+
+
+**tasks**:表示该 group 所控制的 task pid,可读写。
+
+
+**id**:创建 group 时随机生成,用于唯一标识一个 group,只读。
+
+
+**mode**:表示当前 group 的分配方式,目前仅支持 shareable 方式。
+
+
+**mon\_groups**: 该目录用于创建仅用于监控功能的子 group,暂不可用。
+
+
+**size**:表示该 group 下各个资源所能使用的资源大小,只读。
+
+
+观察 /sys/fs/resctrl 目录可以发现,该目录自带了一个资源调配 group。这个 group 是作为 MPAM 开启后各 cpu 和 task 使用的默认 group 使用的。该 group 默认可以实现对各资源 100% 的占用。
+
+
+### 3.2.2 资源隔离与schemata文件
+
+
+使用资源隔离特性的关键是 schemata 文件,schemata 中包含了对该 group 的资源分配方案。其基本格式为如下:
+
+
+
+```
+MB:0= 100;1= 80
+L3:0=ffff;1=fff0
+```
+
+其中,
+
+
+* L3 cache 资源的分配以 bit mask 进行表示,`L3:0=ffff;1=fff0`表示所属该 group 的 cpu 和 task 可以分配到 NUMA 0 的 L3 cache 的完整 16 way,NUMA 1 的 L3 cache 的高 12 way。
+* 内存带宽资源的分配以百分比进行表示,`MB:0=100;1=80`表示所属该 group 的 cpu 和 task 可以分配到 NUMA 0 最多 100% 的内存带宽,NUMA 1 最多 80% 的内存带宽。
+
+
+### 3.2.3 资源监控与mon\_data目录
+
+
+mon\_data 目录下相关文件完成了 MPAM 的资源监控特性,倚天中 mon\_data 目录结构如下:
+
+
+
+```
+mon_data
+|-- mon_L3_00
+| `-- llc_occupancy
+|-- mon_L3_01
+| `-- llc_occupancy
+|-- mon_MB_00
+| `-- mbm_local_bytes
+`-- mon_MB_01
+ `-- mbm_local_bytes
+```
+
+其中,
+
+
+* L3 cache 资源监控对应着 mon\_L3\_ 目录,该目录下包含了对应 NUMA 节点下 L3 cache 资源的当前使用情况。目前该目录下只有 llc\_occupancy 一个文件,该文件以byte为单位显示了当前 group 各个 task 的 L3 cache 用量。
+* 内存带宽资源监控对应着 mon\_MB\_ 目录,该目录下包含了对应 NUMA 节点下内存带宽资源的当前使用情况。目前该目录下只有 mbm\_local\_bytes 一个文件,该文件以 byte/s 为单位显示了当前 group 各个 task 的内存带宽统计值。
+
+
+### 3.2.4 info目录
+
+
+/sys/fs/resctrl 目录下除了包含一个默认 group 所需要的相关文件和目录外,还有一个 info 目录。info 目录中包含了当前机器能够支持 MPAM 扩展中资源分配和监测功能的详细信息。目前倚天机器上该目录中有以下内容:
+
+
+
+```
+info/
+|-- L3
+| |-- bit_usage
+| |-- cbm_mask
+| |-- min_cbm_bits
+| |-- num_closids
+| `-- shareable_bits
+|-- L3_MON
+| |-- max_threshold_occupancy
+| |-- mon_features
+| `-- num_rmids
+|-- MB
+| |-- bandwidth_gran
+| |-- delay_linear
+| |-- min_bandwidth
+| `-- num_closids
+|-- MB_MON
+| |-- mon_features
+| `-- num_rmids
+`-- last_cmd_status
+```
+
+* L3 目录包含了 L3 cache 资源隔离特性的相关信息,其中各文件及其含义为
+
+
++ **bit\_usaged**:以 bitmask 的形式表示 L3 各 way 当前的使用情况,在倚天机器中,默认为`0=XXXXXXXXXXXXXXXX;1=XXXXXXXXXXXXXXXX`。
++ **cbm\_mask**:对应着 L3 cache 资源可以设置的最大 bitmask,同时该 mask 也对应着 100% 的 cache 资源占用。
++ **min\_cbm\_bit**:对 L3 cache 资源可以设置的最小 bit 数。
++ **num\_closids**:L3 cache 资源所能够创建的最大 group 数目,该值包含了 resctrl 文件系统挂载后自带的默认group。
++ **shareable\_bits**:以 bitmask 的形式表示 L3 cache 资源与其他实体(例如I/O)的共享情况。
+
+
+* L3\_MON 目录包含了 L3 cache 资源监控特性的相关信息,其中各文件及其含义为
+
+
++ **max\_threshold\_occupancy**:资源监控 monitor 被释放之后可能无法立即使用,因为之前的 cache 占用会影响 monitor 结果的准确性。max\_threshold\_occupancy 用于配置可以真正释放 monitor 的 cache占用。
++ **mon\_features**:显示 L3 cache 有哪些资源监控特性,与 mon\_data/mon\_L3\_xx 中文件相对应。
++ **num\_rmids**:可用的 monitor 数目,倚天机器该值为 4。
+
+
+* MB 目录包含了内存带宽资源隔离特性相关信息,其中各文件及其含义为:
+
+
++ **bandwidth\_gran**:内存带宽设置的百分比粒度,倚天机器该值为 5。
++ **delay\_linear**:与 Intel 机器中内存带宽资源隔离特性相关的值,倚天机器中默认为 true,即 1。
++ **min\_bandwidth**:内存带宽百分比设置的最小值,与 bandwidth\_gran 相等,倚天机器中该值为 5。
++ **num\_closids**:内存带宽资源所能够创建的最大 group,该数目包含了 resctrl 文件系统的默认 group。
+
+
+* MB\_MON 目录包含了内存带宽资源监控特性相关信息,其中各文件及其含义为:
+
+
++ **mon\_features**:显示内存带宽有哪些资源监控特性,与 mon\_data/mon\_MB\_xx 中文件相对应。
++ **num\_rmids**:可用的 monitor 数目,倚天机器该值为 4。
+
+
+* **last\_cmd\_status**:文件中包含了相关指令所出现的问题,可以通过读取该指令获取 resctrl 文件系统中相关操作失败的原因。
+
+
+## 3.3 MPAM 使用示例
+
+
+### 3.3.1 配置两个资源调配 group
+
+
+
+```
+mount -t resctrl resctrl /sys/fs/resctrl
+cd /sys/fs/resctrl
+# 创建两个资源调配group p0和p1
+mkdir p0 p1
+# 令p0使用Node0的高12路L3 Cache,Node1的低12路L3 Cache
+echo "L3:0=0xfff0;1=0x0fff" > /sys/fs/resctrl/p0/schemata
+# 令p1使用Node0的低12路L3 Cache,Node1的高12路L3 Cache
+echo "L3:0=0x0fff;1=0xfff0" > /sys/fs/resctrl/p1/schemata
+# 限制p0和p1的MB上限不超过50%
+echo "MB:0=50;1=50" > /sys/fs/resctrl/p0/schemata
+echo "MB:0=50;1=50" > /sys/fs/resctrl/p1/schemata
+# 读取两个文件
+cat /sys/fs/resctrl/p0/schemata
+cat /sys/fs/resctrl/p1/schemata
+```
+
+此时 /sys/fs/resctrl/p0/schemata 和 /sys/fs/resctrl/p1/schemata 两个文件中的内容分别为:
+
+
+
+```
+MB:0=50;1=50
+L3:0=fff0;1=0fff
+```
+
+
+```
+MB:0=50;1=50
+L3:0=0fff;1=fff0
+```
+
+### 3.3.2 为指定进程/线程分配资源调配 group
+
+
+以 3.3.1 中已创建的 p0 资源调配 group 为例,此处限制 pid 为 12345 的进程/线程使用 p0 资源调配 group 所限定的资源。需要注意的是,新创建的子进程将继承父进程的 PARTID 和 PMG 信息,但已创建的子进程将不受影响。
+
+
+
+```
+# 将pid 12345加入p0资源调配group
+echo 12345 > /sys/fs/resctrl/p0/tasks
+```
+
+之后,pid 为 12345 的进程/线程将自动从 /sys/fs/resctrl/tasks 移动到 /sys/fs/resctrl/p0/tasks 文件中。
+
+
+### 3.3.3 为指定cpu分配资源调配 group
+
+
+
+```
+# 将cpu 99、100、101移入p1资源调配group
+echo "99-101" > /sys/fs/resctrl/p1/cpus_list
+# 或者
+echo "38,00000000,00000000,00000000" > /sys/fs/resctrl/p1/cpus_list
+```
+
+之后,cpu 99-101 将从 /sys/fs/resctrl/cpus\_list 中移动到 /sys/fs/resctrl/p1/cpus\_list 中。
+
+
+### 3.3.4 读取 cache/内存带宽 的 monitor 值
+
+
+仍然以 3.3.1 中创建的 p0 资源调配group为例,要获取 p0 资源组各进程的资源占用值,通过 cat 即可得到实时监控结果。
+
+
+
+```
+cat /sys/fs/resctrl/p0/mon_data/mon_L3_0*/llc_occupancy
+cat /sys/fs/resctrl/p0/mon_data/mon_MB_0*/mbm_local_bytes
+```
+
+## 3.4 模拟混部L3 cache隔离
+
+
+混部是 MPAM 资源隔离的一个重要应用场景。此处分别以 SPECjbb 2015 和 stress-ng 程序分别模拟云环境上广泛使用的 java 类在线作业上和离线作业,对 MPAM 的 L3 cache 隔离功能进行验证。
+
+
+在前 40s 的时间内,两个程序共享L3 cache所有资源。在约 40s 后,开始隔离在线和离线L3 cache资源的使用,在离线任务 L3 cache 的配比分别为 0xffff 和 0xf。
+
+
+
+
+
+通过实验结果可以看到,在 L3 cache 资源共享的情况下,离线资源对在线资源干扰明显,L3 cache 竞争激烈,波动幅度很大;在对 L3 cache 资源进行隔离后,一方面离线得到了持续有效的压制,L3 cache 占有率大幅下降,另一方面在线性能提升明显,平均 L3 cache 占用提升了约 78%,且波动幅度变小,L3 cache 占用更加稳定。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247.md"
new file mode 100644
index 0000000000000000000000000000000000000000..897bbc104b8fc169729a65eabe73dc3a1a04b1d3
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247.md"
@@ -0,0 +1,223 @@
+
+文/龙蜥社区内核开发人员 陈善佩、吴一昊、邓二伟
+
+# Plugsched 是什么
+Plugsched 是 Linux 内核调度器子系统热升级的 SDK, **它可以实现在不重启系统、应用的情况下动态替换调度器子系统,毫秒级 downtime** 。Plugsched 可以对生产环境中的内核调度特性动态地进行增、删、改,以满足不同场景或应用的需求,且支持回滚。
+
+基于 plugsched 实现的调度器热升级,不修改现有内核代码,就能获得较好的可修改能力,天然支持线上的老内核版本。如果提前在内核调度器代码的关键数据结构中加入 Reserve 字段,可以额外获得修改数据结构的能力,进一步提升可修改能力。
+
+Plugsched 开源链接:https://gitee.com/anolis/plugsched
+
+
+
+# Plugsched 可以解决什么问题
+那么 Plugsched 诞生的背景或者想要解决的问题是什么?我们认为有以下 4 点:
+
+* **应用场景不同,最佳调度策略不同:** 应用种类极大丰富,应用特征也是千变万化 (throughput-oriented workloads, us-scale latency critical workloads, soft real-time, and energy efficiency requirements),使得调度策略的优化比较复杂,不存在“一劳永逸”的策略。因此,允许用户定制调度器满足不同的场景是必要的。
+* **调度器迭代慢:** Linux 内核经过很多年的更新迭代,代码变得越来越繁重。调度器是内核最核心的子系统之一,它的结构复杂,与其它子系统紧密耦合,这使得开发和调试变得越发困难。此外,Linux 很少增加新的调度类,尤其是不太可能接受非通用或场景针对型的调度器,上游社区在调度领域发展缓慢。
+* **内核升级困难:** 调度器内嵌 (built-in)在内核中,上线调度器的优化或新特性需要升级内核版本。内核发布周期通常是数月之久,这将导致新的调度器无法及时应用在生产系统中。再者,要在集群范围升级新内核,涉及业务迁移和停机升级,对业务方来说代价昂贵。
+* **无法升级子系统。** kpatch 和 livepatch 是函数粒度的热升级方案,可修改能力较弱,不能实现复杂的逻辑改动; eBPF 技术在内核网络中广泛应用,但现在调度器还不支持 ebpf hook,将来即使支持,也只是实现局部策略的灵活修改,可修改能力同样较弱。
+
+Plugsched 能将调度器子系统从内核中提取出来,以模块的形式对内核调度器进行热升级。通过对调度器模块的修改,能够针对不同业务定制化调度器,而且使用模块能够更敏捷的开发新特性和优化点,并且可以在不中断业务的情况下上线。
+
+
+图1 plugsched:业务不中断
+
+
+
+**使用 plugsched 具有以下 6 大优势:**
+* **与内核发布解耦:** 调度器版本与内核版本解耦,不同业务可以使用不同调度策略;建立持续运维能力,加速调度问题修复、策略优化落地;提升调度领域创新空间,加快调度器技术演进和迭代;
+* **可修改能力强:** 可以实现复杂的调度特性和优化策略,能人之所不能;
+* **维护简单:** 不修改内核代码,或少量修改内核代码,保持内核主线干净整洁;在内核代码 Tree 外独立维护非通用调度策略,采用 RPM 的形式发布和上线;
+* **简单易用:** 容器化的 SDK 开发环境,一键生成 RPM,开发测试简洁高效;
+* **向下兼容:** 支持老内核版本,使得存量业务也能及时享受新技术红利;
+* **高效的性能:** 毫秒级 downtime,可忽略的 overhead。
+
+
+
+# Plugsched 应用案例
+Plugsched 相比 kpatch 和 livepatch 可修改能力更强,热升级范围更广,plugsched 是子系统范围的热升级,而后者是函数级别的热升级。**对于 plugsched 而言,无论是 bugfix,还是性能优化,甚至是特性的增、删、改,都可胜任**。鉴于 plugsched 较强的可修改能力,它可应用到以下场景:
+
+* **快速开发、验证、上线新特性,稳定后放入内核主线;**
+* **针对不同业务场景做定制优化,以 RPM 包的形式发布和维护非通用调度器特性;**
+* **统一管理调度器热补丁,避免多个热补丁之间的冲突而引发故障。**
+
+
+
+**应用案例1:新增 Group Identity 调度特性**
+Group Identity 是阿里云用于混部场景的调度特性,它基于 CFS 调度器增加了一颗存储低优先级任务的红黑树,而且会对每一个 cgroup 分配一个默认优先级,用户也可自行配置其优先级,当队列中存在高优先级任务时,低优先级任务会停止运行。我们利用 plugsched 对 anck 4.19 的一个老版本内核(没有该调度特性)进行调度器热升级,并将 Group Identity 调度特性移植到生成的调度器模块中,涉及 7 个文件,2500+ 行的修改量。
+
+安装该调度器模块后,在系统中创建两个 cpu cgroup A 和 B,并绑定同一个 CPU,分别设置最高和最低优先级,然后各自创建一个 busy loop 任务。理论上,当 A 中有任务执行时,B 中的任务会停止运行。此时用 top 工具查看该 CPU 利用率,发现只有一个利用率是 100% 的 busy loop 任务,说明模块中的 Group Identity 特性已生效;而动态卸载该模块后,出现了两个各占 50% CPU 的 busy loop 任务,说明模块已经失效。
+
+
+
+**应用案例2:与内核发布解耦及定制化调度器**
+阿里云某客户使用的旧版本内核,由于该内核调度器对 load 的统计算法不合理,导致 CPU 利用率过高,虽然修复补丁已经合入内核主线,但是新内核版本还未发布,而且业务方也不打算更换内核,因为集群中部署了大量的业务,升级内核成本较高。
+
+除此之外,客户的内核开发人员对其混部业务场景(Group Identity 调度特性)进行了针对性的优化,想将优化内容合入内核主线。但是,阿里云内核开发人员发现,该优化内容在其它场景中有性能回退,属于非通用优化,因此不允许将优化内容合入主线。
+
+于是,客户的内核开发人员使用 plugsched 将优化修复内容全部移植到调度器模块中,最后规模部署。该案例可以体现出 plugsched 的与内核发布解耦、定制化调度器的优势。
+
+
+
+# 如何使用 Plugsched
+目前,plugsched 默认支持 Anolis OS 7.9 ANCK 系统发行版,其它系统需要[调整边界配置](./docs/Support-various-Linux-distros.md)。为了减轻搭建运行环境的复杂度,我们提供了的容器镜像和 Dockerfile,开发人员不需要自己去搭建开发环境。为了方便演示,这里购买了一台阿里云 ECS(64CPU + 128GB),并安装 Anolis OS 7.9 ANCK 系统发行版,我们将会对内核调度器进行热升级。
+
+1. 登陆云服务器后,先安装一些必要的基础软件包:
+```shell
+# yum install anolis-repos -y
+# yum install podman kernel-debuginfo-$(uname -r) kernel-devel-$(uname -r) --enablerepo=Plus-debuginfo --enablerepo=Plus -y
+```
+
+2. 创建临时工作目录,下载系统内核的 SRPM 包:
+```shell
+# mkdir /tmp/work
+# uname -r
+4.19.91-25.2.an7.x86_64
+# cd /tmp/work
+# wget https://mirrors.openanolis.cn/anolis/7.9/Plus/source/Packages/kernel-4.19.91-25.2.an7.src.rpm
+```
+
+3. 启动并进入容器:
+```shell
+# podman run -itd --name=plugsched -v /tmp/work:/tmp/work -v /usr/src/kernels:/usr/src/kernels -v /usr/lib/debug/lib/modules:/usr/lib/debug/lib/modules docker.io/plugsched/plugsched-sdk
+# podman exec -it plugsched bash
+# cd /tmp/work
+```
+
+4. 提取 4.19.91-25.1.al7.x86_64 内核源码:
+```shell
+# plugsched-cli extract_src kernel-4.19.91-25.2.an7.src.rpm ./kernel
+```
+
+5. 进行边界划分与提取:
+```shell
+# plugsched-cli init 4.19.91-25.2.an7.x86_64 ./kernel ./scheduler
+```
+
+6. 提取后的调度器模块代码在 ./scheduler/kernel/sched/mod 中, 新增一个 sched\_feature 并打包生成 rpm 包:
+```diff
+diff --git a/scheduler/kernel/sched/mod/core.c b/scheduler/kernel/sched/mod/core.c
+index 9f16b72..21262fd 100644
+--- a/scheduler/kernel/sched/mod/core.c
++++ b/scheduler/kernel/sched/mod/core.c
+@@ -3234,6 +3234,9 @@ static void __sched notrace __schedule(bool preempt)
+ struct rq *rq;
+ int cpu;
+
++ if (sched_feat(PLUGSCHED_TEST))
++ printk_once("I am the new scheduler: __schedule\n");
++
+ cpu = smp_processor_id();
+ rq = cpu_rq(cpu);
+ prev = rq->curr;
+diff --git a/scheduler/kernel/sched/mod/features.h b/scheduler/kernel/sched/mod/features.h
+index 4c40fac..8d1eafd 100644
+--- a/scheduler/kernel/sched/mod/features.h
++++ b/scheduler/kernel/sched/mod/features.h
+@@ -1,4 +1,6 @@
+ /* SPDX-License-Identifier: GPL-2.0 */
++SCHED_FEAT(PLUGSCHED_TEST, false)
++
+ /*
+ * Only give sleepers 50% of their service deficit. This allows
+ * them to run sooner, but does not allow tons of sleepers to
+```
+```shell
+# plugsched-cli build /tmp/work/scheduler
+```
+
+7. 将生成的 rpm 包拷贝到宿主机,退出容器,查看当前 sched\_features:
+```text
+# cp /usr/local/lib/plugsched/rpmbuild/RPMS/x86_64/scheduler-xxx-4.19.91-25.2.an7.yyy.x86_64.rpm /tmp/work
+# exit
+exit
+# cat /sys/kernel/debug/sched_features
+GENTLE_FAIR_SLEEPERS START_DEBIT NO_NEXT_BUDDY LAST_BUDDY CACHE_HOT_BUDDY WAKEUP_PREEMPTION NO_HRTICK NO_DOUBLE_TICK NONTASK_CAPACITY TTWU_QUEUE NO_SIS_AVG_CPU SIS_PROP NO_WARN_DOUBLE_CLOCK RT_PUSH_IPI RT_RUNTIME_SHARE NO_LB_MIN ATTACH_AGE_LOAD WA_IDLE WA_WEIGHT WA_BIAS NO_WA_STATIC_WEIGHT UTIL_EST ID_IDLE_AVG ID_RESCUE_EXPELLEE NO_ID_EXPELLEE_NEVER_HOT NO_ID_LOOSE_EXPEL ID_LAST_HIGHCLASS_STAY
+```
+
+8. 安装调度器包,且新增了一个 PLUGSCHED\_TEST sched\_feature(关闭状态):
+```text
+# rpm -ivh /tmp/work/scheduler-xxx-4.19.91-25.2.an7.yyy.x86_64.rpm
+# lsmod | grep scheduler
+scheduler 503808 1
+# dmesg | tail -n 10
+[ 2186.213916] cni-podman0: port 1(vethfe1a04fa) entered forwarding state
+[ 6092.916180] Hi, scheduler mod is installing!
+[ 6092.923037] scheduler: total initialization time is 6855921 ns
+[ 6092.923038] scheduler module is loading
+[ 6092.924136] scheduler load: current cpu number is 64
+[ 6092.924137] scheduler load: current thread number is 667
+[ 6092.924138] scheduler load: stop machine time is 249471 ns
+[ 6092.924138] scheduler load: stop handler time is 160616 ns
+[ 6092.924138] scheduler load: stack check time is 85916 ns
+[ 6092.924139] scheduler load: all the time is 1097321 ns
+# cat /sys/kernel/debug/sched_features
+NO_PLUGSCHED_TEST GENTLE_FAIR_SLEEPERS START_DEBIT NO_NEXT_BUDDY LAST_BUDDY CACHE_HOT_BUDDY WAKEUP_PREEMPTION NO_HRTICK NO_DOUBLE_TICK NONTASK_CAPACITY TTWU_QUEUE NO_SIS_AVG_CPU SIS_PROP NO_WARN_DOUBLE_CLOCK RT_PUSH_IPI RT_RUNTIME_SHARE NO_LB_MIN ATTACH_AGE_LOAD WA_IDLE WA_WEIGHT WA_BIAS NO_WA_STATIC_WEIGHT UTIL_EST ID_IDLE_AVG ID_RESCUE_EXPELLEE NO_ID_EXPELLEE_NEVER_HOT NO_ID_LOOSE_EXPEL ID_LAST_HIGHCLASS_STAY
+```
+
+9. 打开新的 sched\_feature,“I am the new scheduler: \_\_schedule” 信息出现在 dmesg 日志中:
+```text
+# echo PLUGSCHED_TEST > /sys/kernel/debug/sched_features
+# dmesg | tail -n 5
+[ 6092.924138] scheduler load: stop machine time is 249471 ns
+[ 6092.924138] scheduler load: stop handler time is 160616 ns
+[ 6092.924138] scheduler load: stack check time is 85916 ns
+[ 6092.924139] scheduler load: all the time is 1097321 ns
+[ 6512.539300] I am the new scheduler: __schedule
+```
+
+10. 卸载调度器包后,新的 sched\_feature 被删除:
+```text
+# rpm -e scheduler-xxx
+# dmesg | tail -n 8
+[ 6717.794923] scheduler module is unloading
+[ 6717.809110] scheduler unload: current cpu number is 64
+[ 6717.809111] scheduler unload: current thread number is 670
+[ 6717.809112] scheduler unload: stop machine time is 321757 ns
+[ 6717.809112] scheduler unload: stop handler time is 142844 ns
+[ 6717.809113] scheduler unload: stack check time is 74938 ns
+[ 6717.809113] scheduler unload: all the time is 14185493 ns
+[ 6717.810189] Bye, scheduler mod has be removed!
+#
+# cat /sys/kernel/debug/sched_features
+GENTLE_FAIR_SLEEPERS START_DEBIT NO_NEXT_BUDDY LAST_BUDDY CACHE_HOT_BUDDY WAKEUP_PREEMPTION NO_HRTICK NO_DOUBLE_TICK NONTASK_CAPACITY TTWU_QUEUE NO_SIS_AVG_CPU SIS_PROP NO_WARN_DOUBLE_CLOCK RT_PUSH_IPI RT_RUNTIME_SHARE NO_LB_MIN ATTACH_AGE_LOAD WA_IDLE WA_WEIGHT WA_BIAS NO_WA_STATIC_WEIGHT UTIL_EST ID_IDLE_AVG ID_RESCUE_EXPELLEE NO_ID_EXPELLEE_NEVER_HOT NO_ID_LOOSE_EXPEL ID_LAST_HIGHCLASS_STAY
+```
+**注意:不可以用“rmmod”命令直接卸载调度器模块,应使用“rpm 或 yum”标准命令卸载调度器包。**
+
+
+
+# Plugsched 实现原理
+**我们通过以上知道了 Plugsched 是什么、应用案例,那它实现原理是什么?**
+
+调度器子系统在内核中并非是一个独立的模块,而是内嵌在内核中,与内核其它部分紧密相连。
+
+**Plugsched 采用“模块化”的思想**:它提供了边界划分程序,确定调度器子系统的边界,把调度器从内核代码中提取到独立的目录中,开发人员可对提取出的调度器代码进行修改,然后编译成新的调度器内核模块,动态替换内核中旧的调度器。对子系统进行边界划分和代码提取,需要处理函数和数据,而后生成一个独立的模块。
+
+**对于函数而言**,调度器模块对外呈现了一些关键的函数,以这些函数为入口就可以进入模块中,我们称之为接口函数。通过替换内核中的这些接口函数,内核就可以绕过原有的执行逻辑进入新的调度器模块中执行,即可完成函数的升级。模块中的函数,除了接口函数外,还有内部函数,其它的则是外部函数。
+
+**对于数据**,调度器模块默认使用并继承内核中原有的数据,对于调度器重要的数据,比如运行队列状态等,可以通过状态重建技术自动重新初始化,这类数据属于私有数据,而其它则是共享数据。为了灵活性,plugsched 允许用户手动设置私有数据,手动设置的私有数据会在模块中保留定义,但需要对它们进行初始化。对于结构体而言,plugsched 将只被调度器访问的结构体成员分类为内部成员,其它为非内部成员。调度器模块允许修改内部成员的语义,禁止修改非内部成员的语义。如果结构体所有成员都是内部成员,则调度器模块允许修改整个结构体。但是,建议优先使用结构体中的保留字段,而不是修改现有成员。
+
+
+
+# Plugsched 设计方案
+Plugsched 主要包含两大部分,第一部分是调度器模块边界划分与代码提取部分,第二部分是调度器模块热升级部分,这两部分是整个方案的核心。其整体设计方案如下:
+
+
+图2 plugsched 整体架构
+
+
+
+首先进行的是调度器模块边界划分和代码提取流程,由于调度器本身并不是模块,因此需要明确调度器的边界才能将它模块化。边界划分程序会根据边界配置信息(主要包含代码文件、接口函数等信息)从内核源代码中将调度器模块的代码提取到指定目录,然后开发人员可在此基础上进行调度器模块的开发,最后编译生成调度器 RPM 包,并可安装在对应内核版本的系统中。安装后会替换掉内核中原有的调度器,安装过程会经历以下几个关键过程:
+
+* **符号重定位**:解析模块对部分内核符号的访问;
+* **栈安全检查**:类似于 kpatch,函数替换前必须进行栈安全检查,否则会出现宕机的风险。plugsched 对栈安全检查进行了并行和二分优化,提升了栈安全检查的效率,降低了停机时间;
+* **接口函数替换**:用模块中的接口函数动态替换内核中的函数;
+* **调度器状态重建**:采用通用方案自动同步新旧调度器的状态,极大的简化数据状态的一致性维护工作。
+
+
+
+# 总结
+Plugsched 使得调度器从内核中解放出来,开发人员可以对调度器进行专项定制,而不局限于内核通用调度器;内核维护也变得更加轻松,因为开发人员只需要关注通用调度器的开发与迭代,定制化调度器可通过 RPM 包的形式进行发布;内核调度器代码也会变得简洁,无需再被各个场景的优化混淆起来。
+
+未来,plugsched 会支持新版本内核和其它平台,持续对其易用性进行优化,并提供更多的应用案例。最后,欢迎更多的开发者能参与到 plugsched 中。
\ No newline at end of file
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\350\265\204\346\272\220\351\232\224\347\246\273FAQ.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\350\265\204\346\272\220\351\232\224\347\246\273FAQ.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215.md"
new file mode 100644
index 0000000000000000000000000000000000000000..4a59a0791832bc2a7e212ecbf4b6161897a7c7b1
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215.md"
@@ -0,0 +1,169 @@
+
+# 背景介绍
+
+
+ 2014年,阿里开始了第一次探索混部,经过七年磨练,这把资源利用率大幅提升的利剑正式开始商用。通过从计算资源、内存资源、存储资源、网络资源等全链路的隔离以及毫秒级的自适应调度能力,阿里可以在双十一的流量下进行全时混部,通过智能化的决策与运维能力,支撑着内部百万级的Pod混部,不管是CPU与GPU资源,普通容器与安全容器,包括国产化环境各种异构基础设施,都能实现高效混部,这让阿里核心电商业务生产集群成本下降了50%以上,同时核心业务受到的干扰小于5%。在商用化对外线下输出的版本里面,我们将完全基于云原生社区标准,以插件化的方式无缝的安装在k8s集群为输出形态交付客户。其中核心的OS层隔离能力,已经发布到支持多架构的开源、中立、开放的Linux操作系统发行版-龙蜥(Anolis OS)中。
+
+
+# 混部和资源隔离之间的关系:**资源隔离是混部的基石**
+
+
+混部就是将不同类型的业务在同一台机器上混合部署起来,让它们共享机器上的CPU、内存、IO等资源,目的就是最大限度地提高资源利用率,从而降低采购和运营等成本。混部通常是将不同优先级的任务混合在一起,例如高优先的实时任务(对时延敏感,资源消耗低;称为在线)和低优先级批处理任务(对时延不敏感,资源消耗高;称为离线),当高优先级业务需要资源时,低优先级任务需要立即归还,并且低优先级任务的运行不能对高优先级任务造成明显干扰。
+
+
+为了满足混部的需求,在单机维度的内核资源隔离技术是最为关键的一项技术,龙蜥云内核在资源隔离的技术上深耕多年,并且在行业中处于领先地位,这些内核资源隔离技术主要涉及内核中的调度、内存和IO这三大子系统,并且在各个子系统领域根据云原生的混部场景进行了深入的改造和优化,关键优化包括但不限于:cpu group identity技术,SMT expeller技术,基于cgroup的内存异步回收技术等。其中cpu group identity已经申请对应的专利,有独立的知识产权。这些关键的技术使客户有能力在云原生混部场景中根据业务特点给出最优解决方案,可有效提高用户的资源使用率并最终降低用户资源的使用成本,非常适用于容器云混部场景,同时也是大规模化混合部署方案所强依赖的关键技术。
+
+
+下图是资源隔离能力在整个混部方案中的位置:
+
+
+# 为什么需要资源隔离:**资源隔离会遇到哪些拦路虎**
+
+
+假设我们现在有一台服务器,上面运行了高优的在线业务,以及离线任务也在上面运行运行。在线任务对响应时间 (Response Time, RT) 的需求是很明确的,要求尽可能低的RT,故被称之为延迟敏感型(Latency-Sensitive, LS) 负载;离线任务永远是有多少资源吃多少资源的,故此类负载被称之为 Best Effort (BE),如果我们对在线和离线任务不加干涉,那么离线任务很有可能会频繁、长期占用各种资源,从而让在线任务没有机会调度,或者调度不及时,或者获取不到带宽等等,从而出现在线业务RT急剧升高的情况。所以在这种场景下我们一定需要必要的手段来对在线和离线容器进行资源使用上的隔离,来确保在线高优容器在使用资源时可以及时的获取,最终能够在提升整体资源使用率的情况下保障高优容器的QoS。
+
+
+我们这边通过一个例子,说明一下在线和离线混着跑的时候,可能出现的情况:
+
+
+* 首先最有可能发生在离线竞争的,可能是CPU,因为CPU调度是核心,在线和离线任务可能分别会调度到一个核上,相互抢执行时间;
+* 当然任务也可能会分别跑到相互对应的一对HT上,相互竞争指令发射带宽和其他流水线资源;
+* 接下来CPU的各级缓存必然是会被消耗掉的,而缓存资源是有限的,所以这里涉及到了缓存资源划分的问题;
+* 再接下来,假设我们已经完美解决了各级缓存的资源划分,后面还是有问题。首先是内存是CPU缓存的下一级,内存本身也类似,会发生争抢,对于在线和离线任务分别来说都是需要像CPU缓存一样进行资源划分的;
+* 另外当CPU最后一级缓存(Last Level Cache, LLC)没有命中的时候,内存的带宽(我们称之为运行时容量,以有别于内存大小划分这种静态容量)会变高,所以内存和CPU缓存之间的资源消耗,是相互影响的;
+* 然后我们假设CPU和内存资源都没问题,对于本机来说现在隔离已经做得很好了,但是在线高优的业务和离线任务的运行过程中都是和网络有密切的关系,那么很容易理解,网络也可能是需要隔离的;
+* 最后,线上部分机型对IO的使用可能会发生抢占,我们需要有效的IO隔离策略。
+
+
+以上就是一个很简单的资源隔离流程的思路,可以看到每一环都有可能会出现干扰或者竞争。
+
+
+# 隔离技术方案介绍:**独有的隔离技术方案,各显神通**
+
+
+内核资源隔离技术主要涉及内核中的调度、内存和 IO 这三大子系统,这些技术基于 Linux CGroup V1 提供资源的基本隔离划分以及 QoS 保障,适用于容器云场景,同时也是大规模化混合部署方案所强依赖的关键技 术。
+
+
+除了基本的 CPU、内存和 IO 资源隔离技术外,龙蜥内核还实现有资源隔离视图、资源监控指标 SLI (ServiceLevelIndicator) 以及资源竞争分析工具等,提供一整套集监控、告警、运维、诊断等整套的资源隔 离和混部解决方案,如下图所示
+
+
+
+
+
+## 弹性容器场景的调度器优化
+
+
+如何保证计算服务质量的同时尽可能提高计算资源利用率,是容器调度的经典问题。随着 CPU 利用率不断 提升,CPU 带宽控制器暴露出弹性不足的问题日趋严重,面对容器的短时间 CPU 突发需求,带宽控制器需要对容器的 CPU 使用进行限流,避免影响负载延迟和吞吐。
+
+
+Anolis OS 中的 CPU Burst 技术是一种弹性容器带宽控制技术,在满足平均 CPU 使用率低于一定限制的条件下,CPU Burst 允许短时间的 CPU 突发使用,实现服务质量提升和容器负载加速。
+
+
+在容器场景中使用 CPU Burst 之后,测试容器的服务质量显著提升,如下图所示,在实测中可以发现使用该特性技术以后,RT长尾问题几乎消失。
+
+
+
+
+
+## Group Identity 技术
+
+
+为了满足业务方在cpu资源隔离上的需求,在满足cpu资源利用最大化的情况下,保证高优业务的服务质量不受影响,或将影响范围控制在一定范围,此时内核调度器需要赋予高优先级的任务更多的调度机会来最小化其调度延迟,并把低优先级任务对其带来的影响降到最低,这是行业中通用的需求。
+
+
+为了满足以上需求,我们引入了Group Identity的概念,即每个cpu cgroup会有一个身份识别,以CPU CGroup组为单位实现调度特殊优先级,提升高优先级组的及时抢占能力确保了高优先级任务的性能,适用于在线和离线混跑的业务场景。当在离线混部时,可以最大程度降低由于离线业务引入的在线业务调度不及时的问题,增加高优先业务的cpu抢占时机等底层等核心技术保障在线业务在cpu调度延迟上不受离线业务的影响。
+
+
+## SMT expeller
+
+
+在某些线上业务场景中,使用超线程的情况下的 QPS 比未使用超线程时下降明显,并且相应 RT 也增加了 不少。根本原因跟超线程的物理性质有关,超线程技术在一个物理核上模拟两个逻辑核,两个逻辑核具有各自独立的寄存器(eax、ebx、ecx、msr等等)和APIC,但会共享使用物理核的执行资源,包括执行引擎、L1/L2缓存、TLB和系统总线等等。这就意味着,如果一对HT的一个核上跑了在线任务,与此同时它对应的HT核上跑了一个离线任务,那么它们之间是会发生竞争的。这就是我们需要解决的问题。
+
+
+为了尽可能减轻这种竞争的影响,我们想要让一个核上的在线任务执行的时候,它对应的HT上不再运行离线任务;或者当一个核上有离线任务运行的时候,而在线任务调度到了其对应的HT上时,离线任务会被驱赶走。听起来离线混得很惨对不对,但是这就是我们保证HT资源不被争抢的机制。
+
+
+SMT expeller 特性是基于 Group Identity 框架进一步实现了超线程(HT)隔离调度,保障高优先级业务不会受到来自 HT 的低优先级任务干扰。通过 Group Identity 框架进一步实现的超线程调度隔离,可以很好的保障高优先级业务不会受到来自对应HT上的低优先级任务的干扰。
+
+
+## 处理器硬件资源管理技术
+
+
+龙蜥内核支持 Intel®Resource Director Technology(Intel®RDT),它是一种处理器支持的硬件资源 管理技术。包括监控 Cache 资源的 Cache Monitoring Technology (CMT) ,监控内存带宽的 Memory Bandwidth Monitoring (MBM),负责 Cache 资源分配的 Cache Allocation Technology(CAT) 和监 控内存带宽的 Memory Bandwidth Allocation(MBA)。
+
+
+其中,CAT 使得 LLC(Last Level Cache)变成了一种支持 QualityofService(QoS) 的资源。在 混部环境里面,如果没有 LLC 的隔离,离线应用不停的读写数据导致大量的 LLC 占用,会导致在线的 LLC 被 不断污染,影响数据访问甚至硬件中断延迟升高、性能下降。
+
+
+MBA 用于内存带宽分配。对于内存带宽敏感的业务来说,内存带宽比 LLC 控制更能影响性能和时延。在 混部环境里面,离线通常是资源消耗型的,特别是一些 AI 类型的作业对内存带宽资源的消耗非常大,内存占用 带宽一旦达到瓶颈,可能使得在线业务的性能和时延成倍的下降,并表现出 CPU 水位上升。龙蜥内核目前已经 全面支持多种处理器的资源隔离功能。
+
+
+## Memcg 后台回收
+
+
+在原生的内核系统中,当容器的内存使用量达到他的使用上限时,此时再申请使用内存时,在当前的进程上下文中就会进行直接内存回收的动作,这无疑会影响当前进程的执行效率,引起性能问题。那我们是否有方法当容器的内存达到一定水线的时候让其提前进行内存的异步回收,这样就有比较大的概率避免容器内的进程在申请使用内存时由于内存使用达到上限而进入直接内存回收。
+
+
+我们知道在内核中有一个kswapd的后台内核线程,用来当系统的内存使用量达到一定水位以后来进行异步的内存回收,但是这里有一种情况,比如当前高优的业务容器的内存使用已经达到一个比较高的情况,但是宿主机的总体的空闲内存还有很多,这样内核的kswapd的线程就不会被唤醒进行内存回收,这样这些内存使用压力大的高优容器的内存就没有机会被回收,所以这是个比较大的矛盾,由于目前原生内核中是没有memory cgroup级别的内存异步回收机制,也就是说容器的内存回收严重依赖宿主机层面的kswapd的回收或者只能依靠自己的同步回收,这会严重的影响一些高优容器的业务由于内存回收不及时引入的性能问题。
+
+
+基于以上背景,anolis os提供了一个类似宿主机层面的kswapd的基于memcg的异步回收策略,用于按照用户需求提前进行容器级别的内存回收机制,做到提前内存释压。
+
+
+具体的异步回收过程可以通过下面这幅图进行描述:
+
+
+
+
+
+## Memcg 全局水位线分级
+
+
+通常资源消耗型的离线任务可能会时常瞬间申请大量的内存,使得系统的空闲内存触及全局min水线,引发系统所有任务进入直接内存回收的慢速流程,时延敏感型的在线业务很容易发生性能抖动。此场景下,无论是全局kswapd后台回收还是memcg级别的后台回收机制,都是无能为力的。
+
+
+我们基于"内存消耗型的离线任务通常对时延不敏感"这样一个事实,设计了"memcg的全局min水线分级功能"来解决上述抖动难题。在标准upstream全局共享min水线的基础上,将离线任务的全局min水线上移让其提前进入直接内存回收,同时将时延敏感的在线任务的全局min水线下移,在一定程度上实现了离线任务和在线任务的min水线隔离。这样当离线任务瞬间大量内存申请的时候,会将离线任务抑制在其上移的min水线,避免了在线任务发生直接内存回收,随后当全局kswapd回收一定量的内存后,离线任务的短时间抑制得以解除。
+
+
+我们的核心思想就是通过为在离线容器设置不同标准的全局水位线来控制在离线容器申请内存的动作,这样能让离线容器的任务在申请内存时先与在线业务进入直接内存回收,用于解决离线容器瞬间申请大量内存引发的问题。
+
+
+对linux内存管理有一定基础的同学也可以查阅下面这幅图,他详细的记录了在离线容器混部过程中在多种水位线的作用下的一个走势图:
+
+
+
+
+
+## memcg OOM 优先级
+
+
+在真实的业务场景中,特别是内存超卖环境,当发生global OOM的时候,有理由去选择杀掉那些优先级比较低的离线业务,而保护高优先级在线业务;当发生离线memcg OOM的时候,有理由去选择杀掉那些优先级比较低的作业,而保高优先级离线作业。这其实是云原生场景中一个比较通用的需求,但是目前的标准Linux内核并不具备这个能力,在选择杀进程的时候,内核会有一个算法去选择victim,但通常是找一个oom score最大的进程杀,这个被杀的进程有可能是在线高优业务进程,这并不是我们想看到的。
+
+
+基于以上原因,anolis os提供了一个memcg OOM优先级的特性,通过该特性我们可以保障在系统由于内存紧张而发生OOM时通过选择低优的业务进程进行kill,从而避免高优业务进程被杀的可能,可以大幅降低由于在线业务进程退出而给客户业务带来的影响。
+
+
+## CGroupV1 Writeback 限流
+
+
+block IO cgroup自合入内核之后,一直存在一个问题:只能对direct IO进行限流(buffer IO之后短期内执行fsync也可以限流),因为这些IO到达block throttle层时,当前进程就是真正发起IO的进程,根据进程可以获取到相应的cgroup从而正确记账,如果超过了用户设置的带宽/IOPS上限,则进行限制。对于那些buffer写,且最终由kworker线程下发的IO,block throttle层无法通过当前进程获取IO所属的cgroup,也就无法对这些IO进行限流。
+
+
+基于以上背景,目前在Cgroup V2版本中已经支持异步IO限流,但是在Cgroup V1中并不支持,由于目前在云原生环境下主要还是使用Cgroup V1版本,阿里云内核团队通过建立page<->memcg<->blkcg这三者的关系实现了在Cgroup V1中对IO异步限流的功能,限流的主要算法基本上和Cgroup V2保持一致。
+
+
+## blk-iocost 权重控制
+
+
+正常情况下,为了避免一个IO饥饿型作业轻易耗尽整个系统IO资源,我们会设置每个cgroup的IO带宽上限,其最大缺点是即使设备空闲,配置上限的cgroup在其已发送IO超过上限时不能继续发送IO,引起存储资源浪费。
+
+
+基于以上需求,出现了一种IO控制器-IOCOST,该控制器是基于blkcg的权重来分配磁盘的资源,可以做到在满足业务IO QOS的前提下,尽最大程度利用磁盘的IO资源,一旦出现磁盘IO能力达到上限导致触及QOS设置的目标时,此时iocost控制器会通过权重来控制各个group的io使用,在此基础上,blk-iocost又拥有一定的自适应能力,尽可能的避免磁盘能力被浪费。
+
+
+# 展望与期待
+
+
+在阿里云的线下输出产品族内,我们会把混部的能力通过ACK Anywhere产品家族,以及CNStack(CloudNative Stack)产品家族,进行输出。整体解决方案结合OpenAnolis龙蜥操作系统内核,网络Qos技术等,输出给我们的客户。
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213.md" "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213.md"
new file mode 100644
index 0000000000000000000000000000000000000000..8201098190c9a669dfdaa88a21d9bfdce11fd70f
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213.md"
@@ -0,0 +1,1080 @@
+
+# 背景
+
+
+为了给用户提供一份完整的alibaba cloud linux资源隔离使用指导说明手册,本文将从用户的角度出发,提供OS各个子系统中关于资源隔离详细的使用说明,并会详细描述各个隔离手段的使用背景,让用户更好的了解各个资源隔离手段在哪些场景使用,使用限制是什么。
+
+
+让用户最终能够简单的使用alibaba cloud linux资源隔离是本文的目的。
+
+
+# 目标人群
+
+
+本文的使用人员需要具备一定的关于cgroup的基础知识,对linux操作系统有初步的了解。本文适合那些想快速使用alibaba cloud kernel的人员,也适合想简单了解alibaba cloud kernel资源隔离能力的人员。
+
+
+# 背景知识
+
+
+如果你对linux的cgroup的使用有所了解,本段内容可以跳过,如果你对cgroup从未了解过,建议阅读下本背景知识,并在自己的测试机器上进行演练来加深了解。
+
+
+我们所有的资源隔离手段几乎都是基于linux的cgroup进行实现和优化,Linux Cgroups 的全称是 Linux Control Group。它最主要的作用,就是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等。而我们平时使用的容器,他的底层技术就是cgroup技术。
+
+
+在 Linux 中,Cgroups 给用户暴露出来的操作接口是文件系统,即它以文件和目录的方式组织在操作系统的 /sys/fs/cgroup 路径下,我们可以用 mount 指令把它们展示出来,这条命令是:
+
+
+
+```
+[root@AliYun ~]# mount -t cgroup
+cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
+cgroup on /sys/fs/cgroup/rdma type cgroup (rw,nosuid,nodev,noexec,relatime,rdma)
+cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
+cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
+cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
+cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
+cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
+cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio)
+cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
+cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
+cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
+cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
+```
+
+可以看到,在 /sys/fs/cgroup 下面有很多诸如 cpuset、cpu、 memory 这样的子目录,也叫子系统。这些都是我这台机器当前可以被 Cgroups 进行限制的资源种类。而在子系统对应的资源种类下,你就可以看到该类资源具体可以被限制的方法。比如,对 CPU 子系统来说,我们就可以看到如下几个配置文件,这些配置文件就是我们这边所谓的对外配置接口,可以通过手动的方式进行资源使用的配置:
+
+
+
+```
+[root@AliYun cpu]# ls
+assist cpuacct.usage_all cpu.cfs_period_us
+cgroup.clone_children cpuacct.usage_percpu cpu.cfs_quota_us
+cgroup.procs cpuacct.usage_percpu_sys cpu.identity
+cgroup.sane_behavior cpuacct.usage_percpu_user cpu.shares
+cpuacct.block_latency cpuacct.usage_sys cpu.stat
+cpuacct.cgroup_wait_latency cpuacct.usage_user notify_on_release
+cpuacct.ioblock_latency cpuacct.wait_latency release_agent
+cpuacct.proc_stat cpu.bvt_warp_ns tasks
+cpuacct.stat cpu.cfs_burst_us
+cpuacct.usage cpu.cfs_init_buffer_us
+```
+
+我们这边就以容器的cpu规格的配置进行举例,这里主要涉及cfs\_period 和 cfs\_quota 两个关键词。这两个参数需要组合使用,可以用来限制进程在长度为 cfs\_period 的一段时间内,只能被分配到总量为 cfs\_quota 的 CPU 时间。
+
+
+而这样的配置文件又如何使用呢?
+
+
+你需要在对应的子系统下面创建一个目录,比如,我们现在进入 /sys/fs/cgroup/cpu 目录下:
+
+
+
+```
+[root@AliYun cpu]# mkdir test
+[root@AliYun cpu]# cd test
+[root@AliYun test]# ls
+cgroup.clone_children cpuacct.usage_percpu cpu.cfs_period_us
+cgroup.procs cpuacct.usage_percpu_sys cpu.cfs_quota_us
+cpuacct.block_latency cpuacct.usage_percpu_user cpu.identity
+cpuacct.cgroup_wait_latency cpuacct.usage_sys cpu.shares
+cpuacct.ioblock_latency cpuacct.usage_user cpu.stat
+cpuacct.proc_stat cpuacct.wait_latency notify_on_release
+cpuacct.stat cpu.bvt_warp_ns tasks
+cpuacct.usage cpu.cfs_burst_us
+cpuacct.usage_all cpu.cfs_init_buffer_us
+```
+
+这个目录就称为一个“控制组”。你会发现,操作系统会在你新创建的 test 目录下,自动生成该子系统对应的资源限制文件。
+
+
+现在,我们在后台执行这样一条脚本:
+
+
+
+```
+[root@AliYun test]# while : ; do : ; done &
+[1] 24227
+```
+
+显然,它执行了一个死循环,可以把计算机的 CPU 吃到 100%,根据它的输出,我们可以看到这个脚本在后台运行的进程号(PID)是 24227。
+
+
+这样,我们可以用 top 指令来确认一下 CPU已经被打满:
+
+
+
+
+
+而此时,我们可以通过查看 test 目录下的文件,看到 test 控制组里的 CPU quota 还没有任何限制(即:-1),CPU period 则是默认的 100 ms(100000 us):
+
+
+
+```
+[root@AliYun test]# cat cpu.cfs_quota_us
+-1
+[root@AliYun test]# cat cpu.cfs_period_us
+100000
+```
+
+接下来,我们可以通过修改这些文件的内容来设置限制。比如,向 test 组里的 cfs\_quota 文件写入 20 ms(20000 us):
+
+
+
+```
+[root@AliYun test]# echo 20000 > cpu.cfs_quota_us
+[root@AliYun test]# cat cpu.cfs_quota_us
+20000
+```
+
+结合前面的介绍,你应该能明白这个操作的含义,它意味着在每 100 ms 的时间里,被该控制组限制的进程只能使用 20 ms 的 CPU 时间,也就是说这个进程只能使用到 20% 的 CPU 带宽。
+
+
+接下来,我们把被限制的进程的 PID 写入 test 组里的 tasks 文件,上面的设置就会对该进程生效了:
+
+
+
+```
+[root@AliYun test]# echo 24227 > tasks
+```
+
+
+
+
+可以看到,计算机的 CPU 使用率立刻降到了 20%.
+
+
+除 CPU 子系统外,Cgroups 的每一个子系统都有其独有的资源限制能力,比如:
+
+
++ blkio,为块设备设定I/O 限制,一般用于磁盘等设备;
++ cpuset,为进程分配单独的 CPU 核和对应的内存节点;
++ memory,为进程设定内存使用的限制。
+
+
+Linux Cgroups 的设计还是比较易用的,简单粗暴地理解呢,它就是一个子系统目录加上一组资源限制文件的组合。而对于 Docker 等 Linux 容器项目来说,它们只需要在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录),然后在启动容器进程之后,把这个进程的 PID 填写到对应控制组的 tasks 文件中就可以了。
+
+
+# 特别提醒
+
+
+Alinux内核完全兼容对应的centos的原生内核,所以这意味着所有centos内核中自带的资源隔离方法在Alinux中都有,阿里云在各个资源维度有针对云原生场景下的各种需要进行资源隔离的场景做了额外的优化,这部分的优化内容并不能方向从centos中找到,属于阿里云的核心资源隔离能力,详细使用细节可以参见各个资源的指导手册。
+
+
+# 内存资源隔离使用指导
+
+
+
+
+
+* 频繁的全局kswapd可能造成在线容器的page cache被频繁回收,造成IO颠簸,影响性能。对应的解决办法详见本文对应的章节:memcg 内存被回收保护水线
+* 目前混部环境中,经常会发生离线在短时间内分配超过20GB的内存,突破主机的min水线,影响宿主机上的所有容器。主要表现为:宿主机load抖动,业务延迟增加等问题。对应的解决办法详见本文对应的章节:memcg 全局最低水位线
+* 当在线容器的内存使用达到上限,再申请使用内存时当前的进程上下文中就会进行直接内存回收的动作,这无疑会影响当前进程的执行效率,引起性能问题。对应的解决办法详见本文对应的章节:容器内存异步回收
+* 当global OOM发生时,在选择那个task被杀的时候,最理想状态是去选择低优的离线容器的进程进行kill。这样能最大程度的保障在线容器的QoS。对应的解决办法详见本文对应的章节:memcg OOM 优先级
+* 我们在反复重建容器或者删除容器以后,由于cgroup中一些引用信息没有清理干净,可能会产生类似僵尸进程一样的僵尸(zombie)memcg。大量的zombie memcgs数目堆积,会产生各种并发症,曾经引发多起严重的线上故障,例如memory.stat访问慢,内存回收遍历大量memcg,长尾调度时延等。对应的解决办法详见本文对应的章节:回收 zombie memcgs
+* 当我们想提高low和high水线去控制全局kswapd回收行为的时候,就必须采用一个很大的min水线,这样就会造成很大的内存浪费(因为min水线以下的内存平时用不到)。而low-min之间的差值(即1/4 min)太小,就会很容易触及min水线,进入内存同步回收流程,造成重要业务的RT毛刺,表现为整机load高(由于D状态增多)。对应的解决办法详见本文对应的章节:整机内存水线优化
+
+
+## 容器内存异步回收
+
+
+### 需求来源
+
+
+在原生的内核系统中,当容器的内存使用量达到他的使用上限时,此时再申请使用内存时,在当前的进程上下文中就会进行直接内存回收的动作,这无疑会影响当前进程的执行效率,引起性能问题。那我们是否有方法当容器的内存达到一定水线的时候让其提前进行内存的异步回收,这样就有比较大的概率避免容器内的进程在申请使用内存时由于内存使用达到上限而进入直接内存回收。
+
+
+我们知道在内核中有一个kswapd的后台内核线程,用来当系统的内存使用量达到一定水位以后来进行异步的内存回收,但是这里有一种情况,比如当前高优的业务容器的内存使用已经达到一个比较高的情况,但是宿主机的总体的空闲内存还有很多,这样内核的kswapd的线程就不会被唤醒进行内存回收,这样这些内存使用压力大的高优容器的内存就没有机会被回收,所以这是个比较大的矛盾,由于目前原生内核中是没有memory cgroup级别的内存异步回收机制,也就是说容器的内存回收严重依赖宿主机层面的kswapd的回收或者只能依靠自己的同步回收,这会严重的影响一些高优容器的业务由于内存回收不及时引入的性能问题。
+
+
+基于以上背景,操作系统团队开发了一个类似宿主机层面的kswapd的基于memcg的异步回收策略,用于按照用户需求提前进行容器级别的内存回收机制,做到提前内存释压。
+
+
+### 功能简介
+
+
+这里我们将介绍基于容器的异步内存回收的过程,这里有两个关键的水位线,如下图所示,memory.limit\_in\_bytes是容器的内存规格,即容器最大能使用的内存量,这不是我们本次的主角。跟容器内存异步回收相关的有两个指标:memory.wmark\_high和memory.wmark\_low。其中high水位线用来指示何时开启容器的内存异步回收线程,换句话说当容器的内存使用量达到high水位线时内核会自动唤醒对应的kworker线程用于针对该容器的内存异步回收。那回收到什么程度会结束此次的异步回收呢,答案是当回收线程回收到memory.wmark\_low水位线时,此时回收线程就会停止回收。
+
+
+
+
+
+具体的异步回收过程可以通过下面这幅图进行描述:
+
+
+
+
+
+### 使用说明
+
+
+
+
+| | |
+| --- | --- |
+| 接口 | 简介 |
+| memory.wmark\_ratio | 该接口用于设置是否启用memcg后台异步回收功能,以及设置异步回收功能开始工作的memcg内存水位线。单位是相对于memcg limit的百分之几。取值范围:0~100* 默认值为0,该值也表示禁用memcg后台异步回收功能。
+* 取值为非0时,表示开启memcg后台异步回收功能并设置对应的水位线。
+ |
+| memory.wmark\_high | 只读接口,说明如下:* 当memcg内存使用超过该接口的值时,后台异步回收功能启动。
+* 该接口的值由**(memory.limit\_in\_bytes \* memory.wmark\_ratio / 100)**计算获得。
+* memcg后台异步回收功能被禁用时,memory.wmark\_high默认为一个极大值,从而达到永不触发后台异步回收功能的目的。
+* memcg根组目录下不存在该接口文件。
+ |
+| memory.wmark\_low | 只读接口,说明如下:* 当memcg内存使用低于该接口的值时,后台异步回收结束。
+* 该接口的值由**memory.wmark\_high - memory.limit\_in\_bytes \* memory.wmark\_scale\_factor / 10000**计算得出。
+* memcg根组目录下不存在该接口文件。
+ |
+
+
+### 注意事项
+
+
+请注意,这里并不是内存回收的越多越好,比如一下章节将要讲到的,page cache有助于提高业务进程的性能,如果我们把memory.wmark\_high和memory.wmark\_low的水位设置的过低,这样可能会因为page cache被回收的太多而引起业务进程性能抖动的问题。
+
+
+建议配置值:90%以上,经验值可以配置为95%
+
+
+memory.wmark\_scale\_factor和memory.wmark\_ratio继承规则:创建时,继承父组的值。
+
+
+需求实现:Alinux2及以上版本。
+
+
+## memcg 内存被回收保护水线
+
+
+### 需求来源
+
+
+我们先从一个简单的案例说起,总所周知,page cache可以提升我们的业务应用的性能,减少IO的直接操作,加速文件的读写速度,page cache它处于内核层,并且由内核直接管理分配,并在系统内存紧张的时候会开始回收page cache释放内存。我们刚有提到page cache可以提升业务的性能,如果当业务对应的page cache被回收以后,下次再次访问对应的业务数据时可能就会引起性能抖动问题,所以当内核开始回收的时候我们该高优回收哪些业务容器的page cache,是否需要为某些容器保留部分的page cache不被回收,这样能保证这些容器的服务质量,其实这也是我们业务的需求,我们如何保障高优业务的服务质量,比如当在离线业务容器混部的时候,如何保障page cache在回收的时候先回收离线容器的,如何保障为高优业务容器保留对应的page cache,使其能有较大概率再次访问到cache数据。所以操作系统团队基于此背景从cgroup v2中backport了关于memcg qos相关特性代码,memcg qos就是用来告知系统在回收page cache的时候如何做到按需回收。
+
+
+### 功能简介
+
+
+正常情况下,当出现系统内存紧张的时候,内核会在每个memcg中(业务容器使用的内存)回收内存,默认情况下内核是不区分对待各个容器的内存的,都是按照正常流程进行回收,高优容器的内存和离线容器的内存有同样的概率被回收掉,为了使内核在回收内存时能区分对待:高优的容器少回收内存或者说允许其保留一部分的内存不被回收,尽可能的去回收低优和离线容器的内存。这里我们引入了memcg qos的三个接口用来控制这个动作:
+
+
+
+
+| | |
+| --- | --- |
+| 接口 | 简介 |
+| memory.high | 当 memory cgroup 内进程的内存使用量超过了该值后就会立即触发memcg reclaim进行直接的内存回收。 |
+| memory.low | 当容器内进程的内存使用量在这个水线以下时,内核会 Best-effort memory protection,也就是说在内核进行内存回收的时候就会先去回收不属于该 memory cgroup 的 Page Cache,等到其他容器的 Page Cache 被回收掉后如果回收的内存还不够,再来回收这些 Page Cache。 |
+| memory.min | 当容器内进程的内存使用量低于该值时,在系统进行内存回收的时候即使其他容器内的 Page Cache 都被回收完了也不会去回收这些 Page Cache,你可以理解为这个水线下的内存是禁止被回收的。 |
+
+
+
+
+
+我们这边通过下面这幅图来举例说明这个过程:
+
+
+
+
+
+我们假设整个系统只有3个业务容器,每个业务容器按照容器的高优程度,分别去设置cgroup下的min、low、high三个值,比如设置的值为上图所示,高优的容器的memory.min和low的水线设置的比其他两个容器的高,而将离线容器的min和low水线直接设置为0。这样当系统的内存紧张的时候发起内存回收时,内核会按照正常逻辑去回收那些内存使用量达到灰色部分的容器,即那些内存使用超过memory.low水线的容器,然后才会去回收那些内存使用量达到绿色部分的容器,然后那些内存使用量只有红色部分的容器是不会进行内存回收。这样我们就做到了先回收离线容器的内存(他的min和low的水线值为0),高优容器由于设置了min和low的水位线,如果内存使用量没有超过对应的水线,这部分内存是最后被回收或禁止回收,这就是我们想要的效果,也即"需求来源"的章节中描述的期望达成的状态。
+
+
+### 使用说明
+
+
+这边只需要按需配置memory.high、memory.low、memory.min三个值就行。其中memory.high这个只需要使用默认的值就行。
+
+
+如果是离线容器,或者说是非常低优的容器,我们这边可以直接将min和low这两个水线设置为0,如果是高优的业务容器,这边建议将min的值设置为15%\*memory.limit\_in\_bytes,low的值设置为30%\*memory.limit\_in\_bytes。
+
+
+### 注意事项
+
+
+1. memory.min的值不建议设置的太高,如果设置的太高,并且host上有很多类似的高优容器,这样内核在进行内存回收的时候,可能会因为太多禁止被回收的内存而导致回收不到足够的内存而间接的引发OOM.
+2. 如果有内存超卖场景,并且超卖的内存比较多,并且高优的容器在host会部署的比较多,我们此时将高优容器的memory.min值尽量设置的偏小一点,因为这部分内存在整机内存回收的时候是不允许被回收的,如果超卖严重,并且host上过多的高优容器,导致最终很多内存都无法被回收,这样会引起OOM。
+3. 继承规则:默认值为0,不继承。
+4. 需求实现:Alinux2及以上版本。
+
+
+## memcg 全局最低水位线
+
+
+### 需求背景
+
+
+通常资源消耗型的离线任务可能会时常瞬间申请大量的内存,使得系统的空闲内存触及全局min水线,引发系统所有任务进入直接内存回收的慢速流程,时延敏感型的在线业务很容易发生性能抖动。此场景下,无论是全局kswapd后台回收还是memcg级别的后台回收机制,都是无能为力的。
+
+
+我们基于"内存消耗型的离线任务通常对时延不敏感"这样一个事实,设计了"memcg的全局min水线分级功能"来解决上述抖动难题。在标准upstream全局共享min水线的基础上,将离线任务的全局min水线上移让其提前进入直接内存回收,同时将时延敏感的在线任务的全局min水线下移,在一定程度上实现了离线任务和在线任务的min水线隔离。这样当离线任务瞬间大量内存申请的时候,会将离线任务抑制在其上移的min水线,避免了在线任务发生直接内存回收,随后当全局kswapd回收一定量的内存后,离线任务的短时间抑制得以解除。
+
+
+### 功能简介
+
+
+我们的核心思想就是通过为在离线容器设置不同标准的全局水位线来控制在离线容器申请内存的动作,这样能让离线容器的任务在申请内存时先与在线业务进入直接内存回收,用于解决离线容器瞬间申请大量内存引发的问题,如下图所示,在A的情况下,由于系统剩余的内存比较充裕,远大于BE wmark min的水位线,这种情况下,不管是在线还是离线容器的进程都不会进入内存直接回收的路径,属于快速内存分配的蜜月期,此时在离线容器的任务都能快速申请到内存。在B中情况下,此时可以假设由于离线容器瞬间申请了大量内存,导致系统的可用内存下降到了BE wmark min的水线,接下去离线任务继续申请和使用内存时就会进入direct reclaim路径并且被限速,但是此时在线容器的进程还是可以快速的申请到内存,这样就保障了我们在线容器业务的服务质量。如果此时系统内存继续下降,到了C情况,此时系统内存下降到了LS wmark min的水线,这个时候在线容器的进程才会进入direct reclaim进行直接内存回收,此时在线容器的服务质量才会受到影响。很明显,这种多标准的水位线可以为我们解决"需求背景"中描述的问题,防止离线容器由于瞬间申请大量内存而把系统内存耗尽而影响在线业务。
+
+
+
+
+
+
+
+
+对linux内存管理有一定基础的同学也可以查阅下面这幅图,他详细的记录了在离线容器混部过程中在多种水位线的作用下的一个走势图:
+
+
+
+
+
+### 使用说明
+
+
+这里主要通过配置memory.wmark\_min\_adj这个接口来控制容器的全局水位线。
+
+
+该接口的含义为基于全局min水线所作出的调整(adj意思是adjustment)百分比,范围为[-25, 50],默认值为0。root group不存在该文件。具体地,正值代表了调整范围[0, WMARK\_MIN],负值代表了调整范围[WMARK\_MIN, WMARK\_LOW];其中WMARK\_MIN和WMARK\_LOW分别代表了全局min水线和low水线的值)。
+
+
+例如:
+
+
+
+```
+-25 means memcg WMARK_MIN is "WMARK_MIN + (WMARK_MIN - 0) * (-25%)"
+ 50 means memcg WMARK_MIN is "WMARK_MIN + (WMARK_LOW - WMARK_MIN) * 50%"
+```
+
+负值代表min水线下移,代表的是对内存QoS要求高的memcg组(例如在线业务)。
+
+
+正值代表min水线上移,代表的是对内存QoS要求低的memcg组(例如离线业务),当其上移的min水线被触及后,会做throttle操作,throttle的时间与所消耗的低于其min水线之下的内存总量成线性比例关系,throttle的时间取值范围为[1ms, 1000ms]。
+
+
+### 注意事项
+
+
+负值代表min水线下移,代表的是对内存QoS要求高的memcg组(例如在线业务)
+
+
+正值代表min水线上移,代表的是对内存QoS要求低的memcg组(例如离线业务)
+
+
+memory.wmark\_min\_adj继承规则:创建时,继承父组的值。
+
+
+需求实现:Alinux2及以上版本。
+
+
+## 整机内存水线优化
+
+
+### 需求来源
+
+
+全局分配和回收采用的三个内存水线:min, low, high。大体上,当空闲内存低于low时会触发全局kswapd异步回收内存,当空闲内存大于high水位时停止回收。当空闲内存低于min时会触发direct reclaim。之前的内核采用” /proc/sys/vm/min\_free\_kbytes”(建议配置为系统总内存的1.5%左右)来控制这3个水位,计算公式如下:
+
+
+low = min + 1/4 min
+
+
+high = low + 1/4 min
+
+
+上述只是简单地使用一个固定的比例划分这3个水线,这样会有一个严重的问题,当我们想提高low和high水线去控制全局kswapd回收行为的时候,就必须采用一个很大的min水线,这样就会造成很大的内存浪费(因为min水线以下的内存平时用不到)。而low-min之间的差值(即1/4 min)太小,就会很容易触及min水线,进入内存同步回收流程,造成重要业务的RT毛刺,表现为整机load高(由于D状态增多)。
+
+
+整机内存水线优化就是可以保证一个相对较小的min水线就可以得到一个大的low和high水线值,经测试在混部环境中的效果非常好,具体优如下:
+
+
+引入一个额外的配置” /proc/sys/vm/watermark\_scale\_factor”(建议配置值300),表示采用整机总内存大小的一个比例值来放大low-min以及low-high之间的水线差,为异步kswapd赢得宝贵的时间,这样在空闲内存触及min水线之前,全局kswapd可以有相对较多的时间去做异步回收。
+
+
+### 功能简介
+
+
+通过如下图所示,在通过watermark\_scale\_factor来增加min和low之间的gap以后,当内存的水线下降到low以后,内核会提前进入kswapd进行后台内存回收,这样可以在内存下降到min之前为kswapd争取到足够的时间进行内存异步回收,降低系统进入direct reclaim的概率。
+
+
+
+
+
+### 使用说明
+
+
+通过按需配置/proc/sys/vm/watermark\_scale\_factor即可,使用比较简单。
+
+
+### 注意事项
+
+
+该配置是针对host的,并不是针对个别容器,也就是说在容器创建的时候无需配置该接口,如有需要可以在整机维度进行配置。
+
+
+需求实现:Alinux2及以上版本。
+
+
+## memcg OOM 优先级
+
+
+### 需求来源
+
+
+OOM分为两种: memcg OOM和global OOM。无论哪种OOM,在选择杀进程的时候,内核会有一个算法去选择victim,但通常是找一个oom score最大的进程杀。在真实的业务场景中,特别是内存超卖环境,当发生global OOM的时候,有理由去选择杀掉那些优先级比较低的离线业务,而保护高优先级在线业务;当发生离线memcg OOM的时候,有理由去选择杀掉那些优先级比较低的作业,而保高优先级离线作业。这就是"memcg OOM优先级"所解决的场景,目前的标准Linux内核并不具备这个能力。
+
+
+### 功能简介
+
+
+本组设置memory.use\_priority\_oom后,当本组发生OOM时,就会对其下的所有子组进行OOM优先级遍历。memory.oom.group被设置时,会杀掉其下(包括其子组)的所有可杀任务(设置-1000的oom\_score\_adj不会被杀)。
+
+
+例如,如下层级结构,使能了memory.use\_priority\_oom
+ root
+
+
+ / \
+
+
+ A B
+
+
+ / \ / \
+
+
+ C D E F
+
+
+
+
+
+ memory.priority:
+
+
+ A: 10, B: 8
+
+
+ C: 5, D: 6, E: 7, F: 8
+
+
+
+
+
+当发生global OOM时,从根组(root)开始按每个层级数据最小的原则遍历路径root->B->E,最终E被选出来作为被杀对象。
+
+
+### 使用说明
+
+
+
+
+| | |
+| --- | --- |
+| 接口 | 简介 |
+| memory.use\_priority\_oom | 功能开关,默认为0表示不使能本功能;写1表示使能本功能。
+设置/sys/fs/cgroup/memory/memory.use\_priority\_oom会使能global OOM按优先级进行查杀。 |
+| memory.priority | 设定memcg的OOM优先级,默认值为0, 允许的范围[0, 12],数值越大,优先级越高。优先级的生效范围为同级memcg之间。当发生OOM时,会顺着memcg的层次自上而下选择一个优先级数值最低的组杀,相同优先级的组则按照先后顺序。 |
+| memory.oom.group | 通常,一个作业组是一个整体,其中的某个进程被杀会影响全局的业务工作,因此最好是按组杀。此接口可以实现按整个memcg组进行整体杀的功能。默认值为0,表示禁用整组杀;写1开启整组杀。 |
+
+
+### 注意事项
+
+
+memory.use\_priority\_oom、memory.priority、memory.oom.group继承规则:不继承,默认值0。
+
+
+使用过程中主要风险来自存量的memcg和新创建的memcg由于优先级不匹配,可能出现误杀的情况。所以如果存在容器漂移或者容器新建的场景,需要评估当前已有容器的OOM 优先级以及新容器优先级。
+
+
+需求实现:Alinux2及以上版本。
+
+
+## 回收 zombie memcgs
+
+
+### 需求来源
+
+
+当删除cgroup的目录后虽然用户态已经看不到它,但在内核中代表cgroup的结构体会一直存在直到所有对它的引用被释放。只要它依然存在,就会消耗相应的资源。只有当被删除的memory cgroup中的页都被回收掉,相应的引用都被释放,该memory cgroup才会彻底被删除,这可能会需要很长的时间,如果当中的一些页被活跃的使用,这些页可能永远不会被回收掉。另外,还有其他各种各样的问题,同样会导致删除的cgroup继续留在系统中。僵尸cgroup虽然不会导致严重的后果,但依然是个问题。每个僵尸cgroup都会占用200KB的内存,随着僵尸cgroup的增加相应的内存消耗也会增加。同时这些僵尸cgroup会增加遍历cgroup树的开销。曾经引发多起严重的线上故障,例如memory.stat访问慢,内存回收遍历大量memcg,长尾调度时延等。
+
+
+为了解决zombie memcgs数目并发症,Ali4000已经默认关闭了kmem,同时提供异步、同步接口用以清理残留的离线 memcg,这就是我们引入了memcg后台定制回收功能"zombie memcgs reaper"的原因。
+
+
+### 使用说明
+
+
+具体的memcg接口在/sys/kernel/mm/memcg\_reaper/中:reap, reap\_background, scan\_interval, pages\_scan, verbose
+
+
+
+
+| | |
+| --- | --- |
+| 接口 | 简介 |
+| reap | "One-shot trigger"模式,只回收一次,类似于/proc/sys/vm/drop\_caches接口,由用户主动单次触发。
+写1表示启动一次回收尝试,但并不保证回收完,需要用户自行决策是否进行多次写。 |
+| reap\_background | "Background kthread reaper"模式,会在后台自动进行周期性回收,永久运行。推荐使用此模式。
+默认值为0,表示禁用此功能。设置1开启。 |
+| scan\_interval | "Background kthread reaper"模式下,用于控制周期性回收的间隔,默认为5秒。 |
+| pages\_scan | "Background kthread reaper"模式下,用于控制每个周期内回收的页面数,默认值为1310720(5GiB for 4KiB page)。scan\_interval和pages\_scan用于防止回收过猛,导致的IO压力。 |
+| verbose | 调试开关,默认为0,表示关闭; 写1表示开启一些debug打印。 |
+
+
+### 注意事项
+
+
+* 这个特性的前提是内核不开启memcg kmem的特性。可以通过修改cmdline的参数进行关闭该特性。
+* 可能会有一定的sys cpu损耗。
+* 别把回收周期和回收页面数设置的太激进,可能会导致io压力。
+
+
+# cpu资源隔离使用指导
+
+
+这里主要介绍:弹性cpu带宽控制技术,group identity,SMT expeller技术,llc技术。由于cpu share和cpuset为通用的内核资源隔离技术,这里不做使用说明介绍,有兴趣的同学可以参考网上相关资料。
+
+
+
+
+
+## CPU Burst-弹性CPU带宽控制技术
+
+
+### 需求来源
+
+
+我们的服务宗旨是让客户花最少的钱获得最好的服务质量,或者让单个容器在保证业务服务质量的同时尽量提高容器的cpu使用率,让用户在有限的资源下运行更多的任务,等于降低了用户的使用成本,但是在现实的场景中,在业务的视角可能会出现容器的cpu平均使用率并不高,但是业务的容器却时不时的会出现短时间内的throttle现象,由于容器被限流最终导致业务延迟等问题。比如如下图所示:
+
+
+
+
+
+从图中可以看到在一个4核cpu规格的容器上,从一秒的时间周期去看容器的cpu使用率只有百分之60左右,远没有达到容器的使用规格,在业务方看来,他们买的4核规格的cpu服务,实际并没有真正使用4核,但是你们却把我限流了,这是不合理的,为了解决这个问题,目前业务的同学常用的只有如下两个选择:
+
+
+* 提高容器的cpu规格,比如此处将cpu的规格提高到5核(设置cpu.cfs\_quota\_us为500000),但是这样势必会让业务方花费更多的金钱来购买cpu的资源,增加了业务方的使用成本,并不是最理想的方案。
+* 在保持容器规格不变的情况下,同比例提高period和quota的值,使周期内的quota变大,但是由于周期也同比例变大,这样可能会引入新的问题,一旦出现限流(throttle),需要等待下次被unthrottle的周期(period)变长,导致业务出现更大的延迟,很明显这也不是一个最好的办法。
+
+
+
+
+
+很明显以上两个解决方案都不是很好的改善业务同学的感受,关于业务同学的困扰我们能够理解,但是我们换一个视角去看这个问题,从100毫秒的时间跨度去看,在这100毫秒周期内,由于业务的突发处理,导致短时间内的cpu被打爆,超出容器规格,导致被限流,这从底层的技术人员的角度去看又是合理的。
+
+
+所以我们的需求就来自以上这些矛盾点,在保证业务容器不因突发的业务处理(burst)而被throttle,又能尽量提高容器的cpu使用率,让业务方感觉到“物超所值”。
+
+
+### 功能简介
+
+
+本feature的核心思想就是在本周期内没有用完的时间可以把这部分没用的runtime放到下一周期,这样有助于降低由于burst业务的突发运行带来的throttle的风险。
+
+
+这边通过场景演示来说明一下这个原理:
+
+
+
+
+
+### 使用说明
+
+
+* 如果要使用此功能,首先要确保以下配置是否打开,默认是打开状态。
+
+
+
+```
+[root@AliYun assist]# cat /proc/sys/kernel/sched_cfs_bw_burst_enabled
+1
+```
+
+* 需要在对应的group目录配置cpu.cfs\_burst\_us,这个值的意思是在period周期内最大允许burst的时间,默认情况下为0,即不开启此功能,此值的配置范围为[0, quota]。
+* 我们还可以通过查看cpu.stat的状态接口来查看当前group有没有出现过burst,如下打印信息中nr\_burst即为出现burst的总次数,burst\_time即为总共burst的时间,这里最好配合nr\_throttled(总的throttle次数)和throttled\_time(总的throttle的时间)。因为burst不一定会引发throttle,这也是我们想要达到的预期效果,如果有throttle的次数增加,可能是我们的cpu.cfs\_burst\_us值配置的不够大。如果burst\_time一直在累加,但是throttle并没有在累加,这说明我们的功能起到了很好的作用。
+
+
+
+```
+[root@AliYun assist]# cat cpu.stat
+nr_periods 114816
+nr_throttled 9
+throttled_time 512420200
+current_bw 5000000
+nr_burst 0
+burst_time 0
+```
+
+### 注意事项
+
+
+* 当负载的平均CPU使用低于limit时不产生限流,满足细粒度的突发需求。但是不能在CPU资源不足的情况下使CPU更快运行。他解决的是burst的需求,并不是无中生有。
+* 我们可以通过cpu.stat的接口来获取本特性的收益值,可以观察burst\_time的值的大小,即是burst的总时间,原本这些时间是业务容器的throttle的时间。
+* burst值配置的越大,能带来的风险也越大,换句话说可能短时间内容器使用的cpu更多,可能会对其他容器产生cpu竞争压力。
+
+
+## Group Identity
+
+
+### 需求来源
+
+
+为了满足业务方在资源隔离上的需求,在满足资源利用最大化的情况下,保证高优业务的服务质量不受影响,或将影响范围控制在一定范围,此时内核调度器需要赋予高优先级的任务更多的调度机会来最小化其调度延迟,并把低优先级任务对其带来的影响降到最低。
+
+
+为了满足以上需求,我们引入了Group Identity的概念,即每个cpu cgroup会有一个身份识别,按优先级由高到低排序依次为:
+
+
+* ID\_HIGHCLASS:在线任务,对延迟敏感,可以抢占离线任务,但不能抢占其它的在线任务和普通系统任务;
+* ID\_NORMAL:普通系统任务,如 sshd, systemd, init 等, 这是任务的默认分类;
+* ID\_UNDERCLASS:离线任务,对延迟不敏感;
+
+
+### 功能简介
+
+
+在被赋予不同的group identity时,底层内核会根据优先级的高低,可以最大程度降低由于离线业务引入的在线业务调度不及时的问题,增加高优先业务的cpu抢占时机等底层核心技术保障在线业务在cpu调度延迟上不受离线业务的影响。这些优先级的作用范围遵从cpu cgroup的资源管理概念,即相对于同一层的任务生效,对上不生效,对下生效,和同优先级任务之间的竞争基本服从CFS规则,但ID\_UNDERCLASS身份的任务没有最小保底运行时间的保障。具体如下:
+
+
+* ID\_HIGHCLASS
+
+
+高优先级的CFS任务,对低于其优先级的任务有更多的抢占机会。次高优先级CFS任务在调度时会有以下行为变化:
+
+
+1. 被唤醒时,如果当前运行的是低优先级任务,可无条件进行抢占
+2. 被唤醒时,如果当前运行的是普通任务且自身的vruntime超前于它,可无视唤醒保底运行时间进行抢占
+3. 排队运行时,如果当前运行的是普通或者低优先级任务,且自身的vruntime超前于它,可无视保底运行时间进行抢占
+
+
+* ID\_NORMAL
+
+
+普通的CFS任务,对低于其优先级的任务有更多的抢占机会,普通CFS任务在调度时会有以下行为变化:
+
+
+1. 被唤醒时,如果当前运行的是低优先级任务,可无条件进行抢占
+2. 排队运行时,如果当前运行的是低优先级任务,且自身的vruntime超前于它,可无视保底运行时间进行抢占
+
+
+* ID\_UNDERCLASS
+
+
+低优先级的CFS任务,次低优先级CFS任务在调度时会有以下行为变化:
+
+
+1. 被唤醒时,vruntime会有默认1ms的惩罚时间,可通过sysctl\_sched\_bvt\_place\_epsilon进行配置
+2. 如果远端SMT上运行了SMT驱逐者任务,则无法被调度上CPU,等同于被踢出运行队列
+
+
+### 使用说明
+
+
+"Group Identity"通过CPU CGroup v1接口"cpu.bvt\_warp\_ns"配置:
+
+
+
+
+| | | |
+| --- | --- | --- |
+| 值 | 含义 | 说明 |
+| 0 | 该cgroup中任务为普通系统任务 | 默认优先级 |
+| -1 | 该cgroup中的任务为低优先级任务 | 优先级最低 |
+| 1 | 该cgroup中的任务为高优先级任务 | 优先级高 |
+| 2 | 该cgroup中的任务为在线任务, 并具有SMT驱逐能力(见下文) | 优先级最高 |
+
+
+#### 调度特性开关配置接口
+
+
+运行以下命令,您可以通过**sched\_features**接口查看到内核调度特性的默认配置。
+
+
+**cat** /sys/kernel/debug/sched\_features
+
+
+具体说明如下:
+
+
+
+
+| | | |
+| --- | --- | --- |
+| **调度特性** | **说明** | **默认值** |
+| **ID\_IDLE\_AVG** | 该特性与**ID\_IDLE\_SAVER**身份标识配合,把**ID\_UNDERCLASS**任务的运行时间计入空闲时长,防止只有**ID\_UNDERCLASS**任务运行时仍保留空闲CPU(Idle CPU)的问题,避免资源浪费。 | **ID\_IDLE\_AVG**:表示特性为启用状态。 |
+| **ID\_RESCUE\_EXPELLEE** | 该特性作用于负载均衡场景,如果任务无法找到可用的CPU资源,则正在进行驱逐**ID\_UNDERCLASS**任务的CPU会成为负载均衡的目标。用于帮助**ID\_UNDERCLASS**任务尽快摆脱被驱逐的状态。 | **ID\_RESCUE\_EXPELLEE**:表示特性为启用状态。 |
+| **ID\_EXPELLEE\_NEVER\_HOT** | 该特性被启用后,正在被驱逐的任务在判断是否需要迁移至其他CPU时,不会因为热缓存的原因而造成拒绝迁移。用于帮助**ID\_UNDERCLASS**任务尽快摆脱被驱逐的状态。 | **NO\_ID\_EXPELLEE\_NEVER\_HOT**:表示特性为关闭状态。 |
+| **ID\_LOOSE\_EXPEL** | 该特性被启用后,CPU不会在每次选择任务时更新驱逐状态,而是根据内核参数**sched\_expel\_update\_interval**设置的时间自动更新。该特性的开关仅影响CPU选择任务时的状态更新,不影响处理IPI中断的更新。 | **NO\_ID\_LOOSE\_EXPEL**:表示特性为关闭状态。 |
+| **ID\_LAST\_HIGHCLASS\_STAY** | 该特性被启用后,CPU上最后一个运行的**ID\_HIGHCLASS**任务不会被迁移至其他CPU上。 | **ID\_LAST\_HIGHCLASS\_STAY**:表示特性为启用状态。 |
+| **ID\_EXPELLER\_SHARE\_CORE** | 该特性开启时允许**ID\_SMT\_EXPELLER**的任务优先选择已经有**ID\_SMT\_EXPELLER**任务的物理核,该特性关闭时则不允许。
+该特性关闭时可以尽可能的把**ID\_SMT\_EXPELLER**的任务分散到各个物理核上,从而避免**ID\_SMT\_EXPELLER**任务之间的相互干扰。 | **ID\_EXPELLER\_SHARE\_CORE**:表示特性为启用状态。 |
+
+
+#### 用于sysctl配置内核参数的接口
+
+
+Group Identity的部分功能的实现需要以内核参数的取值作为参考。相关内核参数的具体说明如下表:
+
+
+
+
+| | | | |
+| --- | --- | --- | --- |
+| **内核参数** | **说明** | **单位** | **默认值** |
+| **/proc/sys/kernel/sched\_expel\_update\_interval** | CPU在选择任务时,驱逐状态的自动更新时间间隔。仅在**ID\_LOOSE\_EXPEL**特性开启时生效。 | ms | 10 |
+| **/proc/sys/kernel/sched\_expel\_idle\_balance\_delay** | CPU在驱逐状态下,**idle balance**的最小时间间隔。取值为-1时表示不允许进行**idle balance**。
+当CPU上均为**ID\_UNDERCLASS**任务且任务在被驱逐时,CPU的状态可以理解为空闲状态,在该状态下CPU会进行**idle balance**以提高负载均衡的效果,但会对**ID\_UNDERCLASS**任务造成损伤。通过设置**sched\_expel\_idle\_balance\_delay**参数可以缓解该问题。 | ms | -1 |
+| **/proc/sys/kernel/sched\_idle\_saver\_wmark** | 设置CPU空闲时间的水位线。当**ID\_IDLE\_SAVER**任务被唤醒时,只会尝试找到高于该水位线的空闲CPU,不会尝试找到低于该水位线的空闲CPU。 | ns | 0 |
+
+
+#### 信息输出说明
+
+
+在使用Group Identity功能期间,您可以运行以下命令,查看多维度的参数信息。
+
+
+**cat** /proc/sched\_debug
+
+
+输出的参数说明如下:
+
+
+
+
+| | |
+| --- | --- |
+| **参数** | **说明** |
+| **nr\_high\_running** | 当前CPU上运行的**ID\_HIGHCLASS**任务数量。 |
+| **nr\_under\_running** | 当前CPU上运行的**ID\_UNDERCLASS**任务数量。 |
+| **nr\_expel\_immune** | 当前CPU上运行的非**ID\_UNDERCLASS**任务数量。 |
+| **smt\_expeller** | 当前CPU是否有**ID\_SMT\_EXPELLER**任务在运行。参数值为1表示有;参数值为0表示无。 |
+| **on\_expel** | 当前CPU的SMT对端是否有**ID\_SMT\_EXPELLER**任务在运行。参数值为1表示有;参数值为0表示无。 |
+| **high\_exec\_sum** | 当前CPU上**ID\_HIGHCLASS**任务的累计运行时间。 |
+| **under\_exec\_sum** | 当前CPU上**ID\_UNDERCLASS**任务的累计运行时间。 |
+| **h\_nr\_expel\_immune** | 当前**cfs\_rq**上运行的非**ID\_UNDERCLASS**任务数量。 |
+| **expel\_start** | CPU在驱逐任务的开始阶段,两个红黑树结构的最小虚拟运行时间的差距。 |
+| **expel\_spread** | 由于CPU驱逐状态造成的两个红黑树结构最小虚拟运行时间的累计差距。 |
+| **min\_under\_vruntime** | 低优先级红黑树结构的最小虚拟运行时间。 |
+
+
+
+
+
+### 注意事项
+
+
+* 低优先级父组下的高优先级子组仍为低优先级,会被SMT驱逐者驱逐,不建议线上使用此种组合的配置。
+* 高优先级强调的是低延迟,而非高吞吐量,两者一般情况下是相互矛盾的,低延迟并不意味着高性能。
+
+
+## SMT expeller
+
+
+### 需求来源
+
+
+超线程技术在一个物理核上模拟两个逻辑核,两个逻辑核具有各自独立的寄存器(eax、ebx、ecx、msr等等)和APIC,但会共享使用物理核的执行资源,包括执行引擎、L1/L2缓存、TLB和系统总线等等。这就意味着,如果一对HT的一个核上跑了在线任务,与此同时它对应的HT核上跑了一个离线任务,那么它们之间是会发生竞争的。为了尽可能减轻这种竞争的影响,我们想要让一个核上的在线任务执行的时候,它对应的HT上不再运行离线任务;或者当一个核上有离线任务运行的时候,而在线任务调度到了其对应的HT上时,离线任务会被驱赶走。这就是我们保证HT资源不被争抢的机制。
+
+
+### 功能简介
+
+
+当一个核上的在线任务执行的时候,它对应的HT上不再运行离线任务;或者当一个核上有离线任务运行的时候,而在线任务调度到了其对应的HT上时,离线任务会被驱赶走。这就是我们保证HT资源不被争抢的机制。
+
+
+### 使用说明
+
+
+"Group Identity"通过CPU CGroup v1接口"cpu.bvt\_warp\_ns"配置:
+
+
+
+
+| | | |
+| --- | --- | --- |
+| 值 | 含义 | 说明 |
+| 0 | 该cgroup中任务为普通系统任务 | 默认优先级 |
+| -1 | 该cgroup中的任务为低优先级任务 | 优先级最低 |
+| 1 | 该cgroup中的任务为高优先级任务 | 优先级高 |
+| 2 | 该cgroup中的任务为在线任务, 并具有SMT驱逐能力(见下文) | 优先级最高 |
+
+
+### 注意事项
+
+
+请参考group identity方案中的注意事项章节。
+
+
+# IO资源隔离使用指导
+
+
+
+
+
+## cgroup writeback throttle
+
+
+### 需求来源
+
+
+block IO cgroup自合入内核之后,一直存在一个问题:只能对direct IO进行限流(buffer IO之后短期内执行fsync也可以限流),因为这些IO到达block throttle层时,当前进程就是真正发起IO的进程,根据进程可以获取到相应的cgroup从而正确记账,如果超过了用户设置的带宽/IOPS上限,则进行限制。对于那些buffer写,且最终由kworker线程下发的IO,block throttle层无法通过当前进程获取IO所属的cgroup,也就无法对这些IO进行限流。
+
+
+基于以上背景,目前在Cgroup V2版本中已经支持异步IO限流,但是在Cgroup V1中并不支持,由于目前在云原生环境下主要还是使用Cgroup V1版本,阿里云内核团队通过建立page<->memcg<->blkcg这三者的关系实现了在Cgroup V1中对IO异步限流的功能,限流的主要算法基本上和Cgroup V2保持一致。
+
+
+### 功能简介
+
+
+在Cgroup V1中实现了和Cgroup V2一样的IO异步限速的功能,可以解决由于IO在writeback过程中无法精准的进行IO限速的问题,可以在混部场景中对离线业务的IO进行限速,防止由于离线业务对IO的过度使用而影响在线业务。一旦配置限速writeback功能以后,不但可以限制异步IO,同时也可以限制direct IO。
+
+
+cgroup writeback功能需要memcg和blkcg协同工作,完成Buffered I/O的限速,但是内核接口cgroup v1的各个控制子系统间默认不协同工作。因此需要通过一定的规则把memcg和blkcg连接起来,规则为:通过任意一个memcg必须可以找到与之唯一对应的blkcg。即memcg和blkcg的映射关系可以是一对一或多对一,不可以是一对多或多对多。
+
+
+例如,存在进程A和B,对它们进行Buffered I/O限速,需要遵循以下约束:
+
+
+* 如果A和B分属不同的memcg,它们可以映射到不同的blkcg,只需各自一一对应。例如:A属于memcg1,blkcg1;B属于memcg2,blkcg0。
+* 如果A和B分属不同的memcg,它们也可以映射到同一个blkcg。例如:A属于memcg1,B属于memcg2,A和B都属于blkcg2。
+* 如果A和B属于相同的memcg,那么它们只能映射到同一个blkcg。例如:A和B均属于memcg0,它们同时属于blkcg3。
+
+
+### 使用说明
+
+
+可以参考:
+
+
+#### 第一步:确定当前内核是否支持writeback throttle的功能
+
+
+首先确认系统是否支持cgroup writeback的功能,通过读取内核文件/proc/cmdline,如果内核命令行参数中带有cgwb\_v1字段则不需要做以下三个步骤,否则需要进行如下三个步骤进行功能的开启:
+
+
+* 通过命令grubby内添加cgwb\_v1字段开启该功能。本示例中内核版本为 4.19.36-12.al7.x86\_64,您在操作中需要更换为实际的内核版本,内核版本的查看命令为 uname -a:
+
+
+
+```
+grubby --update-kernel="/boot/vmlinuz-4.19.36-12.al7.x86_64" --args="cgwb_v1"
+```
+
+* 重启系统使功能生效
+
+
+
+```
+reboot
+```
+
+* 使用以下命令读取内核文件/proc/cmdline,确认内核命令行参数中带有cgwb\_v1字段。此时,blkcg下的blkio.throttle.write\_bps\_device及blkio.throttle.write\_iops\_device接口能够对Buffered I/O进行限速。
+
+
+
+```
+cat /proc/cmdline | grep cgwb_v1
+```
+
+#### 第二步:建立blkcg和memcg映射关系
+
+
+这里我通过创建1个memcg的cgroup和1个blkcg的cgroup目录,通过建立两者之间的关系来说明使用方法:
+
+
+
+```
+#分别建立blkcg和memcg目录。
+sudo mkdir /sys/fs/cgroup/blkio/blkcg1
+sudo mkdir /sys/fs/cgroup/memory/memcg1
+#通过将业务进程PID attach到blkcg和memcg容器中,使blkcg和memcg因为attach了相同的pid而产生关联
+sudo bash -c "echo $$ > /sys/fs/cgroup/blkio/blkcg1/cgroup.procs" # $$为您的进程ID
+sudo bash -c "echo $$ > /sys/fs/cgroup/memory/memcg1/cgroup.procs" # $$为您的进程ID
+```
+
+注意:实际的使用场景中可能需要通过runc或rund将对应业务同时attach到memcg和blkcg中去。
+
+
+#### 第三步:设置限流值
+
+
+通过lsblk命令可以获取对应磁盘的MAJ和MIN号,在限流中需要使用它们:
+
+
+
+```
+[root@iZbp14ah12fefuzd6rh5rkZ ~]# lsblk
+NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
+vdb 253:16 0 100G 0 disk
+vdc 253:32 0 100G 0 disk
+vda 253:0 0 40G 0 disk
+└─vda1 253:1 0 40G 0 part /
+```
+
+使用blkcg下的blkio.throttle.write\_bps\_device接口对Buffered I/O进行限速,这里当您的进程在写vdb盘的时候会被限流为10M:
+
+
+
+```
+# 通过设备号配置磁盘的回写限流bps为10 M
+sudo bash -c "echo 253:16 10485760 > /sys/fs/cgroup/blkio/blkcg1/blkio.throttle.write_bps_device"
+```
+
+### 注意事项
+
+
+* 需要进行writeback限制的进程需要同时attach到memcg和blkcg,如果不attach,则记账到根组;
+* 同一个memcg里的进程,不能属于不同的blkcg。如下图中css\_set1中的进程都被attach到memcg\_1和blkcg\_1,这些进程生成的脏页对应的回刷IO会被记账到blkcg\_1,memcg\_1和blkcg\_1属于一对一的关系;同理,css\_set2/css\_set3/css\_set4里的进程都分别被attach到memcg\_2/ memcg\_3/memcg\_4和blkcg\_2,这些进程生成的脏页对应的回刷IO被记账到blkcg\_2,memcg\_2/ memcg\_3/memcg\_4和blkcg\_2为多对一的关系,这些都是允许的。如果在此基础上,又来一组进程css\_set5,他们被attach到memcg\_4和blkcg\_1上,出现了memcg与blkcg一对多的关系,这就是不允许的,后续css\_set4和css\_set5里进程生成的脏页对应的回刷IO会被记账到根组。
+* 为了避免出现意外情况,建议您在启用cgroup writeback功能后,对进程进行Buffered I/O限速前,优先设置blkcg的cgroup.procs接口,向该接口写入一个进程ID来保证blkcg映射的唯一性。
+* 在实际运维中,可能出现进程移动到其它cgroup的情况。根据上述规则,如果进程在memcg之间移动,不会出现问题,但如果进程在blkcg之间移动,将会出现异常情况。为了避免产生异常,该功能的代码中定义了规则:一旦工作中的blkcg内的进程发生blkcg间的移动,则将映射关系直接指向root blkcg。由于一般情况是不在root blkcg设置限流阈值,所以当映射关系直接指向root blkcg时,限速功能会失效。
+* 如果是云盘,需要将rotation的参数置1
+* 
+
+
+## blk-iocost
+
+
+### 需求来源
+
+
+正常情况下,为了避免一个IO饥饿型作业轻易耗尽整个系统IO资源,我们会设置每个cgroup的IO带宽上限,其最大缺点是即使设备空闲,配置上限的cgroup在其已发送IO超过上限时不能继续发送IO,引起存储资源浪费。
+
+
+基于以上需求,出现了一种IO控制器-IOCOST,该控制器是基于blkcg的权重来分配磁盘的资源,可以做到在满足业务IO QOS的前提下,尽最大程度利用磁盘的IO资源,一旦出现磁盘IO能力达到上限导致触及QOS设置的目标时,此时iocost控制器会通过权重来控制各个group的io使用,在此基础上,blk-iocost又拥有一定的自适应能力,尽可能的避免磁盘能力被浪费。
+
+
+### 功能简介
+
+
+由Tejun Heo开发的iocost控制器是基于权重比例来分配磁盘能力,每个cgroup根据设置的权重来获取磁盘时间,从而获得相应的带宽。在此基础上,blk-iocost又拥有一定的自适应能力,尽可能的避免磁盘能力被浪费。
+
+
+IO控制器如何根据权重分配每个cgroup所能使用的磁盘能力不太容易,这是由于不同类型IO请求实际所占用磁盘处理资源是不一样的,简单统计每cgroup的iops或者带宽是不充分的,因此io.weight控制器提出一个IO请求成本计算模型(cost model),该模型计算每个IO请求预计会占用的设备时间(device time),大体计算逻辑为:首先基于该IO请求是顺序还是随机,会赋值一个初始预计消耗设备时间,然后根据该请求的大小,以page为单位,计算出一个设备时间(IO请求越大,则相应的设备时间越大),然后将初始设备时间和根据请求大小算出的设备时间相加,就得到一个IO请求预计将消耗的总设备时间。控制器已经内置若干默认IO成本计算参数,但系统管理员也可以通过配置root cgroup中的io.weight.cost\_model来修改特定设备对应的IO成本计算参数,需要配置的参数有设备最大吞吐量,rand iops, sequential iops。
+
+
+当一个cgroup不发送请求时,它处于inactive状态,此时它的权重不会被考虑。一旦该cgroup需要发送IO,它就被激活,此时会计算在整棵层级树中的权重比例。以如下层级为例:
+
+
+
+
+
+cgroup B不发送请求,那么A0和A1各占50%的比例。若B开始发送请求,B获得300/(100+300) 也就是 75%的比例,A0和A1各占12.5%。这些比例称为hweights(hierarchical weights),所有被激活的cgroup的hweights总和为1。
+
+
+### 接口说明
+
+
+可以参考:
+
+
+
+
+| | | |
+| --- | --- | --- |
+| 接口 | 描述 | 配置说明 |
+| cost.qos | 可读可写接口,接口文件只存在于blkcg根组。在cgroup v1中,该接口文件完整名称为blkio.cost.qos,在cgroup v2中,该接口文件完整名称为io.cost.qos。该接口主要实现blk-iocost功能以及基于延迟(latency)权重限制I/O服务质量(Qos)的速率。
+当实现blk-iocost功能之后,内核按延迟数值统计以下比例:超过读写延迟rlat|wlat的请求占所有请求的比例。当该比例超过读写延迟百分比rpct|wpct时,内核认为设备达到饱和状态,会降低往磁盘发送请求的速率。默认情况下,rlat|wlat的值为0,表示该功能未启用。 | 每行配置以设备的Major号和Minor号开头(格式为MAJ:MIN),后边衔接其他配置项,说明如下。* enable:是否开启blk-iocost controller,即开启blk-iocost功能。默认值0为关闭状态,修改值为1时开启功能。
+* ctrl:控制模式,可选值为auto或者user。使用auto时,内核自动探测设备类型并使用内置参数;使用user,则需要输入以下QoS控制参数。
+* rpct:读延迟百分比,取值范围为[0,100]。
+* rlat:读延迟,单位为us。
+* wpct:写延迟百分比,取值范围为[0,100]。
+* wlat:写延迟,单位为us。
+* min:最小速率调整比例,取值范围为[1,10000]。
+* max:最大速率调整比例,取值范围为[1,10000]。
+ |
+| cost.model | 可读可写接口,只存在于blkcg根组。在cgroup v1中,该接口文件完整名称为blkio.cost.model,在cgroup v2中,该接口文件完整名称为io.cost.model。该接口用于设置成本模型(cost model)。 | 每行配置以设备的Major号和Minor号开头(格式为MAJ:MIN),后边衔接其他配置项,说明如下。* ctrl:控制模式,可选值为auto或user,表示是否使用用户输入模型参数。
+* model:模型参数,当前只实现了一种模型linear。当模型参数为linear时,定义如下建模参数。
++ [r|w]bps:最大顺序IO带宽。
++ [r|w]seqiops:顺序 IOPS(Input/Output Operations Per Second)。
++ [r|w]randiops:随机 IOPS(Input/Output Operations Per Second)。
+ |
+| cost.weight | 可读可写接口,只存在blkcg的子组中。在cgroup v1中,该接口文件完整名称为blkio.cost.weight,在cgroup v2中,该接口文件完整名称为io.cost.weight。该接口用于配置子组的权重,范围为[1,10000],默认值为100。该接口可以为每个设备配置权重,也可以修改该整个子组的默认权重。 | * 为接口设置权重值:表示修改blkcg的默认权重。
+* 为接口设置端口号和权重值MAJ:MIN :表示修改设备上的blkcg的权重。
+ |
+
+
+### 使用说明
+
+
+#### 第一步:为对应的磁盘生成相应的cost model数据
+
+
+在进行IO评测的时候需要获取iocost的model模型数据,iocost\_coed\_gen.py用来获取model数据,这个脚本可以使用内核源码中的tools/cgroup/iocost\_coef\_gen.py脚本来生成,或者从以下网址可以获取脚本的源码,这个脚本会通过直接读写磁盘来获取对应的磁盘模型数据,所以会破坏磁盘上的数据或文件系统,可以在磁盘被格式化前进行,只需要获取一次即可,比如我这边获取/dev/vdc盘的数据,可以用如下命令获取,最后一行输出的数据就是我们需要的数据
+
+
+
+```
+[root@iZbp14ah12fefuzd6rh5rkZ ~]# python3 iocost_coed_gen.py --testdev /dev/vdc
+Test target: vdc(253:32)
+Temporarily disabling elevator and merges
+Determining rbps...
+Jobs: 1 (f=1): [R(1)][100.0%][r=128MiB/s,w=0KiB/s][r=1,w=0 IOPS][eta 00m:00s]
+rbps=179879083, determining rseqiops...
+Jobs: 1 (f=1): [R(1)][100.0%][r=26.5MiB/s,w=0KiB/s][r=6791,w=0 IOPS][eta 00m:00s]
+rseqiops=6862, determining rrandiops...
+Jobs: 1 (f=1): [r(1)][100.0%][r=26.6MiB/s,w=0KiB/s][r=6800,w=0 IOPS][eta 00m:00s]
+rrandiops=6830, determining wbps...
+Jobs: 1 (f=1): [W(1)][100.0%][r=0KiB/s,w=128MiB/s][r=0,w=1 IOPS][eta 00m:00s]
+wbps=179882078, determining wseqiops...
+Jobs: 1 (f=1): [W(1)][100.0%][r=0KiB/s,w=26.6MiB/s][r=0,w=6798 IOPS][eta 00m:00s]
+wseqiops=6862, determining wrandiops...
+Jobs: 1 (f=1): [w(1)][100.0%][r=0KiB/s,w=26.6MiB/s][r=0,w=6806 IOPS][eta 00m:00s]
+wrandiops=6830
+Restoring elevator to none and nomerges to 0
+
+253:32 rbps=179879083 rseqiops=6862 rrandiops=6830 wbps=179882078 wseqiops=6862 wrandiops=6830
+```
+
+然后将最后一行的数据写入对应磁盘的cost model文件中,如下所示:
+
+
+
+```
+echo "253:32 rbps=179879083 rseqiops=6862 rrandiops=6830 wbps=179882078 wseqiops=6862 wrandiops=6830" > /sys/fs/cgroup/blkio/blkio.cost.model
+```
+
+注意:不需要在所有的机器上都执行这个操作,同样的磁盘的model数据是一样的,我们只需要获取一次即可,然后将对应的数据写入blkio root目录的blkio.cost.model接口文件即可。
+
+
+#### 第二步:配置磁盘的QOS,开启blk-iocost
+
+
+这里假设使用cost.qos接口为设备253:32开启blk-iocost功能,并且当读写延迟rlat|wlat的请求有95%超过5 ms时,认为磁盘饱和。内核将进行磁盘发送请求速率的调整,调整区间为最低降至原速率的50%,最高升至原速率的150%:
+
+
+
+```
+echo "253:32 enable=1 ctrl=user rpct=95.00 rlat=5000 wpct=95.00 wlat=5000 min=50.00 max=150.00" > /sys/fs/cgroup/blkio/blkio.cost.qos
+```
+
+#### 第三步:为容器分配io权重
+
+
+这里可以根据业务容器不同的io的时延等级,给与设置不同的io权重,假设这里设置be blkcg的io权重为50,lc blkcg的io权重为1000:
+
+
+
+```
+echo "253:32 50" > /sys/fs/cgroup/blkio/blkcg_be/blkio.cost.weight
+echo "253:32 50" > /sys/fs/cgroup/blkio/blkcg_lc/blkio.cost.weight
+```
+
+这样在IO资源使用饱和时,会根据blkcg的io权重进行io资源的分配。
+
+
+### 注意事项
+
+
+在ECS实例中使用blk-iocost功能启动**ctrl=auto**配置项时,如果对应的云盘为高效云盘、SSD云盘、ESSD云盘或NVMe SSD本地盘类型时,需要手动将对应磁盘的**rotational**属性设置为0:
+
+
+
+```
+#[$DISK_NAME]为磁盘名称
+echo 0 > /sys/block/[$DISK_NAME]/queue/rotational
+```
+
+另外切记不要使用分区的maj和min的值作为参数进行配置,需要使用硬盘的maj和min值进行配置。
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/sig-info.yaml" "b/sig/Anolis\350\277\201\347\247\273SIG/sig-info.yaml"
index 7683c4ae38370635ffd62710f8276ba1306334e2..3d7048b1f2a64c104f7d76d60fb25f0dab715c84 100644
--- "a/sig/Anolis\350\277\201\347\247\273SIG/sig-info.yaml"
+++ "b/sig/Anolis\350\277\201\347\247\273SIG/sig-info.yaml"
@@ -5,8 +5,9 @@ description: OpenAnolis作为一个新的OS开源社区,为了用户能够更
en_description: As a new OS open source community, Anolis OS needs to provide migration guidance and migration tools for migrating from other OS to Anolis OS i
mailing_list: os@lists.openanolis.cn
meeting_url: https://openanolis.cn
-maintainers:
-- openanolis_id:ceshi002
+meeting_minutes_url: https://www.openeuler.org/zh/sig/sig-detail/?name=Kernel
+maintainers:
+- openanolis_id: ceshi002
gitee_id:
name:
organization:
@@ -14,15 +15,13 @@ maintainers:
- openanolis_id: ceshi001
gitee_id:
name:
-- openanolis_id:ceshi004
+- openanolis_id: ceshi004
gitee_id:
name:
-- openanolis_id:
+- openanolis_id: abc123
gitee_id:
name:
contributors:
-- openanolis_id:
- gitee_id:
repositories:
- repo:
- anolis/testfarm
@@ -31,4 +30,7 @@ repositories:
- anolis/tone-runner
- anolis/tone-agent
- anolis/tone-agent-proxy
- - anolis/tone-agent-front
\ No newline at end of file
+ - anolis/tone-agent-front
+ - anolis/community
+ - anolis-challenge/activity-docs-test
+ - anolis-challenge/activity-common-task
\ No newline at end of file
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG01/README.en.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/README.en.md"
similarity index 100%
rename from "sig/Anolis\350\277\201\347\247\273SIG01/README.en.md"
rename to "sig/Anolis\350\277\201\347\247\273SIG02/README.en.md"
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG01/README.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/README.md"
similarity index 100%
rename from "sig/Anolis\350\277\201\347\247\273SIG01/README.md"
rename to "sig/Anolis\350\277\201\347\247\273SIG02/README.md"
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/Cloud_Kernel_\344\272\247\345\223\201\347\256\200\344\273\213/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/Cloud_Kernel_\344\272\247\345\223\201\347\256\200\344\273\213/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..8e463b096dfb28b1ad1697b2ee4ea21fbc80e846
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/Cloud_Kernel_\344\272\247\345\223\201\347\256\200\344\273\213/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/dingding_group_qa.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/dingding_group_qa.png"
new file mode 100644
index 0000000000000000000000000000000000000000..c5b855ba68d171d8ff86213120b6db9abb79bcf8
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/dingding_group_qa.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.11.14\343\200\221Cloud_Kernel\344\273\243\347\240\201\345\220\210\345\271\266\346\265\201\347\250\213\345\217\230\346\233\264/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.11.14\343\200\221Cloud_Kernel\344\273\243\347\240\201\345\220\210\345\271\266\346\265\201\347\250\213\345\217\230\346\233\264/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..62dc7b6b0032e519b579904258e138907fd55970
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.11.14\343\200\221Cloud_Kernel\344\273\243\347\240\201\345\220\210\345\271\266\346\265\201\347\250\213\345\217\230\346\233\264/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b3d694d5986e8236c6689d2576c38dc8aef02474
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..89e8edb07188edf919b880e5caf9bad3cb072d1e
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..0ea00c803d57b2689cd4a5edcce4de3c35b62e7b
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..0457558710f096384b44c13d0390ad788b0db560
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..380ae5996919384b397842341f37a4698d1109cf
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9304c3aebcd602970c06d5fdfbdd326cbadee253
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f0782be572dff8e4befca5989fb7f32feaae883f
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..1e0d3c14fcded55abd4f2ad39479abb5c76f0050
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..fa7da5d383820ff2a6d0ddaff29938e36fb360e7
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..80187bd3d11a7edb94ab2237e0c30dc217eb0c83
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f2bb4248a9386583e637d85d8009b4e28a21a722
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..fddcb74f5c9a9e7b6ae714d7527695b8af147661
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..a841c6380b4c5ac16d172b524940b5fd030b3927
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232DMESG_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232DMESG_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..dec01fec232e11cca5e54a6ccc32e21b199575cb
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232DMESG_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..ab5f3485686d34b385b7706bfb22a28259777941
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..8416444ae596818142b187f27a5895531e155e63
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..bb5c37e746e0b78a77903d6b279b9d351aa32922
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..ca310e0f41e61f3e0964ac19704fd07af704fe7e
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..7324b7e19438810c058546a055c640be709f4843
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..2af59d1371fb10ecaa3324e5aa4f746d1008c783
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..4527db2df8937827d6fd7876e0382533ef0e69e9
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..cd6474e495ea5ab1483f9ee937b6f4d5c39062a5
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_5.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..da4ad25a7cca35fc9876d6ff26879246fbbe7586
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_5.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..47b10a693407189e1e7703c470b51df2e2048013
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..a47ed97da917f61f81b8c28c0174d9e4479b8fa3
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..ba86bbe47e77a4b3dd6b48493c289b1ddd20040f
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..49048ef55c3ff70684bf0f0f35b9d8b365384be9
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f59092869cc9c39b595c95109b7d84117f66b9ea
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..74072b56ea1bb7cba1eb3f03ba735fb70627abf7
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..248e6445b9869598280f71ea4c43c880be85533e
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_10.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_10.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9d2cee1c3836c8da875c7baf12a890a4e59365fd
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_10.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_11.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_11.png"
new file mode 100644
index 0000000000000000000000000000000000000000..dfe650b0c62a67a8500cb5f65daf0e99fefe8663
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_11.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..3b16ced8c3e1ff7d506c40d37d66c5c86dce9382
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b986cb29b49d6dad487ae789c5fcfa58ff76e6fb
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..05753d4cc7cb7f87f81b93eaa010cb9ac9850b11
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_5.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..85bc9f951e34353ac0c023e58f2fc336475f2f63
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_5.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_6.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_6.png"
new file mode 100644
index 0000000000000000000000000000000000000000..45282ecfb0c0d2d8fe1c4f919e09a04a8a2f5547
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_6.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_7.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_7.png"
new file mode 100644
index 0000000000000000000000000000000000000000..45282ecfb0c0d2d8fe1c4f919e09a04a8a2f5547
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_7.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_8.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_8.png"
new file mode 100644
index 0000000000000000000000000000000000000000..7af6ece254049856eeab8bb11ff3e19ab332fdfa
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_8.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_9.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_9.png"
new file mode 100644
index 0000000000000000000000000000000000000000..a7104e9b46e0f6e24b72020d653e3140fede8eda
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_9.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..369ef9d313640f62bba3459944af705a3365f75a
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..83526fa8cf9970957ce61102244f0dd759a70cf3
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..95472b08774a80401adc22b5701848d397c3c909
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..efacbe74a8b24f0969a4245002cc3fd75f3c92b1
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..44799418f12fd06d4922fcb7740a8bf6367e753d
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..727fb493b49b429143195a68ef00d4d3406d41cd
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f05d93a1edc145b8c315cbd62f4084c36708122c
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f6c03f4ce83423ee42454a2027b99a8bb71b16ef
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..a798ff256c3f6abc0b1dfaa200bab76962adbb3b
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..bb5c5e8ec2ee954701e0c49a2b7209462b5fe610
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f863b7c1a111f35db9fc16742807cbf611520b29
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..e9c0f9d166126e8fde6cd3d822cd982a38fef0f5
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..0f3a2dd7b0c1d288b5673f0e37d4f005113ef4a9
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_5.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..0bddeb4655513c3a1dd7291d4c29e5092c4734ff
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_5.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..7f37c60b633e2dd00d64a2a4efafc88a0447c32b
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..2145aec1966cfbc621be0efa9eaa865abb517c59
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..a0af706ace2308e440a572caffcdfbdd3d2d0a97
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..7cbcbc9dce3471d2404f2f5d923c195a2c3de2b2
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d5c16cc68db0638fb6eae6d42ab0c751fcc79dd8
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..59ebe6c002c5994c6084e7af37152d6ae226928f
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..e7f35b123c413f2f023e4c83f9129812cb7ea674
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d37b6c3d8e347bb277f4036910acc10d7b72f756
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d2d969a0f704ee9268077b9ea3f7cd227ae480a9
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..a5499779a58080c817c8ff36d8064c495ac1e5b6
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_5.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..43959c1a7372c156ae31431fd7725dc19dc7577d
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_5.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..4d3c493790bdc85217baadab774837db8174b1c5
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..209fc652359363a47a41ec2218fd8bc173baf27f
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..691cc43166d4c318395cd51b1e0fecbbe98274a7
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..413371b395a8f3c1b791f2a1dd0edaaf0832c15f
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..01d195ccff245f413daaa53619e9586d9af29037
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..a526e09cca6111af785c2eb4ef8bd013c091a1d4
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..31f6d007f009bcc149452e15fefcd16fff0bf5f5
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_5.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d7cf172a4603d4613e9700e81420563cf8747ba4
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_5.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_6.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_6.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f80f8094a9b3398ccba84fc258522191857ee6d3
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_6.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..cd4e2172e8b9225fa5843634ec8b38778e32cf5b
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..54c06edbd4dda8bcf171eb06bbf0eb274623a2ed
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b7c769b0ad81dfa9720abd13839b38cd7f37a2b8
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..c93631f36ea52dc552571594af9c14445b58bf36
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..3a2b0b7f3590b03626f0cf287a5b7fb51b71e4a0
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_5.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..184e9226627bcea1d2b40b749ba5fdebb35f7b13
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_5.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_6.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_6.png"
new file mode 100644
index 0000000000000000000000000000000000000000..93b0c090d2a688b08de89c82ba4ce26dc138ec54
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_6.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_7.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_7.png"
new file mode 100644
index 0000000000000000000000000000000000000000..2eb64a4df5cdda266178b2575c88ef1da134d200
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_7.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_8.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_8.png"
new file mode 100644
index 0000000000000000000000000000000000000000..e8065d561c7ad9c7bdd4d47b398befe6234d6ac7
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_8.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_9.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_9.png"
new file mode 100644
index 0000000000000000000000000000000000000000..51a44717b0d1347a64a6721304a301d63aaf372a
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_9.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..4adf2fd8ec3b352a1eef36a715895b59472fd0c4
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..501748e393b27959d95ddf79066a2c9c1c840db2
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b88cf41c53388655041dbec55f3c7d6094c1f959
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..30b5718cf47bd0a7604c4febe56ad8c5b6b3f67e
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..e9d50acfa8c565b1731e4355999efa1a4efa08eb
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..88d9e372a0ddd57408e351ba5391faac0358ba73
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..2b698da7f47590295eb2fc53179c64bdcfe4ed55
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..7c37a1db235aa78013ca7faaf1158263ff0579ea
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9c47e4e9b8bee43d6b33f01345a6ea2d6c585e49
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d68ee6d6911568f4952bb704ced2bd7426578374
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..c257a26648e809c2e37549e2fe4472300e6a9d1a
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..be45fa1e21ea22de702cafabaa8b8467084a066c
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b1bed8770605d31e48a5184beb182ed6e53f4695
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..2704bb5aaac5e2a48480b1174ad4db673358e3be
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d68ee6d6911568f4952bb704ced2bd7426578374
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..1bbd3dd0a6d3b53d767f4f5f508a7cb0ef717b30
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..e791ecb3d3090cf1efc8e562a2af9e9fe7a2d100
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/assets/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..500f8c9925971c4b339cc352fc4cec6b59229220
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG02/assets/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.11.14\343\200\221Cloud_Kernel\344\273\243\347\240\201\345\220\210\345\271\266\346\265\201\347\250\213\345\217\230\346\233\264.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.11.14\343\200\221Cloud_Kernel\344\273\243\347\240\201\345\220\210\345\271\266\346\265\201\347\250\213\345\217\230\346\233\264.md"
new file mode 100644
index 0000000000000000000000000000000000000000..f8b33d6c6f93c4f09b98240cb859287be32f067d
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.11.14\343\200\221Cloud_Kernel\344\273\243\347\240\201\345\220\210\345\271\266\346\265\201\347\250\213\345\217\230\346\233\264.md"
@@ -0,0 +1,100 @@
+大家好,我们对龙蜥社区内核代码仓库Cloud Kernel的代码贡献流程进行了优化。
+
+
+我们已于2022年11月9日上线了自动添加reviewed-by签名和PR link的功能,后续合入PR将不再需要开发者手动force push,请各位龙蜥社区开发者和maintainer注意流程的变更。
+
+
+# 变更内容
+
+
+原来合入的流程为:
+
+
+1. fork Cloud Kernel仓库
+2. 提bugzilla
+3. 编写代码,提交至个人仓库
+4. 提交PR,通过门禁测试
+5. maintainer review通过,在PR评论区给出reviewed-by签名
+6. 在commit中添加reviewed-by签名和PR link
+7. force push
+8. 开发者评论/checksig检查签名
+9. maintainer评论/merge合入代码
+
+
+
+新的流程优化掉了第6、7、8步,省掉了手动添加reviewed-by和PR link,force push以及check-sig的动作,让大家在合入代码时更加方便。
+
+
+# 注意事项
+
+
+## 对于开发者
+
+
+如果您是Cloud Kernel开发者:
+
+
+1. 不用再手动添加reviewed-by和PR link,然后再force push。只要拿到了maintainer的Rewiewed-by签名,就不用管后续的事情了。
+2. 标签变化。新增自动签名功能后,后续PR将不再支持/check-sig命令和anolis\_sign\_pass等标签,改由anolis\_merge\_pass等标签标识合入状态。
+3. 在/merge以后,会有一个非常短暂的时间窗口,这期间从仓库git fetch的代码是不带Reviewed-by/Acked-by签名的,这可能对您的开发造成些微影响。
+ - 该问题与门禁实现有关。门禁会先调用OpenAPI关闭PR(这阶段会合入不带签名的commit),再通过force push的方式将带有前面的commit刷到devel-4.19/devel-5.10开发分支。
+ - 如果您在git fetch后发现有这个问题,请重置一下您的分支
+ - 如果您在提交新的PR时发现有这个问题,请通过git rebase解决
+
+
+## 对于Maintainer
+
+
+如果您是Cloud Kernel Maintainer:
+
+
+1. 只有在小龙提示自动签名完成以后,才算作代码合入成功。这之前,小龙会先合入PR,但并不是一个最终的状态。
+
+
+
+
+
+2. 该功能支持添加多个maintainer的签名。
+3. 非maintainer的签名,也会被门禁自动挑选合入到commit log中。
+4. 以Xiao Long 为例,不支持的签名格式有:
+
+
+
+
+| | |
+| --- | --- |
+| 示例 | 说明 |
+| /merge Reviewed-by: Xiao Long | 将/merge直接与签名放在同一行内。
+这会被门禁视为传参给/merge,目前不支持传参。
+请将二者放到不同行内 |
+
+
+4. 以Xiao Long 为例,支持的签名格式有:
+
+
+
+
+| | |
+| --- | --- |
+| 示例 | 说明 |
+| Reviewed-by: Xiao Long | 正常的reviewed-by签名 |
+| Acked-by: Xiao Long | 正常的acked-by签名 |
+| reviewed-by: Xiao Long | 首字母小写 |
+| acked-by: Xiao Long | 首字母小写 |
+| Acked-by: Xiao Long xiaolong@openanolis.org | 不带尖括号(在网页渲染时,尖括号会被视为html的标记,从而不展示) |
+| reviewed-by: Xiao Long | "-by:"后不带空格 |
+| `Reviewed-by: Xiao Long ` | 签名带有反引号(用于在PR界面保留尖括号) |
+| balabala reviewed-by: Xiao Long balabala | 签名隐藏在一行中,前后有内容 |
+| balabala
+balabala
+reviewed-by: Xiao Long
+balabala | 签名隐藏在一段中 |
+| /merge | 不加任何评论,直接/merge。若最终/merge的maintainer未显式给出任何回复,则门禁会自动加上该maintainer的签名 |
+| /mergeReviewed-by: Xiao Long | 在/merge时,新起一行,顺便加上了签名 |
+| 第一个评论:Acked-by: Xiao Long
+第二个评论:Reviewed-by: Xiao Long | 先给了acked-by签名,再给了reviewed-by签名。最终使用acked-by,原则上是哪种先出现用哪个。 |
+| 在commit log中: Acked-by: Xiao Long
+在PR评论中: Reviewed-by: Xiao Long | commit log中已有签名。
+最终会保留commit log中的签名,该功能用于兼容老的合入机制。 |
+| | |
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e088cf16bbdf9128e2ae80c8ed7925a4006a2b5f
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264.md"
@@ -0,0 +1,93 @@
+
+# 1. 背景
+
+
+当前,对于Cloud Kernel的某些commit,开发者们无法根据commit log获取到bugzilla链接中的相关背景信息。这是因为:
+
+
+* commit log中只有bugzilla的ID(即`ANBZ: #xxx` 信息)
+* 受限于某些原因,bugzilla当前并未向所有人开放浏览权限。
+
+
+
+
+
+**为了满足开发者们对Cloud Kernel的commit进行溯源的需要**,同时考虑到gitee上的PR链接对所有人开放了浏览权限,因此我们决定对现有开发流程进行优化。
+
+
+具体而言如下:
+
+
+首先,在commit log里面加上了PR链接,如此可通过commit log反查到PR。
+
+
+接下来,要求开发者们在提交PR时,在PR正文中带上bugzilla信息以及背景描述信息,如此:
+
+
+* 如果用户有bugzilla权限,就可以看到bugzilla信息。
+* 如果用户没有bugzilla权限,那么可以通过PR了解到commit的背景。
+
+
+
+
+
+此外,考虑到开发流程变得更加严格,更加冗长了,我们也正在优化门禁,未来将上线自动添加PR链接及reviewed-by签名的功能,简化流程。
+
+
+当前流程给您带来的不便,请多多谅解。
+
+
+# 2. 变更指南
+
+
+## 2.1 从未向Cloud Kernel提交过代码
+
+
+如果您从未向Cloud Kernel提交过代码,请参考新规范全文。一步步跟着操作就行,每个步骤我们都有示例。
+
+
+新规范的链接在这里:
+
+
+我们将规范拆分成了总体流程、bugzilla规范、commit规范和PR规范四篇。
+
+
+
+
+
+## 2.2 已熟悉原有提交流程
+
+
+如果您已经熟悉原来的那套流程,即:制作补丁、开bugzilla、提PR。
+
+
+那么,**以下步骤需要注意**:
+
+
+**1. 提交PR时,请按照规定格式来写**,而不像之前那样很随意。**该规则已纳入门禁检测**。
+
+
+PR格式要求带上bugzilla链接和**技术背景描述**(不低于10个字)。请把PR的正文当做向linux社区发送补丁的时候cover-letter那样对待,以便让龙蜥社区开发者了解技术背景。
+
+
+参考链接:。
+
+
+
+
+
+**2.** 在PR review完毕,准备添加reviewer的签名后/merge合并时,原来只需要在commit log里面加上reviewed-by即可,现在**要求还要加上PR链接**。**该规则已纳入门禁检测。**
+
+
+参考链接:。
+
+
+
+
+
+具体案例您可以参考[这个PR](https://gitee.com/anolis/cloud-kernel/commit/4a1a5547bd7ec65d734368ac8e93e415c52220f0):
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.8.3\343\200\221Cloud_Kernel_devel-5.10\345\210\206\346\224\257\345\217\230\346\233\264.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.8.3\343\200\221Cloud_Kernel_devel-5.10\345\210\206\346\224\257\345\217\230\346\233\264.md"
new file mode 100644
index 0000000000000000000000000000000000000000..593e2547d6d6bfda7d99f779ef4f815f117c39ba
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.8.3\343\200\221Cloud_Kernel_devel-5.10\345\210\206\346\224\257\345\217\230\346\233\264.md"
@@ -0,0 +1,10 @@
+大家好,因ANCK 5.10新版本发布的需要,我们基于linux社区5.10.134的代码进行了rebase。
+目前Cloud Kennel仓库的devel-5.10与release-5.10的代码均已被force push。
+
+请大家注意:
+1. 未合入的PR将会发生冲突。
+2. 请检查自己的代码,重新拉取新的devel-5.10分支进行开发。
+
+仓库地址:
+https://gitee.com/anolis/cloud-kernel
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.9.28\343\200\221Anolis8_5.10.134-12\347\211\210\346\234\254\345\206\205\346\240\270\345\217\221\345\270\203.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.9.28\343\200\221Anolis8_5.10.134-12\347\211\210\346\234\254\345\206\205\346\240\270\345\217\221\345\270\203.md"
new file mode 100644
index 0000000000000000000000000000000000000000..5ac89325da4b9581eded775349bf5471a330e388
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.9.28\343\200\221Anolis8_5.10.134-12\347\211\210\346\234\254\345\206\205\346\240\270\345\217\221\345\270\203.md"
@@ -0,0 +1,55 @@
+大家好,Anolis8已发布新版本内核5.10.134-12,欢迎您下载体验。
+
+
+
+
+
+**使用该内核的方法:**
+
+
+1. 首先,下载并安装Anolis8:
+2. 然后,按照如下方法升级内核:
+ 1. yum install -y yum-utils anolis-experimental-release
+ 2. yum-config-manager --enable Experimental
+ 3. yum install -y kernel-5.10.134-12.an8
+
+
+
+
+
+**本次内核更新日志如下:**
+
+
+* 内核升级到5.10.134
+* 重要的缺陷及安全漏洞修复
+* 支持倚天710处理器
+* 支持磐久M物理机
+* 优化在倚天平台上的基础性能
+* ARM64支持mpam特性
+* 增加AMD SEV热迁移能力的guest支持
+* ARM64 crashkernel支持预留4G以上内存
+* ARM64支持对kernel module的hotfix
+* 支持ftrace osnoise tracer
+* 支持 ext4 fast commit 特性,该特性对于 fsync 比较频繁的应用如 MySQL/PostgreSQL 数据库有比较明显的性能优化。相应的 e2fsprogs 版本更新至 1.46.0。
+* 支持网讯10GB网卡
+
+
+**龙蜥自研:**
+
+
+* 支持datop监控NUMA跨node访问以及进程粒度内存冷热识别
+* 填充可执行二进制文件末尾2M未对齐部分,部分场景性能再提升2%
+* 支持 XFS 16k 原子写特性,相比默认打开双写,有至多 50% 的性能提升,同时显著减少磁盘 IO。相应的 xfsprogs 和 mariadb 也更新至龙蜥 yum repo。相比硬件原子写方案,该方案至少有着以下优点:
+ + 基于 CoW 机制;
+ + 不依赖硬件;
+ + 无运行时 IO 链路配置依赖。
+
+
+ 另外,该优化效果可以与代码段大页特性叠加。使用手册:
+
+
+* 支持 nydus + erofs over fscache 容器镜像加速。该特性由龙蜥社区贡献,于 5.19 合并到社区主线,并成为社区首个源生支持的容器镜像加速方案。相关技术博客:
+* 支持 fd passthrough 和 fd attach 增强特性。其中 fd passthrough 能将常用场景的 IO 延迟降低到先前的 10%;fd attach 支持无损恢复 fuse 挂载点连接,提升生产环境的稳定性。
+* kidled支持匿名页、文件页以及slab的扫描。
+* 新增memory.use\_priority\_swap接口,支持按cgroup优先级进行内存swap。
+* SMC 新增 1-RTT、RDMA DIM 支持,优化 CQ 中断处理逻辑,数据路径 QPS 提升 40%。引入 SMC 自动化测试能力,修复数十个稳定性问题;
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\344\273\243\347\240\201\345\244\247\351\241\265-mysql\346\200\247\350\203\275\346\265\213\350\257\225.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\344\273\243\347\240\201\345\244\247\351\241\265-mysql\346\200\247\350\203\275\346\265\213\350\257\225.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\344\273\243\347\240\201\345\244\247\351\241\265-mysql\346\200\247\350\203\275\346\265\213\350\257\225.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\351\276\231\350\234\245\345\206\205\346\240\270\347\232\204_Load_Averages_\345\211\226\346\236\220(\344\270\212).md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\351\276\231\350\234\245\345\206\205\346\240\270\347\232\204_Load_Averages_\345\211\226\346\236\220(\344\270\212).md"
new file mode 100644
index 0000000000000000000000000000000000000000..68caa548fbe3da879182beb14461ad4b49d4953e
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\351\276\231\350\234\245\345\206\205\346\240\270\347\232\204_Load_Averages_\345\211\226\346\236\220(\344\270\212).md"
@@ -0,0 +1,4 @@
+/img1.jpeg)
+
+点击[这里](https://www.bilibili.com/video/BV1R34y197Lw/)参看.
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\351\276\231\350\234\245\345\206\205\346\240\270\347\232\204_Load_Averages_\345\211\226\346\236\220(\344\270\213).md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\351\276\231\350\234\245\345\206\205\346\240\270\347\232\204_Load_Averages_\345\211\226\346\236\220(\344\270\213).md"
new file mode 100644
index 0000000000000000000000000000000000000000..e68954407328329fce3f3769179cae89ffbd8b1f
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\351\276\231\350\234\245\345\206\205\346\240\270\347\232\204_Load_Averages_\345\211\226\346\236\220(\344\270\213).md"
@@ -0,0 +1,4 @@
+/img1.jpeg)
+
+视频回放正在准备中, 敬请期待...
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2021.11.01~2021.11.14.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2021.11.01~2021.11.14.md"
new file mode 100644
index 0000000000000000000000000000000000000000..8836ff2b507693190017a459eb94c992dad7b341
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2021.11.01~2021.11.14.md"
@@ -0,0 +1,81 @@
+### 会议主题
+
+
+首次非正式会议, 自由讨论的形式, 聊聊龙蜥内核版本计划, 研发流程及后续双周会主题等
+
+
+### 会议时间
+
+
+2021.11.03 15:00-17:00
+
+
+### 与会人
+
+
+* 会议主持: Shiloong
+* 来自统信,龙芯, 阿里云的龙蜥社区爱好者
+
+
+### 会议纪要
+
+
+* 会议由 Shioong 发起主持, 开场简单介绍了龙蜥 ANCK 版本情况及当前基本研发流程.
+
+
+* 自由讨论中, 谢仲天提出如何尽快参与到内核社区共建的问题. 讨论认为,
+
+
+* + 1) 主动参与: 可通过向社区贡献开源特性参与社区内核研发; 可通过积极关注 kernel-sig bug 管理平台, 积极承担特性/bug 研发任务来参与;
+ + 2) 被动参考: 确定统一接口人, 由社区统一分派研发任务.
+
+
+* + 总之社区是极其开放的, 欢迎大家积极参与其中.
+
+
+* 卢彦表示关注内核性能测试相关 benchmark 评价与测试验收标准
+
+
+* + 阿里云在这一块有多年积累, 一些成熟经验计划在社区推广;
+ + 这块建议放到社区相应的 [QA Sig](https://openanolis.cn/sig/QA) 进一步深入交流.
+
+
+* 李雪峰介绍了龙芯内核同源异构相关进展:
+
+
+* + 表示龙芯内部已经有相关计划;
+ + 因这块工作量较大, 涉及内核及工具链; 且与架构相关的bug 一般难度较大.
+ + 龙芯内部还需要进一步讨论, 以确定排期等相关事项.
+
+
+* + 会上讨论认为这块可以在龙芯 sig 里进一步对齐.
+ + 当前ANCK 已经推出5.10内核, 希望能在这个内核尽快做起来.
+
+
+* 最后大家讨论了 kernel-sig 双周会的相关问题:
+
+
+* + 目前暂定双周会固定时间为第一周周三下午3:00-5:00; 下一次双周会时间 2021.11.17 15:00-17:00;
+ + 疫情期间以线上会议为主, 待国家放开后考虑线下会议;
+
+
+* + 会上头脑风暴了双周会话题:
+
+
+* + - 双周会会有一些例行事项: 1) kernel-sig 双周大事回顾; 2) kernel-sig 相关事项决策等等;
+ - 客户现场案例分享相关: 如在真实客户现场遇到的问题, 解决方案, 经验等分享交流;
+
+
+* + - 内核子系统相关: 如内核子系统相关新特性技术分享, 实例业务应用案例等;
+ - 内核相关业界软硬技术热点研讨: 如 eBPF 应用等等;
+
+
+* + - 客户解决方案相关话题: 如1)客户具体案例分享; 2) 应用软件生态适配相关话题;
+ - ANCK 内核历史经典问题,案例分享;
+
+
+* + - 软硬件协同, 跨平台支持技术等;
+ - 内核相关系列技术讲座;
+
+
+* + - 会上大家提议后面可以发起 ACK (Anolis Cloud Kernel 开发者大会); 待国内疫情放开后, 可以考虑先搞起线下 meetup.
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2021.11.15~2021.11.28.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2021.11.15~2021.11.28.md"
new file mode 100644
index 0000000000000000000000000000000000000000..c7c29a7bfe95059ba72fcf5fcd937c03c820ac6c
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2021.11.15~2021.11.28.md"
@@ -0,0 +1,52 @@
+## 会议主题
+
+
+技术分享:<龙蜥内核 load average 剖析(上)>及龙蜥内核自由讨论
+
+
+## 会议时间
+
+
+2021.11.17 15:00-17:00
+
+
+## 与会人
+
+
+会议主持: Shiloong
+
+
+技术分享人: xunlei
+
+
+参与人: 龙蜥社区
+
+
+## 会议纪要
+
+
+* 会议前1小时庞训磊带来了精彩的技术分享<龙蜥内核 load averages 剖析> 上半部分直播;
+
+
++ 感兴趣的社区爱好者可以到[这里](https://openanolis.cn/video/440158297192218780)(https://openanolis.cn/video/440158297192218780)观看回放.
+
+
+* 直播结束后, 大家就分享的内容及龙蜥内核相关话题自由讨论; 大家对这次技术分享反馈相当不错, 并积极互动讨论.
+
+
++ 社区爱好者陈国斌(音)提出希望技术分享能增加一些实操性的演示; 这部分会在下次分享中安排;
++ 社区爱好者耕深提到是否能搞几次虚拟化相关的技术分享; 这部分后续可以与龙蜥社区的"虚拟化 SIG"组合作推出. 也欢迎大家积极参加龙蜥社区共建中来;
+
+
++ 有社区爱好者提到对调度器及其优化感兴趣, 希望能安排分享龙蜥内核在调度器相关的优化; 这个后面会考虑安排;
++ 有社区爱好者对 eBPF 技术落地龙蜥内核感兴趣, 希望能有相关分享; 龙蜥内核在 eBPF 邻域是有一些创新与积累的, 后面计划安排;
+
+
+* 自由讨论时, 统信参与龙蜥 kernel-sig 研发的同学反馈目前的 Bug Tracker 状态更新不及时, 造成有些信息不对称.
+
+
++ 这个情况基本属实, 目前正在改进中, 后续会把 kernel-sig 相关的 bug 管理迁移至新的平台. 届时也会加强 bug 管理.
+
+
+感谢庞训磊为大家带来精彩讲解, 也感谢芹菜,邢秀帮忙筹划本次技术分享!
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2021.11.29~2021.12.12.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2021.11.29~2021.12.12.md"
new file mode 100644
index 0000000000000000000000000000000000000000..cc693bec33f50f25d178039e043baf9dabbf3c13
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2021.11.29~2021.12.12.md"
@@ -0,0 +1,21 @@
+## 会议主题
+技术分享:及龙蜥内核动态更新
+
+## 会议时间
+2021.12.1 15:00-17:00
+
+## 与会人
+会议主持: Shiloong
+技术分享人: Xunlei
+参与人: 龙蜥社区
+
+## 会议纪要
++ 前半段直播技术分享, 感谢庞训磊为大家带来精彩讲解, 感兴趣或错过的, 可以到观看[回放](https://www.bilibili.com/video/BV1R34y197Lw/).
++ 会议传达了龙蜥内核 cloud-kernel 基础设施迁移的最新情况:
+ + 代码托管平台已经迁移至Gitee: https://gitee.com/anolis/cloud-kernel;
+ + 缺陷与需求管理平台已经迁移到 Bugzilla: https://bugzilla.openanolis.cn;
+ + 相关的开发流程也已经更新;
++ 会议传达了最新龙蜥内核版本发布情况:
+ + ANCK-4.19 内核发布最新版本4.19.91-25, 已经同步到 yum 源支持更新安装;
+ + ANCK-5.10 内核最新版本研发中, 预计2022.1.17发布.
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2021.12.13~2021.12.26.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2021.12.13~2021.12.26.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e1ef7d82d40c50f34644b9c91acf1c1f25539500
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2021.12.13~2021.12.26.md"
@@ -0,0 +1,16 @@
+## 会议主题
++ 龙蜥内核新研发流程讲解
++ 龙蜥内核 kernel-sig 自由讨论
+## 会议时间
+2021.12.15 15:00-17:00
+## 与会人
++ 会议主持: Shiloong
++ 参与人: 龙蜥社区kernel-SIG
+## 会议记要
+1. 龙蜥内核新研发流程讲解.
+2. 龙蜥社区 kernel-sig 补丁规范答疑: 对首次通过龙蜥社区公开的补丁, 需要加上 anolis 标签, 以龙蜥自研补丁发布;
+3. 龙蜥内核社区公开征召技术分享, 以增加社区技术分享活跃度;
+4. 前期推广以技术分享为主, 后面增加技术 workshop, 技术讨论等形式, 丰富 kernel-sig 的技术研讨及新技术孵化.
+5. 鼓励更多内核相关的理事单位参加双周会.
+6. kernel-sig 技术分享主题征集.
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.01.10~2022.01.23.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.01.10~2022.01.23.md"
new file mode 100644
index 0000000000000000000000000000000000000000..3e4c0e6b49e9f47a71447d482a8a0baaf12fbb3d
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.01.10~2022.01.23.md"
@@ -0,0 +1,16 @@
+本期双周会为技术分享
+
+## 分享主题
+系统性能监控工具ssar使用介绍和案例分享
+
+## 直播内容
+ssar整机指标功能使用介绍,ssar进程级指标使用介绍,ssar的load特色指标使用介绍。ssar解决单机生产问题案例剖析。[直播回放](https://www.bilibili.com/video/BV19S4y157Xa?spm\_id\_from=333.999.0.0)
+## 听众收益
+了解ssar的基本功能和使用,初步学习用ssar解决单机OS问题的诊断。
+## 适合人群
+系统运维工程师、linux系统编程工程师、内核爱好者。
+## 讲师头衔
+闻茂泉(广成)龙蜥社区跟踪诊断SIG核心成员,阿里云运维专家。
+## 讲师介绍
+负责阿里云计算平台事业部的基础运维相关工作,目前是龙蜥社区ssar和iodump开源诊断工具的maintainer。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.03.07~2022.03.20.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.03.07~2022.03.20.md"
new file mode 100644
index 0000000000000000000000000000000000000000..534454b3eb62499e70db0418097ff860f30d6344
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.03.07~2022.03.20.md"
@@ -0,0 +1,4 @@
+本期技术分享《datop -- 轻量级靶向内存热点扫描工具介绍与入门》
+
+欢迎到 OpenAnolis Kernel SIG 钉群收看直播回放。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.03.21~2022.04.03.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.03.21~2022.04.03.md"
new file mode 100644
index 0000000000000000000000000000000000000000..976065ee9a2c3643867e712bb7b830f724c5dc46
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.03.21~2022.04.03.md"
@@ -0,0 +1,7 @@
+本期技术分享
+1. 《通过sealer实现整个集群Build&Share&Run》
+
+2. 《硬件兼容性 SIG 分享》
+
+欢迎到 OpenAnolis Kernel SIG 钉群收看直播回放。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.04.04~2022.04.17.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.04.04~2022.04.17.md"
new file mode 100644
index 0000000000000000000000000000000000000000..b7d2cce980ecfc4378940c4469cd2e24d7866014
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.04.04~2022.04.17.md"
@@ -0,0 +1,4 @@
+本期技术分享《内核内存被改和内存泄漏难题的线上解决方案》
+
+欢迎到 OpenAnolis Kernel SIG 钉群收看直播回放。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.04.18~2022.05.01.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.04.18~2022.05.01.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.07.20~2022.08.03.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.07.20~2022.08.03.md"
new file mode 100644
index 0000000000000000000000000000000000000000..b07d6e40219c62e1766ac42a351f41f0651a458d
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.07.20~2022.08.03.md"
@@ -0,0 +1,4 @@
+与会人: 卢彦 道引 落盘 子札
+
+主题:讨论了ANCK-5.10对ARMv9的支持情况,以及ANCK-5.10的分支管理和版本发布计划。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.08.04~2022.08.24.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.08.04~2022.08.24.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e4cd765f488d13c958d7efc53af68663d1da7ab4
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.08.04~2022.08.24.md"
@@ -0,0 +1,4 @@
+与会人:卢彦 王晓华 道引 落盘 行信 王帅
+
+主题:分享了ARMv9 MPAM的龙蜥内核方案,基于/sys/fs/resctrl/实现的LLC和MB的隔离方案,并做了实际案例分享和效果演示。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.08.25~2022.09.07.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.08.25~2022.09.07.md"
new file mode 100644
index 0000000000000000000000000000000000000000..fc4abb36858a52fae2da85021d9ff7db045af4ba
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.08.25~2022.09.07.md"
@@ -0,0 +1,18 @@
+与会人:卢彦 王晓华 道引 落盘 要麻 半叶
+
+主题:
+
+1)要麻分享了ARM64 RAS的龙蜥内核方案,并做了实际案例分享和测试用例建议。
+ - RAS错误处理流程
+
+ UE non fatal类型错误是不可纠正但可恢复的错误,例如出现错误的内存存储的非内核使用的数据结构,后续不再使用对应内存即可,或者是非关键数据在cache中,将对应cache内容丢弃即可,都不会也不必要导致crash。
+ - RAS错误注入流程
+ https://gitee.com/anolis/ras-tools 可用于错误注入的工具
+ - Rasdaemon工具解读日志方法
+
+2)半叶对OS Noise背景噪声检测机制及检测工具进行介绍
+ - ANCK 5.10 支持该功能,在进行benchmark跑分时可以先提前检测包括中断、软中断、NMI、硬件自身 干扰、其他任务干扰等噪声,避免噪声对benchmark跑分结果的准确性造成干扰
+ - OS Noise的trace机制在正常的生产环境中部署会有一定开销,可以使用用户态的检测工具(无法统 计硬件噪声),该工具开销低,可用于生产部署。同时,使用该工具对调度指标进行监控可分析
+ benchmark运行行为,排查干扰运行的因素。
+ - 硬件噪声主要包括会陷入BIOS的硬件中断,在新机型验证方面比较有用。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.09.08~2022.09.21.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.09.08~2022.09.21.md"
new file mode 100644
index 0000000000000000000000000000000000000000..2c04b50983c970d96b7dab2533807ce4b46d5a56
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.09.08~2022.09.21.md"
@@ -0,0 +1,12 @@
+与会人:卢彦 、焦芬芳、王毅博、苟浩、道引、行信、半叶、谷米、落盘
+
+主题:
+- datop工具介绍
+ - ANCK 5.10 已支持该功能,分析内存冷热和跨numa访问,工具开销低,可常态化部署
+ - 工具地址 https://gitee.com/anolis/data-profile-tools
+ - 跨numa访问统计准确性
+ 工具通过仿真统计跨numa访问,存在一定的定量误差,但是不存在定性误差
+- ancert-m工具介绍和演示
+- APP Noise用户态工具演示
+- 介绍了kdump可调可测能力的研发。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.09.22~2022.10.12.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.09.22~2022.10.12.md"
new file mode 100644
index 0000000000000000000000000000000000000000..648b6616934ffefaaa46b60836267aea0d2efec0
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.09.22~2022.10.12.md"
@@ -0,0 +1,11 @@
+# 与会人
+卢彦、焦芬芳、咸正、彧斌、云里、道引、落盘
+
+
+# 主题
+ARM64 PMU相关内容介绍,对ARM64 PMU进行了讲解,PMU从机制都进行了覆盖,并就perf使用问题,以及发生任务迁移时的场景进行了互动交流。
+- PMU的基本原理
+- ARM64 SPE 功能介绍
+- perf相关功能介绍
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.10.13~2022.10.26.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.10.13~2022.10.26.md"
new file mode 100644
index 0000000000000000000000000000000000000000..8f5f78b1a082d09c2c065216b929156cef3e05b6
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\344\274\232/2022.10.13~2022.10.26.md"
@@ -0,0 +1,9 @@
+# 与会人
+卢彦、焦芬芳、苟浩、道引、落盘
+
+
+# 主题
+- 交流了ARM baseos部分需要关注的包。
+- ras-tools是基于APEI的通用工具,服务器需要更新配套的BIOS版本才能使用。
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\346\212\245/2021.10.18~2021.10.31.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\346\212\245/2021.10.18~2021.10.31.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ff1cb9a0546b95d630b6512bab635c0b33774ed2
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\346\212\245/2021.10.18~2021.10.31.md"
@@ -0,0 +1,27 @@
+
+**内核研发**
+
+
+* ANCK-4.19 CK25 代码本周(11.30)冻结, 新特性需求研发代码基本完成合入, 主要特性:
+
+
++ 支持商密特性更新及 bugfix;
++ 支持代码段大页优化;
+
+
++ 支持 SM2/SM3加密算法组合签名;
++ fs/buffer 性能优化;
+
+
++ 支持内核 SM4算法的 AVX/AVX2指令集优化;
+
+
+* ANCK-5.10 下一个版本开发中, 预计11.30代码冻结, 12.30日发布;
+
+
+**SIG运作**
+
+
+* 讨论决定下周三(暂定11.3下午3:00-5:00)召开第一次 kernel-sig 双周会, 主题暂定为;
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\346\212\245/2021.11.01~2021.11.14.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\346\212\245/2021.11.01~2021.11.14.md"
new file mode 100644
index 0000000000000000000000000000000000000000..b024c157bcbd7852404b4388babf1113afa979ae
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\346\212\245/2021.11.01~2021.11.14.md"
@@ -0,0 +1,14 @@
+**内核研发**
+
+
+* ANCK-4.19 下一个版本 4.19.91-25 rc1 已经开始发布测试;
+
+
+* ANCK-5.10 下一个版本开发路线图有调整, 代码冻结时间调整为2021.12.10, 发布日期调整为 2022.1.17;
+
+
+**SIG运作**
+
+
+* 顺利招开了龙蜥社区 kernel-SIG 第一期双周会, 统信, 龙芯及阿里云社区爱好者在一起自由畅谈龙蜥内核发展, 头脑风暴了内核相关的技术话题, 为后续双周会技术分享做准备.
+ + 详细周会纪要请参看[这里](https://openanolis.cn/sig/Cloud-Kernel/doc/426213132286165112).
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\346\212\245/2021.11.15~2021.11.28.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\346\212\245/2021.11.15~2021.11.28.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\346\212\245/2021.11.29~2021.12.12.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\346\212\245/2021.11.29~2021.12.12.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\346\212\245/2021.12.13~2021.12.26.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\346\212\245/2021.12.13~2021.12.26.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\346\212\245/2021.12.27~2022.1.9.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\346\212\245/2021.12.27~2022.1.9.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\346\212\245/2022.1.10~2022.1.23.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\346\212\245/2022.1.10~2022.1.23.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\346\212\245/2022.1.24~2022.2.6.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\217\214\345\221\250\346\212\245/2022.1.24~2022.2.6.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2200\343\200\221\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227\347\233\256\345\275\225.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2200\343\200\221\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227\347\233\256\345\275\225.md"
new file mode 100644
index 0000000000000000000000000000000000000000..3e65665f4c7d72c4b9533d4b038c361d03adc62c
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2200\343\200\221\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227\347\233\256\345\275\225.md"
@@ -0,0 +1,31 @@
+
+### [【1】Anolis OS环境搭建教程](https://openanolis.cn/sig/Cloud-Kernel/doc/607571974230928479?preview=)
+
+
+### [【2】内核编译安装 - Make方式](https://openanolis.cn/sig/Cloud-Kernel/doc/607587039726485317?preview=)
+
+
+### [【3】内核编译安装 - RPM包方式](https://openanolis.cn/sig/Cloud-Kernel/doc/607593708787100770?preview=)
+
+
+### [【4】Cloud Kernel开发基本流程](https://openanolis.cn/sig/Cloud-Kernel/doc/607596680293474815?preview=)
+
+
+### [【4-1】向Cloud Kernel报告BUG](https://openanolis.cn/sig/Cloud-Kernel/doc/607601736106142822?preview=)
+
+
+### [【4-2】Cloud Kernel补丁规范](https://openanolis.cn/sig/Cloud-Kernel/doc/607603338330374166?preview=)
+
+
+### [【4-3】PR(Pull Request)规范](https://openanolis.cn/sig/Cloud-Kernel/doc/607605992881480196?preview=)
+
+
+### [【5】向Cloud Kernel报告CVE](https://openanolis.cn/sig/Cloud-Kernel/doc/607607272530076167?preview=)
+
+
+### [【6】订阅Cloud Kernel邮件列表](https://openanolis.cn/sig/Cloud-Kernel/doc/607613103206853741?preview=)
+
+
+### [【7】Cloud Kernel仓库代码管理](https://openanolis.cn/sig/Cloud-Kernel/doc/381448004602003761?preview=)
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ae47b98e47f3326d04df1542d6f5dec7bd5a9054
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213.md"
@@ -0,0 +1,407 @@
+# 写在前面
+
+
+Anolis OS 是 OpenAnolis 社区推出的完全开源、中立、开放的发行版,它支持多计算架构,也面向云端场景优化。
+
+
+在您使用Anolis OS之前,我们提供了一个预装Anolis OS的在线机器资源服务。我们**强烈建议**您访问[**龙蜥实验室**](https://lab.openanolis.cn/#/apply/home),使用Web页面及机器人等形式自动创建和管理机器资源,以此来对Anolis OS进行体验。
+
+
+您可以访问[龙蜥实验室使用指南](https://www.yuque.com/anolis-docs/community/peng85),来进行**一键申请**和**免费试用**。
+
+
+
+
+
+
+
+
+
+我们提供两种方式安装Anolis OS:
+
+
+* ISO镜像安装
+* qcow虚拟机镜像安装
+
+
+
+
+## 一、通过ISO进行安装
+
+
+### 1.1 ISO镜像下载
+
+
+登陆下载界面获取Anolis OS最新iso镜像文件
+
+
+
+
+
+
+
+
+
+
+
+### 1.2 镜像安装
+
+
+参考该文档,通过图形化安装接口部署Anolis8/7至目标平台:
+
+
+
+
+
+## 二、 通过qcow虚拟机镜像安装
+
+
+首先,验证CPU是否支持KVM;
+
+
+`egrep '(vmx|svm)' /proc/cpuinfo`
+
+
+如果结果中有vmx(Intel)或svm(AMD)字样,就说明CPU是支持的。
+
+
+如果您是买的ECS,或者已经开了虚拟机,那大概率没办法再通过KVM的方式进行安装。
+
+
+### 2.1 虚拟机镜像下载
+
+
+登陆下载界面获取Anolis OS最新qcow2镜像文件
+
+
+
+
+
+这里以7.9为例:点击网址中的下载按钮后,选择相应架构的文件夹进入,既可以看到对应的下载列表,请选择**AnolisOS-7.9-GA-x86\_64-ANCK.qcow2**文件进行下载。
+
+
+
+
+
+### 2.2 安装依赖包
+
+
+`sudo yum install -y qemu-kvm libvirt virt-install bridge-utils`
+
+
+### 2.3 启动前配置
+
+
+#### 2.3.1 libvirt服务
+
+
+开启libvirt服务
+
+
+`systemctl start libvirtd`
+
+
+设置开机启动
+
+
+`systemctl enable libvirtd`
+
+
+查看状态操作结果
+
+
+`systemctl status libvirtd`
+
+
+
+
+
+`systemctl is-enabled libvirtd`
+
+
+
+
+
+
+#### 2.3.2 打开虚拟化的网络支持
+
+
+`sudo virsh net-autostart default`
+
+
+`sudo virsh net-start default`
+
+
+`sudo sysctl -w net.ipv4.ip_forward=1` # 也可以写到配置文件里持久化
+
+
+
+
+
+**TIPS:**
+
+
+`sudo virsh net-autostart default` 执行过程中可能会卡住,此时将 `/etc/modprobe.d/blacklist.conf` 文件中的 "blacklist nf\_conntrack\_ipv4" 语句注释掉,例如
+
+
+
+```
+...
+#blacklist nf_conntrack_ipv4
+```
+
+之后再执行 `sudo virsh net-autostart default`
+
+
+#### 2.3.3 修改kvm权限
+
+
+直接设置成root启动
+
+
+
+```
+cat >> /etc/libvirt/qemu.conf << EOF
+user = "root"
+group = "root"
+EOF
+systemctl restart libvirtd.service
+```
+
+#### 2.3.4 建立链接
+
+
+查看qemu-kvm路径
+
+
+`whereis qemu-kvm`
+
+
+
+```
+qemu-kvm: /etc/qemu-kvm /usr/libexec/qemu-kvm /usr/share/qemu-kvm /usr/share/man/man1/qemu-kvm.1.gz
+```
+
+
+
+
+建立软连接
+
+
+`ln -s /usr/libexec/qemu-kvm /usr/bin/qemu-kvm`
+
+
+
+#### 2.3.5 创建xml配置文件
+
+
+示例文件的名称为anolis.xml,请根据提示修改您的镜像路径
+
+
+您可以按照注释自己酌情修改。
+
+
+
+```
+
+ anolis
+ 16777216
+ 8
+
+
+
+
+ hvm
+
+
+
+
+
+
+
+
+
+
+
+ destroy
+ restart
+ restart
+
+
+ /usr/bin/qemu-kvm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+
+
+
+### 2.4 虚拟机的启动与管理
+
+
+#### 2.4.1 使用virsh命令启动虚拟机
+
+
+
+新机器执行virsh命令可能会有setlocale: No such file or directory的警告,可安装语言包
+
+
+`yum install -y glibc-langpack-zh`
+
+
+
+`sudo virsh define 虚拟机名.xml`
+
+
+`sudo virsh start 虚拟机名` # 请修改为KVM虚拟机的真实名称。
+
+
+vm 默认的账户和密码为:
+
+
+* 用户名:`anuser`
+* 密码:`anolisos`
+
+
+
+
+
+
+
+
+
+
+
+
+
+#### 2.4.2 切换root用户并允许ssh root登录
+
+
+1. `sudo su`
+2. 输入密码`anolisos`
+3. 修改root密码:`passwd root`
+4. 修改`/etc/ssh/sshd_config`:
+
+
+
+
+```
+PasswordAuthentication yes
+
+PermitRootLogin yes
+```
+
+
+#### 2.4.3 虚拟机的访问
+
+
+可以通过下列方式访问VM:
+
+
+* 通过 vnc 访问宿主机的 IP,登录VM,查看 IP
+* 通过 `sudo virsh console 虚拟机名` 登录 VM(请注意可能会有一段时间的黑屏,VM启动过程没有输出到屏幕),查看 IP
+* 获取到 Guest IP 之后,通过 `ssh root@` 登录 VM.
+
+
+#### 2.4.3 查询虚拟机在宿主机对应串口设备
+
+
+`virsh ttyconsole 虚拟机名`
+
+
+
+#### 2.4.4 其余virsh命令
+
+
+`virsh list` #显示本地活动虚拟机
+
+
+`virsh list –-all` #显示本地所有的虚拟机(活动的+不活动的)
+
+
+`virsh define 虚拟机名.xml` #通过配置文件定义一个虚拟机(这个虚拟机还不是活动的)
+
+
+`virsh undefine 虚拟机名.xml` #删除虚拟机配置
+
+
+`virsh start 虚拟机名` #启动名字为ubuntu的非活动虚拟机
+
+
+`virsh create 虚拟机名.xml` # 创建虚拟机(创建后,虚拟机立即执行,成为活动主机)
+
+
+`virsh suspend 虚拟机名` # 暂停虚拟机
+
+
+`virsh resume 虚拟机名` # 启动暂停的虚拟机
+
+
+`virsh shutdown 虚拟机名` # 正常关闭虚拟机
+
+
+`virsh destroy 虚拟机名` # 强制关闭虚拟机
+
+
+`virsh dominfo 虚拟机名` #显示虚拟机的基本信息
+
+
+`virsh domname 2` # 显示id号为2的虚拟机名
+
+
+`virsh domid 虚拟机名` # 显示虚拟机id号
+
+
+`virsh domuuid 虚拟机名` # 显示虚拟机的uuid
+
+
+`virsh domstate 虚拟机名` # 显示虚拟机的当前状态
+
+
+`virsh dumpxml 虚拟机名` # 显示虚拟机的当前配置文件(可能和定义虚拟机时的配置不同,因为当虚拟机启动时,需要给虚拟机分配id号、uuid、vnc端口号等等)
+
+
+`virsh setmem 虚拟机名 512000` #给不活动虚拟机设置内存大小
+
+
+`virsh setvcpus 虚拟机名 4` # 给不活动虚拟机设置cpu个数
+
+
+`virsh edit 虚拟机名` # 编辑配置文件(一般是在刚定义完虚拟机之后)
+
+
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217.md"
new file mode 100644
index 0000000000000000000000000000000000000000..db8a3eed99bd77755d654f9e4bc81bc6258774f8
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217.md"
@@ -0,0 +1,410 @@
+# 写在前面
+
+
+**在进行本教程之前,我们****强烈建议****您:**
+
+
+1. **在****qemu虚拟机中进行操作****,防止安装内核的动作破坏您的现有环境**
+2. **虚拟机OS推荐选择****Anolis OS 8**
+3. **编译内核版本建议****5.10****,其他版本内核操作同理**
+
+
+**本篇教程将****以 Anolis OS 8环境+ 5.10内核编译 为例****。**
+
+
+
+## 1. 拉取内核代码仓库
+
+
+Cloud Kernel 是龙蜥操作系统(Anolis OS)内核,是基于Linux社区主线稳定版,访问以下地址可以查看详细信息。
+
+
+
+
+
+### 1.1 全量拉取
+
+
+首先,保证已经安装Git。
+
+
+
+`sudo yum install -y git`
+
+
+
+接着,复制内核代码仓库到本地,并选择需要编译的目标分支:
+
+
+
+1. 复制内核代码库到本地
+
+
+`git clone https://gitee.com/anolis/cloud-kernel.git`
+
+
+2. 切换到目标分支
+
+
+`cd cloud-kernel`
+
+
+`git checkout devel-5.10 -b devel-5.10`
+
+
+
+### 1.2 指定分支拉取
+
+
+注意到,git clone 默认是取回 master 分支,而Cloud Kernel分支量较大,commit较多,在网络状态不佳的情况下需要大量的下载时间。如果我们只需要特定分支进行编译,可以通过-b参数进行指定。
+
+
+
+
+
+
+
+如:拉取5.10版本内核分支
+
+
+`git clone https://gitee.com/anolis/cloud-kernel.git -b devel-5.10`
+
+
+实际上,如果我们指定的是branch,clone下来的仍然包含了该branch的完整历史,所以还是有较大的文件传输。如果想进一步缩减下载量,可以通过对commit depth进行限制。
+
+
+`git clone https://gitee.com/anolis/cloud-kernel.git -b devel-5.10 --depth 1`
+
+
+通过设置depth=1,这样只会clone最近一次commit。
+
+
+
+
+
+
+## 2. 安装依赖包
+
+
+### 2.1 Anolis OS、CentOS等
+
+
+
+安装开发工具包组
+
+
+`sudo yum groupinstall "development tools"`
+
+
+安装ncurse-devel包 (make menuconfig 文本界面窗口依赖包)
+
+
+`sudo yum install -y ncurses-devel`
+
+
+安装ssl依赖
+
+
+`sudo yum install -y openssl-devel`
+
+
+安装libelf依赖
+
+
+`sudo yum install -y elfutils-libelf-devel`
+
+
+安装dwarves
+
+
+`sudo yum install -y dwarves`
+
+
+
+## 3. 配置内核
+
+
+### 3.1 默认内核配置文件
+
+
+龙蜥操作系统内核提供默认内核配置文件, 常用x86架构和arm架构的配置文件如下:
+
+
+
+* arch/arm64/configs/anolis\_defconfig
+* arch/arm64/configs/anolis-debug\_defconfig
+* arch/x86/configs/anolis\_defconfig
+* arch/x86/configs/anolis-debug\_defconfig
+
+
+
+其中anolis\_defconfig为最常用的**默认配置**,anolis-debug\_defconfig为debug测试版本。
+
+
+
+
+
+您可以通过命令 `make help`列出支持的默认配置, 如下:
+
+
+
+
+
+
+### 3.2 make现有的内核配置文件
+
+
+进入到下载好的cloud-kernel目录下:
+
+
+
+`cd 你的工作目录/cloud-kernel`
+
+
+
+对于默认配置,我们可以直接进行make:
+
+
+
+`make anolis_defconfig`
+
+
+arch目录下包含了各种不同架构,更多config配置详见相应架构的configs文件夹,可以选择进行make
+
+
+
+在make完成后,我们可以在当前cloud-kernel目录下得到.config文件,作为我们之后内核编译使用的配置文件。
+
+
+
+
+
+## 4. 编译内核并运行
+
+
+### 4.1 内核编译
+
+
+这里需要您选择与您当前架构相同的kernel进行编译,我们此教程不涉及交叉编译,不考虑在x86进行arm版本编译,反之亦然。
+
+
+
+直接进行make即可开始内核编译,我们可以通过-j来指定CPU核心数来开启多线程编译以加快编译速度
+
+
+`make -j$(nproc)`
+
+
+
+如果看到以下提示,则代表内核编译成功。其中,bzImage是kernel镜像格式vmlinux经过压缩后得到。
+
+
+(在arm架构中,生成的kernel镜像压缩文件为arch/arm64/boot/Image.gz)
+
+
+
+
+
+### 4.2 内核安装
+
+
+内核编译完成后,我们可以通过执行以下命令对编译好的内核进行安装。
+
+
+
+编译完成后执行make modules\_install 安装内核模块
+
+
+`make modules_install`
+
+
+安装内核核心文件
+
+
+`make install`
+
+
+如需将新版本内核设置为默认启动内核,可以使用此命令
+
+
+`grub2-set-default 0`
+
+
+重启
+
+
+`reboot`
+
+
+
+重启进入系统后,查看内核版本
+
+
+`uname -a`
+
+
+成功安装。
+
+
+
+
+
+
+## 5 修改配置文件(可选)
+
+
+在对内核进行正式编译之前,我们可以对.config文件进行修改,来更改内核编译配置
+
+
+### 5.1 通过自带脚本进行更改
+
+
+为了方便对config进行管理,scripts文件夹中提供config脚本对.config进行修改
+
+
+
+```
+scripts/config的一些说明:
+commands:
+ --enable|-e option Enable option
+ --disable|-d option Disable option
+ --module|-m option Turn option into a module
+ --set-str option string Set option to "string"
+ --set-val option value Set option to value
+ --undefine|-u option Undefine option
+ --state|-s option Print state of option (n,y,m,undef)
+ --enable-after|-E beforeopt option Enable option directly after other option
+ --disable-after|-D beforeopt option Disable option directly after other option
+ --module-after|-M beforeopt option Turn option into module directly after other option
+
+ commands can be repeated multiple times
+
+options:
+ --file config-file .config file to change (default .config)
+ --keep-case|-k Keep next symbols' case (dont' upper-case it)
+```
+
+
+
+
+
+##
+
+
+
+举例:通过`scripts/config`开启/关闭/修改config选项
+
+
+
+创建config\_change.sh `chmod u+x config_change.sh`
+
+
+`./config_change.sh 你的工作目录/cloud-kernel/.config`
+
+
+
+```
+bash 你的工作目录/cloud-kernel/scripts/config --file $1 \
+-e CONFIG_XXX \ #开启CONFIG_XXX
+-d CONFIG_XXX \ #关闭CONFIG_XXX
+-m CONFIG_XXX \ #将CONFIG_XXX设置为module
+...
+```
+
+
+### 5.2 通过menuconfig进行修改
+
+
+在Linux里面我们所看到的menuconfig界面是通过配置内核顶层的Kconfig产生的,而当输入make menuconfig命令的时候系统会读取Makefile来解析Kconfig。
+
+
+
+`make menuconfig`
+
+
+
+
+
+
+在menuconfig图形界面,我们能够更加清晰地看到各个config相关的详细描述信息,来对各个config的管理的功能有进一步的了解。
+
+
+在对信息修改后,记住将修改保存到.config
+
+
+
+
+
+
+### 5.3 修改内核名称
+
+
+在menuconfig界面中,我们还能对编译的内核名称进行修改:
+
+
+
+General setup --->local version -append to kernel release
+
+
+此处修改内核名称为5.10.112-001.my\_test\_kernel.x86\_64
+
+
+
+
+
+
+
+
+
+
+## 6. 自动化脚本
+
+
+我们可以对内核编译过程编写自动化脚本来提高编译效率。(这里以x86为例,其他架构请自行更改)
+
+
+
+```
+bash 你的工作目录/cloud-kernel/scripts/config --file $1 \
+-e CONFIG_XXX \ #开启CONFIG_XXX
+-d CONFIG_XXX \ #关闭CONFIG_XXX
+-m CONFIG_XXX \ #将CONFIG_XXX设置为module
+...
+```
+
+
+```
+BUILD_DIR="你的工作目录/build/cloud-kernel/"
+SOURCE_DIR="你的工作目录/cloud-kernel/"
+
+mkdir $BUILD_DIR -p
+cd $SOURCE_DIR
+if ! [ -f "$BUILD_DIR/.config" ]; then
+ cp $SOURCE_DIR/arch/x86/configs/anolis_defconfig $BUILD_DIR/.config -f
+fi
+
+./config_change.sh $BUILD_DIR/.config
+make O=$BUILD_DIR -j$(nproc)
+
+```
+
+如需更改配置,我们只需要对config\_change.sh进行修改,并运行./build.sh即可一键执行对内核的编译。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217.md"
new file mode 100644
index 0000000000000000000000000000000000000000..6209f94c4abcd0858429125c6770ff0758f89cf1
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217.md"
@@ -0,0 +1,250 @@
+## 1. 前期准备
+
+
+### 1.1 准备Anolis OS环境
+
+
+如果您正在使用Anolis OS,请忽视这个步骤。
+
+
+如果您没有使用Anolis OS,我们**强烈建议在Anolis OS环境下进行操作**,以保证之后的打包流程能顺利进行。
+
+
+#### 1.1.1 镜像版本选择
+
+
+* 我们推荐根据想要编译的内核版本选择相应版本的Anolis OS。
+
+
++ kernel 5.10 -- Anolis OS 8
++ kernel 4.19 -- Anolis OS 7
+
+
+#### 1.1.2 本地镜像与docker镜像下载(二选一)
+
+
+* 您可以从龙蜥社区下ISO镜像或者qcow镜像以使用Anolis OS
+
+
+
+
+
+* 你也可以使用Anolis OS docker镜像
+
+
+
+
+
+
+
+| |
+| --- |
+|
+
+1. 根据tag拉取相应的系统版本(这里以8.6-x86\_64为例)
+
+
+`docker pull openanolis/anolisos:8.6-x86_64`
+2. 查看下载的镜像
+
+
+`docker images`
+示例结果如下:
+`REPOSITORY TAG IMAGE ID CREATED SIZE`
+`docker.io/openanolis/anolisos 8.6-x86_64 6b03ceb18d9c 9 days ago 211 MB`
+3. 运行镜像
+
+
+`docker run -it 6b03ceb18d9c /bin/bash`
+
+ |
+
+
+
+### 1.2 拉取内核代码仓库
+
+
+更多细节参见**内核编译**章节
+
+
+
+`git clone https://gitee.com/anolis/cloud-kernel.git -b devel-5.10`
+
+
+1.3 下载内核打包脚本
+
+
+
+仓库地址:
+
+
+需要根据当前的系统版本和需要打包的内核选择相应的分支。
+
+
+Anolis 8 编译kernel 5.10
+
+
+
+`git clone https://gitee.com/src-anolis-sig/ck-build.git -b an8-5.10`
+
+
+
+Anolis 7 编译kernel 4.19
+
+
+
+`git clone https://gitee.com/src-anolis-sig/ck-build.git -b an7-4.19`
+
+
+
+
+
+## 2. 安装依赖包
+
+
+
+1. 安装开发工具包组
+
+
+`sudo yum groupinstall "development tools" -y`
+
+
+2. 其他依赖
+
+
++ Anolis 8
+
+
+`sudo yum install -y audit-libs-devel binutils-devel java-devel ncurses-devel newt-devel numactl-devel openssl-devel pciutils-devel perl perl-devel xmlto python3-docutils dwarves bc elfutils-devel python3-devel rsync net-tools`
+
+
++ Anolis 7
+
+
+`sudo yum install -y xmlto asciidoc openssl-devel hmaccalc python-devel newt-devel perl pesign perl-ExtUtils-Embed elfutils-libelf-devel`
+
+
+
+## 3.修改代码
+
+
+在打包之前,如果需要的话,您可以对cloud kernel的代码进行一些修改。
+
+
+修改代码需要注意两个事情:
+
+
+1. 如果是要打开某些config的开关,请按照如下操作:
+ 1. 执行`make anolis_defconfig`,这一步会拷贝`arch/{x86,arm64}/configs/anolis_defconfig`的文件为`cloud-kernel/.config`
+ 2. 执行`make menuconfig`,修改某些config选项
+ 3. 根据对应的arch,将.config拷贝回`arch/{x86,arm64}/configs/anolis_defconfig`进行覆盖
+ 4. git add & git commit将修改后的config加入git中进行管理
+2. 任何代码和config的修改,都需要使用git add & git commit将修改加入到git中进行管理。这是因为该打包脚本,会以git HEAD对应的代码进行编译出包。
+
+
+## 4.内核打包
+
+
+进入到ck-bulid工作目录
+
+
+
+`cd 你的工作目录/ck-build`
+
+
+
+### 4.1 建立kernel源码链接
+
+
+
+`ln -s 你的工作目录/cloud-kernel cloud-kernel`
+
+
+
+注意:如果您在编译anolis8-4.19的rpm包时,发现有该报错信息:
+
+
+
+请使用该命令:
+
+
+`ln -s 你的工作目录/cloud-kernel ck.git`
+
+
+这是由于某些历史遗留原因导致的。
+
+
+### 4.2 执行打包命令
+
+
+这里提供基础包的打包命令,也可以根据自己需求进行更改,具体参数请参考FAQ
+
+
+
+`BUILD_NUMBER='自定义版本号' BUILD_VARIANT='default' BUILD_EXTRA='base' ./build.sh`
+
+
+
+### 4.3 输出路径
+
+
+rpm包输出路径:`你的工作目录/ck-build/outputs/自定义版本号`
+
+
+
+## FAQ
+
+
+### 打包选项
+
+
+在进行build之前,您可以对build的可执行选项进行了解,以方便您能更快的编译出自己所需要的rpm包
+
+
+一共有3个可填项BUILD\_VARIANT,BUILD\_EXTRA和BUILD\_NUMBER
+
+
+通过控制BUILD\_VARIANT和BUILD\_EXTRA,我们可以选择生成rpm包的种类,具体参照以下表格。
+
+
+
+
+| | | | |
+| --- | --- | --- | --- |
+| BUILD\_VARIANT
+BUILD\_EXTRA | default | only-debug | with-debug |
+| base | +headers
++default
+-debug | +headers
+-default
++debug | +headers
++default
++debug |
+| with-debuginfo | +debuginfo |
+| full | +tools +doc +perf |
+
+
+BUILD\_NUMBER则代表了包的版本号(默认为0),可以对这个参数定义进行更改(不限于数字)。
+
+
+比如,当我们使用参数
+
+
+`BUILD_NUMBER='test' BUILD_VARIANT='with-debug' BUILD_EXTRA='base'`
+
+
+生成的rpm包如下:
+
+
+
+
+
+
+
+
+
+
+
+###
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG.md"
new file mode 100644
index 0000000000000000000000000000000000000000..c008876d933d93c0849ef970c87202fe273e9469
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG.md"
@@ -0,0 +1,102 @@
+
+# 一、关于bugzilla
+
+
+龙蜥bugzilla平台是管理Cloud Kernel补丁的核心入口,其网址为。
+
+
+不管是您发现了任何**BUG、CVE**漏洞,还是想为Cloud Kernel贡献代码,都可以在bugzilla平台创建一个工单反馈相关信息给我们。
+
+
+
+# 二、bugzilla的使用
+
+
+## 1. 创建bugzilla账号
+
+
+bugzilla账号与龙蜥社区帐号是关联的:
+
+
++ 如果您已拥有龙蜥社区帐号,直接进入[bugzilla主页](https://bugzilla.openanolis.cn/)使用龙蜥社区帐号登陆即可。
++ 如果您还未拥有龙蜥社区帐号,可以先进入进行帐号申请,申请完毕之后再进入[bugzilla主页](https://bugzilla.openanolis.cn/)使用龙蜥社区帐号进行登陆。
+
+
+## 2. 创建bugzilla工单
+
+
+当您想创建一个bugzilla工单时,您可以直接在[bugzilla主页](https://bugzilla.openanolis.cn/)点击 **【 File a Bug 】** 按钮进行创建。创建流程如下:
+
+
+**step 1:**
+
+
+选择【**ANCK:龙蜥云内核 Anolis Cloud Kernel** 项目】
+
+
+
+
+
+**step 2:**
+
+
+选择bug所属版本
+
+
+PS: 如果在5.10和4.19上**都存在相应的Bug**,选择5.10并且在描述或者评论中说明相应情况即可。
+
+
+
+
+
+**step 3:**
+
+
+填写Bug详细信息,
+
+
+- 带红色星号(\*)的为**必填/选**内容
+- 点击每个字段的名称,即可跳转该字段的详细介绍
+- 请尽可能的按照bugzilla所提供的描述模版详细描述您的问题。
+
+
+
+
+
+
+
+
+**step 4:**
+
+
+在完成基本信息的填写之后,需要点击左上角的**【Show Advanced Fields】**,展开进阶选项,如图所示:
+
+
+
+
+
+然后在**keyword字段**选择您的工单类型:
+
+
+
+
+
+
+
+
+**step 5:**
+
+
+当您填写完相关信息之后,点击**【Submit Bug】**即可生成对应的bugzilla工单,每个bugzilla工单都有一个独一无二的ID。
+
+
+此ID会用于后续您提交patch的一系列流程中。
+
+
+
+
+
+
+#
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-2\343\200\221Cloud_Kernel\350\241\245\344\270\201\350\247\204\350\214\203.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-2\343\200\221Cloud_Kernel\350\241\245\344\270\201\350\247\204\350\214\203.md"
new file mode 100644
index 0000000000000000000000000000000000000000..b1c4b051ddd817f141e9664e69d3382d7de6a95a
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-2\343\200\221Cloud_Kernel\350\241\245\344\270\201\350\247\204\350\214\203.md"
@@ -0,0 +1,250 @@
+将代码合入cloud-kernel时,**请根据patch分类**,调整patch的subject、commit log、SOB(Signed-off-by)等内容:
+
+
+* **回合自upstream或第三方社区的补丁**,参考小节“回合自upstream或第三方社区的补丁”。
+* **自研补丁**,参考小节“自研补丁”
+* **CVE补丁**,参考小节“CVE补丁”
+
+
+注意:**所有补丁内容中均不能出现中文**
+
+
+
+## 1. 回合自upstream或第三方社区的补丁
+
+
+### 范例
+
+
+
+```
+sched/fair: Fix wrong cpu selecting from isolated domain
+
+ANBZ: #1468
+
+commit df3cb4ea1fb63ff326488efd671ba3c39034255e upstream.
+
+#commit body ......
+
+Signed-off-by: Andrew Morton
+Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx
+Reviewed-by: Linus Torvalds
+```
+
+### 规范细则
+
+
+* 补丁标题/subject: 保持原标题不变。
+* 补丁日志/commit log
+
+
++ 第一行
+
+
+- **附上**对应问题的**bugzilla ID**号。如果还没有bugzilla id,需要前往[bugzilla](https://bugzilla.openanolis.cn/)提交问题.
+
+
+* 格式:`**ANBZ +冒号+空格+#+bugzilla ID**`
+* 范例:`**ANBZ: #42**`
+* "ANBZ" 即是 "Anolis bugzilla"
+
+
++ 第二行
+
+
+- 空行
+
+
++ 第三行
+
+
+- 添加源补丁commit ID 及补丁来源信息。
+
+
+- 如果您的补丁**来自于upstream**
+
+
+* + - * 格式:`**commit <完整 hash 值> upstream.**`
+ * 范例:`commit 916e6d1a5ef17a6b3bffad0f086f173cde4240d8 upstream.`
+ - 如果您的补丁**来自于upstream,但尚未进入mainline**
+ * 格式:`**commit <完整 hash 值> .**`
+ * 范例:
+ + `commit b66eb3a6e427b059101c6c92ac2ddd899014634c net-next.`
+ + `commit 353f7988dd8413c47718f7ca79c030b6fb62cfe5 linux-block.`
+
+
+- 如果您的补丁**来自第三方社区补丁**
+
+
+* 格式:`**commit <完整 hash 值> <社区名>.**`
+* 范例:`commit 916e6d1a5ef17a6b3bffad0f086f173cde4240d8 openEuler.`
+
+
+- 如果您的补丁**来自社区邮件列表**中,尚未接收的补丁
+
+
+* 格式:`**cherry-picked from + <邮件链接>.**`
+* 范例: `cherry-picked from https://lore.kernel.org/linux-block/20210811142624.618598-1-ming.lei@redhat.com/`
+
+
+* 补丁签名/SOB
+
+
++ 保留原补丁的完整签名,在其后**追加****回合人的签名**
+
+
+- 格式:`**Signed-off-by: <名字> <邮箱地址>**`
+- 范例:`Signed-off-by: Andrew Morton `
+
+
+* PR链接(**由门禁自动添加**)
+
+
++ 在回合人签名后面追加**PR链接**
+
+
+- 格式:`**Link: **`
+- 范例:`Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx`
+
+
+* Reviewed-by(**由门禁自动添加**)
+
+
++ 在PR链接后追加评审人签名
+
+
+- 格式:`**Reviewed-by: <名字> <邮箱地址>**`
+- **范例:**`Reviewed-by: Linus Torvalds `
+
+
+### 回合补丁的修正
+
+
+如因下列原因需要修正的:
+
+
++ 如为解决合并冲突而做的代码适配改动;
++ 对源 commit log 添加新的描述改动;
++ ......
+
+
+都需要在 commit log 里特别注明, 并且**放在您的签名之上**。
+
+
+* 格式: **`[: comments]`**
+* 范例:
+
+
+
+```
+[fix up build warning - gregkh]
+Signed-off-by: Greg Kroah-Hartman
+```
+
+
+
+
+## 2. 自研补丁
+
+
+### 范例
+
+
+
+```
+anolis: scsi: target: tcmu: use new rw_semaphore to protect truncate
+
+ANBZ: #1310
+
+#commit body ......
+
+
+Signed-off-by: Andrew Morton
+Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx
+Reviewed-by: Linus Torvalds
+```
+
+### 规范细则
+
+
+* 补丁标题/subject
+
+
++ 对未被 Linux upstream及第三方开源社区接收的**自研补丁**, 标题前需要加 **`anolis:`** 标签
++ 格式:**`anolis: <标签>`**
+
+
++ 范例:`anolis: uio: Replace mutex info_lock with percpu_ref to improve performance`
+
+
+* 补丁日志/commit log
+
+
++ 附上对应问题的**bugzilla id号**。如果还没有bugzilla ID,需要前往[bugzilla](https://bugzilla.openanolis.cn/)提交问题。
++ 格式:**`ANBZ +冒号+空格+#+bugzilla ID.`**
++ 范例:`ANBZ: #1310`
++ 注:**ANBZ** —— **AN**olis **B**ug**Z**illa
+
+
+* 补丁签名/SOB(Signed-off-by)
+
+
++ 在commit log尾部附上作者签名,
++ 格式:**`Signed-off-by: <名字> <邮箱地址>`**
++ 范例:`Signed-off-by: Andrew Morton `
+
+
+* PR链接(**由门禁自动添加**)
+
+
++ 在回合人签名后面追加**PR链接**
+
+
+- 格式:**`Link: `**
+- 范例:`Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx`
+
+
+* Reviewed-by(**由门禁自动添加**)
+
+
++ 在PR链接后追加评审人签名
+
+
+- 格式:**`Reviewed-by: <名字> <邮箱地址>`**
+- **范例:**`Reviewed-by: Linus Torvalds `
+
+
+## 3. CVE补丁
+
+
+### 范例
+
+
+
+```
+tty: fix deadlock caused by calling printk() under tty_port->lock
+
+ANBZ: #1499
+
+commit 71a174b39f10b4b93223d374722aa894b5d8a82e upstream.
+
+#commit body ......
+
+Signed-off-by: Andrew Morton
+Fixes: CVE-2022-1462
+Signed-off-by: Greg Kroah-Hartman
+Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx
+Reviewed-by: Linus Torvalds
+```
+
+### 规范细则
+
+
+* 根据补丁的来源,参照上文的 **“回合自upstream或第三方社区的补丁规范”** 或 **“自研补丁规范”。**
+* 此外,**额外**在您的**补丁签名的上一行**加上**CVE-ID**
+
+
++ 格式:**`Fixes + 冒号 + 空格 + CVE-ID`**
++ 范例:`Fixes: CVE-2022-1462`
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-3\343\200\221PR(Pull_Request)\350\247\204\350\214\203.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-3\343\200\221PR(Pull_Request)\350\247\204\350\214\203.md"
new file mode 100644
index 0000000000000000000000000000000000000000..9493e467db9881c4303024cdbf8666cd2d74bf85
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-3\343\200\221PR(Pull_Request)\350\247\204\350\214\203.md"
@@ -0,0 +1,83 @@
+当您打算提交pr时,首先明确该pr所属的分类:
+
+
+* **BUG**
+* **CVE**
+* **Feature**
+
+
+**参考示例:**
+
+
+
+# PR标题
+
+
+PR标题不做强制要求,此处仅做建议。
+
+
++ bug类
+
+
+- 建议标题格式:`**[内核版本号] + [Bugfix] +描述**`
+- 范例:`[5.10] [Bugfix] Bug fix for kvm fpu`
+
+
++ CVE类
+
+
+- 建议标题格式:`**[内核版本号] + Bugfix for + CVE-ID**`
+- 范例:`[5.10] Bugfix for CVE-2022-1729`
+
+
++ Feature类
+
+
+- 建议标题格式:`**[内核版本号] + [Feature] + 冒号 + 描述**`
+- 范例:`[5.10] [Feature] : 海光CSV功能扩展`
+
+
+# PR正文
+
+
+正文部分强制要求如下,如果不符合规范,将被**门禁**拒绝:
+
+
+
+```
+bugzilla:
+
+
+
+
+```
+
+其中:
+
+
+* **第一行:bugzilla链接**
+* 第二行:空行
+* **第三行及以下:描述问题背景信息,不少于10个字**
+
+
+
++ 可以直接将bugzilla中的内容复制到描述部分
++ 如果回合自上游社区或者其他社区补丁,建议附上相应链接
++ 门禁将第三行及以下全部视为背景信息,可为中文或英文(英文每个单词视为一个字)。
+
+
+参考示例:
+
+
+
+```
+bugzilla: https://bugzilla.openanolis.cn/show_bug.cgi?id=1672
+
+To improve the code quality of iommu:SIOV - Sync IOMMU to upsteam 5.15
+
+- Merge some bugfixes related to iommu & intel vt-d
+- Align some basic functions related to SIOV
+- Merge iommu iopf framework
+```
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213.md"
new file mode 100644
index 0000000000000000000000000000000000000000..fefc2073257ba2c62031b7c45b85af4d25d82eb6
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213.md"
@@ -0,0 +1,153 @@
+
+为了让您的代码顺利进入Cloud Kernel中,您需要按照以下步骤进行:
+
+
+## 一、准备工作
+
+
+### 1. 注册账号/登陆
+
+
+参与龙蜥内核开发, 需要先注册龙蜥社区及 Gitee 平台账号, 并将两个账号关联.
+步骤如下:
+
+
+1. [注册龙蜥社区账号](https://gitee.com/link?target=https%3A%2F%2Fpassport.openanolis.cn%2Fregister), (已有账号的略过此步);
+2. [注册 Gitee 账号](https://gitee.com/signup), (已有账号的略过此步);
+3. 关联两个账号. 因涉及下节提到的 CLA 签署, 需要将两个账号关联. 直接登录龙蜥社区在 **【账号设置】 -> 【安全设置】** 里可以操作绑定 Gitee 账号.
+
+
+
+
+
+
+### 2. 签署CLA
+
+
+向龙蜥内核贡献代码, 必须先签署 CLA. 可以登录龙蜥社区后, 打开[CLA页面](https://openanolis.cn/pact/contributor) 进行 CLA 签署.
+
+
+注意:
+
+
+* 以人个名义贡献的, 可签署个人 CLA;
+* 以公司名义贡献的, 需要签署公司 CLA;
+* 详情请咨询贵公司相关法务.
+
+
+### 3. fork代码仓库
+
+
+龙蜥 Cloud Kernel 不允许开发者直接向官方代码仓库提交代码, 必须通过向官方代码仓库提交 **PR(Pull Request)** 的方式来合并代码。所以对长期代码贡献者(开发者), 建议先 fork 官方代码仓库到个人账号下, 先将待贡献的代码(补丁)提交到个人代码仓库。
+
+
+操作流程:
+
+
+1. 进入[anolis/cloud-kernel](https://gitee.com/anolis/cloud-kernel) ,点击右上角的 **【Forked】** 按钮,克隆cloud-kernel仓库至个人账号下。
+
+
+
+
+
+
+
+
+2. 克隆完毕之后,git clone 您个人账号下的内核代码库到您的开发环境,进行开发。
+
+
+
+
+
+
+## 二、[bugzilla](https://bugzilla.openanolis.cn/) 确认
+
+
+1. 提交代码前,根据[**bugzilla教程**](https://openanolis.cn/sig/Cloud-Kernel/doc/607601736106142822)进入bugzilla查看是否有对应的**bugzilla**,如果没有则需要根据教程创建新的bugzilla工单。
+2. 获取**bugzilla ID**。
+
+
+示例:图中 **1461** 即为bugzilla ID
+
+
+
+
+
+## 三、补丁制作
+
+
+1. 制作补丁,明确补丁分类(自研、回合、CVE)。
+
+
+2. 根据[**cloud-kernel补丁规范**](https://openanolis.cn/sig/Cloud-Kernel/doc/607603338330374166),确认**补丁标题、补丁日志、补丁签名、回合补丁修正**等部分符合规范。[参考范例](https://gitee.com/anolis/cloud-kernel/commit/dd884ad6baea91e9ea91824f31a5ee64bb58aab8)。
+
+
+3. push代码至个人账号下的内核代码库。
+
+
+
+## 四、提交Pull Request
+
+
+1. 登录 openAnolis 社区Gitee个人账号下的代码仓库页面;
+
+
+2. 点击 **【新建 Pull Request】** 创建合并请求;
+
+
+
+
+
+ 3. 填写PR信息:
+
+
++ 选择目标库为 **【kernel/cloud-kernel】**
++ 选取正确的**源及目标分支**
++ 选择合适的**评审人**。自动指定评审人的功能正在开发,目前您可以通过加入[Cloud Kernel Sig 钉钉群](https://openanolis.cn/sig/Cloud-Kernel)与我们取得联系。
+
+
+
+
+
+
+
+
+4. 根据[**Cloud-Kernel PR规范**](https://openanolis.cn/sig/Cloud-Kernel/doc/607603338330374166)中的要求,编辑好补丁描述,提交PR请求。[PR示例](https://gitee.com/anolis/cloud-kernel/pulls/449)。
+
+
+5. 当您提交完PR后,会有机器人自动帮您进行代码审核验证。
+
+
++ 代码**检测通过**,会有如下提示:
+
+
+
+
+
++ 代码**检测未通过**:
+
+ 1. 请自行修改代码后,使用 **`git push --force`** 重新push至个人仓库下
+ 2. 在pr链接下评论 **`/retest`** 重新触发代码检测。
+ 3. 若因为某些特殊原因导致无法通过检测,可联系maintainer回复 **`/skip-test`** 跳过检测。详见:
+
+
+
+
+
+6. 评审人回复通过并附上签名。
+
+
+
+
+
+
+7. 评审人评论 **`/merge`** 合入代码
+
+
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE.md"
new file mode 100644
index 0000000000000000000000000000000000000000..3904a43fab38397aa2603913bc40a3230bc2e856
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE.md"
@@ -0,0 +1,142 @@
+
+CVE是Cloud Kernel中很关注的部分,报告或修复CVE的流程,我们已经在【Cloud Kernel开发基本流程】一文中提及。
+
+
+但考虑到CVE的重要程度,我们再单独以一篇文档来详细描述报告和修复CVE的步骤。
+
+
+当您想报告或修复CVE时,请按照以下步骤进行:
+
+
+# 一、提交bugzilla
+
+
+1. 首先需要前往[**bugzilla**](https://openanolis.cn/sig/Cloud-Kernel/doc/607607272530076167)查看是否存在相应的bugzilla,如果不存在则需要根据教程创建新的bugzilla工单。
+
+
+* 创建bugzilla时,根据[**bugzilla教程**](https://openanolis.cn/sig/Cloud-Kernel/doc/607601736106142822)进行创建。但是需要注意以下几点:
+
+
+* **bugzilla的Summary必须带上CVE-ID**
+* **在keyword字段必须选择CVE**
+
+
+2. 获取**bugzilla ID**
+
+
+
+
+
+# 二、制作补丁
+
+
+1. 根据[**cloud-kernel补丁规范**](https://openanolis.cn/sig/Cloud-Kernel/doc/607603338330374166)中的CVE规范,确认**补丁标题、补丁日志、补丁签名、回合补丁修正**等部分符合规范。
+
+
+范例:
+
+
+> tty: fix deadlock caused by calling printk() under tty\_port->lock
+>
+> \
+> **ANBZ: #1499**
+>
+>
+> \
+> **commit 71a174b39f10b4b93223d374722aa894b5d8a82e upstream.**
+>
+>
+> \
+> #commit body ......
+>
+> \
+> Signed-off-by: Andrew Morton
+>
+> **Fixes: CVE-2022-1462**
+>
+> **Signed-off-by:Greg Kroah-Hartman **
+>
+> **Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx**
+>
+> **Reviewed-by: Linus Torvalds **
+>
+
+\
+**参考范例:`Fixes: CVE-2022-1462`**
+
+
+2. push代码至个人账号下的内核代码库。
+
+
+
+# 三、提交Pull Request
+
+
+1. 登录 openAnolis 社区Gitee个人账号下的代码仓库页面;
+
+
+2. 点击 **【新建 Pull Request】** 创建合并请求;
+
+
+
+
+
+3. 填写PR信息:
+
+
++ 选择目标库为 **【kernel/cloud-kernel】**
++ 选取正确的**源及目标分支**
++ 选择合适的**评审人**。目前自动指定评审人的功能正在开发,您现在可以通过加入[Cloud Kernel Sig 钉钉群](https://openanolis.cn/sig/Cloud-Kernel)与我们取得联系。
+
+
+
+
+
+4. 参考[**Cloud-Kernel PR规范**](https://openanolis.cn/sig/Cloud-Kernel/doc/607605992881480196)中对CVE的要求,编辑好补丁描述,提交PR请求。
+
+
++ **PR标题中必须带上CVE-ID**
+
+
+范例:**`[5.10] Bugfix for CVE-2022-1729`**
+
+
+5. 当您提交完PR后,会有机器人自动帮您进行代码审核验证。
+
+
++ 如果代码检测未通过:
+
+
+1. 请自行修改代码后,使用 **`git push --force`** 重新push至个人仓库下
+2. 在pr链接下评论 **`/retest`** 重新触发代码检测。
+3. 评审人回复通过并附上签名。
+4. 依次将**PR链接和评审人签名**添加到相应 **commit log 末尾处**,并且使用 **`git push --force`** 提交更新。
+
+
+格式:
+
+
+
+```
+Link:https://gitee.com/anolis/cloud-kernel/pulls/xxx.com
+Reviewed-by: xxx <邮箱>
+```
+
+范例:
+
+
+让最后10个 commit 都加上PR链接`Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx` 以及评审人签名`Reviewed-by: Linus Torvalds `的命令:
+
+
+
+```
+git filter-branch -f --msg-filter ' cat && echo "Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx" && echo "Reviewed-by: Linus Torvalds "' HEAD~10..HEAD
+```
+
+8. 在PR下评论,**`/check-sig`** 提交签名检查命令
+
+
+9. 联系maintainer评论 **`/merge`** 即可进入代码合入流程
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250.md"
new file mode 100644
index 0000000000000000000000000000000000000000..55461a2a9501b1b25449deaa75b6e069203aac3f
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250.md"
@@ -0,0 +1,41 @@
+
+Cloud Kernel邮件列表主要用于Sig消息推送和技术交流,您可以通过邮件列表与我们取得联系。
+
+
+## 订阅步骤:
+
+
+1. 打开[cloud-kernel@lists.openanolis.cn](https://lists.openanolis.cn/postorius/lists/cloud-kernel.lists.openanolis.cn)并且登陆您的龙蜥社区账号。
+2. 填写邮箱地址以及您的名称
+
+
+
+
+
+
+
+
+3. 点击 **【Subscribe】** 即可完成订阅,您将收到该邮件:
+
+
+
+
+
+4. 点击 **【Manage Subscription】** 进入订阅配置
+
+
+
+
+
+
+
+
+5. 根据提示个人喜好配置**Global Mailman Settings**。
+
+
+**注意:Delivery status需要Enable**,否则您无法收到我们的邮件。
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2207\343\200\221Cloud_Kernel_\344\273\223\345\272\223\344\273\243\347\240\201\347\256\241\347\220\206.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2207\343\200\221Cloud_Kernel_\344\273\223\345\272\223\344\273\243\347\240\201\347\256\241\347\220\206.md"
new file mode 100644
index 0000000000000000000000000000000000000000..479e5282441eca6fa84e05a51a3c4600d132d803
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2207\343\200\221Cloud_Kernel_\344\273\223\345\272\223\344\273\243\347\240\201\347\256\241\347\220\206.md"
@@ -0,0 +1,63 @@
+
+
+
+
+## 仓库地址
+
+
+https://gitee.com/anolis/cloud-kernel
+
+
+## 分支管理
+
+
+
+
+| | | |
+| --- | --- | --- |
+| **分支** | **说明** | **生命周期\*** |
+| master | 跟踪 Linux 主线 mainline, 每日自动同步. | 长期 |
+| devel-4.19 | 4.19内核开发分支 | 待定 |
+| release-4.19 | 4.19内核发布分支 | 待定 |
+| devel-5.10 | 5.10内核开发分支 | 待定 |
+| release-5.10 | 5.10内核发布分支 | 待定 |
+
+
+
+\*龙蜥内核各版本生命周期待规划后更新
+
+
+
+## Maintainer 管理机制
+
+
+龙蜥内核模块众多,目前还有很多重要的模块 Maintainer 虚位以待,如当前炙手可热的 BPF 等技术。我们欢迎广大社区同学参与进来,共同贡献,一起打造更多丰富功能,更加稳定可靠的龙蜥内核。
+
+
+### 申请成为龙蜥内核模块 Maintainer
+
+
+可以通过他人推荐或自荐来成为龙蜥内核模块的 Maintainer,方式如下:
+
+
+1、向 [cloud kernel 邮件列表](https://openanolis.cn/sig/Cloud-Kernel/doc/cloud-kernel@lists.openanolis.cn) 发送一封邮件,标题为:Add someone as somemodule's maintainer(他人推荐),或者 Add myself as somemodule's maintainer(自荐),并在邮件中阐述推荐理由,包括但不限于:在该模块实现的特性,修复的问题等,以此证明你在该模块的维护能力。其中,代码提交是重要的参考,可以是 Linux 内核上游的补丁,也可以是龙蜥内核主线的补丁。
+
+
+2、当前 Maintainer 成员针对邮件回复投票,重点参考相关领域 Maintainer 的投票结论,获得 3 位或以上 ACK,即可申请成功,将姓名和龙蜥社区 ID 更新到 Maintainer 列表当中。
+
+
+### 退出龙蜥内核模块 Maintainer
+
+
+因各种原因,不再参与社区活动维护相应模块,如提交补丁,Review 其他同学提交的补丁等,需要有相应的机制退出。退出方式如下:
+
+
+1、本人主动退出,向 [cloud kernel 邮件列表](https://openanolis.cn/sig/Cloud-Kernel/doc/cloud-kernel@lists.openanolis.cn) 发送一封邮件,标题为:Remove myself as somemodule's maintainer,并在邮件中阐述退出理由;社区 TC 在综合考虑后,确认退出,从当前 Maintainer 列表中移除。
+
+
+2、按月检视 Maintainer 的活跃程度,对于长时间没有参加社区活动的 Maintainer,如提交补丁,Review 其他同学提交的补丁等,视情况确认退出,并当前 Maintainer 列表中移除。
+
+
+3、维护历史 Maintainer 列表中,退出的 Maintainer 会在该表中列出曾经维护的模块和时间周期,作为社区历史 Credit 留存。
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/Release_Notes/ANCK_4.19_ReleaseNote.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/Release_Notes/ANCK_4.19_ReleaseNote.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e7a1110583eb1bcdccd485388c302ca05fd330b6
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/Release_Notes/ANCK_4.19_ReleaseNote.md"
@@ -0,0 +1,130 @@
+# 4.19.91-26.y
+
+
+## 4.19.91-26
+
+
+发布时间:2022-05-24
+
+
+发布链接:
+
+
+*
+*
+
+
+内核更新:
+
+
+* 版本更新至 4.19.91-26
+* 重要内核缺陷及安全漏洞(CVE)修复
+* 龙蜥自研混部资源隔离特性Group Identity增加支持
+* 龙蜥自研多租户容器网络 QoS 隔离特性增强
+* 龙蜥自研冷 slab 内存监测与回收特性支持
+* 龙蜥自研 UKFEF 特性支持
+* Megaraid\_sas 设备驱动支持
+* virtio-net 支持 XDP Socket
+* 基于 EROFS 实现 RAFS v6 格式支持
+* livepatch 增加 static key 支持
+* SMR zoned 设备支持
+* ext4 delalloc buffer写性能优化
+* Kunit 测试框架支持
+* ARM 架构支持 kdump crashkernel 分配4G以上内存
+* ARM 架构 CMN PMU 特性支持
+* perf c2c 功能支持
+
+
+## 4.19.91-26.1
+
+
+发布时间:2022-08-02
+
+
+发布链接:
+
+
+* [https://anas.openanolis.cn/errata/detail/ANSA-2022:0602](https://anas.openanolis.cn/errata/detail/ANSA-2022:0603)
+*
+
+
+内核更新:
+
+
+* 修复CVE: CVE-2022-32250
+
+
+## 4.19.91-26.2
+
+
+发布时间:2022-08-26
+
+
+发布链接:
+
+
+*
+*
+
+
+内核更新:
+
+
+* 修复CVE: CVE-2022-2586
+
+
+## 4.19.91-26.3
+
+
+发布时间:2022-09-02
+
+
+发布链接:
+
+
+*
+*
+
+
+内核更新:
+
+
+* 修复CVE: CVE-2022-2978
+
+
+## 4.19.91-26.4
+
+
+发布时间:2022-09-16
+
+
+发布链接:
+
+
+*
+*
+
+
+内核更新:
+
+
+* 修复CVE: CVE-2022-2639
+
+
+## 4.19.91-26.5
+
+
+发布时间:2022-10-11
+
+
+发布链接:
+
+
+*
+*
+
+
+内核更新:
+
+
+* 修复CVE: CVE-2022-3176
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/Release_Notes/ANCK_5.10_ReleaseNote.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/Release_Notes/ANCK_5.10_ReleaseNote.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e5cb3fe247e6aa7cffc4dd4ea390bb0d01c1d85f
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/Release_Notes/ANCK_5.10_ReleaseNote.md"
@@ -0,0 +1,117 @@
+# 5.10.134-12.y
+
+
+## 5.10.134-12
+
+
+发布时间: 2022-09-06
+
+
+发布链接:
+
+
+内核更新:
+
+
+* 内核升级到5.10.134
+* 重要的缺陷及安全漏洞修复
+* 支持倚天710处理器
+* 支持磐久M物理机
+* 优化在倚天平台上的基础性能
+* ARM64支持mpam特性
+* 增加AMD SEV热迁移能力的guest支持
+* ARM64 crashkernel支持预留4G以上内存
+* ARM64支持对kernel module的hotfix
+* 支持ftrace osnoise tracer
+* 支持 ext4 fast commit 特性,该特性对于 fsync 比较频繁的应用如 MySQL/PostgreSQL 数据库有比较明显的性能优化。相应的 e2fsprogs 版本更新至 1.46.0。
+* 支持网讯10GB网卡
+
+
+**龙蜥自研:**
+
+
+* 支持datop监控NUMA跨node访问以及进程粒度内存冷热识别
+* 填充可执行二进制文件末尾2M未对齐部分,部分场景性能再提升2%
+* 支持 XFS 16k 原子写特性,相比默认打开双写,有至多 50% 的性能提升,同时显著减少磁盘 IO。相应的 xfsprogs 和 mariadb 也更新至龙蜥 yum repo。相比硬件原子写方案,该方案至少有着以下优点:
+
+
+a)基于 CoW 机制;
+
+
+b)不依赖硬件;
+
+
+c)无运行时 IO 链路配置依赖。
+
+
+另外,该优化效果可以与代码段大页特性叠加。
+
+
+使用手册:
+
+
+* 支持 nydus + erofs over fscache 容器镜像加速。该特性由龙蜥社区贡献,于 5.19 合并到社区主线,并成为社区首个源生支持的容器镜像加速方案。相关技术博客:
+* 支持 fd passthrough 和 fd attach 增强特性。其中 fd passthrough 能将常用场景的 IO 延迟降低到先前的 10%;fd attach 支持无损恢复 fuse 挂载点连接,提升生产环境的稳定性。
+* kidled支持匿名页、文件页以及slab的扫描。
+* 新增memory.use\_priority\_swap接口,支持按cgroup优先级进行内存swap。
+* SMC 新增 1-RTT、RDMA DIM 支持,优化 CQ 中断处理逻辑,数据路径 QPS 提升 40%。引入 SMC 自动化测试能力,修复数十个稳定性问题;
+
+
+# 5.10.112-11.y
+
+
+## 5.10.112-11
+
+
+发布时间: 2022-05-24
+
+
+内核更新:
+
+
+* 内核升级到5.10.112
+* 重要的缺陷及安全漏洞修复
+* Hygon CSV2 机密虚拟机特性支持
+* 龙蜥自研代码多副本特性支持
+* 龙蜥自研代码大页功能增强
+* Guest OS 256 CPU 支持
+* 龙蜥自研Kfence增加内存越界 UAF等问题定位能力
+* SMC 多场景下吞吐、时延性能提升,建联速度提升,多个稳定性、兼容问题修复;
+* Intel SPR 特性支持:AMX, vAMX, IPI虚拟化,Intel\_idle, TDX 等
+* AMD 特性支持:SEV-ES,ptdma,CPU frequency, k10temp, EDAC 等
+* 阿里倚天 710 特性支持:DDR PMU,PCIe PMU 驱动支持,CMN-700,RAS
+* coresight 特性支持
+* ARM 架构特性支持: ARM SPE perf memory profiling/c2c,
+* virtiofs: 支持文件级 DAX
+* smmu event polling 支持
+
+
+## 5.10.112-11.1
+
+
+发布时间: 2022-07-15
+
+
+发布链接:
+
+
+内核更新:
+
+
+* 修复CVE: CVE-2022-34918
+
+
+## 5.10.112-11.2
+
+
+发布时间: 2022-08-05
+
+
+内核更新:
+
+
+* 修复CVE:CVE-2022-32250
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270CVE\344\270\223\351\241\271/ANCK_CVE\344\277\256\345\244\215\350\256\260\345\275\225.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270CVE\344\270\223\351\241\271/ANCK_CVE\344\277\256\345\244\215\350\256\260\345\275\225.md"
new file mode 100644
index 0000000000000000000000000000000000000000..f07dbce6a1c9d5c7a709d1baf3d8924f9603654d
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270CVE\344\270\223\351\241\271/ANCK_CVE\344\277\256\345\244\215\350\256\260\345\275\225.md"
@@ -0,0 +1,76 @@
+
+# 4.19
+
+
+
+
+| | |
+| --- | --- |
+| 发布版本 | changelog |
+| 4.19.91-26.3 | CVE-2022-2978 |
+| 4.19.91-26.2 | CVE-2022-2586 |
+| 4.19.91-26.1 | CVE-2022-32250 |
+
+
+# 5.10
+
+
+
+
+| | |
+| --- | --- |
+| 发布版本 | changelog |
+| 5.10.112-11.2 | CVE-2022-32250 |
+| 5.10.112-11.1 | CVE-2022-34918 |
+| 5.10.134-12 | CVE-2021-33655
+CVE-2021-33656
+CVE-2022-0494
+CVE-2022-0500
+CVE-2022-1012
+CVE-2022-1184
+CVE-2022-1462
+CVE-2022-1652
+CVE-2022-1729
+CVE-2022-1734
+CVE-2022-1786
+CVE-2022-1789
+CVE-2022-1836
+CVE-2022-1966
+CVE-2022-1972
+CVE-2022-1974
+CVE-2022-1975
+CVE-2022-2078
+CVE-2022-21123
+CVE-2022-21125
+CVE-2022-21166
+CVE-2022-21499
+CVE-2022-21505
+CVE-2022-2153
+CVE-2022-2318
+CVE-2022-23816
+CVE-2022-2503
+CVE-2022-2586
+CVE-2022-2588
+CVE-2022-26365
+CVE-2022-2639
+CVE-2022-28893
+CVE-2022-29581
+CVE-2022-2959
+CVE-2022-2978
+CVE-2022-29900
+CVE-2022-29901
+CVE-2022-32250
+CVE-2022-32296
+CVE-2022-32981
+CVE-2022-33740
+CVE-2022-33741
+CVE-2022-33742
+CVE-2022-33743
+CVE-2022-33744
+CVE-2022-33981
+CVE-2022-34918
+CVE-2022-36123
+CVE-2022-36879
+CVE-2022-36946 |
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270CVE\344\270\223\351\241\271/\351\241\271\347\233\256\347\256\200\344\273\213.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270CVE\344\270\223\351\241\271/\351\241\271\347\233\256\347\256\200\344\273\213.md"
new file mode 100644
index 0000000000000000000000000000000000000000..7fe512a097fbcdbf1be0f66957c0653f2662729e
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270CVE\344\270\223\351\241\271/\351\241\271\347\233\256\347\256\200\344\273\213.md"
@@ -0,0 +1,4 @@
+本项目专注于:
+- 高危CVE的分析、POC和处理。
+- 龙蜥社区贡献的CVE案例分享。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220.md"
new file mode 100644
index 0000000000000000000000000000000000000000..d8d8d5f7ea67371721d640d941991d8ea0ad4191
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220.md"
@@ -0,0 +1,641 @@
+
+
+
+前面一篇文章中,我们简要的介绍了一下osnoise的相关信息,本篇文章主要针对其源代码进行分析阐述。
+
+
+
+# 一、数据结构:
+
+
+
+```
+/*
+ * NMI runtime info.
+ */
+struct osn_nmi {
+ u64 count;
+ u64 delta_start;
+};
+
+/*
+ * IRQ runtime info.
+ */
+struct osn_irq {
+ u64 count;
+ u64 arrival_time;
+ u64 delta_start;
+};
+
+#define IRQ_CONTEXT 0
+#define THREAD_CONTEXT 1
+/*
+ * sofirq runtime info.
+ */
+struct osn_softirq {
+ u64 count;
+ u64 arrival_time;
+ u64 delta_start;
+};
+
+/*
+ * thread runtime info.
+ */
+struct osn_thread {
+ u64 count;
+ u64 arrival_time;
+ u64 delta_start;
+};
+
+/*
+ * Runtime information: this structure saves the runtime information used by
+ * one sampling thread.
+ */
+struct osnoise_variables {
+ struct task_struct *kthread;
+ bool sampling;
+ pid_t pid;
+ struct osn_nmi nmi;
+ struct osn_irq irq;
+ struct osn_softirq softirq;
+ struct osn_thread thread;
+ local_t int_counter;
+};
+```
+
+
+osnoise用来记录结果的主要数据结构为`struct osnoise_variables`其中:
+
+
++ `struct task_struct *kthread`:采样线程的tcb。
++ `bool sampling`:采样开关
++ `pit_t pid`:采样线程的pid
++ `struct osn_nmi nmi`:保存nmi噪声的相关信息
++ `struct osn_irq irq`:保存irq噪声的相关信息
++ `struct osn_softiq softirq`:保存softirq噪声的相关信息
++ `struct osn_thread thread`:保存其他线程噪声的相关信息
++ `local_t int_counter`:保存噪声的总次数
+
+
+
+# 二、工作原理:
+
+
+## 2.1 注册trace\_point
+
+
+如第一篇文章所述,osnoise引入了一组trace\_point。通过这些trace\_point,开发人员可以获取噪声的详细信息。注册trace\_point的代码如下(以irq\_noise为例):
+
+
+
+```
+TRACE_EVENT(irq_noise,
+
+ TP_PROTO(int vector, const char *desc, u64 start, u64 duration),
+
+ TP_ARGS(vector, desc, start, duration),
+
+ TP_STRUCT__entry(
+ __field( u64, start )
+ __field( u64, duration)
+ __string( desc, desc )
+ __field( int, vector )
+
+ ),
+
+ TP_fast_assign(
+ __assign_str(desc, desc);
+ __entry->vector = vector;
+ __entry->start = start;
+ __entry->duration = duration;
+ ),
+
+ TP_printk("%s:%d start %llu.%09u duration %llu ns",
+ __get_str(desc),
+ __entry->vector,
+ __print_ns_to_secs(__entry->start),
+ __print_ns_without_secs(__entry->start),
+ __entry->duration)
+);
+```
+
+
+关于trace\_point这里我们不做过多介绍,感兴趣的读者可以去内核文件`include/trace/events/osnoise.h`下查看相应源代码。
+
+
+## 2.2 注册osnoise tracer
+
+
+这部分主要是涉及到osnoise的初始化过程,该过程主要就是将osnoise注册近ftrace中并且初始化相关的tracefs。注册的过程通过`register_tracer(&osnoise_tracer)`实现。
+
+
+
+```
+static struct tracer osnoise_tracer __read_mostly = {
+ .name = "osnoise",
+ .init = osnoise_tracer_init,
+ .reset = osnoise_tracer_reset,
+ .start = osnoise_tracer_start,
+ .stop = osnoise_tracer_stop,
+ .print_header = print_osnoise_headers,
+ .allow_instances = true,
+};
+```
+
+
+## 2.3 注册tracepoint钩子函数:
+
+
+osnoise 统计信息的方式就是通过在相应的tracepoint中注册钩子函数。因此这部分即是osnoise的核心部分,本篇文章将重点分析该模块。
+
+
+osnoise首先会将各种事件的钩子函数插入对应的tracepoint中,这一动作由`osnoise_hook_events()`函数执行,将该函数裁剪后如下:
+
+
+
+```
+static int osnoise_hook_events(void)
+{
+ ...
+ retval = hook_irq_events();
+ ...
+ retval = hook_softirq_events();
+ ...
+ retval = hook_thread_events();
+ ...
+}
+```
+
+
+该函数主要是针对irq、softirq、thread事件插入一些采样函数。
+
+
+### hook\_irq\_events
+
+
+hook\_irq\_events()主要是实现对irq事件的统计。如下:
+
+
+
+```
+static int hook_irq_events(void)
+{
+ ...
+ ret = register_trace_irq_handler_entry(trace_irqentry_callback, NULL);
+ ...
+ ret = register_trace_irq_handler_exit(trace_irqexit_callback, NULL);
+ ...
+}
+```
+
+
+主要是在irq\_handler\_entry 和 irq\_handler\_exit处插入相应的处理函数。最终插入的处理函数为osnoise\_trace\_irq\_entry() 和 osnoise\_trace\_irq\_exit()。
+
+
+
+```
+void osnoise_trace_irq_entry(int id)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+
+ if (!osn_var->sampling)
+ return;
+
+ osn_var->irq.arrival_time = time_get();
+ set_int_safe_time(osn_var, &osn_var->irq.delta_start);
+ osn_var->irq.count++;
+
+ local_inc(&osn_var->int_counter);
+}
+void osnoise_trace_irq_exit(int id, const char *desc)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+ int duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ duration = get_int_safe_duration(osn_var, &osn_var->irq.delta_start);
+ trace_irq_noise(id, desc, osn_var->irq.arrival_time, duration);
+ osn_var->irq.arrival_time = 0;
+ cond_move_softirq_delta_start(osn_var, duration);
+ cond_move_thread_delta_start(osn_var, duration);
+}
+```
+
+
+在irq handler的入口处插入的函数为osnoise\_trace\_irq\_entry,分析该函数:
+
+
++ 在irq.arrival\_time中记录本次irq事件的开始时间。
++ 在irq.delta\_start中记录本次irq事件的准确开始时间。
++ irq噪声事件的次数+1。
++ 噪声事件总体次数+1。
+
+
+在这里我们发现,除了在irq.arrival\_time中记录了一个irq开始时间之外,还通过set\_int\_safe\_time函数在 irq.delta\_start中都记录了一个开始时间。那么他们之间有什么区别呢?在这里我们先按下不表,后文会对其进行解释分析。
+
+
+在irq handler的出口处插入的函数为osnoise\_trace\_irq\_exit,该函数的主要作用:
+
+
++ 根据之前记录的osn\_var->irq.delta\_start计算出本次irq事件的持续时间。
++ 调用trace\_irq\_noise将本次irq事件的**中断号,中断名称、开始时间、持续时间**放到ftrace的ringbuffer中。
++ 清空osn\_var->irq.arrival\_time 表示此次irq事件结束。
+
+
+我们注意到在该函数的末尾处有cond\_move\_softirq\_delta\_start 以及 cond\_move\_thread\_delta\_start函数。其实形如此类的函数一共有三个:
+
+
++ cond\_move\_irq\_delta\_start
++ cond\_move\_softirq\_delta\_start
++ cond\_move\_thread\_delta\_start
+
+
+函数的形式都是一样的,我们以 cond\_move\_softirq\_delta\_start()为例:
+
+
+
+```
+static inline void
+cond_move_softirq_delta_start(struct osnoise_variables *osn_var, u64 duration)
+{
+ if (osn_var->softirq.delta_start)
+ osn_var->softirq.delta_start += duration;
+}
+```
+
+
++ 这个函数会在osnoise\_trace\_irq\_exit、trace\_osnoise\_callback中调用,前者我们知道是irq事件退出时的钩子函数,而后者则是nmi事件的钩子函数。
++ 可以看到该函数的主要功能是将softirq.delta\_start的开始时间推后一个duration。
+
+
+换句话说,这个函数是为了校准低优先级事件的开始时间。以下图为例:
+
+
++ 在t1时刻进入了softirq,此时记录**softirq.arrival\_time = t1**,**softirq.delta\_time = t1**。
++ 然后在t2时刻,来了一个irq抢占了softirq,进入irq的执行函数。
++ t3时刻离开irq执行完毕继续执行softirq。irq执行时间**duration = t3-t2**。同时调用cond\_move\_softirq\_delta\_start,更新softirq开始时间**softirq.delta\_start += duration;**
++ 在t4时刻softirq执行完毕退出。
+
+
+那么本次softirq的持续时间实际上应该是t4 - (t1 + duration) = t4 - **softirq.delta\_start。**
+
+
+
+
+因此,需要高优先级的对低优先级的事件的时间进行校准。
+
+
++ 对于nmi事件,需要调用
+
+
+- cond\_move\_irq\_delta\_start
+- cond\_move\_softirq\_delta\_start
+- cond\_move\_thread\_delta\_start
+
+
++ 对于irq事件,需要调用
+
+
+- cond\_move\_softirq\_delta\_start
+- cond\_move\_thread\_delta\_start
+
+
++ 对于softirq事件,需要调用
+
+
+- cond\_move\_thread\_delta\_start
+
+
+### hook\_softirq\_events
+
+
+与irq的钩子函数一样,需要注册tracepoint softirq\_entry、softirq\_exit的钩子函数。最终注册的钩子函数如下:
+
+
+
+```
+static void trace_softirq_entry_callback(void *data, unsigned int vec_nr)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+
+ if (!osn_var->sampling)
+ return;
+
+ osn_var->softirq.arrival_time = time_get();
+ set_int_safe_time(osn_var, &osn_var->softirq.delta_start);
+ osn_var->softirq.count++;
+
+ local_inc(&osn_var->int_counter);
+}
+static void trace_softirq_exit_callback(void *data, unsigned int vec_nr)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+ int duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ if (unlikely(timerlat_enabled()))
+ if (!timerlat_softirq_exit(osn_var))
+ return;
+
+ duration = get_int_safe_duration(osn_var, &osn_var->softirq.delta_start);
+ trace_softirq_noise(vec_nr, osn_var->softirq.arrival_time, duration);
+ cond_move_thread_delta_start(osn_var, duration);
+ osn_var->softirq.arrival_time = 0;
+}
+```
+
+
+可以发现对softirq的统计方式与对irq的统计方式一摸一样,在这里我们便不做详细分析,读者可以参考上面对hook\_irq\_events()的分析。
+
+
+### hook\_thread\_events
+
+
+osnoise通过在tracepoint sched\_switch注册钩子函数,来统计thread noise。函数如下所示:
+
+
+
+```
+static void
+trace_sched_switch_callback(void *data, bool preempt,
+ struct task_struct *p,
+ struct task_struct *n,
+ unsigned int prev_state)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+
+ if (p->pid != osn_var->pid)
+ thread_exit(osn_var, p);
+
+ if (n->pid != osn_var->pid)
+ thread_entry(osn_var, n);
+}
+static void
+thread_entry(struct osnoise_variables *osn_var, struct task_struct *t)
+{
+ if (!osn_var->sampling)
+ return;
+ /*
+ * The arrival time will be used in the report, but not to compute
+ * the execution time, so it is safe to get it unsafe.
+ */
+ osn_var->thread.arrival_time = time_get();
+
+ set_int_safe_time(osn_var, &osn_var->thread.delta_start);
+
+ osn_var->thread.count++;
+ local_inc(&osn_var->int_counter);
+}
+static void
+thread_exit(struct osnoise_variables *osn_var, struct task_struct *t)
+{
+ int duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ if (unlikely(timerlat_enabled()))
+ if (!timerlat_thread_exit(osn_var))
+ return;
+
+ duration = get_int_safe_duration(osn_var, &osn_var->thread.delta_start);
+
+ trace_thread_noise(t, osn_var->thread.arrival_time, duration);
+
+ osn_var->thread.arrival_time = 0;
+}
+```
+
+
+sched\_switch()为线程切换的核心函数,在该trace\_sched\_switch函数中的p表示前一个线程,n表示下一个要执行的线程,即从线程p切换到线程n。
+
+
+此时存在三种情况:
+
+
++ 从采样线程切换到其他线程
+
+
+- 执行thread\_entry()函数,标志一个噪声的进入
+
+
++ 从其他线程切换到采样线程
+
+
+- 执行thread\_exit()函数,标志上一个噪声的结束
+
+
++ 从其他线程切换到其他线程
+
+
+- 先执行thread\_exit()函数,标志上一个噪声的结束
+- 再执行thread\_entry()函数,标志下一个噪声的进入
+
+
+换句话说,该钩子函数会统计除了采样线程外其他所有线程执行的时间。其中thread\_entry()和thread\_exit()的具体实现与上面对irq事件统计的函数实现类似,此处不再过多赘述。
+
+
+### nmi\_events
+
+
+对于NMI事件的统计比较特殊,在ftrace\_nmi\_enter和ftrace\_nmi\_exit中直接调用trace\_osnoise\_callback获取nmi noise,并且调用trace\_nmi\_noise将duration放到ftrace的ringbuffer中。
+
+
+
+```
+static inline void ftrace_nmi_exit(void)
+{
+ ...
+ if (trace_osnoise_callback_enabled)
+ trace_osnoise_callback(false);
+ ...
+}
+static inline void ftrace_nmi_exit(void)
+{
+ ...
+ if (trace_osnoise_callback_enabled)
+ trace_osnoise_callback(false);
+ ...
+}
+void trace_osnoise_callback(bool enter)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+ u64 duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ /*
+ * Currently trace_clock_local() calls sched_clock() and the
+ * generic version is not NMI safe.
+ */
+ if (!IS_ENABLED(CONFIG_GENERIC_SCHED_CLOCK)) {
+ if (enter) {
+ osn_var->nmi.delta_start = time_get();
+ local_inc(&osn_var->int_counter);
+ } else {
+ duration = time_get() - osn_var->nmi.delta_start;
+
+ trace_nmi_noise(osn_var->nmi.delta_start, duration);
+
+ cond_move_irq_delta_start(osn_var, duration);
+ cond_move_softirq_delta_start(osn_var, duration);
+ cond_move_thread_delta_start(osn_var, duration);
+ }
+ }
+
+ if (enter)
+ osn_var->nmi.count++;
+}
+```
+
+
+主要函数为trace\_osnoise\_callback(bool enter),该函数通过一个bool值来判断当前是进入nmi中断还是退出nmi中断,进而进行相应的处理,统计方法和其他事件统计方法一直。可以看到在NMI的钩子函数中,会调用到
+
+
++ cond\_move\_irq\_delta\_start(osn\_var, duration);
++ cond\_move\_softirq\_delta\_start(osn\_var, duration);
++ cond\_move\_softirq\_delta\_start(osn\_var, duration);
+
+
+这三个函数去校准其他低优先级事件的统计。与我们之前的分析一致。
+
+
+## 2.4 采样
+
+
+上面介绍了osnoise对各类事件采样的方法,接下来,我们分析一下osnoise的采样流程。osnoise开始采样的函数调用流程为osnoise\_tracer\_start->osnoise\_workload\_start->start\_per\_cpu\_kthreads->start\_kthread->osnoise\_main->run\_osnoise。
+
+
+
+采样的核心函数为run\_osnoise,将代码裁剪后如下:
+
+
+
+```
+static int run_osnoise(void)
+{
+ ...
+
+ threshold = tracing_thresh ? : 5000;
+
+ osn_var->sampling = true;
+
+ runtime = osnoise_data.sample_runtime * NSEC_PER_USEC;
+
+ stop_in = osnoise_data.stop_tracing * NSEC_PER_USEC;
+
+ start = time_get();
+
+ last_int_count = set_int_safe_time(osn_var, &last_sample);
+
+ do {
+
+ int_count = set_int_safe_time(osn_var, &sample);
+
+ noise = time_sub(sample, last_sample);
+
+ total = time_sub(sample, start);
+
+ if (total < last_total) {
+ osnoise_taint("total overflow!");
+ break;
+ }
+
+ last_total = total;
+
+ if (noise >= threshold) {
+ int interference = int_count - last_int_count;
+
+ if (noise > max_noise)
+ max_noise = noise;
+
+ if (!interference)
+ hw_count++;
+
+ sum_noise += noise;
+
+ trace_sample_threshold(last_sample, noise, interference);
+
+ if (osnoise_data.stop_tracing)
+ if (noise > stop_in)
+ osnoise_stop_tracing();
+ }
+
+ last_sample = sample;
+ last_int_count = int_count;
+
+ } while (total < runtime && !kthread_should_stop());
+
+ osn_var->sampling = false;
+
+ ...
+}
+```
+
+
+
+分析采样函数的主体逻辑流程图如下所示:
+
+
+
+
+
+即通过不断的轮询TSC寄存器,将每次轮询的间隙与预设的threshold进行对比,判断是否发生噪声,如果发生了噪声且噪声不是由其他可测量事件所造成的,就认为发生了硬件噪声。
+
+
+其中:
+
+
+* threshold :两次轮询TSC寄存器时间之差,被认为是噪声的最小值,默认设为5us。
+* osn\_var->sampling:标志位,标志是否开启采样。
+* runtime:预设的本次采样时间。
+* start :记录本次采样开始的时间
+* last\_sample : 记录上次读取tsc寄存器的值
+* sample : 记录本次读取tsc寄存器的值
+* noise = time\_sub(sample, last\_sample) : 计算本次和上次轮询tsc寄存器的时间之差。
+* total :记录从采样开始到现在所经历的时间
+* 如果noise >= threshold,则视为发生了噪声,进行统计计算
+
+
++ max\_noise: 记录最大的单个噪声值
++ interference: 记录本次噪声内事件发生的次数,如果为0则代表是硬件噪声。
++ hw\_count: 记录硬件噪声的次数,当interference为0时,增加。
+
+
+* 轮询tsc寄存器,直到total>=runtime,结束本次采样。
+
+
+
+# 三、小结
+
+
+以上便是对osnoise的代码分析。osnoise就是站在一个普通进程的视角上,统计所有会打断他的事件,包含irq、softirq、nmi、thread、hw。
+
+
+对于前四种事件内核中都提供了相应的tracepoint,只需要注册相应的回掉函数到tracepoint中即可统计到相关的信息。而hw无法被直接统计测量,因此在osnoise中就通过不断的轮询tsc寄存器,将任意两次轮询的差值与threshold进行比较,如果大于threshold就认为发生了噪声,当发生噪声时如果其他四个事件都未发生就认为发生了硬件延迟。
+
+
+由于irq、softirq、nmi、thread都有相应的tracepoint可以供我们使用,在不考虑hw的情况下我们其实可以直接在用户态实现相关信息的采集。下篇文章我们会尝试在用户态,利用bcc通过动态插桩的方式来实现一个简单的osnoise背景噪声统计工具。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace_osnoise_\346\200\273\350\247\210.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace_osnoise_\346\200\273\350\247\210.md"
new file mode 100644
index 0000000000000000000000000000000000000000..782c9a33160ade07820bfa6300aa0fd6cc5779c9
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace_osnoise_\346\200\273\350\247\210.md"
@@ -0,0 +1,179 @@
+
+
+
+# Ftrace: osnoise 总览
+
+
+
+
+
+
+
+
+
+
+
+## 一、osnoise是什么?
+
+
+
+
+在linux系统中,一个普通线程在执行过程中会被各种各样的事件所干扰打断,如NMI、IRQ、SOFTIRQ、来自硬件的干扰以及来自其他线程的干扰。这些事件对于一个普通线程来说,就相当于噪声一样的存在。在Linux 5.14-rc1中,引入了一个新的tracer——osnoise tracer。osnoise从一个线程的视角出发,统计出所有对他有干扰的噪声,进而协助开发人员分析系统背景噪声情况。
+
+
+### 1.1 噪声分类
+
+
+在osnoise tracer中,将统计的噪声分为了以下五个大类:
+
+
++ IRQ:硬中断
++ SOFTIRQ:软中断
++ NMI:不可屏蔽中断
++ HW:来自硬件的噪声。
++ THREAD:来自其他线程的影响。
+
+
+其中,HW(hardware latency)表示某些底层硬件或者固件的行为引起的大型系统延迟。在Ftrace中,有一个名为hwlat\_detector的tracer,它的主要目的就是用来检测硬件噪声。osnoise的设计思想借鉴了hwlat\_detector。
+
+
+### 1.2 hwlat
+
+
+hwlat\_detector的工作原理简单来说就是在一段时间内,关闭irq、softirq以及抢占,然后不断的去轮询TSC(Time Stamp Counter)寄存器的值。由于关闭了中断及抢占,任意两次读取之间的间隙都是由于硬件噪声或者来自其他不可屏蔽中断的噪声(NMI)。
+
+
+如图所示:
+
+
+
+
+
+在一段时间内,采样线程不断的去循环读取TSC寄存器,在一个循环内会连续读取两次TSC寄存器。假设本次循环读取的时间分别为t1、t2,上次循环读取的时间为last\_t1、last\_t2。则:
+
+
++ t1与t2的时间之差,last\_t1、last\_t2的时间之差,称为inner\_latency。
++ t1与last\_t2的时间之差,称为outer\_latency。
++ tracing\_thresh为预设的阀值,如果观察到任何超过阀值的延迟就认为发生了噪声事件。
++ 在hwlat中,会不断的计算inner\_latency和outer\_latency。然后将其值与预设的tracing\_thresh值进行对比,如果大于tracing\_thresh,就认为发生了噪声事件。
++ 在hwlat采样期间,会同时追踪nmi中断事件。因此,观察到的任何超过阀值的延迟如果不是nmi造成的,那么就认为是hardware latency。
+
+
+### 1.3 osnoise实现
+
+
+前面我们介绍了hwlat的实现。简而言之,hwlat关闭irq、softirq、抢占等事件,通过不断的轮询TSC寄存器以及追踪NMI中断来探测延迟事件,观察到的任何延迟都是由NMI或者硬件造成的。
+
+
+osnoise的实现思想和hwlat类似,不过osnoise不会关闭irq、softirq、抢占等事件,而是在采样的同时追踪各类事件。在irq\_handler\_entry、irq\_handler\_exit、softirq\_entry、softirq\_exit、sched\_switch、nmi\_enter、nmi\_exit处也插入相应的钩子函数。进而统计出各类事件发生的次数以及持续时间。如果观测到的任意延迟不是由以上时间造成的,那么就认为是硬件噪声。
+
+
+## 二、osnoise tracer
+
+
+### 2.1 配置文件
+
+
+osnoise在`/sys/kernel/debug/tracing/` 目录下有一系列可配置文件, 含义如下:
+
+
+* **osnoise/cpus:** osnoise采样的目标cpu,默认是所有cpu。
+* **osnoise/period\_us:** osnoise线程的周期。默认是1000000ms,即1s。
+* **osnoise/runtime\_us:** osnoise线程在一个周期内的采样时间。默认是1000000ms,即1s。
+* **osnoise/stop\_tracing\_us:** 当单个噪声的最大值超过这个阀值时,停止采样。默认为0,即关闭该选项。
+* **osnoise/stop\_tracing\_total\_us:** 当总计噪声超过这个阀值时,停止采样。默认为0,即关闭该选项。
+* **tracing\_thresh**: 两次轮询TSC寄存器时间之差,被认为是噪声的最小值,单位为us。当配置为0时,默认设为5us。
+
+
+### 2.2 使用方法
+
+
+1. 将osnoise写入的current\_tracer:
+
+
+`echo osnoise > /sys/kernel/debug/tracing/current_tracer`
+
+
+2. 打开traceing\_on:
+
+
+`echo 1 > /sys/kernel/debug/tracing/tracing_on`
+
+
+3. 查看trace结果:
+
+
+`cat /sys/kernel/debug/tracing/trace`
+
+
+
+
+
+
+
+
+这里显示的是系统整体采样的结果各个字段的含义如下:
+
+
+* TASK-PID:采样线程的PID。
+* CPU:采样的CPU ID
+* TIMESTAMP:时间戳
+* RUNTIME IN US:采样时间,单位us
+* NOISE IN US:本次采样时间内的总计噪声时间,单位us。
+* %OF CPU AVAILABLE:在一个RUNTIME周期内,采样线程可以获得的cpu利用率。
+* HW、NMI、IRQ、SIRQ、THREAD:分别表示各类噪声事件发生的次数。
+
+
+## 三、osnoise trace\_point
+
+
+### 3.1 trace\_point
+
+
+osnoise除了提供tracer外,还提供了一组trace\_points,以协助开发人员对噪声进行进一步分析。可以在`/sys/kernel/debug/tracing/events/osnoise/`看到相关tracepoint:
+
+
+* **sample\_threshold:** 追踪任何高于阀值的噪声事件。阀值即为上文提到的tracing\_thresh,默认为5us。
+* **nmi\_noise:** nmi噪声,包含其持续时间。
+* **irq\_noise:** irq噪声,包含其持续时间。
+* **softirq\_noise:** softirq噪声,包含其持续时间
+* **thread\_noise:** 其他线程噪声,包含其持续时间
+
+
+### 3.2 使用方法
+
+
+前面我们已经介绍了osnoise tracer的使用,它可以让我们直观的看到整个系统级别的各种噪声事件的总和。如果我们像看到每种噪声或者是说指定噪声类型的事件的详细信息,就需要用到osnoise提供的trace\_point。
+
+
+打开trace\_point总开关:
+
+
+`echo 1 > /sys/kernel/debug/tracing/events/osnoise/enable`
+
+
+查看trace日志:
+
+
+`cat /sys/kernel/debug/tracing/trace`
+
+
+输出如下所示:
+
+
+
+
+
+
+日志中包含了所有噪声的详细信息,包括其名字,开始事件,持续时间等等。关于其输出的具体格式可以查看对应trace\_point文件夹下的format文件。
+
+
+trace\_ponit文件位置在`/sys/kernel/debug/tracing/events/osnoise/`下。
+
+
+除了总开关外,每个事件有自己单独的开关,在对应tracepoint目录下。如irq\_noise的开关为`/sys/kernel/debug/tracing/events/osnoise/irq_noise/enable`。用户可以根据自己的需求只追踪相应的事件,从而过滤掉其他不需要关注的信息。
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220.md"
new file mode 100644
index 0000000000000000000000000000000000000000..d8d8d5f7ea67371721d640d941991d8ea0ad4191
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220.md"
@@ -0,0 +1,641 @@
+
+
+
+前面一篇文章中,我们简要的介绍了一下osnoise的相关信息,本篇文章主要针对其源代码进行分析阐述。
+
+
+
+# 一、数据结构:
+
+
+
+```
+/*
+ * NMI runtime info.
+ */
+struct osn_nmi {
+ u64 count;
+ u64 delta_start;
+};
+
+/*
+ * IRQ runtime info.
+ */
+struct osn_irq {
+ u64 count;
+ u64 arrival_time;
+ u64 delta_start;
+};
+
+#define IRQ_CONTEXT 0
+#define THREAD_CONTEXT 1
+/*
+ * sofirq runtime info.
+ */
+struct osn_softirq {
+ u64 count;
+ u64 arrival_time;
+ u64 delta_start;
+};
+
+/*
+ * thread runtime info.
+ */
+struct osn_thread {
+ u64 count;
+ u64 arrival_time;
+ u64 delta_start;
+};
+
+/*
+ * Runtime information: this structure saves the runtime information used by
+ * one sampling thread.
+ */
+struct osnoise_variables {
+ struct task_struct *kthread;
+ bool sampling;
+ pid_t pid;
+ struct osn_nmi nmi;
+ struct osn_irq irq;
+ struct osn_softirq softirq;
+ struct osn_thread thread;
+ local_t int_counter;
+};
+```
+
+
+osnoise用来记录结果的主要数据结构为`struct osnoise_variables`其中:
+
+
++ `struct task_struct *kthread`:采样线程的tcb。
++ `bool sampling`:采样开关
++ `pit_t pid`:采样线程的pid
++ `struct osn_nmi nmi`:保存nmi噪声的相关信息
++ `struct osn_irq irq`:保存irq噪声的相关信息
++ `struct osn_softiq softirq`:保存softirq噪声的相关信息
++ `struct osn_thread thread`:保存其他线程噪声的相关信息
++ `local_t int_counter`:保存噪声的总次数
+
+
+
+# 二、工作原理:
+
+
+## 2.1 注册trace\_point
+
+
+如第一篇文章所述,osnoise引入了一组trace\_point。通过这些trace\_point,开发人员可以获取噪声的详细信息。注册trace\_point的代码如下(以irq\_noise为例):
+
+
+
+```
+TRACE_EVENT(irq_noise,
+
+ TP_PROTO(int vector, const char *desc, u64 start, u64 duration),
+
+ TP_ARGS(vector, desc, start, duration),
+
+ TP_STRUCT__entry(
+ __field( u64, start )
+ __field( u64, duration)
+ __string( desc, desc )
+ __field( int, vector )
+
+ ),
+
+ TP_fast_assign(
+ __assign_str(desc, desc);
+ __entry->vector = vector;
+ __entry->start = start;
+ __entry->duration = duration;
+ ),
+
+ TP_printk("%s:%d start %llu.%09u duration %llu ns",
+ __get_str(desc),
+ __entry->vector,
+ __print_ns_to_secs(__entry->start),
+ __print_ns_without_secs(__entry->start),
+ __entry->duration)
+);
+```
+
+
+关于trace\_point这里我们不做过多介绍,感兴趣的读者可以去内核文件`include/trace/events/osnoise.h`下查看相应源代码。
+
+
+## 2.2 注册osnoise tracer
+
+
+这部分主要是涉及到osnoise的初始化过程,该过程主要就是将osnoise注册近ftrace中并且初始化相关的tracefs。注册的过程通过`register_tracer(&osnoise_tracer)`实现。
+
+
+
+```
+static struct tracer osnoise_tracer __read_mostly = {
+ .name = "osnoise",
+ .init = osnoise_tracer_init,
+ .reset = osnoise_tracer_reset,
+ .start = osnoise_tracer_start,
+ .stop = osnoise_tracer_stop,
+ .print_header = print_osnoise_headers,
+ .allow_instances = true,
+};
+```
+
+
+## 2.3 注册tracepoint钩子函数:
+
+
+osnoise 统计信息的方式就是通过在相应的tracepoint中注册钩子函数。因此这部分即是osnoise的核心部分,本篇文章将重点分析该模块。
+
+
+osnoise首先会将各种事件的钩子函数插入对应的tracepoint中,这一动作由`osnoise_hook_events()`函数执行,将该函数裁剪后如下:
+
+
+
+```
+static int osnoise_hook_events(void)
+{
+ ...
+ retval = hook_irq_events();
+ ...
+ retval = hook_softirq_events();
+ ...
+ retval = hook_thread_events();
+ ...
+}
+```
+
+
+该函数主要是针对irq、softirq、thread事件插入一些采样函数。
+
+
+### hook\_irq\_events
+
+
+hook\_irq\_events()主要是实现对irq事件的统计。如下:
+
+
+
+```
+static int hook_irq_events(void)
+{
+ ...
+ ret = register_trace_irq_handler_entry(trace_irqentry_callback, NULL);
+ ...
+ ret = register_trace_irq_handler_exit(trace_irqexit_callback, NULL);
+ ...
+}
+```
+
+
+主要是在irq\_handler\_entry 和 irq\_handler\_exit处插入相应的处理函数。最终插入的处理函数为osnoise\_trace\_irq\_entry() 和 osnoise\_trace\_irq\_exit()。
+
+
+
+```
+void osnoise_trace_irq_entry(int id)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+
+ if (!osn_var->sampling)
+ return;
+
+ osn_var->irq.arrival_time = time_get();
+ set_int_safe_time(osn_var, &osn_var->irq.delta_start);
+ osn_var->irq.count++;
+
+ local_inc(&osn_var->int_counter);
+}
+void osnoise_trace_irq_exit(int id, const char *desc)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+ int duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ duration = get_int_safe_duration(osn_var, &osn_var->irq.delta_start);
+ trace_irq_noise(id, desc, osn_var->irq.arrival_time, duration);
+ osn_var->irq.arrival_time = 0;
+ cond_move_softirq_delta_start(osn_var, duration);
+ cond_move_thread_delta_start(osn_var, duration);
+}
+```
+
+
+在irq handler的入口处插入的函数为osnoise\_trace\_irq\_entry,分析该函数:
+
+
++ 在irq.arrival\_time中记录本次irq事件的开始时间。
++ 在irq.delta\_start中记录本次irq事件的准确开始时间。
++ irq噪声事件的次数+1。
++ 噪声事件总体次数+1。
+
+
+在这里我们发现,除了在irq.arrival\_time中记录了一个irq开始时间之外,还通过set\_int\_safe\_time函数在 irq.delta\_start中都记录了一个开始时间。那么他们之间有什么区别呢?在这里我们先按下不表,后文会对其进行解释分析。
+
+
+在irq handler的出口处插入的函数为osnoise\_trace\_irq\_exit,该函数的主要作用:
+
+
++ 根据之前记录的osn\_var->irq.delta\_start计算出本次irq事件的持续时间。
++ 调用trace\_irq\_noise将本次irq事件的**中断号,中断名称、开始时间、持续时间**放到ftrace的ringbuffer中。
++ 清空osn\_var->irq.arrival\_time 表示此次irq事件结束。
+
+
+我们注意到在该函数的末尾处有cond\_move\_softirq\_delta\_start 以及 cond\_move\_thread\_delta\_start函数。其实形如此类的函数一共有三个:
+
+
++ cond\_move\_irq\_delta\_start
++ cond\_move\_softirq\_delta\_start
++ cond\_move\_thread\_delta\_start
+
+
+函数的形式都是一样的,我们以 cond\_move\_softirq\_delta\_start()为例:
+
+
+
+```
+static inline void
+cond_move_softirq_delta_start(struct osnoise_variables *osn_var, u64 duration)
+{
+ if (osn_var->softirq.delta_start)
+ osn_var->softirq.delta_start += duration;
+}
+```
+
+
++ 这个函数会在osnoise\_trace\_irq\_exit、trace\_osnoise\_callback中调用,前者我们知道是irq事件退出时的钩子函数,而后者则是nmi事件的钩子函数。
++ 可以看到该函数的主要功能是将softirq.delta\_start的开始时间推后一个duration。
+
+
+换句话说,这个函数是为了校准低优先级事件的开始时间。以下图为例:
+
+
++ 在t1时刻进入了softirq,此时记录**softirq.arrival\_time = t1**,**softirq.delta\_time = t1**。
++ 然后在t2时刻,来了一个irq抢占了softirq,进入irq的执行函数。
++ t3时刻离开irq执行完毕继续执行softirq。irq执行时间**duration = t3-t2**。同时调用cond\_move\_softirq\_delta\_start,更新softirq开始时间**softirq.delta\_start += duration;**
++ 在t4时刻softirq执行完毕退出。
+
+
+那么本次softirq的持续时间实际上应该是t4 - (t1 + duration) = t4 - **softirq.delta\_start。**
+
+
+
+
+因此,需要高优先级的对低优先级的事件的时间进行校准。
+
+
++ 对于nmi事件,需要调用
+
+
+- cond\_move\_irq\_delta\_start
+- cond\_move\_softirq\_delta\_start
+- cond\_move\_thread\_delta\_start
+
+
++ 对于irq事件,需要调用
+
+
+- cond\_move\_softirq\_delta\_start
+- cond\_move\_thread\_delta\_start
+
+
++ 对于softirq事件,需要调用
+
+
+- cond\_move\_thread\_delta\_start
+
+
+### hook\_softirq\_events
+
+
+与irq的钩子函数一样,需要注册tracepoint softirq\_entry、softirq\_exit的钩子函数。最终注册的钩子函数如下:
+
+
+
+```
+static void trace_softirq_entry_callback(void *data, unsigned int vec_nr)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+
+ if (!osn_var->sampling)
+ return;
+
+ osn_var->softirq.arrival_time = time_get();
+ set_int_safe_time(osn_var, &osn_var->softirq.delta_start);
+ osn_var->softirq.count++;
+
+ local_inc(&osn_var->int_counter);
+}
+static void trace_softirq_exit_callback(void *data, unsigned int vec_nr)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+ int duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ if (unlikely(timerlat_enabled()))
+ if (!timerlat_softirq_exit(osn_var))
+ return;
+
+ duration = get_int_safe_duration(osn_var, &osn_var->softirq.delta_start);
+ trace_softirq_noise(vec_nr, osn_var->softirq.arrival_time, duration);
+ cond_move_thread_delta_start(osn_var, duration);
+ osn_var->softirq.arrival_time = 0;
+}
+```
+
+
+可以发现对softirq的统计方式与对irq的统计方式一摸一样,在这里我们便不做详细分析,读者可以参考上面对hook\_irq\_events()的分析。
+
+
+### hook\_thread\_events
+
+
+osnoise通过在tracepoint sched\_switch注册钩子函数,来统计thread noise。函数如下所示:
+
+
+
+```
+static void
+trace_sched_switch_callback(void *data, bool preempt,
+ struct task_struct *p,
+ struct task_struct *n,
+ unsigned int prev_state)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+
+ if (p->pid != osn_var->pid)
+ thread_exit(osn_var, p);
+
+ if (n->pid != osn_var->pid)
+ thread_entry(osn_var, n);
+}
+static void
+thread_entry(struct osnoise_variables *osn_var, struct task_struct *t)
+{
+ if (!osn_var->sampling)
+ return;
+ /*
+ * The arrival time will be used in the report, but not to compute
+ * the execution time, so it is safe to get it unsafe.
+ */
+ osn_var->thread.arrival_time = time_get();
+
+ set_int_safe_time(osn_var, &osn_var->thread.delta_start);
+
+ osn_var->thread.count++;
+ local_inc(&osn_var->int_counter);
+}
+static void
+thread_exit(struct osnoise_variables *osn_var, struct task_struct *t)
+{
+ int duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ if (unlikely(timerlat_enabled()))
+ if (!timerlat_thread_exit(osn_var))
+ return;
+
+ duration = get_int_safe_duration(osn_var, &osn_var->thread.delta_start);
+
+ trace_thread_noise(t, osn_var->thread.arrival_time, duration);
+
+ osn_var->thread.arrival_time = 0;
+}
+```
+
+
+sched\_switch()为线程切换的核心函数,在该trace\_sched\_switch函数中的p表示前一个线程,n表示下一个要执行的线程,即从线程p切换到线程n。
+
+
+此时存在三种情况:
+
+
++ 从采样线程切换到其他线程
+
+
+- 执行thread\_entry()函数,标志一个噪声的进入
+
+
++ 从其他线程切换到采样线程
+
+
+- 执行thread\_exit()函数,标志上一个噪声的结束
+
+
++ 从其他线程切换到其他线程
+
+
+- 先执行thread\_exit()函数,标志上一个噪声的结束
+- 再执行thread\_entry()函数,标志下一个噪声的进入
+
+
+换句话说,该钩子函数会统计除了采样线程外其他所有线程执行的时间。其中thread\_entry()和thread\_exit()的具体实现与上面对irq事件统计的函数实现类似,此处不再过多赘述。
+
+
+### nmi\_events
+
+
+对于NMI事件的统计比较特殊,在ftrace\_nmi\_enter和ftrace\_nmi\_exit中直接调用trace\_osnoise\_callback获取nmi noise,并且调用trace\_nmi\_noise将duration放到ftrace的ringbuffer中。
+
+
+
+```
+static inline void ftrace_nmi_exit(void)
+{
+ ...
+ if (trace_osnoise_callback_enabled)
+ trace_osnoise_callback(false);
+ ...
+}
+static inline void ftrace_nmi_exit(void)
+{
+ ...
+ if (trace_osnoise_callback_enabled)
+ trace_osnoise_callback(false);
+ ...
+}
+void trace_osnoise_callback(bool enter)
+{
+ struct osnoise_variables *osn_var = this_cpu_osn_var();
+ u64 duration;
+
+ if (!osn_var->sampling)
+ return;
+
+ /*
+ * Currently trace_clock_local() calls sched_clock() and the
+ * generic version is not NMI safe.
+ */
+ if (!IS_ENABLED(CONFIG_GENERIC_SCHED_CLOCK)) {
+ if (enter) {
+ osn_var->nmi.delta_start = time_get();
+ local_inc(&osn_var->int_counter);
+ } else {
+ duration = time_get() - osn_var->nmi.delta_start;
+
+ trace_nmi_noise(osn_var->nmi.delta_start, duration);
+
+ cond_move_irq_delta_start(osn_var, duration);
+ cond_move_softirq_delta_start(osn_var, duration);
+ cond_move_thread_delta_start(osn_var, duration);
+ }
+ }
+
+ if (enter)
+ osn_var->nmi.count++;
+}
+```
+
+
+主要函数为trace\_osnoise\_callback(bool enter),该函数通过一个bool值来判断当前是进入nmi中断还是退出nmi中断,进而进行相应的处理,统计方法和其他事件统计方法一直。可以看到在NMI的钩子函数中,会调用到
+
+
++ cond\_move\_irq\_delta\_start(osn\_var, duration);
++ cond\_move\_softirq\_delta\_start(osn\_var, duration);
++ cond\_move\_softirq\_delta\_start(osn\_var, duration);
+
+
+这三个函数去校准其他低优先级事件的统计。与我们之前的分析一致。
+
+
+## 2.4 采样
+
+
+上面介绍了osnoise对各类事件采样的方法,接下来,我们分析一下osnoise的采样流程。osnoise开始采样的函数调用流程为osnoise\_tracer\_start->osnoise\_workload\_start->start\_per\_cpu\_kthreads->start\_kthread->osnoise\_main->run\_osnoise。
+
+
+
+采样的核心函数为run\_osnoise,将代码裁剪后如下:
+
+
+
+```
+static int run_osnoise(void)
+{
+ ...
+
+ threshold = tracing_thresh ? : 5000;
+
+ osn_var->sampling = true;
+
+ runtime = osnoise_data.sample_runtime * NSEC_PER_USEC;
+
+ stop_in = osnoise_data.stop_tracing * NSEC_PER_USEC;
+
+ start = time_get();
+
+ last_int_count = set_int_safe_time(osn_var, &last_sample);
+
+ do {
+
+ int_count = set_int_safe_time(osn_var, &sample);
+
+ noise = time_sub(sample, last_sample);
+
+ total = time_sub(sample, start);
+
+ if (total < last_total) {
+ osnoise_taint("total overflow!");
+ break;
+ }
+
+ last_total = total;
+
+ if (noise >= threshold) {
+ int interference = int_count - last_int_count;
+
+ if (noise > max_noise)
+ max_noise = noise;
+
+ if (!interference)
+ hw_count++;
+
+ sum_noise += noise;
+
+ trace_sample_threshold(last_sample, noise, interference);
+
+ if (osnoise_data.stop_tracing)
+ if (noise > stop_in)
+ osnoise_stop_tracing();
+ }
+
+ last_sample = sample;
+ last_int_count = int_count;
+
+ } while (total < runtime && !kthread_should_stop());
+
+ osn_var->sampling = false;
+
+ ...
+}
+```
+
+
+
+分析采样函数的主体逻辑流程图如下所示:
+
+
+
+
+
+即通过不断的轮询TSC寄存器,将每次轮询的间隙与预设的threshold进行对比,判断是否发生噪声,如果发生了噪声且噪声不是由其他可测量事件所造成的,就认为发生了硬件噪声。
+
+
+其中:
+
+
+* threshold :两次轮询TSC寄存器时间之差,被认为是噪声的最小值,默认设为5us。
+* osn\_var->sampling:标志位,标志是否开启采样。
+* runtime:预设的本次采样时间。
+* start :记录本次采样开始的时间
+* last\_sample : 记录上次读取tsc寄存器的值
+* sample : 记录本次读取tsc寄存器的值
+* noise = time\_sub(sample, last\_sample) : 计算本次和上次轮询tsc寄存器的时间之差。
+* total :记录从采样开始到现在所经历的时间
+* 如果noise >= threshold,则视为发生了噪声,进行统计计算
+
+
++ max\_noise: 记录最大的单个噪声值
++ interference: 记录本次噪声内事件发生的次数,如果为0则代表是硬件噪声。
++ hw\_count: 记录硬件噪声的次数,当interference为0时,增加。
+
+
+* 轮询tsc寄存器,直到total>=runtime,结束本次采样。
+
+
+
+# 三、小结
+
+
+以上便是对osnoise的代码分析。osnoise就是站在一个普通进程的视角上,统计所有会打断他的事件,包含irq、softirq、nmi、thread、hw。
+
+
+对于前四种事件内核中都提供了相应的tracepoint,只需要注册相应的回掉函数到tracepoint中即可统计到相关的信息。而hw无法被直接统计测量,因此在osnoise中就通过不断的轮询tsc寄存器,将任意两次轮询的差值与threshold进行比较,如果大于threshold就认为发生了噪声,当发生噪声时如果其他四个事件都未发生就认为发生了硬件延迟。
+
+
+由于irq、softirq、nmi、thread都有相应的tracepoint可以供我们使用,在不考虑hw的情况下我们其实可以直接在用户态实现相关信息的采集。下篇文章我们会尝试在用户态,利用bcc通过动态插桩的方式来实现一个简单的osnoise背景噪声统计工具。
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210.md"
new file mode 100644
index 0000000000000000000000000000000000000000..782c9a33160ade07820bfa6300aa0fd6cc5779c9
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210.md"
@@ -0,0 +1,179 @@
+
+
+
+# Ftrace: osnoise 总览
+
+
+
+
+
+
+
+
+
+
+
+## 一、osnoise是什么?
+
+
+
+
+在linux系统中,一个普通线程在执行过程中会被各种各样的事件所干扰打断,如NMI、IRQ、SOFTIRQ、来自硬件的干扰以及来自其他线程的干扰。这些事件对于一个普通线程来说,就相当于噪声一样的存在。在Linux 5.14-rc1中,引入了一个新的tracer——osnoise tracer。osnoise从一个线程的视角出发,统计出所有对他有干扰的噪声,进而协助开发人员分析系统背景噪声情况。
+
+
+### 1.1 噪声分类
+
+
+在osnoise tracer中,将统计的噪声分为了以下五个大类:
+
+
++ IRQ:硬中断
++ SOFTIRQ:软中断
++ NMI:不可屏蔽中断
++ HW:来自硬件的噪声。
++ THREAD:来自其他线程的影响。
+
+
+其中,HW(hardware latency)表示某些底层硬件或者固件的行为引起的大型系统延迟。在Ftrace中,有一个名为hwlat\_detector的tracer,它的主要目的就是用来检测硬件噪声。osnoise的设计思想借鉴了hwlat\_detector。
+
+
+### 1.2 hwlat
+
+
+hwlat\_detector的工作原理简单来说就是在一段时间内,关闭irq、softirq以及抢占,然后不断的去轮询TSC(Time Stamp Counter)寄存器的值。由于关闭了中断及抢占,任意两次读取之间的间隙都是由于硬件噪声或者来自其他不可屏蔽中断的噪声(NMI)。
+
+
+如图所示:
+
+
+
+
+
+在一段时间内,采样线程不断的去循环读取TSC寄存器,在一个循环内会连续读取两次TSC寄存器。假设本次循环读取的时间分别为t1、t2,上次循环读取的时间为last\_t1、last\_t2。则:
+
+
++ t1与t2的时间之差,last\_t1、last\_t2的时间之差,称为inner\_latency。
++ t1与last\_t2的时间之差,称为outer\_latency。
++ tracing\_thresh为预设的阀值,如果观察到任何超过阀值的延迟就认为发生了噪声事件。
++ 在hwlat中,会不断的计算inner\_latency和outer\_latency。然后将其值与预设的tracing\_thresh值进行对比,如果大于tracing\_thresh,就认为发生了噪声事件。
++ 在hwlat采样期间,会同时追踪nmi中断事件。因此,观察到的任何超过阀值的延迟如果不是nmi造成的,那么就认为是hardware latency。
+
+
+### 1.3 osnoise实现
+
+
+前面我们介绍了hwlat的实现。简而言之,hwlat关闭irq、softirq、抢占等事件,通过不断的轮询TSC寄存器以及追踪NMI中断来探测延迟事件,观察到的任何延迟都是由NMI或者硬件造成的。
+
+
+osnoise的实现思想和hwlat类似,不过osnoise不会关闭irq、softirq、抢占等事件,而是在采样的同时追踪各类事件。在irq\_handler\_entry、irq\_handler\_exit、softirq\_entry、softirq\_exit、sched\_switch、nmi\_enter、nmi\_exit处也插入相应的钩子函数。进而统计出各类事件发生的次数以及持续时间。如果观测到的任意延迟不是由以上时间造成的,那么就认为是硬件噪声。
+
+
+## 二、osnoise tracer
+
+
+### 2.1 配置文件
+
+
+osnoise在`/sys/kernel/debug/tracing/` 目录下有一系列可配置文件, 含义如下:
+
+
+* **osnoise/cpus:** osnoise采样的目标cpu,默认是所有cpu。
+* **osnoise/period\_us:** osnoise线程的周期。默认是1000000ms,即1s。
+* **osnoise/runtime\_us:** osnoise线程在一个周期内的采样时间。默认是1000000ms,即1s。
+* **osnoise/stop\_tracing\_us:** 当单个噪声的最大值超过这个阀值时,停止采样。默认为0,即关闭该选项。
+* **osnoise/stop\_tracing\_total\_us:** 当总计噪声超过这个阀值时,停止采样。默认为0,即关闭该选项。
+* **tracing\_thresh**: 两次轮询TSC寄存器时间之差,被认为是噪声的最小值,单位为us。当配置为0时,默认设为5us。
+
+
+### 2.2 使用方法
+
+
+1. 将osnoise写入的current\_tracer:
+
+
+`echo osnoise > /sys/kernel/debug/tracing/current_tracer`
+
+
+2. 打开traceing\_on:
+
+
+`echo 1 > /sys/kernel/debug/tracing/tracing_on`
+
+
+3. 查看trace结果:
+
+
+`cat /sys/kernel/debug/tracing/trace`
+
+
+
+
+
+
+
+
+这里显示的是系统整体采样的结果各个字段的含义如下:
+
+
+* TASK-PID:采样线程的PID。
+* CPU:采样的CPU ID
+* TIMESTAMP:时间戳
+* RUNTIME IN US:采样时间,单位us
+* NOISE IN US:本次采样时间内的总计噪声时间,单位us。
+* %OF CPU AVAILABLE:在一个RUNTIME周期内,采样线程可以获得的cpu利用率。
+* HW、NMI、IRQ、SIRQ、THREAD:分别表示各类噪声事件发生的次数。
+
+
+## 三、osnoise trace\_point
+
+
+### 3.1 trace\_point
+
+
+osnoise除了提供tracer外,还提供了一组trace\_points,以协助开发人员对噪声进行进一步分析。可以在`/sys/kernel/debug/tracing/events/osnoise/`看到相关tracepoint:
+
+
+* **sample\_threshold:** 追踪任何高于阀值的噪声事件。阀值即为上文提到的tracing\_thresh,默认为5us。
+* **nmi\_noise:** nmi噪声,包含其持续时间。
+* **irq\_noise:** irq噪声,包含其持续时间。
+* **softirq\_noise:** softirq噪声,包含其持续时间
+* **thread\_noise:** 其他线程噪声,包含其持续时间
+
+
+### 3.2 使用方法
+
+
+前面我们已经介绍了osnoise tracer的使用,它可以让我们直观的看到整个系统级别的各种噪声事件的总和。如果我们像看到每种噪声或者是说指定噪声类型的事件的详细信息,就需要用到osnoise提供的trace\_point。
+
+
+打开trace\_point总开关:
+
+
+`echo 1 > /sys/kernel/debug/tracing/events/osnoise/enable`
+
+
+查看trace日志:
+
+
+`cat /sys/kernel/debug/tracing/trace`
+
+
+输出如下所示:
+
+
+
+
+
+
+日志中包含了所有噪声的详细信息,包括其名字,开始事件,持续时间等等。关于其输出的具体格式可以查看对应trace\_point文件夹下的format文件。
+
+
+trace\_ponit文件位置在`/sys/kernel/debug/tracing/events/osnoise/`下。
+
+
+除了总开关外,每个事件有自己单独的开关,在对应tracepoint目录下。如irq\_noise的开关为`/sys/kernel/debug/tracing/events/osnoise/irq_noise/enable`。用户可以根据自己的需求只追踪相应的事件,从而过滤掉其他不需要关注的信息。
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220.md"
new file mode 100644
index 0000000000000000000000000000000000000000..41ecbb17a91a745ddf9bfa70e2f998fafefc6a53
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220.md"
@@ -0,0 +1,558 @@
+
+
+
+作者:新绎
+
+
+
+# 写在前面
+
+
+pstore中提供了多种前端来实现捕获各种系统信息来加以调试。这篇文章中,我们会对pstore其中之一的前端`PSTORE\_CONSOLE`进行分析,从原理上分析pstore如何获取kernel printk的信息。
+
+
+# pstore console注册
+
+
+`pstore console`前端注册函数在`fs/pstore/platform.c`中被定义,通过后端初始化过程中被调用并注册,从而能够在系统执行`prink`时获取输出信息,并通过`write`方法将`prink`的输出写入到相应的后端当中。
+
+
+
+```
+static void pstore_console_write(struct console *con, const char *s, unsigned c)
+{
+ struct pstore_record record;
+
+ if (!c)
+ return;
+
+ pstore_record_init(&record, psinfo);
+ record.type = PSTORE_TYPE_CONSOLE;
+
+ record.buf = (char *)s;
+ record.size = c;
+ psinfo->write(&record);
+}
+
+static struct console pstore_console = {
+ .write = pstore_console_write,
+ .index = -1,
+};
+
+static void pstore_register_console(void)
+{
+ /* Show which backend is going to get console writes. */
+ strscpy(pstore_console.name, psinfo->name,
+ sizeof(pstore_console.name));
+ /*
+ * Always initialize flags here since prior unregister_console()
+ * calls may have changed settings (specifically CON_ENABLED).
+ */
+ pstore_console.flags = CON_PRINTBUFFER | CON_ENABLED | CON_ANYTIME;
+ register_console(&pstore_console);
+}
+```
+
+
+其中,pstore\_console的flag开启了3个选项:`CON\_PRINTBUFFER`,`CON\_ENABLED`和`CON\_ANYTIME`。
+
+
+`CON\_PRINTBUFFER`:只有开启了才会接受prink的输出
+
+
+`CON\_ENABLED`:console使能,如果没有开启这个flag需要手动使能(在cmdline中定义)
+
+
+`CON\_ANYTIME`:可以在cpu离线时进行调用
+
+
+
+```
+//console.h
+/*
+ * The interface for a console, or any other device that wants to capture
+ * console messages (printer driver?)
+ *
+ * If a console driver is marked CON_BOOT then it will be auto-unregistered
+ * when the first real console is registered. This is for early-printk drivers.
+ */
+
+#define CON_PRINTBUFFER (1)
+#define CON_CONSDEV (2) /* Last on the command line */
+#define CON_ENABLED (4)
+#define CON_BOOT (8)
+#define CON_ANYTIME (16) /* Safe to call when cpu is offline */
+#define CON_BRL (32) /* Used for a braille device */
+#define CON_EXTENDED (64) /* Use the extended output format a la /dev/kmsg */
+
+struct console {
+ char name[16];
+ void (*write)(struct console *, const char *, unsigned);
+ int (*read)(struct console *, char *, unsigned);
+ struct tty_driver *(*device)(struct console *, int *);
+ void (*unblank)(void);
+ int (*setup)(struct console *, char *);
+ int (*match)(struct console *, char *name, int idx, char *options);
+ short flags;
+ short index;
+ int cflag;
+ void *data;
+ struct console *next;
+};
+```
+
+
+# printk总览
+
+
+
+
+
+
+# printk向console输出过程分析
+
+
+pstore中注册好console之后,console会被动地获取printk的输出,接下来我们分析printk是对console进行输出。
+
+
+## cmdline解析
+
+
+如果console的flag中定义了`CON\_ENABLED`,那么console会默认使能。如果没有定义,则需要在cmdline中手动使能。
+
+
+`kernel/printk.c`中将`'console='`的解析函数`console\_setup`注册到`obs\_kernel\_param`,在kernel启动过程中会遍历所有`obs\_kernel\_param`,接着会调用`console\_setup`来解析。
+
+
+我们通过在cmdline中定义`console=xxx`则能够被`console\_setup`所解析并使能相应的console。
+
+
+
+参数是`'console='`的值字符串,如“ttyS0,115200”,`console\_setup`对`console=`参数值做解析,以ttyS0,115200为例,`buf=“ttyS”`,`idx=0`,`options="115200"`,`brl\_options=NULL`。
+
+
+
+```
+//printk.c 解析cmdline
+/*
+ * Set up a console. Called via do_early_param() in init/main.c
+ * for each "console=" parameter in the boot command line.
+ */
+static int __init console_setup(char *str)
+{
+ char buf[sizeof(console_cmdline[0].name) + 4]; /* 4 for "ttyS" */
+ char *s, *options, *brl_options = NULL;
+ int idx;
+
+ if (_braille_console_setup(&str, &brl_options))
+ return 1;
+
+ /*
+ * Decode str into name, index, options.
+ */
+ if (str[0] >= '0' && str[0] <= '9') {
+ strcpy(buf, "ttyS");
+ strncpy(buf + 4, str, sizeof(buf) - 5);
+ } else {
+ strncpy(buf, str, sizeof(buf) - 1);
+ }
+ buf[sizeof(buf) - 1] = 0;
+ options = strchr(str, ',');
+ if (options)
+ *(options++) = 0;
+#ifdef __sparc__
+ if (!strcmp(str, "ttya"))
+ strcpy(buf, "ttyS0");
+ if (!strcmp(str, "ttyb"))
+ strcpy(buf, "ttyS1");
+#endif
+ for (s = buf; *s; s++)
+ if (isdigit(*s) || *s == ',')
+ break;
+ idx = simple_strtoul(s, NULL, 10);
+ *s = 0;
+
+ __add_preferred_console(buf, idx, options, brl_options);
+ console_set_on_cmdline = 1;
+ return 1;
+}
+__setup("console=", console_setup);
+```
+
+
+`console\_setup`最后调用`\_\_add\_preferred\_console`:
+
+
+kernel利用结构体数组`console\_cmdline[8]`,最多可支持8个cmdline传入的console参数。
+
+
+`\_\_add\_preferred\_console`将name,idx,options保存到数组下一个成员`console\_cmdline`结构体中,如果数组中已有重名,则不添加,并置`selected\_console`为最新添加的`console\_cmdline`的下标。
+
+
+
+**一个例子:**
+
+
+如cmdline中有“console=ttyS0,115200 console=ttyS1,9600”
+
+
+则在`console\_cmdline[8]`数组中`console\_cmdline[0]`代表ttyS0,`console\_cmdline[1]`代表ttyS1,而`preferred\_console=1`。
+
+
+
+```
+//printk.c __add_preferred_console
+static int __add_preferred_console(char *name, int idx, char *options,
+ char *brl_options)
+{
+ struct console_cmdline *c;
+ int i;
+
+ /*
+ * See if this tty is not yet registered, and
+ * if we have a slot free.
+ */
+ for (i = 0, c = console_cmdline;
+ i < MAX_CMDLINECONSOLES && c->name[0];
+ i++, c++) {
+ if (strcmp(c->name, name) == 0 && c->index == idx) {
+ if (!brl_options)
+ preferred_console = i;
+ return 0;
+ }
+ }
+ if (i == MAX_CMDLINECONSOLES)
+ return -E2BIG;
+ if (!brl_options)
+ preferred_console = i;
+ strlcpy(c->name, name, sizeof(c->name));
+ c->options = options;
+ braille_set_options(c, brl_options);
+
+ c->index = idx;
+ return 0;
+}
+```
+
+
+## printk console选择
+
+
+printk内容会一直存在log\_buf中,log\_buf满了之后则会从头在开始存,覆盖掉原来的数据。
+
+
+log\_buf的大小由kernel `menuconfig`中的`CONFIG\_LOG\_BUF\_SHIFT`配置。
+
+
+根据printk的实现原理,printk最后调用`console\_unlock`实现log\_buf数据刷出到设备。
+
+
+kernel下每次printk打印,首先存log\_buf,然后遍历console\_drivers,找到合适console(如果有`execlusive\_console`,则往`execlusive\_console`写,如果没有,则为所有使能的console),刷出log。
+
+
+**默认情况下**`**execlusive\_console=NULL**`,所以printk默认是向所有enable的console写
+
+
+只有一种情况是指定`execlusive\_console`,就是在console注册时
+
+
+
+```
+//printk.c call_console_drivers
+/*
+ * Call the console drivers, asking them to write out
+ * log_buf[start] to log_buf[end - 1].
+ * The console_lock must be held.
+ */
+static void call_console_drivers(const char *ext_text, size_t ext_len,
+ const char *text, size_t len)
+{
+ struct console *con;
+
+ trace_console_rcuidle(text, len);
+
+ if (!console_drivers)
+ return;
+
+ for_each_console(con) {
+ if (exclusive_console && con != exclusive_console)
+ continue;
+ if (!(con->flags & CON_ENABLED))
+ continue;
+ if (!con->write)
+ continue;
+ if (!cpu_online(smp_processor_id()) &&
+ !(con->flags & CON_ANYTIME))
+ continue;
+ if (con->flags & CON_EXTENDED)
+ con->write(con, ext_text, ext_len);
+ else
+ con->write(con, text, len);
+ }
+}
+```
+
+
+## printk console注册
+
+
+注意:linux提供了early console机制(通过`CONFIG\_EARLY\_PRINTK`进行使能),用于实现为设备注册console之前的早期log的输出,对应console也称为boot console,简称bcon。这个console在kernel启动的早期阶段就会被注册,主要通过输出设备(比如串口设备)的简单的write方法直接进行数据打印。而这个write方法也就是平台实现。这时候作为输出的串口设备是基于bootloader中已经初始化完成的。
+
+
+
+1. 如果注册的是bootconsole(kernel早期启动打印),需要检查console\_drivers中没有real console,也就是说bootconsole必须是第一个注册的console。
+2. 检查new console是否是cmdline指定的console,如果是,则使能(`CON\_ENABLE`)并初始化该console
+3. 如果该new console没有使能,退出
+4. 如果new console为bootconsole,则newcon不需要输出register之前的log(`newcon->flags &= ~CON\_PRINTBUFFER`),因为如果bootconsole和new console是同一个设备则会之前的log就输出2次
+5. 把new console加入`console\_drivers`链表,对于置位`CON\_CONSDEV`的console,放在链表首
+6. 加锁
+7. 如果new console置位`CON\_PRINTBUFFER`,则将log全部刷出(暂时修改printk输出的指定唯一`exclusive\_console`为new console,保证将之前的log只输出到new console)
+8. 解锁(console\_unlock()会重新把`exclusive\_console`设置为NULL)
+9. 如果有bootconsole并且不是作为real console继续使用,则unregister bootconsole(从`console\_drivers`中删掉)
+
+```
+//printk.c register_console
+/*
+ * The console driver calls this routine during kernel initialization
+ * to register the console printing procedure with printk() and to
+ * print any messages that were printed by the kernel before the
+ * console driver was initialized.
+ *
+ * This can happen pretty early during the boot process (because of
+ * early_printk) - sometimes before setup_arch() completes - be careful
+ * of what kernel features are used - they may not be initialised yet.
+ *
+ * There are two types of consoles - bootconsoles (early_printk) and
+ * "real" consoles (everything which is not a bootconsole) which are
+ * handled differently.
+ * - Any number of bootconsoles can be registered at any time.
+ * - As soon as a "real" console is registered, all bootconsoles
+ * will be unregistered automatically.
+ * - Once a "real" console is registered, any attempt to register a
+ * bootconsoles will be rejected
+ */
+void register_console(struct console *newcon)
+{
+ int i;
+ unsigned long flags;
+ struct console *bcon = NULL;
+ struct console_cmdline *c;
+ static bool has_preferred;
+
+ if (console_drivers)
+ for_each_console(bcon)
+ if (WARN(bcon == newcon,
+ "console '%s%d' already registered\n",
+ bcon->name, bcon->index))
+ return;
+
+ /*
+ * before we register a new CON_BOOT console, make sure we don't
+ * already have a valid console
+ */
+ if (console_drivers && newcon->flags & CON_BOOT) {
+ /* find the last or real console */
+ for_each_console(bcon) {
+ if (!(bcon->flags & CON_BOOT)) {
+ pr_info("Too late to register bootconsole %s%d\n",
+ newcon->name, newcon->index);
+ return;
+ }
+ }
+ }
+
+ if (console_drivers && console_drivers->flags & CON_BOOT)
+ bcon = console_drivers;
+
+ if (!has_preferred || bcon || !console_drivers)
+ has_preferred = preferred_console >= 0;
+
+ /*
+ * See if we want to use this console driver. If we
+ * didn't select a console we take the first one
+ * that registers here.
+ */
+ if (!has_preferred) {
+ if (newcon->index < 0)
+ newcon->index = 0;
+ if (newcon->setup == NULL ||
+ newcon->setup(newcon, NULL) == 0) {
+ newcon->flags |= CON_ENABLED;
+ if (newcon->device) {
+ newcon->flags |= CON_CONSDEV;
+ has_preferred = true;
+ }
+ }
+ }
+
+ /*
+ * See if this console matches one we selected on
+ * the command line.
+ */
+ for (i = 0, c = console_cmdline;
+ i < MAX_CMDLINECONSOLES && c->name[0];
+ i++, c++) {
+ if (!newcon->match ||
+ newcon->match(newcon, c->name, c->index, c->options) != 0) {
+ /* default matching */
+ BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name));
+ if (strcmp(c->name, newcon->name) != 0)
+ continue;
+ if (newcon->index >= 0 &&
+ newcon->index != c->index)
+ continue;
+ if (newcon->index < 0)
+ newcon->index = c->index;
+
+ if (_braille_register_console(newcon, c))
+ return;
+
+ if (newcon->setup &&
+ newcon->setup(newcon, c->options) != 0)
+ break;
+ }
+
+ newcon->flags |= CON_ENABLED;
+ if (i == preferred_console) {
+ newcon->flags |= CON_CONSDEV;
+ has_preferred = true;
+ }
+ break;
+ }
+
+ if (!(newcon->flags & CON_ENABLED))
+ return;
+
+ /*
+ * If we have a bootconsole, and are switching to a real console,
+ * don't print everything out again, since when the boot console, and
+ * the real console are the same physical device, it's annoying to
+ * see the beginning boot messages twice
+ */
+ if (bcon && ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV))
+ newcon->flags &= ~CON_PRINTBUFFER;
+
+ /*
+ * Put this console in the list - keep the
+ * preferred driver at the head of the list.
+ */
+ console_lock();
+ if ((newcon->flags & CON_CONSDEV) || console_drivers == NULL) {
+ newcon->next = console_drivers;
+ console_drivers = newcon;
+ if (newcon->next)
+ newcon->next->flags &= ~CON_CONSDEV;
+ } else {
+ newcon->next = console_drivers->next;
+ console_drivers->next = newcon;
+ }
+
+ if (newcon->flags & CON_EXTENDED)
+ if (!nr_ext_console_drivers++)
+ pr_info("printk: continuation disabled due to ext consoles, expect more fragments in /dev/kmsg\n");
+
+ if (newcon->flags & CON_PRINTBUFFER) {
+ /*
+ * console_unlock(); will print out the buffered messages
+ * for us.
+ */
+ logbuf_lock_irqsave(flags);
+ console_seq = syslog_seq;
+ console_idx = syslog_idx;
+ /*
+ * We're about to replay the log buffer. Only do this to the
+ * just-registered console to avoid excessive message spam to
+ * the already-registered consoles.
+ *
+ * Set exclusive_console with disabled interrupts to reduce
+ * race window with eventual console_flush_on_panic() that
+ * ignores console_lock.
+ */
+ exclusive_console = newcon;
+ exclusive_console_stop_seq = console_seq;
+ logbuf_unlock_irqrestore(flags);
+ }
+ console_unlock();
+ console_sysfs_notify();
+
+ /*
+ * By unregistering the bootconsoles after we enable the real console
+ * we get the "console xxx enabled" message on all the consoles -
+ * boot consoles, real consoles, etc - this is to ensure that end
+ * users know there might be something in the kernel's log buffer that
+ * went to the bootconsole (that they do not see on the real console)
+ */
+ pr_info("%sconsole [%s%d] enabled\n",
+ (newcon->flags & CON_BOOT) ? "boot" : "" ,
+ newcon->name, newcon->index);
+ if (bcon &&
+ ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV) &&
+ !keep_bootcon) {
+ /* We need to iterate through all boot consoles, to make
+ * sure we print everything out, before we unregister them.
+ */
+ for_each_console(bcon)
+ if (bcon->flags & CON_BOOT)
+ unregister_console(bcon);
+ }
+}
+
+EXPORT_SYMBOL(register_console);
+```
+
+
+## printk打印级别
+
+
+printk可以根据设置的日志级别来确定这个语句最后是否能够打印出来。
+
+
+查看此文件:`cat /proc/sys/kernel/printk`
+
+
+该文件有四个数字值,它们根据日志记录消息的重要性,定义将其发送到何处。
+
+
+
+ 1. 控制台日志级别:优先级高于该值的消息将被打印至控制台
+ 2. 默认的消息日志级别:将用该优先级来打印没有优先级的消息
+ 3. 最低的控制台日志级别:控制台日志级别可被设置的最小值(最高优先级)
+ 4. 默认的控制台日志级别:控制台日志级别的缺省值
+
+内核中共提供了八种不同的日志级别,在 `linux/kernel.h` 中有相应的宏对应。
+
+
+
+```
+#define KERN_EMERG "<0>" /* systemis unusable */
+#define KERN_ALERT "<1>" /* actionmust be taken immediately */
+#define KERN_CRIT "<2>" /*critical conditions */
+#define KERN_ERR "<3>" /* errorconditions */
+#define KERN_WARNING "<4>" /* warning conditions */
+#define KERN_NOTICE "<5>" /* normalbut significant */
+#define KERN_INFO "<6>" /*informational */
+#define KERN_DEBUG "<7>" /*debug-level messages */
+```
+
+
+**可以通过在cmdline中加入“loglevel=X”的语句,来调整日志输入级别。**其中X就是我们想要设置的console\_loglevel的值。
+
+
+# 总结
+
+
+pstore实现console前端的方式很简单:通过注册一个console并且使能即可实现。
+
+
+默认情况下,printk会对所有使能的console进行输出,将log\_buf中的数据写入到使能的console当中。
+
+
+当对pstore的console进行输出时,会触发pstore console的write,将数据写入到相应后端。
+
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257DMESG_\344\273\243\347\240\201\345\210\206\346\236\220.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257DMESG_\344\273\243\347\240\201\345\210\206\346\236\220.md"
new file mode 100644
index 0000000000000000000000000000000000000000..d00e1b42c34c3055a84dfdfe4e134dbab1df1f6d
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257DMESG_\344\273\243\347\240\201\345\210\206\346\236\220.md"
@@ -0,0 +1,210 @@
+
+
+
+作者:新绎
+
+
+
+## 写在前面
+
+
+pstore中提供了多种前端来实现捕获各种系统信息从而加以调试。这篇文章中,我们会对pstore其中之一的前端PSTORE\_DMESG进行分析,从原理上分析pstore如何获取当内核发生panic时kmsg信息。
+
+
+## Pstore注册kmsg\_dumper
+
+
+kmsg\_dumper结构体有两个重要成员:回调函数`dump()`以及相应的`kmsg_dump_reason`。通过对`dump()`进行实现,我们就可以将相应的log信息保存到我们希望保存的地方,并且可以通过`kmsg_dump_reason`来对需要保存的信息进行筛选。
+
+
+
+```
+//kmsg_dump.h
+/**
+* struct kmsg_dumper - kernel crash message dumper structure
+* @list: Entry in the dumper list (private)
+* @dump: Call into dumping code which will retrieve the data with
+* through the record iterator
+* @max_reason: filter for highest reason number that should be dumped
+* @registered: Flag that specifies if this is already registered
+*/
+struct kmsg_dumper {
+ struct list_head list;
+ void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason);
+ enum kmsg_dump_reason max_reason;
+ bool active;
+ bool registered;
+
+ /* private state of the kmsg iterator */
+ u32 cur_idx;
+ u32 next_idx;
+ u64 cur_seq;
+ u64 next_seq;
+};
+
+/*
+ * Keep this list arranged in rough order of priority. Anything listed after
+ * KMSG_DUMP_OOPS will not be logged by default unless printk.always_kmsg_dump
+ * is passed to the kernel.
+ */
+enum kmsg_dump_reason {
+ KMSG_DUMP_UNDEF,
+ KMSG_DUMP_PANIC,
+ KMSG_DUMP_OOPS,
+ KMSG_DUMP_EMERG,
+ KMSG_DUMP_RESTART,
+ KMSG_DUMP_HALT,
+ KMSG_DUMP_POWEROFF,
+};
+```
+
+
+我们可以看到,目前有7种定义的`kmsg\_dump\_reason`,而pstore则关心在系统出现panic时的log信息。在pstore的实现中,pstore通过`pstore\_cannot\_block\_path()`函数对相应的信息进行过滤。
+
+
+
+```
+//pstore_cannot_block_path()
+/*
+ * Should pstore_dump() wait for a concurrent pstore_dump()? If
+ * not, the current pstore_dump() will report a failure to dump
+ * and return.
+ */
+static bool pstore_cannot_block_path(enum kmsg_dump_reason reason)
+{
+ /* In NMI path, pstore shouldn't block regardless of reason. */
+ if (in_nmi())
+ return true;
+
+ switch (reason) {
+ /* In panic case, other cpus are stopped by smp_send_stop(). */
+ case KMSG_DUMP_PANIC:
+ /* Emergency restart shouldn't be blocked. */
+ case KMSG_DUMP_EMERG:
+ return true;
+ default:
+ return false;
+ }
+}
+```
+
+
+其中dmesg前端的主要工作就是为其实现一个`dump()`函数,该函数将从log buffer中读取log信息,然后将其封装为recored之后写入对应的后端设备,其主要定义如下:
+
+
+
+```
+//pstore_dump()
+static struct kmsg_dumper pstore_dumper = {
+ .dump = pstore_dump,
+}
+
+static void pstore_dump(struct kmsg_dumper *dumper,
+ enum kmsg_dump_reason reason)
+{
+ …
+ while (total < kmsg_bytes) {
+ …
+ pstore_record_init(&record, psinfo);
+ …
+ header_size = snprintf(dst, dst_size, "%s#%d Part%u\n", why,
+ oopscount, part);
+ dst_size -= header_size;
+
+ if (!kmsg_dump_get_buffer(&iter, true, dst + header_size,
+ dst_size, &dump_size))
+ break;
+
+ if (big_oops_buf) {
+ zipped_len = pstore_compress(dst, psinfo->buf,
+ header_size + dump_size,
+ psinfo->bufsize);
+ …
+ } else {
+ record.size = header_size + dump_size;
+ }
+
+ ret = psinfo->write(&record);
+ …
+ }
+ …
+}
+
+```
+
+
+## kmsg\_dump实现
+
+
+printk实现了一个`kmsg\_dump()`函数,用于方便其它模块dump内核的log buffer,当内核发生oops、panic或重启等事件时,都会调用该函数dump log信息。其代码实现如下:
+
+
+
+```
+void kmsg_dump(enum kmsg_dump_reason reason)
+{
+ …
+ list_for_each_entry_rcu(dumper, &dump_list, list) {
+ enum kmsg_dump_reason max_reason = dumper->max_reason;
+
+ if (max_reason == KMSG_DUMP_UNDEF) {
+ max_reason = always_kmsg_dump ? KMSG_DUMP_MAX :
+ KMSG_DUMP_OOPS;
+ }
+ if (reason > max_reason)
+ continue;
+
+ dumper->dump(dumper, reason);
+ }
+ rcu_read_unlock();
+}
+```
+
+
+使用`kmsg\_dump()`之前要先使用`kmsg\_dump\_register()`来注册一个dumper,用于实际的log写操作。
+
+
+我们先来看看`kmsg\_dump\_register`的定义,只定义了一个dump\_list,将系统中所有注册的dump都挂在同一个list下,这就说明系统可以注册多个dumper。
+
+
+
+```
+int kmsg_dump_register(struct kmsg_dumper *dumper)
+{
+ …
+ if (!dumper->registered) {
+ dumper->registered = 1;
+ list_add_tail_rcu(&dumper->list, &dump_list);
+ err = 0;
+ }
+ …
+}
+```
+
+
+## 总结
+
+
+pstore dmesg主要工作流程如下:
+
+
+(1)初始化一个record结构体
+
+
+(2)先向其写入pstore头信息,如dmesg reason、oops发生次数等
+
+
+(3)从log buffer中读取一行log信息
+
+
+(4)若需要压缩信息,则执行压缩操作
+
+
+(5)调用后端的写函数,将record写入相应的后端设备
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220.md"
new file mode 100644
index 0000000000000000000000000000000000000000..41ecbb17a91a745ddf9bfa70e2f998fafefc6a53
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220.md"
@@ -0,0 +1,558 @@
+
+
+
+作者:新绎
+
+
+
+# 写在前面
+
+
+pstore中提供了多种前端来实现捕获各种系统信息来加以调试。这篇文章中,我们会对pstore其中之一的前端`PSTORE\_CONSOLE`进行分析,从原理上分析pstore如何获取kernel printk的信息。
+
+
+# pstore console注册
+
+
+`pstore console`前端注册函数在`fs/pstore/platform.c`中被定义,通过后端初始化过程中被调用并注册,从而能够在系统执行`prink`时获取输出信息,并通过`write`方法将`prink`的输出写入到相应的后端当中。
+
+
+
+```
+static void pstore_console_write(struct console *con, const char *s, unsigned c)
+{
+ struct pstore_record record;
+
+ if (!c)
+ return;
+
+ pstore_record_init(&record, psinfo);
+ record.type = PSTORE_TYPE_CONSOLE;
+
+ record.buf = (char *)s;
+ record.size = c;
+ psinfo->write(&record);
+}
+
+static struct console pstore_console = {
+ .write = pstore_console_write,
+ .index = -1,
+};
+
+static void pstore_register_console(void)
+{
+ /* Show which backend is going to get console writes. */
+ strscpy(pstore_console.name, psinfo->name,
+ sizeof(pstore_console.name));
+ /*
+ * Always initialize flags here since prior unregister_console()
+ * calls may have changed settings (specifically CON_ENABLED).
+ */
+ pstore_console.flags = CON_PRINTBUFFER | CON_ENABLED | CON_ANYTIME;
+ register_console(&pstore_console);
+}
+```
+
+
+其中,pstore\_console的flag开启了3个选项:`CON\_PRINTBUFFER`,`CON\_ENABLED`和`CON\_ANYTIME`。
+
+
+`CON\_PRINTBUFFER`:只有开启了才会接受prink的输出
+
+
+`CON\_ENABLED`:console使能,如果没有开启这个flag需要手动使能(在cmdline中定义)
+
+
+`CON\_ANYTIME`:可以在cpu离线时进行调用
+
+
+
+```
+//console.h
+/*
+ * The interface for a console, or any other device that wants to capture
+ * console messages (printer driver?)
+ *
+ * If a console driver is marked CON_BOOT then it will be auto-unregistered
+ * when the first real console is registered. This is for early-printk drivers.
+ */
+
+#define CON_PRINTBUFFER (1)
+#define CON_CONSDEV (2) /* Last on the command line */
+#define CON_ENABLED (4)
+#define CON_BOOT (8)
+#define CON_ANYTIME (16) /* Safe to call when cpu is offline */
+#define CON_BRL (32) /* Used for a braille device */
+#define CON_EXTENDED (64) /* Use the extended output format a la /dev/kmsg */
+
+struct console {
+ char name[16];
+ void (*write)(struct console *, const char *, unsigned);
+ int (*read)(struct console *, char *, unsigned);
+ struct tty_driver *(*device)(struct console *, int *);
+ void (*unblank)(void);
+ int (*setup)(struct console *, char *);
+ int (*match)(struct console *, char *name, int idx, char *options);
+ short flags;
+ short index;
+ int cflag;
+ void *data;
+ struct console *next;
+};
+```
+
+
+# printk总览
+
+
+
+
+
+
+# printk向console输出过程分析
+
+
+pstore中注册好console之后,console会被动地获取printk的输出,接下来我们分析printk是对console进行输出。
+
+
+## cmdline解析
+
+
+如果console的flag中定义了`CON\_ENABLED`,那么console会默认使能。如果没有定义,则需要在cmdline中手动使能。
+
+
+`kernel/printk.c`中将`'console='`的解析函数`console\_setup`注册到`obs\_kernel\_param`,在kernel启动过程中会遍历所有`obs\_kernel\_param`,接着会调用`console\_setup`来解析。
+
+
+我们通过在cmdline中定义`console=xxx`则能够被`console\_setup`所解析并使能相应的console。
+
+
+
+参数是`'console='`的值字符串,如“ttyS0,115200”,`console\_setup`对`console=`参数值做解析,以ttyS0,115200为例,`buf=“ttyS”`,`idx=0`,`options="115200"`,`brl\_options=NULL`。
+
+
+
+```
+//printk.c 解析cmdline
+/*
+ * Set up a console. Called via do_early_param() in init/main.c
+ * for each "console=" parameter in the boot command line.
+ */
+static int __init console_setup(char *str)
+{
+ char buf[sizeof(console_cmdline[0].name) + 4]; /* 4 for "ttyS" */
+ char *s, *options, *brl_options = NULL;
+ int idx;
+
+ if (_braille_console_setup(&str, &brl_options))
+ return 1;
+
+ /*
+ * Decode str into name, index, options.
+ */
+ if (str[0] >= '0' && str[0] <= '9') {
+ strcpy(buf, "ttyS");
+ strncpy(buf + 4, str, sizeof(buf) - 5);
+ } else {
+ strncpy(buf, str, sizeof(buf) - 1);
+ }
+ buf[sizeof(buf) - 1] = 0;
+ options = strchr(str, ',');
+ if (options)
+ *(options++) = 0;
+#ifdef __sparc__
+ if (!strcmp(str, "ttya"))
+ strcpy(buf, "ttyS0");
+ if (!strcmp(str, "ttyb"))
+ strcpy(buf, "ttyS1");
+#endif
+ for (s = buf; *s; s++)
+ if (isdigit(*s) || *s == ',')
+ break;
+ idx = simple_strtoul(s, NULL, 10);
+ *s = 0;
+
+ __add_preferred_console(buf, idx, options, brl_options);
+ console_set_on_cmdline = 1;
+ return 1;
+}
+__setup("console=", console_setup);
+```
+
+
+`console\_setup`最后调用`\_\_add\_preferred\_console`:
+
+
+kernel利用结构体数组`console\_cmdline[8]`,最多可支持8个cmdline传入的console参数。
+
+
+`\_\_add\_preferred\_console`将name,idx,options保存到数组下一个成员`console\_cmdline`结构体中,如果数组中已有重名,则不添加,并置`selected\_console`为最新添加的`console\_cmdline`的下标。
+
+
+
+**一个例子:**
+
+
+如cmdline中有“console=ttyS0,115200 console=ttyS1,9600”
+
+
+则在`console\_cmdline[8]`数组中`console\_cmdline[0]`代表ttyS0,`console\_cmdline[1]`代表ttyS1,而`preferred\_console=1`。
+
+
+
+```
+//printk.c __add_preferred_console
+static int __add_preferred_console(char *name, int idx, char *options,
+ char *brl_options)
+{
+ struct console_cmdline *c;
+ int i;
+
+ /*
+ * See if this tty is not yet registered, and
+ * if we have a slot free.
+ */
+ for (i = 0, c = console_cmdline;
+ i < MAX_CMDLINECONSOLES && c->name[0];
+ i++, c++) {
+ if (strcmp(c->name, name) == 0 && c->index == idx) {
+ if (!brl_options)
+ preferred_console = i;
+ return 0;
+ }
+ }
+ if (i == MAX_CMDLINECONSOLES)
+ return -E2BIG;
+ if (!brl_options)
+ preferred_console = i;
+ strlcpy(c->name, name, sizeof(c->name));
+ c->options = options;
+ braille_set_options(c, brl_options);
+
+ c->index = idx;
+ return 0;
+}
+```
+
+
+## printk console选择
+
+
+printk内容会一直存在log\_buf中,log\_buf满了之后则会从头在开始存,覆盖掉原来的数据。
+
+
+log\_buf的大小由kernel `menuconfig`中的`CONFIG\_LOG\_BUF\_SHIFT`配置。
+
+
+根据printk的实现原理,printk最后调用`console\_unlock`实现log\_buf数据刷出到设备。
+
+
+kernel下每次printk打印,首先存log\_buf,然后遍历console\_drivers,找到合适console(如果有`execlusive\_console`,则往`execlusive\_console`写,如果没有,则为所有使能的console),刷出log。
+
+
+**默认情况下**`**execlusive\_console=NULL**`,所以printk默认是向所有enable的console写
+
+
+只有一种情况是指定`execlusive\_console`,就是在console注册时
+
+
+
+```
+//printk.c call_console_drivers
+/*
+ * Call the console drivers, asking them to write out
+ * log_buf[start] to log_buf[end - 1].
+ * The console_lock must be held.
+ */
+static void call_console_drivers(const char *ext_text, size_t ext_len,
+ const char *text, size_t len)
+{
+ struct console *con;
+
+ trace_console_rcuidle(text, len);
+
+ if (!console_drivers)
+ return;
+
+ for_each_console(con) {
+ if (exclusive_console && con != exclusive_console)
+ continue;
+ if (!(con->flags & CON_ENABLED))
+ continue;
+ if (!con->write)
+ continue;
+ if (!cpu_online(smp_processor_id()) &&
+ !(con->flags & CON_ANYTIME))
+ continue;
+ if (con->flags & CON_EXTENDED)
+ con->write(con, ext_text, ext_len);
+ else
+ con->write(con, text, len);
+ }
+}
+```
+
+
+## printk console注册
+
+
+注意:linux提供了early console机制(通过`CONFIG\_EARLY\_PRINTK`进行使能),用于实现为设备注册console之前的早期log的输出,对应console也称为boot console,简称bcon。这个console在kernel启动的早期阶段就会被注册,主要通过输出设备(比如串口设备)的简单的write方法直接进行数据打印。而这个write方法也就是平台实现。这时候作为输出的串口设备是基于bootloader中已经初始化完成的。
+
+
+
+1. 如果注册的是bootconsole(kernel早期启动打印),需要检查console\_drivers中没有real console,也就是说bootconsole必须是第一个注册的console。
+2. 检查new console是否是cmdline指定的console,如果是,则使能(`CON\_ENABLE`)并初始化该console
+3. 如果该new console没有使能,退出
+4. 如果new console为bootconsole,则newcon不需要输出register之前的log(`newcon->flags &= ~CON\_PRINTBUFFER`),因为如果bootconsole和new console是同一个设备则会之前的log就输出2次
+5. 把new console加入`console\_drivers`链表,对于置位`CON\_CONSDEV`的console,放在链表首
+6. 加锁
+7. 如果new console置位`CON\_PRINTBUFFER`,则将log全部刷出(暂时修改printk输出的指定唯一`exclusive\_console`为new console,保证将之前的log只输出到new console)
+8. 解锁(console\_unlock()会重新把`exclusive\_console`设置为NULL)
+9. 如果有bootconsole并且不是作为real console继续使用,则unregister bootconsole(从`console\_drivers`中删掉)
+
+```
+//printk.c register_console
+/*
+ * The console driver calls this routine during kernel initialization
+ * to register the console printing procedure with printk() and to
+ * print any messages that were printed by the kernel before the
+ * console driver was initialized.
+ *
+ * This can happen pretty early during the boot process (because of
+ * early_printk) - sometimes before setup_arch() completes - be careful
+ * of what kernel features are used - they may not be initialised yet.
+ *
+ * There are two types of consoles - bootconsoles (early_printk) and
+ * "real" consoles (everything which is not a bootconsole) which are
+ * handled differently.
+ * - Any number of bootconsoles can be registered at any time.
+ * - As soon as a "real" console is registered, all bootconsoles
+ * will be unregistered automatically.
+ * - Once a "real" console is registered, any attempt to register a
+ * bootconsoles will be rejected
+ */
+void register_console(struct console *newcon)
+{
+ int i;
+ unsigned long flags;
+ struct console *bcon = NULL;
+ struct console_cmdline *c;
+ static bool has_preferred;
+
+ if (console_drivers)
+ for_each_console(bcon)
+ if (WARN(bcon == newcon,
+ "console '%s%d' already registered\n",
+ bcon->name, bcon->index))
+ return;
+
+ /*
+ * before we register a new CON_BOOT console, make sure we don't
+ * already have a valid console
+ */
+ if (console_drivers && newcon->flags & CON_BOOT) {
+ /* find the last or real console */
+ for_each_console(bcon) {
+ if (!(bcon->flags & CON_BOOT)) {
+ pr_info("Too late to register bootconsole %s%d\n",
+ newcon->name, newcon->index);
+ return;
+ }
+ }
+ }
+
+ if (console_drivers && console_drivers->flags & CON_BOOT)
+ bcon = console_drivers;
+
+ if (!has_preferred || bcon || !console_drivers)
+ has_preferred = preferred_console >= 0;
+
+ /*
+ * See if we want to use this console driver. If we
+ * didn't select a console we take the first one
+ * that registers here.
+ */
+ if (!has_preferred) {
+ if (newcon->index < 0)
+ newcon->index = 0;
+ if (newcon->setup == NULL ||
+ newcon->setup(newcon, NULL) == 0) {
+ newcon->flags |= CON_ENABLED;
+ if (newcon->device) {
+ newcon->flags |= CON_CONSDEV;
+ has_preferred = true;
+ }
+ }
+ }
+
+ /*
+ * See if this console matches one we selected on
+ * the command line.
+ */
+ for (i = 0, c = console_cmdline;
+ i < MAX_CMDLINECONSOLES && c->name[0];
+ i++, c++) {
+ if (!newcon->match ||
+ newcon->match(newcon, c->name, c->index, c->options) != 0) {
+ /* default matching */
+ BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name));
+ if (strcmp(c->name, newcon->name) != 0)
+ continue;
+ if (newcon->index >= 0 &&
+ newcon->index != c->index)
+ continue;
+ if (newcon->index < 0)
+ newcon->index = c->index;
+
+ if (_braille_register_console(newcon, c))
+ return;
+
+ if (newcon->setup &&
+ newcon->setup(newcon, c->options) != 0)
+ break;
+ }
+
+ newcon->flags |= CON_ENABLED;
+ if (i == preferred_console) {
+ newcon->flags |= CON_CONSDEV;
+ has_preferred = true;
+ }
+ break;
+ }
+
+ if (!(newcon->flags & CON_ENABLED))
+ return;
+
+ /*
+ * If we have a bootconsole, and are switching to a real console,
+ * don't print everything out again, since when the boot console, and
+ * the real console are the same physical device, it's annoying to
+ * see the beginning boot messages twice
+ */
+ if (bcon && ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV))
+ newcon->flags &= ~CON_PRINTBUFFER;
+
+ /*
+ * Put this console in the list - keep the
+ * preferred driver at the head of the list.
+ */
+ console_lock();
+ if ((newcon->flags & CON_CONSDEV) || console_drivers == NULL) {
+ newcon->next = console_drivers;
+ console_drivers = newcon;
+ if (newcon->next)
+ newcon->next->flags &= ~CON_CONSDEV;
+ } else {
+ newcon->next = console_drivers->next;
+ console_drivers->next = newcon;
+ }
+
+ if (newcon->flags & CON_EXTENDED)
+ if (!nr_ext_console_drivers++)
+ pr_info("printk: continuation disabled due to ext consoles, expect more fragments in /dev/kmsg\n");
+
+ if (newcon->flags & CON_PRINTBUFFER) {
+ /*
+ * console_unlock(); will print out the buffered messages
+ * for us.
+ */
+ logbuf_lock_irqsave(flags);
+ console_seq = syslog_seq;
+ console_idx = syslog_idx;
+ /*
+ * We're about to replay the log buffer. Only do this to the
+ * just-registered console to avoid excessive message spam to
+ * the already-registered consoles.
+ *
+ * Set exclusive_console with disabled interrupts to reduce
+ * race window with eventual console_flush_on_panic() that
+ * ignores console_lock.
+ */
+ exclusive_console = newcon;
+ exclusive_console_stop_seq = console_seq;
+ logbuf_unlock_irqrestore(flags);
+ }
+ console_unlock();
+ console_sysfs_notify();
+
+ /*
+ * By unregistering the bootconsoles after we enable the real console
+ * we get the "console xxx enabled" message on all the consoles -
+ * boot consoles, real consoles, etc - this is to ensure that end
+ * users know there might be something in the kernel's log buffer that
+ * went to the bootconsole (that they do not see on the real console)
+ */
+ pr_info("%sconsole [%s%d] enabled\n",
+ (newcon->flags & CON_BOOT) ? "boot" : "" ,
+ newcon->name, newcon->index);
+ if (bcon &&
+ ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV) &&
+ !keep_bootcon) {
+ /* We need to iterate through all boot consoles, to make
+ * sure we print everything out, before we unregister them.
+ */
+ for_each_console(bcon)
+ if (bcon->flags & CON_BOOT)
+ unregister_console(bcon);
+ }
+}
+
+EXPORT_SYMBOL(register_console);
+```
+
+
+## printk打印级别
+
+
+printk可以根据设置的日志级别来确定这个语句最后是否能够打印出来。
+
+
+查看此文件:`cat /proc/sys/kernel/printk`
+
+
+该文件有四个数字值,它们根据日志记录消息的重要性,定义将其发送到何处。
+
+
+
+ 1. 控制台日志级别:优先级高于该值的消息将被打印至控制台
+ 2. 默认的消息日志级别:将用该优先级来打印没有优先级的消息
+ 3. 最低的控制台日志级别:控制台日志级别可被设置的最小值(最高优先级)
+ 4. 默认的控制台日志级别:控制台日志级别的缺省值
+
+内核中共提供了八种不同的日志级别,在 `linux/kernel.h` 中有相应的宏对应。
+
+
+
+```
+#define KERN_EMERG "<0>" /* systemis unusable */
+#define KERN_ALERT "<1>" /* actionmust be taken immediately */
+#define KERN_CRIT "<2>" /*critical conditions */
+#define KERN_ERR "<3>" /* errorconditions */
+#define KERN_WARNING "<4>" /* warning conditions */
+#define KERN_NOTICE "<5>" /* normalbut significant */
+#define KERN_INFO "<6>" /*informational */
+#define KERN_DEBUG "<7>" /*debug-level messages */
+```
+
+
+**可以通过在cmdline中加入“loglevel=X”的语句,来调整日志输入级别。**其中X就是我们想要设置的console\_loglevel的值。
+
+
+# 总结
+
+
+pstore实现console前端的方式很简单:通过注册一个console并且使能即可实现。
+
+
+默认情况下,printk会对所有使能的console进行输出,将log\_buf中的数据写入到使能的console当中。
+
+
+当对pstore的console进行输出时,会触发pstore console的write,将数据写入到相应后端。
+
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232DMESG_\344\273\243\347\240\201\345\210\206\346\236\220.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232DMESG_\344\273\243\347\240\201\345\210\206\346\236\220.md"
new file mode 100644
index 0000000000000000000000000000000000000000..d00e1b42c34c3055a84dfdfe4e134dbab1df1f6d
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232DMESG_\344\273\243\347\240\201\345\210\206\346\236\220.md"
@@ -0,0 +1,210 @@
+
+
+
+作者:新绎
+
+
+
+## 写在前面
+
+
+pstore中提供了多种前端来实现捕获各种系统信息从而加以调试。这篇文章中,我们会对pstore其中之一的前端PSTORE\_DMESG进行分析,从原理上分析pstore如何获取当内核发生panic时kmsg信息。
+
+
+## Pstore注册kmsg\_dumper
+
+
+kmsg\_dumper结构体有两个重要成员:回调函数`dump()`以及相应的`kmsg_dump_reason`。通过对`dump()`进行实现,我们就可以将相应的log信息保存到我们希望保存的地方,并且可以通过`kmsg_dump_reason`来对需要保存的信息进行筛选。
+
+
+
+```
+//kmsg_dump.h
+/**
+* struct kmsg_dumper - kernel crash message dumper structure
+* @list: Entry in the dumper list (private)
+* @dump: Call into dumping code which will retrieve the data with
+* through the record iterator
+* @max_reason: filter for highest reason number that should be dumped
+* @registered: Flag that specifies if this is already registered
+*/
+struct kmsg_dumper {
+ struct list_head list;
+ void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason);
+ enum kmsg_dump_reason max_reason;
+ bool active;
+ bool registered;
+
+ /* private state of the kmsg iterator */
+ u32 cur_idx;
+ u32 next_idx;
+ u64 cur_seq;
+ u64 next_seq;
+};
+
+/*
+ * Keep this list arranged in rough order of priority. Anything listed after
+ * KMSG_DUMP_OOPS will not be logged by default unless printk.always_kmsg_dump
+ * is passed to the kernel.
+ */
+enum kmsg_dump_reason {
+ KMSG_DUMP_UNDEF,
+ KMSG_DUMP_PANIC,
+ KMSG_DUMP_OOPS,
+ KMSG_DUMP_EMERG,
+ KMSG_DUMP_RESTART,
+ KMSG_DUMP_HALT,
+ KMSG_DUMP_POWEROFF,
+};
+```
+
+
+我们可以看到,目前有7种定义的`kmsg\_dump\_reason`,而pstore则关心在系统出现panic时的log信息。在pstore的实现中,pstore通过`pstore\_cannot\_block\_path()`函数对相应的信息进行过滤。
+
+
+
+```
+//pstore_cannot_block_path()
+/*
+ * Should pstore_dump() wait for a concurrent pstore_dump()? If
+ * not, the current pstore_dump() will report a failure to dump
+ * and return.
+ */
+static bool pstore_cannot_block_path(enum kmsg_dump_reason reason)
+{
+ /* In NMI path, pstore shouldn't block regardless of reason. */
+ if (in_nmi())
+ return true;
+
+ switch (reason) {
+ /* In panic case, other cpus are stopped by smp_send_stop(). */
+ case KMSG_DUMP_PANIC:
+ /* Emergency restart shouldn't be blocked. */
+ case KMSG_DUMP_EMERG:
+ return true;
+ default:
+ return false;
+ }
+}
+```
+
+
+其中dmesg前端的主要工作就是为其实现一个`dump()`函数,该函数将从log buffer中读取log信息,然后将其封装为recored之后写入对应的后端设备,其主要定义如下:
+
+
+
+```
+//pstore_dump()
+static struct kmsg_dumper pstore_dumper = {
+ .dump = pstore_dump,
+}
+
+static void pstore_dump(struct kmsg_dumper *dumper,
+ enum kmsg_dump_reason reason)
+{
+ …
+ while (total < kmsg_bytes) {
+ …
+ pstore_record_init(&record, psinfo);
+ …
+ header_size = snprintf(dst, dst_size, "%s#%d Part%u\n", why,
+ oopscount, part);
+ dst_size -= header_size;
+
+ if (!kmsg_dump_get_buffer(&iter, true, dst + header_size,
+ dst_size, &dump_size))
+ break;
+
+ if (big_oops_buf) {
+ zipped_len = pstore_compress(dst, psinfo->buf,
+ header_size + dump_size,
+ psinfo->bufsize);
+ …
+ } else {
+ record.size = header_size + dump_size;
+ }
+
+ ret = psinfo->write(&record);
+ …
+ }
+ …
+}
+
+```
+
+
+## kmsg\_dump实现
+
+
+printk实现了一个`kmsg\_dump()`函数,用于方便其它模块dump内核的log buffer,当内核发生oops、panic或重启等事件时,都会调用该函数dump log信息。其代码实现如下:
+
+
+
+```
+void kmsg_dump(enum kmsg_dump_reason reason)
+{
+ …
+ list_for_each_entry_rcu(dumper, &dump_list, list) {
+ enum kmsg_dump_reason max_reason = dumper->max_reason;
+
+ if (max_reason == KMSG_DUMP_UNDEF) {
+ max_reason = always_kmsg_dump ? KMSG_DUMP_MAX :
+ KMSG_DUMP_OOPS;
+ }
+ if (reason > max_reason)
+ continue;
+
+ dumper->dump(dumper, reason);
+ }
+ rcu_read_unlock();
+}
+```
+
+
+使用`kmsg\_dump()`之前要先使用`kmsg\_dump\_register()`来注册一个dumper,用于实际的log写操作。
+
+
+我们先来看看`kmsg\_dump\_register`的定义,只定义了一个dump\_list,将系统中所有注册的dump都挂在同一个list下,这就说明系统可以注册多个dumper。
+
+
+
+```
+int kmsg_dump_register(struct kmsg_dumper *dumper)
+{
+ …
+ if (!dumper->registered) {
+ dumper->registered = 1;
+ list_add_tail_rcu(&dumper->list, &dump_list);
+ err = 0;
+ }
+ …
+}
+```
+
+
+## 总结
+
+
+pstore dmesg主要工作流程如下:
+
+
+(1)初始化一个record结构体
+
+
+(2)先向其写入pstore头信息,如dmesg reason、oops发生次数等
+
+
+(3)从log buffer中读取一行log信息
+
+
+(4)若需要压缩信息,则执行压缩操作
+
+
+(5)调用后端的写函数,将record写入相应的后端设备
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ae0745cbba745886ad0ace066854f42eb9dc8834
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201.md"
@@ -0,0 +1,197 @@
+
+
+
+
+作者:新绎
+
+
+## 写在前面
+
+
+目前,pstore一次只支持打开一个后端。 如果一个新的后端想稍后注册, pstore将拒绝这个请求并返回一个错误。这个设计迫使我们关闭现有后端以使用新后端。
+
+
+内核支持某些类型的后端,例如ramoops和blk。在实际使用当中,我们还可以自行实现多种类型的后端。不同的后端根据不同的场景或业务进行信息收集。因此,他们需要同时工作,以满足各种需求。
+
+
+## 原始实现
+
+
+具体来说,由于全局变量`psinfo`的存在, pstore只接受第一个注册后端。如果一个新的后端想稍后注册, pstore将拒绝这个请求并返回一个错误。
+
+
+
+```
+int pstore_register(struct pstore_info *psi)
+{
+ if (backend && strcmp(backend, psi->name)) {
+ pr_warn("ignoring unexpected backend '%s'\n", psi->name);
+ return -EPERM;
+ }
+
+ /* Sanity check flags. */
+ if (!psi->flags) {
+ pr_warn("backend '%s' must support at least one frontend\n",
+ psi->name);
+ return -EINVAL;
+ }
+
+ /* Check for required functions. */
+ if (!psi->read || !psi->write) {
+ pr_warn("backend '%s' must implement read() and write()\n",
+ psi->name);
+ return -EINVAL;
+ }
+
+ mutex_lock(&psinfo_lock);
+ if (psinfo) {
+ pr_warn("backend '%s' already loaded: ignoring '%s'\n",
+ psinfo->name, psi->name);
+ mutex_unlock(&psinfo_lock);
+ return -EBUSY;
+ }
+ ...
+}
+```
+
+
+psinfo作为后端信息的存储结构体,一个psinfo只能保存一个后端。
+
+
+
+```
+struct pstore_info {
+ struct module *owner;
+ const char *name;
+
+ spinlock_t buf_lock;
+ char *buf;
+ size_t bufsize;
+
+ struct mutex read_mutex;
+
+ int flags;
+ int max_reason;
+ void *data;
+
+ int (*open)(struct pstore_info *psi);
+ int (*close)(struct pstore_info *psi);
+ ssize_t (*read)(struct pstore_record *record);
+ int (*write)(struct pstore_record *record);
+ int (*write_user)(struct pstore_record *record,
+ const char __user *buf);
+ int (*erase)(struct pstore_record *record);
+};
+```
+
+
+## 多后端实现
+
+
+### 修改全局变量
+
+
+在原始`fs/pstore/internal.h`中定义了全局变量`psinfo`
+
+
+`extern struct pstore\_info \*psinfo;`
+
+
+psinfo为后端信息的存储结构体,一个psinfo只能保存一个后端
+
+
+修改后:
+
+
+`extern struct pstore\_backends \*psback;`
+
+
+`psback`保存了所有使能`psinfo`的双向链表头节点。
+
+
+启动`psback`以及双向链表的定义如下:
+
+
+
+```
+struct pstore_info_list {
+ struct pstore_info *psi;
+ struct list_head list;
+ int index;
+};
+
+/**
+ * struct pstore_backends - management of pstore backends
+ * @list_entry: entry of pstore backend driver information list
+ * @front_cnt: count of each enabled frontend
+ * @flag: bitmap of enabled pstore backend
+ * @fs_ready: whether the pstore filesystem is ready
+ *
+ */
+
+struct pstore_backends {
+ struct list_head list_entry;
+ int front_cnt[PSTORE_TYPE_MAX];
+ u16 flag;
+ bool fs_ready;
+};
+```
+
+
+### 前端复用
+
+
+为了防止每注册一个后端就要注册相应的前端造成过多开销,我们选择对已经注册好的前端进行复用。如果当多个后端同时使能了同一前端,那么这个前端将会把自己收集的信息多写到这几个后端当中。
+
+
+
+
+
+
+代码实现:
+
+
+
+```
+static void pstore_dump(struct kmsg_dumper *dumper,
+ enum kmsg_dump_reason reason)
+{
+ struct pstore_info_list *entry;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(entry, &psback->list_entry, list)
+ if (entry->psi->flags & PSTORE_FLAGS_DMESG)
+ pstore_do_dump(dumper, reason, entry->psi, entry->index);
+ rcu_read_unlock();
+}
+```
+
+
+通过rcu锁以及对双向链表遍历的方式,前端可以线程安全地获取所有使能的后端,并且根据后端的使能情况执行写操作。
+
+
+### 让文件系统更直观
+
+
+由于多后端的存在,不同后端的输出文件将显得格外混乱,所以通过文件夹对不同后端进行分类的想法是自然而然产生的。
+
+
+通过修改`inode.c`,在`sys/fs/pstore`下建立相应后端的子文件夹,实现文件归类
+
+
+
+
+
+
+## 总结
+
+
+多后端支持的引入让pstore的使用更加灵活,可以根据不同后端功能以及业务场景同时使能多个后端,实现互不干扰,和谐共存。
+
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210.md"
new file mode 100644
index 0000000000000000000000000000000000000000..fa9fdd8e4bf09b7a262d3bd3720ddccaa753fd61
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210.md"
@@ -0,0 +1,366 @@
+
+
+
+作者:新绎
+
+
+## pstore概述
+
+
+### 定义
+
+
+pstore文件系统,是Persistent Storage的缩写,最早设计的目的是在内核Panic/Oops时能自动转存内核日志(log\_buf)到持久化内存(Persistent Ram),在Panic重启后,把转存的日志以文件形式呈现到用户空间以分析内核崩溃问题。随着版本的不断演进,pstore开始支持console,ftrace等一系列信息获取,提供多方位的日志抓捕功能,来帮助维护人员快速定位问题。
+
+
+### 对比kdump
+
+
+kdump作为一个重量级的问题分析工具,在发生panic时通过kexec加载crash kernel,该kernel会收集内存所有信息到dump core文件中予以保存。kdump的方案适用于服务器这种有大量资源的设备,功能也非常强大,但对嵌入式设备非常不友好。而pstore是个轻量级的内核崩溃日志转存的方案,虽然不能保存所有完整的寄存器等信息,但是不需要大量的内存空间进行部署,功能简洁轻量,在移动端和嵌入式设备的调试中被广泛地使用。
+
+
+
+
+
+
+## pstore配置方法
+
+
+### config选项(基于kernel version 5.10)
+
+
+pstore的各个模块需要在内核编译时通过config进行使能。
+
+
+
+pstore的各个模块需要在内核编译时通过config进行使能。
+
+
+
+
+| | |
+| --- | --- |
+| `CONFIG_PSTORE` | pstore文件系统使能 |
+
+
+* 前端
+
+
+
+
+| | |
+| --- | --- |
+| `CONFIG_PSTORE_PMSG` | 用户空间信息,/dev/pmsg0 |
+| `CONFIG_PSTORE_CONSOLE` | 控制台输出,所有内核信息 |
+| `CONFIG_PSTORE_FTRACE` | 函数调用序列, ftrace 信息 |
+
+
+* 后端
+
+
+
+
+| | |
+| --- | --- |
+| `CONFIG_PSTORE_RAM` | 持久化内存(重启后不会丢失数据的内存) |
+| `CONFIG_PSTORE_ZONE` | 实现存储空间的分配和管理 |
+| `CONFIG_PSTORE_BLK` | 所有可写的块设备 |
+
+
+* 压缩算法(**只针对DMESG前端数据**)
+
+
+
+
+| | |
+| --- | --- |
+| `CONFIG_PSTORE_COMPRESS` | 压缩算法使能 |
+| `CONFIG_PSTORE_DEFLATE_COMPRESS` | 默认压缩算法(deflate) |
+| `CONFIG_PSTORE_LZO_COMPRESS` | LZO压缩 |
+| `CONFIG_PSTORE_LZ4_COMPRESS` | LZ4压缩 |
+| `CONFIG_PSTORE_LZ4HC_COMPRESS` | LZHC(high compression)压缩 |
+| `CONFIG_PSTORE_842_COMPRESS` | 842压缩 |
+| `CONFIG_PSTORE_ZSTD_COMPRESS` | zstd压缩 |
+
+
+#### RAM后端(ramoops)配置方式
+
+
+
+**cmdline方式**
+
+
+example:
+
+
+`ramoops.mem_address=0x800000 ramoops.mem_size=0x10000 ramoops.console_size=0x4000`
+
+
+提供选项:
+
+
+`mem_address`,`mem_size`,`mem_type`,`record_size`,`console_size`,`pmsg_size`
+
+
+`max_reason`,`ramoops_ecc`,`dump_oops`
+
+
+**Platform Data方式**
+
+
+
+```
+#include
+ [...]
+
+ static struct ramoops_platform_data ramoops_data = {
+ .mem_size = <...>,
+ .mem_address = <...>,
+ .mem_type = <...>,
+ .record_size = <...>,
+ .max_reason = <...>,
+ .ecc = <...>,
+ };
+
+ static struct platform_device ramoops_dev = {
+ .name = "ramoops",
+ .dev = {
+ .platform_data = &ramoops_data,
+ },
+ };
+
+ [... inside a function ...]
+ int ret;
+
+ ret = platform_device_register(&ramoops_dev);
+ if (ret) {
+ printk(KERN_ERR "unable to register platform device\n");
+ return ret;
+ }
+
+```
+
+**设备树方式**
+
+
+
+``Documentation/devicetree/bindings/reserved-memory/ramoops.yaml``.
+
+
+
+```
+ For example::
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ ramoops@8f000000 {
+ compatible = "ramoops";
+ reg = <0 0x8f000000 0 0x100000>;
+ record-size = <0x4000>;
+ console-size = <0x4000>;
+ };
+ };
+```
+
+#### BLK后端配置方式
+
+
+**cmdline方式**
+
+
+example:
+
+
+`pstore_blk.blkdev=/dev/mmcblk0p7 pstore_blk.kmsg_size=64 best_effort=y`
+
+
+提供选项:
+
+
+`blkdev`,`kmsg_size`,`pmsg_size`,`console_size`,`ftrace_size`,`max_reason`
+
+
+
+
+
+**Kconfig方式**
+
+
+在编译时设置config
+
+
+`CONFIG_PSTORE_BLK_BLKDEV`
+
+
+`CONFIG_PSTORE_BLK_KMSG_SIZE`
+
+
+`CONFIG_PSTORE_BLK_MAX_REASON`
+
+
+`CONFIG_PSTORE_BLK_PMSG_SIZE`
+
+
+`CONFIG_PSTORE_BLK_CONSOLE_SIZE`
+
+
+`CONFIG_PSTORE_BLK_FTRACE_SIZE`
+
+
+### 配置查看
+
+
+检查 pstore 配置成功与否。
+`cat /sys/module/pstore/parameters/*`
+
+
+
+
+
+
+如图配置,backend = ramoops,compress = deflate,update\_ms = -1
+
+
+检查相关预留 size 是否配置成功(这里以ramoops后端为例)
+`ls /sys/module/ramoops/parameters`
+`cat /sys/module/ramoops/parameters/*`
+
+
+
+
+
+## pstore使用
+
+
+pstore使用十分简单,只要我们使能成功,并且检查各项配置都正确,那么pstore已经可以正常工作了。
+
+
+我们可以通过手动触发crash来查看pstore捕获的日志。
+
+
+`echo c > /proc/sysrq-trigger`
+
+
+在重启之后,我们可以在`/sys/fs/pstore/*` 看到加载的 pstore 数据
+
+
+`ls /sys/fs/pstore/`
+
+
+
+
+
+## pstore框架梳理
+
+
+这里后端以ramoops为例,kernel version = 5.10
+
+
+**【右键-在新标签页中打开图片】[查看原图](https://oss.openanolis.cn/fragment/uqbmggfmkvyziugluctq)**
+
+
+
+
+
+
+### pstore初始化
+
+
+pstore的初始化分为两步,首先是pstore前端和后端的初始化,接着是pstore文件系统的初始化
+
+
+pstore前后端:`postcore_initcall(ramoops_init);`
+
+
+pstore文件系统:`late_initcall(pstore_init);`
+
+
+
+
+
+通过查看相关模块初始化定义,我们发现pstore前后端位于`postcore_initcall`(优先级2)被初始化,而pstore文件系统则在`late_initcall`(优先级7)才会被初始化
+
+
+#### pstore前后端初始化
+
+
+**主要函数**
+
+
+fs/pstore/ram.c:
+
+
+`static int __init ramoops_init(void)`
+
+
+`static int ramoops_probe(struct platform_device *pdev)`
+
+
+fs/pstore/platform.c:
+
+
+`int pstore_register(struct pstore_info *psi)`
+
+
+**流程**
+
+
+1、解析并初始化前后端各种配置参数
+
+
+2、根据参数为每一个使能的前端申请持久化内存空间
+
+
+3、检测到内存中已经存在合法数据:开辟临时内存空间old\_log,将数据写入到old\_log,并刷新持久化内存
+
+
+4、根据flag以此判断是否注册前端,如果使能则对前端进行注册
+
+
+#### pstore文件系统初始化
+
+
+**主要函数**
+
+
+fs/pstore/inode.c:
+
+
+`pstore_init_fs()`
+
+
+`register_filesystem(&pstore_fs_type);`
+
+
+**流程**
+
+
+1、选择压缩函数
+
+
+2、文件系统初始化,读取old\_log数据并在/sys/fs/pstore下挂载
+
+
+
+
+
+### pstore写入数据
+
+
+pstore根据前端的不同,各个前端会分别调用pstore后端的写方法向自己的空间写入数据。
+
+
+具体各个前端的工作模式将会在“Pstore:前端”各章节文档介绍。
+
+
+
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267.md"
new file mode 100644
index 0000000000000000000000000000000000000000..4236a6963503e0e0f11d62ae24994315c5b0c621
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267.md"
@@ -0,0 +1,88 @@
+## 简介
+
+
+基于pstore的kdump调测工具是一个用于收集并存储crash kernel启动并执行vmcore转储过程中串口打印信息的工具,为kdump提供新的feature。
+方便对crash kernel启动并执行dump过程中所遇到的问题进行定位,能够覆盖crash kernel启动的绝大部分时间点。
+目前支持内核态以及用户态信息的全收集。
+
+
+仓库链接:
+
+
+\*目前对于内核pstore的改动已完成,正在进行用户态kdumpctl的整合
+
+
+## 背景
+
+
+目前kdump服务在使用过程中难免会遇到各种问题,导致vmcore无法正常生成。而在各种使用环境和因素的情况下,可能存在问题定位没有串口可用或者需要较高权限和复杂的流程来申请CN串口,那么我们需要一个机制来对crash kernel的打印信息进行转储,方便我们后续进行查看。
+
+
+当前新版的kdump支持在vmcore转储过程中对crash kernel的dmesg顺带进行保存,如下图所示:
+
+
+
+
+
+但是,这样的dmesg信息存储需要在crash kernel成功进入用户态并执行相应的脚本进行实现,如果crash kernel在内核态启动的过程中出现panic,亦或是kdump相关脚本没有正常工作,那么dmesg将无法进行保存。所以目前的crash kernel的dmesg保存机制能覆盖问题的点比较少,我们需要一个能够cover更多问题的调测工具。
+
+
+## 原理
+
+
+### pstore相关原理及修改
+
+
+pstore相关介绍和对应的补丁修改参见:
+
+
+[Pstore总览 - OpenAnolis 龙蜥操作系统开源社区](https://openanolis.cn/sig/Cloud-Kernel/doc/623611346526568454)
+
+
+[Pstore多后端支持补丁](https://openanolis.cn/sig/Cloud-Kernel/doc/646804783491448879)
+
+
+当前的pstore的内核态与用户态的log存储逻辑如下:
+
+
+
+
+
+对于用户态信息,pmsg只会接受用户对其的输入信息,而不会主动获取。而可以产生用户态输出的程序和服务有许多,包括各种service以及dump相关脚本,如果想采用这样一个方案进行用户态信息的收集,我们需要对用户态的输出进行重定向到pmsg。这样的操作有两个比较大的问题:
+
+
+1、重定向后原有的串口将不显示输出
+
+
+2、如果想cover所有用户态输出,需要在用户态进行大量的修改
+
+
+所以,我们希望从根源上高效地解决问题。我们注意到所以用户态向串口输出都会走tty驱动,那么我们可以实现一个新的pstore前端,该前端在tty驱动前有一个hook点,我们可以直接获取到用户态向tty驱动的输出,从而获取相关的log信息。
+
+
+
+
+
+## 工具流程
+
+
+基于pstore的kdump调测工具主要工作在crash kernel中,在crash kernel中配置好pstore后端ramoops相应的参数(内存地址,预留空间大小等),在crash kernel启动过程中会使能pstore并且获取内核态以及用户态的信息,实时输出到ramoops配置好的持久化内存当中。
+
+
+由于机器重启不会掉电(正常情况下),当我们重回第一个kernel的之后,我们对那块内存进行解析,就可以获取crash kernel相应的log输出。
+
+
+
+
+
+## 使用
+
+
+我们对工具进行了包装,与kdump进行融合,pstore相关的配置将由相应的脚本自动实现,使用者无需进行配置。在正常使用过程中,我们将工具包装进了kdumpctl命令。
+
+
+只需要在crash kernel执行过后输入kdumpctl showdebug,就可以很方便地对crash kernel的log输出进行查看。
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/\351\241\271\347\233\256\347\256\200\344\273\213.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/\351\241\271\347\233\256\347\256\200\344\273\213.md"
new file mode 100644
index 0000000000000000000000000000000000000000..8f8b3d07e9fa873033a1f1dcc81e30e3c39ddcb5
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\350\260\203\346\265\213/\351\241\271\347\233\256\347\256\200\344\273\213.md"
@@ -0,0 +1,2 @@
+致力于各种内核调测技术的研发和产品化,包括但不限于kdump/pvdump, pstore, ftrace, 各种probes, perf/pmu, ebpf等技术。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/Anolis_OS\346\224\257\346\214\201\347\232\204\351\251\261\345\212\250\345\210\227\350\241\250.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/Anolis_OS\346\224\257\346\214\201\347\232\204\351\251\261\345\212\250\345\210\227\350\241\250.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250spec\350\247\204\350\214\203.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250spec\350\247\204\350\214\203.md"
new file mode 100644
index 0000000000000000000000000000000000000000..540c85ff72f062433beba350151d0c95f2c53dfc
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250spec\350\247\204\350\214\203.md"
@@ -0,0 +1,104 @@
+### spec文件命名
+
+
+驱动名、仓库名保持一致,因此spec文件的命名方式为「驱动名.spec」。
+
+
+### spec内容规范
+
+
+下面提供了spec文件的通用模板,在合入驱动时需根据实际的驱动修改pkg等字段,需修改的字段如下:
+
+
+1)「pkg」,需修改成驱动名。
+
+
+2)「Summary」,需修改为该驱动的描述。
+
+
+3)「License」,需按照实际的license修改。
+
+
+4)「URL」,可修改为驱动官网链接。
+
+
+5)「%description」,需修改成该驱动的描述。
+
+
+6)「%build」,需根据实际的编译方式修改。
+
+
+7)「%install」,需根据实际的安装路径修改。
+
+
+
+```
+%global pkg ast
+%global pkgversion 1.0
+%global kernel kernel version
+%define anolis_release 1
+
+Name: kmod-%{pkg}
+Version: %(echo %{kernel} | sed -E 's/-/~/g; s/\.(el|al|alios)[0-9]+$//g')
+Release: %{pkgversion}.%{anolis_release}%{?dist}
+Summary: ASPEED Graphics DRM Driver
+License: LBPLv2+ and MIT
+URL: https://www.aspeedtech.com/support_driver/
+Patch0: source-git.patch
+
+# 安装依赖, 和内核版本对应
+Requires: kernel = %{kernel}
+Requires(post): kmod
+Requires(post): dracut
+
+# 构建依赖, 和内核版本对应
+BuildRequires: kernel-devel = %{kernel}
+BuildRequires: kernel-headers = %{kernel}
+BuildRequires: elfutils-libelf-devel
+BuildRequires: gcc
+BuildRequires: kernel-rpm-macros
+BuildRequires: kmod
+BuildRequires: make
+BuildRequires: redhat-rpm-config
+BuildRequires: xz
+
+%description
+RPM Package for ASPEED Graphics DRM Driver
+
+%prep
+%autosetup -p1 -c -T
+
+%build
+pushd src
+%{__make} -C /usr/src/kernels/%{kernel}.%{_arch} %{?_smp_mflags} M=$PWD modules
+popd
+
+%install
+mkdir -p %{buildroot}/lib/modules/%{kernel}.%{_arch}/extra/drivers/gpu/drm/ast
+%{__install} -D -t %{buildroot}/lib/modules/%{kernel}.%{_arch}/extra/drivers/gpu/drm/ast src/ast.ko
+
+# Make .ko objects temporarily executable for automatic stripping
+find %{buildroot}/lib/modules -type f -name \*.ko -exec chmod u+x \{\} \+
+
+# Generate depmod.conf
+%{__install} -d %{buildroot}/%{_sysconfdir}/depmod.d/
+for kmod in $(find %{buildroot}/lib/modules/%{kernel}.%{_arch}/extra -type f -name \*.ko -printf "%%P\n" | sort)
+do
+ echo "override $(basename $kmod .ko) * extra/$(dirname $kmod)" >> %{buildroot}/%{_sysconfdir}/depmod.d/%{pkg}.conf
+done
+
+%clean
+%{__rm} -rf %{buildroot}
+
+%post
+depmod -a %{kernel}.%{_arch}
+dracut -v -f /boot/initramfs-%{kernel}.%{_arch}.img %{kernel}.%{_arch}
+
+%files
+%defattr(644,root,root,755)
+%license licenses
+/lib/modules/%{kernel}.%{_arch}
+%config(noreplace) %{_sysconfdir}/depmod.d/%{pkg}.conf
+
+%changelog
+```
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227.md"
new file mode 100644
index 0000000000000000000000000000000000000000..f8053a0c625e8d9bdfec29cf31ae5213c2a64c0e
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227.md"
@@ -0,0 +1,185 @@
+### 简介
+
+
+龙蜥社区采用Out-of-tree(OOT)的方式管理部分第三方驱动,这部分驱动的版本可以在已发布的内核版本的基础上迭代小版本。一个驱动对应着两个仓库,一个source tree仓库用于管理源码,一个rpm tree仓库用于管理编译打包RPM包。
+
+
+#### 代码管理
+
+
+Source tree仓库的代码组织形式为「src目录」+ 「licenses目录」+ 「spec文件」,「src目录」用于存放驱动源码,「licenses目录」用于存放license,「spec文件」用于编译打包RPM包。
+
+
+#### 版本管理
+
+
+当前[Cloud Kernel](https://gitee.com/anolis/cloud-kernel)有devel-4.19和devel-5.10两个分支对应两个版本,因此source tree仓库也分有devel-4.19和devel-5.10两个分支用于分别适配Cloud Kernel的两个版本。
+
+
+**Cloud Kernel发布版本:**
+
+
+当Cloud Kernel发布版本时会基于OOT驱动source tree仓库的devel-xxx分支拉取release分支,例如要发布4.19.91-27版本,拉取的分支为release-4.19.91-27,然后构建系统将代码和spec文件传到rpm tree仓库编译出包,打包的RPM包会随着Cloud Kernel的版本一起发布。
+
+
+**OOT单独迭代小版本:**
+
+
+当Cloud Kernel的下一个版本还未发布时,OOT驱动可以单独在已经发布的大版本的基础上迭代小版本,例如在4.19.91-27的版本基础上发布4.19.91-27-1版本。
+
+
+### 如何向OOT合入新的驱动
+
+
+下文将以ast为实际例子进行流程说明。
+
+
+#### 创建source tree仓库和rpm tree仓库
+
+
+Maintainer会为驱动创建source tree仓库和rpm tree仓库,然后**将创建好的仓库地址同步到bugzilla**,仓库地址例如:https://gitee.com/anolis/ast 和 https://gitee.com/src-anolis-sig/ast。
+
+
+#### 注册账号/登录
+
+
+参与龙蜥OOT开发,需要先注册龙蜥社区及 Gitee 平台账号,并将两个账号关联。
+步骤如下:
+
+
+* [注册龙蜥社区账号](https://gitee.com/link?target=https%3A%2F%2Fpassport.openanolis.cn%2Fregister)(已有账号的略过此步);
+* [注册 Gitee 账号](https://gitee.com/signup)(已有账号的略过此步);
+* 关联两个账号:因涉及下节提到的 CLA 签署,需要将两个账号关联,直接登录龙蜥社区在【账号设置】 -> 【安全设置】里可以操作绑定 Gitee 账号。
+
+
+ 
+
+
+签署CLA
+向龙蜥OOT贡献代码,必须先签署 CLA。 可以登录龙蜥社区后, 打开[CLA页面](https://openanolis.cn/pact/contributor) 进行 CLA 签署。
+
+
+注意:
+
+
+* 以人个名义贡献的,可签署个人 CLA;
+* 以公司名义贡献的,需要签署公司 CLA;
+* 详情请咨询贵公司相关法务。
+
+
+#### fork代码仓库
+
+
+1、将maintainer创建好的source tree仓库fork到自己的账户,龙蜥采用PR(Pull Request)的方式合并源码。
+
+
+ 
+
+
+2、将fork到个人账号的source tree仓库clone到本地的开发环境。
+
+
+
+
+
+#### 补丁制作
+
+
+1、根据[OOT驱动补丁规范](https://openanolis.cn/sig/Cloud-Kernel/doc/695239829190715269),并且按照「src目录」+ 「licenses目录」+「spec文件」的格式(「src目录」存放源码,「licenses目录」用于存放license,spec文件为编译RPM包所需的文件)制作补丁,spec文件的命名和格式需按照[OOT驱动spec规范](https://openanolis.cn/sig/Cloud-Kernel/doc/684402508139285258??preview=null)上传。
+
+
+2、将commit push到个人账号下的source tree仓库。
+
+
+#### 提交PR(Pull Request)
+
+
+1、登录gitee,进入个人账户下的仓库页面。
+
+
+
+
+
+2、在「Pull Request栏」点击「新建Pull Request」,创建PR。
+
+
+
+
+
+3、填写PR信息:
+
+
+* 选择目标仓库为被fork的source tree仓库。
+* 选择正确的**源及目标分支**。
+* 选择合适的评审人即maintainer,maintainer会将他的账号同步到bugzilla或者钉钉群。
+* 「标题」和「说明」请参考[PR(Pull Request)规范](https://openanolis.cn/sig/Cloud-Kernel/doc/607605992881480196)填写。
+
+
+
+
+
+4、当您提交完PR后,会有机器人自动帮您进行代码审核验证。
+
+
+* 代码**检测通过**,会有如下提示:
+
+
+
+
+
+* 代码**检测未通过**:
+ + 请自行修改代码后,使用**git push --force**重新push至个人仓库下。
+ + 在pr链接下评论 **/retest** 重新触发代码检测。
+ + 若因为某些特殊原因导致无法通过检测,可联系maintainer回复**/skip-test**跳过检测。详见:[龙蜥内核代码门禁系统](https://openanolis.cn/sig/SIG-Infra/doc/594387296754325258)。
+
+
+
+
+
+5、评审人(maintainer)回复通过并附上签名。
+
+
+
+
+
+6、依次将PR链接和评审人签名添加到相应 commit log 末尾处,并且使用git push --force 提交更新。
+
+
+注意:PR链接放在评审人签名前面
+
+
+格式:
+
+
+Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx Reviewed-by: xxx <邮箱>
+
+
+
+
+
+让最后10个 commit 都加上PR链接Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx 以及评审人签名Reviewed-by: Linus Torvalds 的命令:
+
+
+git filter-branch -f --msg-filter ' cat && echo "Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx" && echo "Reviewed-by: Linus Torvalds "' HEAD~10..HEAD
+
+
+
+
+
+7、在PR下评论 **/check-sig**提交签名及PR链接检查命令。
+
+
+
+
+
+8、联系maintainer评论**/merge** 即可进入代码合入流程。
+
+
+
+
+
+9、(可选)最后还需指定一人作为source tree仓库的maintainer,社区maintainer会为该maintainer添加仓库权限,新maintainer负责后续source tree仓库的维护。
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\350\241\245\344\270\201\350\247\204\350\214\203.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\350\241\245\344\270\201\350\247\204\350\214\203.md"
new file mode 100644
index 0000000000000000000000000000000000000000..8522a7f0c86127e085c25b4a2a2112dd0aacf0b7
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\350\241\245\344\270\201\350\247\204\350\214\203.md"
@@ -0,0 +1,48 @@
+将代码合入OOT驱动仓库时,请根据如下规范制作补丁。
+
+
+注意:**所有补丁内容均不能出现中文**
+
+
+## 范例
+
+
+
+```
+sched/fair: Fix wrong cpu selecting from isolated domain
+
+ANBZ: #1468
+
+#commit body ......
+
+Signed-off-by: Andrew Morton
+Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx
+Reviewed-by: Linus Torvalds
+```
+
+## 范例细则
+
+
+* 补丁标题/subject:保持原标题不变。
+* 补丁日志/commit log
+ + 第一行
+ - 附上对应问题的bugzilla ID号。如果还没有bugzilla ID,需要前往[bugzilla](https://bugzilla.openanolis.cn/)提交问题。
+ * 格式:**ANBZ +冒号+空格+#+bugzilla ID**
+ * 范例:**ANBZ: #42**
+ * "ANBZ" 即是 "Anolis bugzilla"
+ + 第二行
+ - 空行。
+ + 第三行及其之后
+ - 具体的commit 内容。
+* 补丁签名/SOB
+ + 保留原补丁的完整签名,在其后追加合入人的签名
+ - 格式:**Signed-off-by: <名字> <邮箱地址>**
+ - 范例:Signed-off-by: Andrew Morton
+* PR链接(初次提交不需要,评审通过后再追加至commit log尾部)
+ + 在回合人签名后面追加PR链接
+ - 格式:**Link: **
+ - 范例:Link:
+* Reviewed-by(初次提交不需要,评审通过后再追加至commit log尾部)
+ + 在PR链接后追加评审人签名
+ - 格式:**Reviewed-by: <名字> <邮箱地址>**
+ - 范例:Reviewed-by: Linus Torvalds
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\345\246\202\344\275\225\346\217\220\344\272\244\347\241\254\344\273\266\345\205\274\345\256\271\346\200\247\346\265\213\350\257\225\347\224\263\350\257\267.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\345\246\202\344\275\225\346\217\220\344\272\244\347\241\254\344\273\266\345\205\274\345\256\271\346\200\247\346\265\213\350\257\225\347\224\263\350\257\267.md"
new file mode 100644
index 0000000000000000000000000000000000000000..0ba118fa1a49e233cab33c2263af1e55172a5e97
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\345\246\202\344\275\225\346\217\220\344\272\244\347\241\254\344\273\266\345\205\274\345\256\271\346\200\247\346\265\213\350\257\225\347\224\263\350\257\267.md"
@@ -0,0 +1,6 @@
+请按照硬件兼容测试申请流程: https://openanolis.cn/sig/HCT/doc/423293128473364249 ,
+
+下载安装ancert,ancert快速开始手册:https://openanolis.cn/sig/HCT/doc/515463617816101039
+
+针对第三方驱动设备执行硬件兼容性测试,审核通过之后,同步测试结果到bugzilla。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\345\246\202\344\275\225\346\217\220\344\272\244\347\254\254\344\270\211\346\226\271\351\251\261\345\212\250\351\233\206\346\210\220\347\224\263\350\257\267.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\345\246\202\344\275\225\346\217\220\344\272\244\347\254\254\344\270\211\346\226\271\351\251\261\345\212\250\351\233\206\346\210\220\347\224\263\350\257\267.md"
new file mode 100644
index 0000000000000000000000000000000000000000..a404159259fcede41aee30466d053dcd40ae2f46
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\345\246\202\344\275\225\346\217\220\344\272\244\347\254\254\344\270\211\346\226\271\351\251\261\345\212\250\351\233\206\346\210\220\347\224\263\350\257\267.md"
@@ -0,0 +1,6 @@
+如果您有意向往Anolis OS中集成您的第三方驱动,请首先提一个龙蜥社区bugzilla用于跟踪合入流程。
+
+具体操作步骤详见"[向CloudKernel报告BUG](https://openanolis.cn/sig/Cloud-Kernel/doc/607601736106142822)",其中「Component」选择「drivers」以保证社区能够第一时间看到。
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\347\254\254\344\270\211\346\226\271\351\251\261\345\212\250\345\246\202\344\275\225\350\277\233\345\205\245Anolis_OS.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\347\254\254\344\270\211\346\226\271\351\251\261\345\212\250\345\246\202\344\275\225\350\277\233\345\205\245Anolis_OS.md"
new file mode 100644
index 0000000000000000000000000000000000000000..50466a9d6029b13d74b528f738847efd2aa1c6e1
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\347\254\254\344\270\211\346\226\271\351\251\261\345\212\250\345\246\202\344\275\225\350\277\233\345\205\245Anolis_OS.md"
@@ -0,0 +1,53 @@
+### 第三方驱动集成形式(Intree 或 Out-of-tree)
+
+
+第三方驱动分为两种集成形式:第一种是集成到[Cloud Kernel](https://gitee.com/anolis/cloud-kernel)里面,与内核版本同步迭代,称为intree;第二种是采用单独的仓库管理,可以在大版本的基础上快速迭代小版本,称为out-of-tree(OOT)。
+
+
+两种集成形式的判定原则为:
+
+
+* 使用较广泛的驱动,在其他主流OS intree支持,则Anolis OS也优先考虑intree支持。
+* 综合厂商意愿和多方意见决定是否intree。
+* 如果第三方驱动与Anolis内核中的相关代码有冲突,则选择out-of-tree。
+* 如果第三方驱动处于开发活跃期,版本节奏与Anolis OS不匹配,则选择out-of-tree。
+
+
+### 第三方驱动集成流程
+
+
+1、第三方厂商提交第三方驱动集成申请,具体操作请点击 [如何提交第三方驱动集成申请](https://openanolis.cn/sig/Cloud-Kernel/doc/658176089664054811) 。
+
+
+2、如果是外设驱动相关,第三方厂商还需要提交硬件兼容性测试申请,具体操作请点击 [如何硬件兼容性测试申请](https://openanolis.cn/sig/Cloud-Kernel/doc/658195172967044331) 。
+
+
+3、强烈建议你加入 [Cloud Kernel SIG](https://openanolis.cn/sig/Cloud-Kernel) 钉钉交流群,可用群号「**35675176」**或扫 [这里](https://openanolis.cn/sig/Cloud-Kernel) 末尾的二维码入群,入群后请查看群公告。
+
+
+
+
+
+通过bugzilla或钉钉群决策出来该第三方驱动是intree还是out-of-tree后,分别走不同的合入流程:
+
+
+#### Intree流程
+
+
+1、第三方厂商提PR(Pull Request)将驱动合入到Anolis kernel中, 具体操作请点击 [内核开发者指南](https://openanolis.cn/sig/Cloud-Kernel/doc/657676881630727957) 。
+
+
+2、根据上述指南完成提交后,第三方厂商更新信息关闭bugzilla。
+
+
+#### Out-of-tree流程
+
+
+社区maintainer会创建source tree仓库和rpm tree仓库,将仓库信息同步至bugzilla中。
+
+
+1、第三方厂商提交PR(Pull Request)将源码 + spec文件合入到source tree仓库,具体操作请点击 [OOT驱动开发者指南](https://openanolis.cn/sig/Cloud-Kernel/doc/660356858711892913?preview=null) 。
+
+
+2、根据上述指南完成提交后,第三方厂商更新信息关闭bugzilla。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\351\241\271\347\233\256\347\256\200\344\273\213.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\351\241\271\347\233\256\347\256\200\344\273\213.md"
new file mode 100644
index 0000000000000000000000000000000000000000..98854f24cfab9915e81a716bcdbe31f57b194ef4
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/\351\241\271\347\233\256\347\256\200\344\273\213.md"
@@ -0,0 +1,14 @@
+本项目致力于维护Anolis OS各个版本的第三方驱动,例如适配支持最新的硬件型号,但不限于硬件外设驱动。
+
+
+
+
+
+相关文档:
+
+
+#### [第三方驱动如何进入Anolis OS](https://openanolis.cn/sig/Cloud-Kernel/doc/657632139127603555?preview=)
+
+
+#### [Anolis OS支持的驱动列表](https://openanolis.cn/sig/Cloud-Kernel/doc/657632317528069334?preview=)
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213.md"
new file mode 100644
index 0000000000000000000000000000000000000000..c3c53de12d0105c4ec0b9895ac7ded0a11993e7f
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213.md"
@@ -0,0 +1,340 @@
+# 1. RAS机制简介
+
+
+为了提高系统的容错能力及可用性, 面向服务器的处理器芯片都需要支持 RAS 机制。RAS是可靠性(Reliability)、可用性(Availability)和可服务性(Serviceability)的简称,分别代表下面的意义:
+
+
+**Reliability**:指的是系统尽可能最大化运行时间,不会意外崩溃,重启甚至系统物理损坏,即对于某些错误能做到自动修复,无法自修复的也尽可能进行隔离,保证系统正常运转。
+
+
+**Availability**:指的是系统最大限度减少非预期宕机的时间,当出现问题也不会影响整个系统的正常运行,在某些情况下甚至可以进行替换组件操作,严格确保系统宕机时间在一定范围内。
+
+
+**Serviceability**:指的是系统提供诊断功能,例如系统日志,动态检测等手段方便管理人员进行系统诊断和维护操作,尽早发现并修复错误。
+
+
+RAS是评估服务器系统容错能力及可用性评测的一项关键指标。错误等级可分为三级分别是可纠正错误(Corrected Error, CE)、可恢复错误(Uncorrected Error, UE)以及致命错误(Fatal),RAS机制实现对错误的分级处理。
+
+
+# 2. RAS机制错误处理流程
+
+
+RAS机制需要硬件、固件、OS内核协同工作才能得以支持,因此需要一个统一高效的接口来进行硬件错误的上报与处理。ACPI Platform Error Interfaces(APEI)正是为解决这一问题而出现,APEI规范统一了软硬件接口。它通过提供BOOT Error Record Table (BERT)、Error Record Serialization Table (ERST)、Error Injection Table (EINJ)以及Hardware Error Source Table (HEST)这四张表来实现OS内核与固件、硬件之间的协同工作,其中,HEST用于错误上报,EINJ用于错误注入。
+
+
+RAS机制错误处理流程如下,当硬件(如CPU、内存、PCIe总线)产生错误时,中断信号会首先交由运行在Secure World的固件处理,固件首先调用CPER库产生规范化的错误信息记录并填入CPER表中,然后将中断信号交由linux内核处理。linux内核中SDEI驱动接收该中断并调用ghes\_proc\_in\_irq函数从ACPI Table中读取错误信息,然后调用ghes\_do\_proc对错误进行处理,并且调用ghes\_print\_estatus打印错误信息。ghes\_do\_proc函数会最终调用memory\_failure函数对内存以及Cache的UE错误进行处理,对于CPU错误进行记录,对于fatal错误则会产生kernel panic。
+
+
+
+
+
+# 3. RAS机制评测流程
+
+
+RAS提供的EINJ机制可以在系统发布之前评测系统的可靠性、容错性以及完备性。EINJ 可以注入各种类型的硬件错误,这些注入的错误通过 EINJ 和底层 firmware 以及硬件共同配合产生的,对于软件来说和硬件真实发生的错误没有差别。
+
+
+APEI按照错误等级以及错误类型进行组合,总共支持以下12种错误注入,需要以实际系统支持的错误注入类型为准。
+
+
+从表中可以看到,错误类型分别有Processor错误、Memory错误、PCIe错误以及Platform错误。典型的Processor错误有L1-Cache/L2-Cache/TLB中出现数据一位或多位翻转;典型的Memory错误有内存中出现数据一位或多位翻转;在ARM架构中,典型的Platform错误有LLC(last level cache)中出现一位或多位位翻转。
+
+
+如果仅一位翻转,那么硬件(比如通过ECC)可以检测到并且纠正,像这样的错误就是Correctable Error,在软件层面则只需要进行记录发生此类错误的次数,在次数未达阀值前不需要进一步处理。如果有一位以上的数据翻转,那么硬件只能检测到发生错误没有能力进行纠正,这就是Uncorrectable Error,需要软件层面根据错误等级提供处理逻辑:如果产生的错误是Uncorrectable Non-Fatal Error,可将该数据直接丢弃;如果产生的错误是Uncorrectable Fatal Error,触发kernel panic重启系统。
+
+
+
+
+| |
+| --- |
+| 0 Processor Correctable
+1 Processor Uncorrectable non-fatal
+2 Processor Uncorrectable fatal |
+| 3 Memory Correctable
+4 Memory Uncorrectable non-fatal
+5 Memory Uncorrectable fatal |
+| 6 PCI Express Correctable
+7 PCI Express Uncorrectable non-fatal
+8 PCI Express Uncorrectable fatal |
+| 9 Platform Correctable
+10 Platform Uncorrectable non-fatal
+11 Platform Uncorrectable fatal |
+
+
+Linux内核进行错误注入的流程如下。EINJ.ko模块封装了APEI进行错误注入的操作细节(具体操作细节可参考ACPI SPEC 18.6.5节),在/apei/einj目录下为用户提供了便于操作的接口。这些参数的意义如下,available\_error\_type展示系统支持注入哪些错误;error\_type是当前注入的错误类型;flags取值与当前错误类型相关;参数param1~param4可传递注入错误的地址、掩码、CPU编号等,也与当前注入的错误类型相关;向error\_inject写1表示开始注入错误。EINJ.ko模块接受到这些参数后,调用EINJ Table中相应的action,由固件进行错误注入。EINJ.ko模块等待错误注入成功后,可继续调用EINJ Table中的action触发该错误,或者直接返回由用户自行触发(参数notrigger置1表示由用户自行触发)。
+
+
+
+
+
+上述流程比较简要地介绍了APEI错误注入机制,linux内核中的APEI Error INJection support模块已经完整地支持了错误注入机制,可调用EINJ.ko模块的接口或者使用封装了该模块接口的ras-tools进行错误注入。
+
+
+错误注入是为了验证系统RAS机制的正确性,因此**RAS评测流程**可分为如下三步:
+
+
+1**.使用ras-tools工具注入错误**,比如,内存、CPU的错误。
+
+
+2.**触发错误**。ras-tools工具默认注入错误后即进行触发。
+
+
+3.**观测系统对错误的处理是否符合预期**,比如,上报的错误信息是否准确,系统对各类错误的处理逻辑是否合理等。
+
+
+# 4. CPU及内存错误注入演示
+
+
+CPU和内存在计算机系统中的具有十分重要地位,它们出现错误有可能导致系统宕机甚至程序执行出错,对于服务器系统来说是不可接受的。因此,本节演示CPU与内存的错误注入。
+
+
+## 4.1 环境准备
+
+
+### 1. 安装EINJ模块
+
+
+使用命令modprobe einj进行模块加载,如果无法加载,则需要配置内核重新编译,可参考文档 :https://docs.kernel.org/firmware-guide/acpi/apei/einj.html
+
+
+此外,由于RAS机制需要固件的支持,如果后续的测试未看到上报的错误信息,那么需要检查固件(BIOS)是否支持RAS,或者将固件更新到最新。
+
+
+### 2. 安装RAS测试工具
+
+
+直接使用EINJ接口进行错误注入比较繁琐,可安装ras-tools工具进行错误注入,该工具由C语言编写,直接编译即可,链接:https://gitee.com/anolis/ras-tools.git
+
+
+### 3. 安装rasdaemon
+
+
+先安装依赖包yum install sqlite perl-DBD-SQLite
+
+
+使用如下命令编译安装rasdaemon,链接:https://github.com/mchehab/rasdaemon.git
+
+
+
+```
+autoreconf -vfi && ./configure --enable-sqlite3 --enable-arm && make
+make install
+```
+
+在命令行中输入rasdaemon -r 即可开启rasdaemon守护进程,rasdaemon支持如下参数。
+
+
+
+```
+ -d, --disable 禁用RAS事件并退出
+ -e, --enable 使能RAS事件并退出
+ -f, --foreground 前台运行
+ -r, --record 通过sqlite3记录事件
+```
+
+rasdaemon用户态守护进程能将捕获系统events并将错误信息输出到log、database或console。
+
+
+查看系统详细的错误处理信息可以通过dmesg命令查看,或者从BMC串口查看。
+
+
+本次测试需要使用rasdaemon -r命令开启该进程,并在跳板机上使用BMC串口连接到目标机。
+
+
+## 4.2 CPU错误注入
+
+
+本文主要使用einj\_mem\_uc工具,该工具可注入内存错误以及CPU错误,可使用命令./einj\_mem\_uc -h查看使用说明。
+
+
+使用./einj\_mem\_uc core\_non\_fatal命令注入一个UE类型的CPU错误。
+
+
+
+```
+./einj_mem_uc core_non_fatal
+0: core_non_fatal vaddr = 0xffff88f22400 paddr = 8a878e400
+injecting ...
+triggering ...
+Manually take page offline
+Test passed
+```
+
+使用BMC串口错误处理详细信息如下,没有时间戳的信息是由固件输出的,有时间戳的信息则是由内核输出的(如果使用dmesg则只能查看到下述带时间戳的信息)。可以看到硬件产生了17号中断,并首先由固件接管。17号中断的意义如下,它是一个CPU错误信号。
+
+
+
+
+| | | | |
+| --- | --- | --- | --- |
+| 17 | nFaultIRQ | Core fault interrupt | Generated from CORE and connect to nFAULTIRQ pins; nFAULTIRQ pins are connected to GIC components; this CPU or other CPUs handle the faults in firmware, firmware behavior is implementation-defined. |
+
+
+可以看到,这个错误是来自L2 Cache的错误,它是不可纠正但可恢复的。恢复手段应该是硬件层面CPU丢弃Cache中的数据,软件层面通过memory\_failure函数删除Cache数据对应的内存页面。
+
+
+
+```
+->Core[8](0x81080000) received intr=17(core), cnt=0xd
+INFO: RAS reg:
+INFO: fr = 10a9a2
+INFO: status = 44800007
+INFO: addr = 8007e0e95fffb7ff
+INFO: misc0 = 4
+INFO: misc1 = 0
+RTC: 2000-01-06 09:32:09
+ core[8] mm(17) return: 0
+--handler(17) end
+[40858.417829] [Firmware Warn]: GHES: Unhandled processor error type: cache error
+[40858.427894] {42}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 4
+[40858.436229] {42}[Hardware Error]: event severity: recoverable
+[40858.441961] {42}[Hardware Error]: precise tstamp: 2000-01-06 09:32:09
+[40858.448473] {42}[Hardware Error]: Error 0, type: recoverable
+[40858.454204] {42}[Hardware Error]: section_type: ARM processor error
+[40858.460629] {42}[Hardware Error]: MIDR: 0x00000000410fd490
+[40858.466272] {42}[Hardware Error]: Multiprocessor Affinity Register (MPIDR): 0x0000000081080000
+[40858.475041] {42}[Hardware Error]: running state: 0x1
+[40858.480163] {42}[Hardware Error]: Power State Coordination Interface state: 0
+[40858.487456] {42}[Hardware Error]: Error info structure 0:
+[40858.493013] {42}[Hardware Error]: num errors: 1
+[40858.497702] {42}[Hardware Error]: error_type: 0, cache error
+[40858.503606] {42}[Hardware Error]: error_info: 0x0000000000800015
+[40858.509857] {42}[Hardware Error]: transaction type: Instruction
+[40858.516109] {42}[Hardware Error]: cache level: 2
+[40858.521058] {42}[Hardware Error]: the error has not been corrected
+[40858.528062] Memory failure: 0x89b78f: recovery action for dirty LRU page: Recovered
+```
+
+## 4.3 内存错误注入
+
+
+使用命令./einj\_mem\_uc single注入一个UE类型的内存错误。该命令首先向一个内存地址注入一个UE类型的内存错误,然后通过读取该地址的数据触发该错误。
+
+
+
+```
+./einj_mem_uc single
+0: single vaddr = 0xffffabcb3400 paddr = 8aaf74400
+injecting ...
+triggering ...
+SIGBUS: addr = 0xffffabcb3400
+page not present
+Test passed
+```
+
+BMC串口中显示详细的错误处理详细信息如下(如果使用dmesg则只能查看到下述带时间戳的信息),硬件产生了一个中断号为0的中断,这代表产生的是一个同步异常。接下来的信息指出该错误是一个可恢复的内存错误,并且展示了产生该错误的内存地址以及ECC寄存器的状态。最后调用memory\_failure函数删除该地址对应的内存页面。
+
+
+
+```
+->Core[8](0x81080000) received intr=0(exception), cnt=0xa
+MM Mem RAS handle,Intr:0
+Ch = 25810000
+ |-ECCERRCNT:10000, ECCSTAT:0, ADVECCSTAT:8000002 ECCSYMBOL:760000
+ |-ECCERRCNTSTAT:0 ECCERRCNT0:0 ECCERRCNT1:0
+ |-ECCCADDR0:0 ECCCADDR1:0 ECCCDATA0~1:0,0
+ |-ECCCSYN0~2:0,0,0 ECCAPSTAT:0
+ |-ECCUADDR0:176D ECCUADDR1:2010480 ECCUDATA0~1:1FF,0
+ |-ECCUSYN0~2:1FF,0,76
+ |-SBRCTL:1C01591B,SBRSTS:0
+RasData->ExceptionEl: 0, UeCnt:0x1
+RTC: 2000-01-06 09:27:58
+Get SystemAddrss through mAddrTransProtocol start
+Get SystemAddrss through mAddrTransProtocol end
+s:0 d:0 ctl:2 ch:0 rank:0 bg:2 b:1 row:176D col:480 DeAddr:DDB599400
+Locate error dimm, Socket:0, Channel:2 Dimm:0
+ core[8] mm(0) return: 0
+--handler(0) end
+[40606.624019] EDAC MC0: 1 UE multi-symbol chipkill ECC on unknown memory (node:0 card:2 module:0 rank:0 bank_group:2 bank_address:1 device:0 row:5997 column:1152 chip_id:0 page:0xddb599 offset:0x400 grain:1 - APEI location: node:0 card:2 module:0 rank:0 bank_group:2 bank_address:1 device:0 row:5997 column:1152 chip_id:0 status(0x0000000000000400): Storage error in DRAM memory)
+[40606.660031] {41}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 2
+[40606.668367] {41}[Hardware Error]: event severity: recoverable
+[40606.674098] {41}[Hardware Error]: precise tstamp: 2000-01-06 09:27:58
+[40606.680611] {41}[Hardware Error]: Error 0, type: recoverable
+[40606.686342] {41}[Hardware Error]: section_type: memory error
+[40606.692159] {41}[Hardware Error]: error_status: Storage error in DRAM memory (0x0000000000000400)
+[40606.701275] {41}[Hardware Error]: physical_address: 0x0000000ddb599400
+[40606.707961] {41}[Hardware Error]: node:0 card:2 module:0 rank:0 bank_group:2 bank_address:1 device:0 row:5997 column:1152 chip_id:0
+[40606.720028] {41}[Hardware Error]: error_type: 5, multi-symbol chipkill ECC
+[40606.727781] Memory failure: 0xddb599: recovery action for dirty LRU page: Recovered
+```
+
+## 4.4 rasdaemon日志读取
+
+
+rasdaemon日志存储在数据库中,可通过ras-mc-ctl --errors读取日志。可以看到rasdaemon简要地记录了系统中的错误信息。
+
+
+
+```
+[root@localhost ras-tools]# ras-mc-ctl --errors
+Memory controller events:
+1 2022-09-01 10:29:28 +0800 1 Uncorrected error(s): multi-symbol chipkill ECC at unknown memory location: 0:-1:-1:-1, addr 4434626552832, grain 0, syndrome 0 APEI location: node:0 card:6 module:0 rank:0 bank_group:6 bank_address:2 device:0 row:529 column:256 chip_id:0 status(0x0000000000000400): Storage error in DRAM memory
+2 2022-09-01 11:25:11 +0800 1 Uncorrected error(s): multi-symbol chipkill ECC at unknown memory location: 0:-1:-1:-1, addr 4434626552832, grain 0, syndrome 0 APEI location: node:0 card:6 module:0 rank:0 bank_group:6 bank_address:2 device:0 row:529 column:256 chip_id:0 status(0x0000000000000400): Storage error in DRAM memory
+3 2022-09-01 11:55:11 +0800 1 Uncorrected error(s): multi-symbol chipkill ECC at unknown memory location: 0:-1:-1:-1, addr 4434626552832, grain 0, syndrome 0 APEI location: node:0 card:6 module:0 rank:0 bank_group:6 bank_address:2 device:0 row:529 column:256 chip_id:0 status(0x0000000000000400): Storage error in DRAM memory
+```
+
+# 5. Q&A
+
+
+Q:RAS机制是否需要BIOS支持?
+
+
+A:需要BIOS支持,并且由于BIOS对RAS支持的更新较快,最好将BIOS更新到最新版本。
+
+
+
+
+
+Q: x86和ARM64的APEI是否一致?
+
+
+A: x86与ARM64的芯片只要都遵循同一套ACPI协议,那么APEI是一致的。
+
+
+
+
+
+Q: RAS注入的错误是真实的错误吗?
+
+
+A: 错误中断是真实触发的;关于内存中的数据,是通过写入ECC相关寄存器模拟的。
+
+
+
+
+
+Q: rasdaemon日志查看是否有更易用的方法?
+
+
+A: 首先安装rasdaemon依赖的库yum install sqlite perl-DBD-SQLite;使用rasdaemon -r 命令启动;
+
+
+ 最后使用 ras-mc-ctl --errors 命令可以查看rasdaemon日志。
+
+
+
+
+
+Q: 可否使用mcelog?
+
+
+A: mcelog的原理是通过读取并解析x86的machine check机制的寄存器信息来捕获硬件错误,因此它是x86专用的,不适用于ARM64。
+
+
+
+
+
+Q:einj\_mem\_uc是否覆盖所有case,例如向用户进程地址空间注入UE,是否kill掉用户进程而让系统保持正常?向内核注入UE,系统是否crash?
+
+
+A:ras-tools工具提供的测试用例比较丰富,可满足RAS机制测试与研发的需求。比如,./einj\_mem\_uc single用例实现用户进程访问UE数据,einj\_mem\_uc程序对SIGBUS信号进行了处理,否则会被直接kill;而./einj\_mem\_uc copyin用例实现内核访问UE数据,系统会crash。
+
+
+
+
+
+Q:由于RAS错误导致内核crash,对应记录未被记录在rasdaemon中,是否合理?
+
+
+A:需要检查是否是rasdaemon某些选项未开启。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220.md"
new file mode 100644
index 0000000000000000000000000000000000000000..2afffe558eb929d14d756b06611e15d90e3fc163
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220.md"
@@ -0,0 +1,182 @@
+## cgroup.memory=nokmem
+
+
+### kmem 是什么
+
+
+kmem 是cgroup 的一个扩展,全称CONFIG\_MEMCG\_KMEM
+
+
+内核内存:专用于Linux内核系统服务使用,是不可swap的,因而这部分内存非常宝贵的。但现实中存在很多针对内核内存资源的攻击,如不断地fork新进程从而耗尽系统资源,即所谓的“fork bomb”。
+
+
+为了防止这种攻击,社区中提议通过linux内核限制cgroup中的kmem容量,从而限制恶意进程的行为,即kernel memory accounting机制。
+
+
+内核内存统计对所有内存控制组默认使能,在启动时传递cgroup.memory=nokmem参数可以禁用该功能,在禁用后,内核内存就不会被统计。
+
+
+### 带来的性能影响
+
+
+#### 相关代码
+
+
+通过解析cmdline,是否传入nokmem会控制cgroup\_memory\_nokmem的值。
+
+
+
+```
+static int __init cgroup_memory(char *s)
+{
+ char *token;
+
+ while ((token = strsep(&s, ",")) != NULL) {
+ if (!*token)
+ continue;
+ if (!strcmp(token, "nosocket"))
+ cgroup_memory_nosocket = true;
+ if (!strcmp(token, "nokmem"))
+ cgroup_memory_nokmem = true;
+ }
+ return 0;
+}
+__setup("cgroup.memory=", cgroup_memory);
+```
+
+cgroup\_memory\_nokmem涉及到的相关函数如下:
+
+
+each slab object pointer to an memcg respectively when kmem account enable, slab page can be used by root mem\_cgroup and children memcg. slab object age is recorded in slab\_age of page when kmem account disable. Otherwise, an special obj\_cgroups pointer will store the value.
+
+
+int kidled\_alloc\_slab\_age(struct page \*page, struct kmem\_cache \*s, gfp\_t flags)
+
+
+static unsigned short \*kidled\_get\_slab\_age\_array(void \*object)
+
+
+static int memcg\_online\_kmem(struct mem\_cgroup \*memcg)
+
+
+意味着使能该参数后,会在slab管理的page分配和释放流程上增加额外的处理逻辑,下面通过实际对比测试来直观的感受一下对应的开销。
+
+
+#### 数据测试
+
+
+通过lmbench对cgroup.memory=nokmem是否使能进行内存测试(5次取平均):
+
+
+
+
+| | | |
+| --- | --- | --- |
+| 测试环境 | 开启cgroup\_memory\_nokmem | Communication bandwidths (Pipe,越大越好) |
+| an8-4.19, memory cgroup 500M | 是 | 4234 |
+| 否 | 3705 |
+| an8-5.10, memory cgroup 500M | 是 | 4125 |
+| 否 | 3659 |
+
+
+### 其他问题
+
+
+#### kmem.slabinfo造成cpu使用率异常
+
+
+该问题只存在于4.19内核,5.10内核实现逻辑改变无此问题,参见mm/slab\_common.c
+
+
+通过CONFIG\_SLAB或CONFIG\_SLUB\_DEBUG会使能kmem.slabinfo,目前anolis默认开启CONFIG\_SLUB\_DEBUG
+
+
+
+```
+#if defined(CONFIG_SLAB) || defined(CONFIG_SLUB_DEBUG)
+ {
+ .name = "kmem.slabinfo",
+ .seq_start = memcg_slab_start,
+ .seq_next = memcg_slab_next,
+ .seq_stop = memcg_slab_stop,
+ .seq_show = memcg_slab_show,
+ },
+#endif
+```
+
+slabinfo通过链表的方式进行组织,意味着访问的时间复杂度为O(n),通过读取相应cgroup下的memory.kmem.slabinfo,可以查看相应的slabinfo信息。
+
+
+
+```
+void *memcg_slab_start(struct seq_file *m, loff_t *pos)
+{
+ struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(m));
+
+ mutex_lock(&slab_mutex);
+ return seq_list_start(&memcg->kmem_caches, *pos);
+}
+
+void *memcg_slab_next(struct seq_file *m, void *p, loff_t *pos)
+{
+ struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(m));
+
+ return seq_list_next(p, &memcg->kmem_caches, pos);
+}
+
+void memcg_slab_stop(struct seq_file *m, void *p)
+{
+ mutex_unlock(&slab_mutex);
+}
+
+int memcg_slab_show(struct seq_file *m, void *p)
+{
+ struct kmem_cache *s = list_entry(p, struct kmem_cache,
+ memcg_params.kmem_caches_node);
+ struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(m));
+
+ if (p == memcg->kmem_caches.next)
+ print_slabinfo_header(m);
+ cache_show(s, m);
+ return 0;
+}
+```
+
+通过特定操作cgroup,可以让memory cgroup产生泄漏,复现方法如下:
+
+
+通过不断创建新的memory cgroup,执行文件操作,并删除memory cgroup,我们可以看到,/sys/fs/cgroup/memory中的cgroup并没有增加,而/proc/cgroup显示存在大量的memory cgroup。
+
+
+
+```
+for ((i=0;i<100000;++i)); do
+ mkdir -p /sys/fs/cgroup/memory/test/test$i
+ echo $$ > /sys/fs/cgroup/memory/test/test$i/tasks
+ mkdir -p /tmp/test/
+ echo 'date' > /tmp/test/test$i
+ echo $$ > /sys/fs/cgroup/memory/test/tasks
+ rmdir /sys/fs/cgroup/memory/test/test$i
+done
+```
+
+脚本执行前:
+
+
+
+
+
+脚本执行后:
+
+
+
+
+
+但是在执行脚本后,查看/sys/fs/cgroup/memory,并不存在对应数量的memory cgroup,产生泄漏。这样,大量的memory cgroup会造成访问slabinfo链表的执行时间大量增加,造成不必要的cpu访问开销。
+
+
+### 结论
+
+
+基于性能测试以及存在的潜在问题,存量的版本建议通过 boot cmdline cgroup.memory=nokmem 来关闭 kmem ,并保证用户习惯的兼容性。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215.md"
new file mode 100644
index 0000000000000000000000000000000000000000..5e0b929172b7964295fa721ac409f93606b5e52d
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215.md"
@@ -0,0 +1,1028 @@
+本文介绍龙蜥内核已支持的内核功能与接口。
+
+
+# Group Identity
+
+
+Group Identity功能可以对每一个CPU cgroup设置身份标识,以区分cgroup中的任务优先级。Group Identity核心是双红黑树设计,在CFS(Completely Fair Scheduler)调度队列的单红黑树基础上,新增了一颗低优先级的红黑树,用于存放低优先级任务。系统内核在调度包含具有身份标识的任务时,会根据不同的优先级做相应处理。
+
+
+在业务的混合部署(延迟敏感型和计算型任务混合部署在同一台实例)场景中,Linux内核调度器需要为高优先级任务赋予更多的调度机会以最小化调度延迟,并需要把低优先级任务对内核调度带来的影响降到最低。
+
+
+基于该场景,ANCK提供了Group Identity功能,为CPU cgroup新增了配置调度优先级的接口,且不同优先级的任务具有以下特点:
+* 高优先级任务的唤醒延迟最小化。
+* 低优先级任务不对高优先级任务造成性能影响。主要体现在:
+ + 低优先级任务的唤醒不会对高优先级任务造成性能影响。
+ + 低优先级任务不会通过共享硬件unit而对高优先级任务造成性能影响。
+
+
+
+
+| | |
+| --- | --- |
+| 接口 | 说明 |
+| `cpu.identity` | 默认取值为0,表示身份标识为`ID_NORMAL`。
+该接口是一个位段,一共有5个比特位,该接口各个比特位的取值说明如下:
+* 空值:表示身份标识为`ID_NORMAL`。
+* 比特位0:表示身份标识为`ID_UNDERCLASS`。
+* 比特位1:表示身份标识为`ID_HIGHCLASS`。
+* 比特位2:表示身份标识为`ID_SMT_EXPELLER`。
+* 比特位3:表示身份标识为`ID_IDLE_SAVER`。
+* 比特位4:表示身份标识为`ID_IDLE_SEEKER`。
+
+
+
+例如,如果设置一个cgroup的身份标识为`ID_HIGHCLASS`和`ID_IDLE_SEEKER`,那么将比特位1和4置为1,其他比特位置为0,得到的二进制表示为:10010,转化为十进制为:18,则执行`echo 18 > /sys/fs/cgroup/cpu/$cg/cpu.identity`即可完成写入。 |
+| `cpu.bvt_warp_ns` | 默认取值为0,表示身份标识为`ID_NORMAL`。该接口的取值说明如下:
+* 2:表示同时具有身份标识`ID_SMT_EXPELLER`、`ID_IDLE_SEEKER`、`ID_HIGHCLASS`,对应的identity值为22。
+* 1:表示同时具有身份标识`ID_HIGHCLASS`、`ID_IDLE_SEEKER`,对应的identity值为18。
+* 0:表示身份标识为`ID_NORMAL`,对应的identity值为0。
+* -1:表示同时具有身份标识`ID_UNDERCLASS`、`ID_IDLE_SAVER`,对应的identity值为9。
+* -2:表示同时具有身份标识`ID_UNDERCLASS`、`ID_IDLE_SAVER`,对应的identity值为9。
+ |
+
+
+
+
+
+# 在cgroup v1接口开启CPU Burst功能
+
+
+
+在容器服务中,容器允许使用的CPU资源被内核的CFS Bandwidth Controller(带宽控制器)限流。当您在cgroup v1接口开启CPU Burst功能后,CPU Burst功能允许容器突发使用限流之外的CPU资源。该功能既可以保证容器运行的服务质量,又不降低容器部署密度。
+
+
+
+
+
+CPU Burst功能允许突发使用的CPU资源依赖于日常的资源积累。比如,容器在日常运行中使用的CPU资源未超过CPU限流,则空余的CPU资源将会被积累。后续当容器运行需要大量CPU资源时,将通过CPU Burst功能突发使用CPU资源,这部分突发使用的资源来源于已积累的资源。以休假体系作为类比:
+
+
+假如您每年休假时间为4天(CPU限流),未休的假期可以存放起来后续使用,但存放上限为4天(CPU Burst)。当您第一年、第二年各只休了1天的假期,那么没有休息的6天假期可以存放起来。当第三年的时候,理论上您可以休息共计10天的假期,但因为有存放上限(CPU Burst),则实际可以休息至多8天的假期。
+
+
+## 开启CPU Burst功能
+
+
+1. 检查cgroup v1接口中的CPU Burst功能的全局开关是否已打开。
+
+
+
+
+```
+cat /proc/sys/kernel/sched_cfs_bw_burst_enabled
+```
+
+
+
+返回结果说明:
+
+ * 如果返回结果为`1`,则表示CPU Burst功能的全局开关已打开。
+
+
+ **说明** 默认情况下,cgroup v1接口中的CPU Burst功能的全局开关为打开状态。
+ * 如果返回结果不为`1`,则表示CPU Burst功能的全局开关已关闭。您可以运行以下命令打开全局开关:
+
+
+
+ ```
+ echo 1 > /proc/sys/kernel/sched_cfs_bw_burst_enabled
+ ```
+2. 在具体的子cgroup中开启CPU Burst功能。
+默认情况下,cgroup v1接口中的CPU Burst功能在各个子cgroup中均未开启。具体的开启方式如下:
+ 1. 进入子cgroup路径下,检查CFS Bandwidth Controller限流是否处于生效状态。
+
+
+
+
+ ```
+ cd /sys/fs/cgroup/cpu/子cgroup目录名称/
+ cat cpu.cfs_period_us
+ cat cpu.cfs_quota_us
+ ```
+
+
+
+ 如果`cpu.cfs_quota_us`对应的返回结果为正整数,则表示CFS Bandwidth Controller限流处于生效状态,进而在启用CPU Burst功能后,容器才可以获得超出CPU限流的CPU资源。
+ 2. 检查当前默认的CPU Burst设置。
+
+
+
+
+ ```
+ cat cpu.cfs_burst_us
+ ```
+
+
+
+ 返回结果的默认值为`0`,表示CPU Burst功能未开启。
+ 3. 设置`cpu.cfs_burst_us`的值以开启CPU Burst功能。
+ 您可以设置一个适用的正整数启用CPU Burst功能,且这个正整数表示子cgroup突发额外使用的CPU资源的上限。本文通过以下示例场景,介绍如何开启CPU Burst功能。
+
+ 1. 配置CFS Bandwidth Controller带宽控制器默认的`cpu.cfs_quota_us`与`cpu.cfs_period_us`。
+ 以下配置,将CPU资源的使用周期(`cpu.cfs_period_us`)设置为100ms,每个周期中的CPU限流(`cpu.cfs_quota_us`)设置为400ms,则子cgroup将会持续获得4个CPU资源(`cpu.cfs_quota_us`/`cpu.cfs_period_us`)。
+
+
+
+ ```
+ echo 400000 > cpu.cfs_quota_us
+ echo 100000 > cpu.cfs_period_us
+ ```
+ 2. 配置`cpu.cfs_burst_us`以开启CPU Burst功能。
+ 以下配置,将CPU Burst的值设置为600ms,表示开启了CPU Burst功能,且允许子cgroup可以突发额外使用最多6个CPU资源(`cpu.cfs_burst_us`/`cpu.cfs_period_us`)。
+
+
+
+ ```
+ echo 600000 > cpu.cfs_burst_us
+ ```
+
+
+## 查询CPU Burst的统计数据
+
+
+1. 进入待查询数据的子cgroup路径下。
+
+
+
+
+```
+cd /sys/fs/cgroup/cpu/子cgroup目录名称/
+```
+2. 查看统计数据。
+
+
+
+
+```
+cat cpu.stat
+```
+
+
+返回结果中,主要的信息说明如下:
+
+ * `nr_burst`数据:当前子cgroup触发CPU Burst的次数。
+ * `burst_time`数据:当前子cgroup突发使用CPU资源的时间。
+
+
+
+
+
+
+
+# 在cgroup v1接口开启PSI功能
+
+
+
+PSI(Pressure Stall Information)是一个可以监控CPU、内存及IO性能异常的内核功能。有关PSI功能的详细信息,您可以通过内核文档`Documentation/accounting/psi.txt`了解。
+
+## 为cgroup v1接口开启PSI功能
+
+
+默认情况下cgroup v1接口的PSI功能为关闭状态。按照以下步骤开启PSI功能。
+
+
+1. 运行`grubby`命令,修改启动参数。
+参数`args`中默认为`"psi=1"`,表示cgroup v2启用PSI功能。将参数修改为`"psi=1 psi_v1=1"`,表示为cgroup v1接口开启PSI功能。 本示例中内核版本为`4.19.81-17.an7.x86_64`,您在操作中需要更换为实际的内核版本,内核版本的查看命令为`uname -a`。
+
+
+
+```
+sudo grubby --update-kernel="/boot/vmlinuz-4.19.81-17.an7.x86_64" --args="psi=1 psi_v1=1"
+```
+2. 重启系统使该功能生效。
+
+
+
+
+```
+sudo reboot
+```
+
+
+## 确认cgroup v1接口的PSI功能已启用
+
+
+系统重启后,您可以执行命令,确认内核`/proc/cmdline`中已启用cgroup v1接口的PSI功能。
+
+
+
+```
+cat /proc/cmdline | grep "psi=1 psi_v1=1"
+```
+
+
+
+## 查询CPU、内存及IO的监控数据
+
+
+当您开启cgroup v1接口的PSI功能时,CPU、内存及IO的PSI监控数据均会输出到cpuacct控制器下,您可以通过以下命令查看详细的监控数据。
+
+
+
+```
+cat /sys/fs/cgroup/cpuacct/cpu.pressure
+cat /sys/fs/cgroup/cpuacct/memory.pressure
+cat /sys/fs/cgroup/cpuacct/io.pressure
+```
+
+
+
+
+
+
+
+
+# Memcg后台异步回收
+
+
+
+
+在社区内核系统中,系统分配内存并在相应memcg中的统计达到memcg设定的内存上限时,会触发memcg级别的直接内存回收。直接内存回收是发生在内存分配上下文的同步回收,因此会影响当前进程的性能。
+
+
+为了解决这个问题,ANCK增加了memcg粒度的后台异步回收功能。该功能的实现不同于全局kswapd内核线程的实现,并没有创建对应的memcg kswapd内核线程,而是采用了workqueue机制来实现,并在cgroup v1和cgroup v2两个接口中,均新增了4个memcg控制接口。
+
+
+注意事项:
+* 当前memcg的内存分配,可能会递归触发父组的后台异步回收。
+* 触发memcg后台异步回收时,会从当前被触发的memcg开始,自上而下做层级回收。
+* 当memory.high接口被配置,并且memory.high的值比memory.limit\_in\_bytes接口的值小的时候,接口memory.wmark\_high和memory.wmark\_low水位线的计算将基于memory.high而不是memory.limit\_in\_bytes。
+
+
+
+
+| 接口 | 说明 |
+| --- | --- |
+| memory.wmark\_ratio | 该接口用于设置是否启用memcg后台异步回收功能,以及设置异步回收功能开始工作的memcg内存水位线。单位是相对于memcg limit的百分之几。取值范围:0~100
+* 默认值为0,该值也表示禁用memcg后台异步回收功能。
+* 取值为非0时,表示开启memcg后台异步回收功能并设置对应的水位线。
+ |
+| memory.wmark\_high | 只读接口,说明如下:
+* 当memcg内存使用超过该接口的值时,后台异步回收功能启动。
+* 该接口的值由`(memory.limit_in_bytes * memory.wmark_ratio / 100)`计算获得。
+* memcg后台异步回收功能被禁用时,memory.wmark\_high默认为一个极大值,从而达到永不触发后台异步回收功能的目的。
+* memcg根组目录下不存在该接口文件。
+ |
+| memory.wmark\_low | 只读接口,说明如下:
+* 当memcg内存使用低于该接口的值时,后台异步回收结束。
+* 该接口的值由`memory.wmark_high - memory.limit_in_bytes * memory.wmark_scale_factor / 10000`计算得出。
+* memcg根组目录下不存在该接口文件。
+ |
+| memory.wmark\_scale\_factor | 该接口用于控制memory.wmark\_high和memory.wmark\_low之间的间隔。单位是相对于memcg limit的万分之几。取值范围:1~1000
+* 该接口在创建时,会继承父组的值(该值为50),该值也是默认值,即memcg limit的千分之五。
+* memcg根组目录不存在该接口文件。
+ |
+
+
+
+
+
+# Memcg全局最低水位线分级
+
+
+
+
+在Linux内核中,全局内存回收对系统性能影响很大。当时延敏感型业务和资源消耗型任务共同部署时,资源消耗型任务时常会瞬间申请大量的内存,使得系统的空闲内存触及全局最低水位线(global wmark\_min),引发系统所有任务进入直接内存回收的慢速路径,引发时延敏感型业务的性能抖动。在此场景下,无论是全局kswapd后台回收还是memcg后台回收,都将无法处理该问题。
+
+
+基于上述场景下的问题,ANCK新增了memcg全局最低水位线分级功能。在global wmark\_min的基础上,将资源消耗型任务的global wmark\_min上移,使其提前进入直接内存回收。将时延敏感型业务的global wmark\_min下移,使其尽量避免直接内存回收。这样当资源消耗型任务瞬间申请大量内存的时候,会通过上移的global wmark\_min将其短时间抑制,避免时延敏感型业务发生直接内存回收。等待全局kswapd回收一定量的内存后,再解除资源消耗型任务的短时间抑制。
+
+
+
+
+
+## 功能接口说明
+
+
+实现memcg全局最低水位线分级功能的接口为memory.wmark\_min\_adj。该接口的值,表示基于全局最低水位线(global wmark\_min)所作出的调整(adjustment)百分比。取值范围:-25 ~ 50,取值范围说明如下:
+* 该接口创建时,继承父组的值(值为0),即默认值为0。
+* 取值范围中的负值是基于调整范围`[0, WMARK_MIN]`的百分比,其中`WMARK_MIN`表示global wmark\_min的值,例如:
+
+
+
+```
+memory.wmark_min_adj=-25, memcg WMARK_MIN is "WMARK_MIN + (WMARK_MIN - 0) * (-25%)"
+```
+
+
+
+
+**说明** 负值也表示global wmark\_min下移,即提高时延敏感型业务的内存子系统服务质量(memcg QoS)。
+* 取值范围中的正值是基于调整范围`[WMARK_MIN, WMARK_LOW]`的百分比,其中`WMARK_MIN`和`WMARK_LOW`分别表示global wmark\_min和global wmark\_low的值,例如:
+
+
+
+```
+memory.wmark_min_adj=50, memcg WMARK_MIN is "WMARK_MIN + (WMARK_LOW - WMARK_MIN) * 50%"
+```
+
+
+
+
+**说明** 正值也表示global wmark\_min上移,即降低资源消耗型任务的内存子系统服务质量(memcg QoS)。
+* 当偏移后的global wmark\_min被触发后,会执行抑制操作,抑制操作的时间和超出的内存使用为线性比例关系。抑制时间的取值范围:1ms ~ 1000ms。
+
+
+
+
+**说明** memcg根组目录下不存在该接口文件。
+
+
+## 接口注意事项
+
+
+在多层级目录的memcg中,有一个`effective memory.wmark_min_adj`的概念,即最终生效的memory.wmark\_min\_adj值。具体规则是在memcg层级路径上遍历取最大值(中间节点的默认值0除外)。例如,有以下层级关系示例。
+
+
+
+```
+ root
+ / \
+ A D
+ / \
+ B C
+ / \
+ E F
+```
+
+
+则各层级设置的接口值与最终生效的接口值,对应关系如下所示。
+
+
+ | 层级 | 各层级设置的接口值 | 最终生效的接口值 |
+| --- | --- | --- |
+| A | -10 | -10 |
+| B | -25 | -10 |
+| C | 0 | 0 |
+| D | 50 | 50 |
+| E | -25 | -10 |
+| F | 50 | 50 |
+
+
+
+
+**说明**
+* 运行命令`cat /sys/fs/cgroup/memory//memory.wmark_min_adj`输出的值为最终生效的值,其中变量``是memcg的根路径。
+* 本功能建议配合较高的全局最低水位线(global wmark\_min)来使用,例如将global wmark\_min值设置为2 GB或更高,您可以通过/proc/sys/vm/min\_free\_kbytes进行设置。
+
+
+
+
+
+## 功能配置示例
+
+
+示例一:为时延敏感型业务所在memcg配置全局最低水位线分级。
+
+
+1. 运行命令`mkdir /sys/fs/cgroup/memory/test-lc`创建测试文件。
+2. 运行命令`echo -25 > /sys/fs/cgroup/memory/test-lc/memory.wmark_min_adj`向接口写入值`-25`,提高时延敏感型业务的memcg QoS。
+
+
+示例二:为资源消耗型任务所在memcg配置全局最低水位线分级。
+
+
+1. 运行命令`mkdir /sys/fs/cgroup/memory/test-be`创建测试文件。
+2. 运行命令`echo 25 > /sys/fs/cgroup/memory/test-be/memory.wmark_min_adj`向接口写入值`25`,降低资源消耗型任务的memcg QoS。
+
+
+
+
+
+
+# Memcg OOM优先级策略功能
+
+
+
+
+在现有内核系统中,内存紧张情况下内核会遍历cgroup,选择耗用内存较多的cgroup进行内存回收,甚至在回收失败的情况下直接OOM,并停止当前cgroup下的所有任务。这对于当前cgroup包含的核心业务来说,会造成很大的影响。为此我们希望这类包含核心业务的cgroup占有的内存不被回收,或者cgroup下的任务在OOM中可以存活下来,以便让内核去选择其他的cgroup进行内存回收或者OOM。
+
+
+为了解决这个问题,ANCK增加了memcg OOM优先级配置功能。该功能在进行OOM操作时,会首先判定cgroup的优先级,选择低优先级的cgroup进行OOM操作。
+
+
+## memcg OOM优先级接口功能说明
+
+
+
+
+ | 接口 | 说明 |
+| --- | --- |
+| `memory.use_priority_oom` | 该接口用于设置是否启用memcg OOM优先级策略功能,取值为0或者1。该接口不会继承,默认值为0。
+* 取值为0时,表示禁用memcg OOM优先级策略功能。
+* 取值为1时,表示开启memcgOOM优先级策略功能。
+ |
+| `memory.priority` | 该接口提供13个级别的memcg优先级以支持不同重要程度的业务。取值范围为0~12,数值越大表示优先级越高。该接口不会继承,默认值为0。
+* 实现一定程度的内存QoS,此处需要说明的优先级值非全局变量,只能在同父cgroup下的兄弟节点进行比较。
+* 对于优先级相等的兄弟节点来说,会按照组的内存使用量来排序选择内存使用最大的进行OOM操作。
+ |
+
+
+## 接口配置示例
+
+
+按如下所示创建6个cgroup子节点A、 B、 C、 D、 E、 F,开启`memory.use_priority_oom`接口,并通过`memory.priority`接口设置OOM的优先级。
+
+
+
+```
+ root
+ / \
+ A B
+ / \ / \
+ C D E F
+```
+
+
+则各层级设置的接口值,对应关系如下所示:
+* A:10
+* B:8
+* C:5
+* D:6
+* E:7
+* F:8
+
+
+
+当在root中进行OOM操作时,它首先迭代查找它的两个子节点A和B,由于B的优先级值低于A,所以会选择B节点作为下一个迭代cgroup继续进行迭代,最终会在子节点E上进行OOM操作,因为它的优先级比其他的兄弟节点低。
+
+
+
+
+
+# THP reclaim功能
+
+
+
+
+
+
+
+Linux操作系统的内存采用分页管理模式,其中的THP(Transparent Huge Page)是指内核中2 MiB或1 GiB大小的大页面(普通的小页面大小为4 KiB),一般被称为透明大页。基于应用程序使用到的内存范围越来越大,地址转换产生的开销变得不可忽视。因此,当服务器上的应用程序申请内存时,内核会根据进程的实际情况动态分配透明大页,透明大页可以减少TLB(Translation Lookaside Buffer) Miss的出现概率,从而提升应用程序的性能。
+
+
+THP在带来性能提升的同时,也产生了一定副作用,即可能产生Memory bloating(内存膨胀)问题。该问题产生的原因说明:透明大页申请释放的粒度为2 MiB(即512个小页面),相较于小页面,透明大页更容易产生内存碎片,进而导致内核分配的内存容量大于实际需要的内存容量。
+
+
+Memory bloating可能引发OOM(Out Of Memory)。例如,一个应用程序实际需要使用2个小页面,即8 KiB内存,但是内核分配了1个透明大页。此时,除去应用程序实际需要的内存(2个小页面),透明大页剩下的内存(510个小页面)大小均为0。最终可能会因RSS(Resident Set Size)内存用量增加而导致OOM。
+
+
+为解决THP可能引发的内存问题。ANCK增加了memcg粒度的THP reclaim功能。在内核回收内存时,该功能会把透明大页拆分为小页面,并将其中的全零页面(zero subpage)回收,从而避免内存的快速膨胀引发OOM。但您需要注意,由于THP reclaim功能会将透明大页拆分为小页面,所以相较于2 MiB大小的透明大页,THP reclaim功能会在一定程度上造成内存性能的回退。
+
+
+## 接口说明
+
+
+实现THP reclaim功能的接口说明,如下表所述:
+
+
+ | 接口 | 说明 |
+| --- | --- |
+| `memory.thp_reclaim` | 开启或关闭THP reclaim功能。支持以下配置项:
+* reclaim:开启THP reclaim功能。
+* swap:预留配置项,目前暂无实际功能。
+* disable:关闭THP reclaim功能。
+
+
+THP reclaim功能默认为关闭状态,即接口默认值为disable。 |
+| `memory.thp_reclaim_stat` | 查看THP reclaim功能当前的状态。接口内的参数说明如下:
+* queue\_length:当前被THP reclaim管理的透明大页数量。
+* split\_hugepage:累计拆分的透明大页数量。
+* reclaim\_subpage:累计回收的全零页面(zero subpage)数量。
+
+
+该接口的参数值按照NUMA node的顺序(node0、node1)从左到右排列。 |
+| `memory.thp_reclaim_ctrl` | 控制THP reclaim功能的触发机制。目前支持以下配置项:
+* threshold:默认值为16。表示当透明大页中的全零页面(zero subpage)数量超过该值时,会触发THP reclaim功能。
+* reclaim:用于主动触发THP reclaim功能。
+ |
+| `/sys/kernel/mm/transparent_hugepage/reclaim` | THP reclaim功能的全局配置接口。支持以下配置项:
+* memcg:该接口的默认配置项。表示每个memory cgroup按照各自的配置开启或关闭THP reclaim,即以每个memory cgroup中的`memory.thp_reclaim`接口配置为准。
+* reclaim:强制开启所有memory cgroup的THP reclaim功能。
+* swap:预留配置项,目前暂无实际功能。
+* disable:强制关闭所有memory cgroup的THP reclaim功能。
+ |
+
+
+
+## 接口配置的操作说明
+
+
+本示例操作中,将创建一个名为test的memory cgroup,以test为例介绍THP reclaim接口的操作说明。
+
+
+1. 运行以下命令,创建一个名为test的memory cgroup。
+
+
+
+
+```
+mkdir /sys/fs/cgroup/memory/test/
+```
+2. 运行以下命令,开启test的THP reclaim功能。
+
+
+
+
+```
+echo reclaim > /sys/fs/cgroup/memory/test/memory.thp_reclaim
+```
+3. 运行以下命令,确认test的THP reclaim功能成功开启。
+
+
+
+
+```
+cat /sys/fs/cgroup/memory/test/memory.thp_reclaim
+```
+
+
+
+返回结果如下图所示,被`[]`包裹的配置项为生效配置项,`[reclaim]`表示test的THP reclaim功能已开启。
+4. 运行以下命令,通过THP reclaim功能的全局配置接口强制开启THP reclaim功能。
+
+
+
+
+```
+echo reclaim > /sys/kernel/mm/transparent_hugepage/reclaim
+```
+
+
+如果您想强制关闭THP reclaim功能,可运行以下命令:
+
+
+
+```
+echo disable > /sys/kernel/mm/transparent_hugepage/reclaim
+```
+
+
+
+
+**说明** THP reclaim功能的全局配置接口`/sys/kernel/mm/transparent_hugepage/reclaim`在设置为强制开启(`reclaim`)或强制关闭(`disable`)时,接口生效的优先级会高于各个memory cgroup中的`memory.thp_reclaim`接口,但不会影响各个memory cgroup中`memory.thp_reclaim`接口的配置。
+5. 运行以下命令,配置test的`memory.thp_reclaim_ctrl`接口的`threshold`配置项。
+
+
+
+
+```
+echo "threshold 32" > /sys/fs/cgroup/memory/test/memory.thp_reclaim_ctrl
+```
+
+
+
+此时,如果透明大页中的全零页面数量超过32,则会触发THP reclaim的全零页面回收功能。
+6. 主动触发THP reclaim的全零页面回收功能。
+主动触发后,THP reclaim会把所有超过`threshold`配置的全零页面回收。配置项`reclaim`存在以下配置方式:
+
+
+**说明** 该配置项的调用方式为同步调用,并且为只写配置项,即您只能向`memory.thp_reclaim_ctrl`接口写入`reclaim`以主动触发THP reclaim的全零页面回收功能,但不能通过cat命令查看到`reclaim`配置项。
+
+
+ * 运行以下命令,会主动触发当前memory cgroup的THP reclaim的全零页面回收功能。
+
+
+
+ ```
+ echo "reclaim 1" > /sys/fs/cgroup/memory/test/memory.thp_reclaim_ctrl
+ ```
+ * 运行以下命令,会主动递归触发当前memory cgroup以及该cgroup下所有子cgroup的THP reclaim的全零页面回收功能。
+
+
+
+ ```
+ echo "reclaim 2" > /sys/fs/cgroup/memory/test/memory.thp_reclaim_ctrl
+ ```
+
+
+ 除了通过`reclaim`主动触发THP reclaim的全零页面回收功能。THP reclaim还会伴随内存回收而触发:
+ + 内存出现OOM时,会触发THP reclaim的全零页面回收功能。
+ + 当memory cgroup触发memory后台异步回收时,会触发THP reclaim的全零页面回收功能。关于memory后台异步回收的更多信息,请参见"Memcg后台异步回收"。
+7. 运行以下命令,查看test的THP reclaim功能状态。
+
+
+
+
+```
+cat /sys/fs/cgroup/memory/test/memory.thp_reclaim_stat
+```
+
+
+
+返回结果示例如下:
+
+
+
+```
+queue_length 14
+split_hugepage 523
+reclaim_subpage 256207
+```
+
+
+## C语言代码测试样例
+
+
+本章节基于C语言提供了进程申请透明大页的代码测试样例。您可以通过以下测试样例,查看到THP reclaim功能在开启与关闭时的区别。
+
+
+1. 运行以下命令,为内存使用量限制接口`memory.limit_in_bytes`设置1 GiB的限制。
+
+
+
+
+```
+echo 1G > /sys/fs/cgroup/memory/test/memory.limit_in_bytes
+```
+
+
+
+设置后,您可以运行以下命令查看`memory.limit_in_bytes`接口的值。
+
+
+
+```
+cat /sys/fs/cgroup/memory/test/memory.limit_in_bytes
+```
+
+
+查看结果如下图所示:
+2. 运行以下命令,关闭memcg后台异步回收功能。
+关于memory后台异步回收的更多信息,请参见"Memcg后台异步回收"。
+
+
+
+```
+echo 0 > /sys/fs/cgroup/memory/test/memory.wmark_ratio
+```
+3. 分别在开启或关闭THP reclaim功能的前提下,运行以下C语言代码进行测试,并查看测试结果。
+
+
+
+
+```
+// 申请1 G内存(即512个透明大页),其中10个透明大页包含部分全零页面。
+#define HUGEPAGE_SIZE 4096 * 512
+int main()
+{
+ int i, thp = 512;
+ char *addr;
+ posix_memalign((void **)&addr, HUGEPAGE_SIZE, HUGEPAGE_SIZE * thp);
+
+ for (i = 0; i < 10; i++) {
+ memset(addr, 0xc, HUGEPAGE_SIZE >> 1);
+ addr += HUGEPAGE_SIZE;
+ }
+
+ for (; i < thp; i++) {
+ memset(addr, 0xc, HUGEPAGE_SIZE);
+ addr += HUGEPAGE_SIZE;
+ }
+
+ pause();
+ return 0;
+}
+```
+
+
+
+测试结果根据THP reclaim功能的开启状态有所不同:
+
+ * 在THP reclaim功能关闭时,进程申请最后一个透明大页会发生OOM。
+ * 在THP reclaim功能开启时,进程申请透明大页过程中,THP reclaim会把前序申请的透明大页拆分为小页,并回收其中的全零页面,最终不会发生OOM。
+
+
+
+
+
+
+
+# 启用cgroup writeback功能
+
+
+
+
+
+## 背景信息
+
+
+
+控制群组(control group)简称为cgroup,分为v1和v2两个版本。本文介绍如何启用cgroup v1的cgroup writeback功能,并对进程进行Buffered I/O限速。
+
+
+## 使用限制
+
+
+在启用cgroup writeback功能之后,您可以先确认内存子系统(memcg)和IO子系统(blkcg)的映射关系是否符合下文所述的规则,再对进程进行Buffered I/O限速。
+
+
+cgroup writeback功能需要memcg和blkcg协同工作,完成Buffered I/O的限速,但是内核接口cgroup v1的各个控制子系统间默认不协同工作。因此需要通过一定的规则把memcg和blkcg连接起来,规则为:通过任意一个memcg必须可以找到与之唯一对应的blkcg。即memcg和blkcg的映射关系可以是一对一或多对一,不可以是一对多或多对多。
+
+
+例如,存在进程A和B,对它们进行Buffered I/O限速,需要遵循以下约束。
+* 如果A和B分属不同的memcg,它们可以映射到不同的blkcg,只需各自一一对应。例如:A属于`memcg1`,`blkcg1`;B属于`memcg2`,`blkcg0`。
+* 如果A和B分属不同的memcg,它们也可以映射到同一个blkcg。例如:A属于`memcg1`,B属于`memcg2`,A和B都属于`blkcg2`。
+* 如果A和B属于相同的memcg,那么它们只能映射到同一个blkcg。例如:A和B均属于`memcg0`,它们同时属于`blkcg3`。
+
+
+为了避免出现意外情况,建议您在启用cgroup writeback功能后,对进程进行Buffered I/O限速前,优先设置blkcg的`cgroup.procs`接口,向该接口写入一个进程ID来保证blkcg映射的唯一性。同时您也可以通过工具查看memcg和blkcg的映射关系,详情请参见确认memcg和blkcg的映射关系。
+
+在实际运维中,可能出现进程移动到其它cgroup的情况。根据上述规则,如果进程在memcg之间移动,不会出现问题,但如果进程在blkcg之间移动,将会出现异常情况。为了避免产生异常,该功能的代码中定义了规则:一旦工作中的blkcg内的进程发生blkcg间的移动,则将映射关系直接指向root blkcg。由于一般情况是不在root blkcg设置限流阈值,所以当映射关系直接指向root blkcg时,限速功能会失效。
+
+
+**注意** 内核代码虽定义了规则避免出现意外,但您需要在实际操作中尽量避免将进程在blkcg间移动。
+
+
+## 开启cgroup writeback功能
+
+
+cgroup v1接口中的cgroup writeback功能默认是关闭的,按照以下步骤开启该功能。
+
+
+1. 通过命令`grubby`内添加`cgwb_v1`字段开启该功能。
+本示例中内核版本为`4.19.36-12.an7.x86_64`,您在操作中需要更换为实际的内核版本,内核版本的查看命令为`uname -a`。
+
+
+
+```
+sudo grubby --update-kernel="/boot/vmlinuz-4.19.36-12.an7.x86_64" --args="cgwb_v1"
+```
+2. 重启系统使功能生效。
+
+
+
+
+```
+sudo reboot
+```
+3. 使用以下命令读取内核文件`/proc/cmdline`,确认内核命令行参数中带有`cgwb_v1`字段。此时,blkcg下的`blkio.throttle.write_bps_device`及`blkio.throttle.write_iops_device`接口能够对Buffered I/O进行限速。
+
+
+
+
+```
+cat /proc/cmdline | grep cgwb_v1
+```
+
+
+## 确认memcg和blkcg的映射关系
+
+
+当您对进程进行Buffered I/O限速之前,您可以使用以下任意一种方式诊断memcg和blkcg的映射关系是否为一对一或多对一。
+
+
+* 查看memcg与blkcg映射关系。
+
+
+
+```
+sudo cat /sys/kernel/debug/bdi/bdi_wb_link
+```
+
+
+返回结果示例如下,该示例表示memcg和blkcg符合一对一的映射规则。
+
+
+
+```
+memory <---> blkio
+memcg1: 35 <---> blkcg1: 48
+```
+* 使用ftrace内核监测工具。
+ 1. 开启ftrace工具。
+
+
+
+ ```
+ sudo bash -c "echo 1 > /sys/kernel/debug/tracing/events/writeback/insert_memcg_blkcg_link/enable"
+ ```
+ 2. 查看信息输出接口。
+
+
+
+ ```
+ sudo cat /sys/kernel/debug/tracing/trace_pipe
+ ```
+
+
+ 输出内容示例如下,其中`memcg_ino=35 blkcg_ino=48`表示memcg和blkcg符合一对一的映射规则。
+
+
+
+ ```
+ <...>-1537 [006] .... 99.511327: insert_memcg_blkcg_link: memcg_ino=35 blkcg_ino=48 old_blkcg_ino=0
+ ```
+
+
+## 验证cgroup writeback是否生效
+
+
+本示例将模拟出两个产生I/O的进程,用于验证cgroup writeback功能是否有效。
+
+
+
+
+**说明**
+* 由于`dd`命令的反馈速度较快,结果使用`iostat`命令查看。
+* 由于`dd`命令为顺序写入,顺序IO回刷时,会生成1 MB数据再回刷,因此设置阈值时,`blkio.throttle.write_bps_device`不得小于1 MB(1048576)。如果设置值小于1 MB,可能会引发IO hang。
+
+
+
+
+1. 模拟出两个产生I/O的进程,并按照限制条件优先设置blkcg的`cgroup.procs`接口。
+
+
+
+
+```
+sudo mkdir /sys/fs/cgroup/blkio/blkcg1
+sudo mkdir /sys/fs/cgroup/memory/memcg1
+sudo bash -c "echo $$ > /sys/fs/cgroup/blkio/blkcg1/cgroup.procs" # $$为您的进程ID
+sudo bash -c "echo $$ > /sys/fs/cgroup/memory/memcg1/cgroup.procs" # $$为您的进程ID
+```
+2. 使用blkcg下的`blkio.throttle.write_bps_device`接口对Buffered I/O进行限速。
+
+
+
+
+```
+sudo bash -c "echo 254:48 10485760 > /sys/fs/cgroup/blkio/blkcg1/blkio.throttle.write_bps_device" # 通过设备号配置磁盘的回写限流bps为10 M
+```
+3. 使用不带参数`oflag=sync`的`dd`命令产生缓存异步I/O。
+
+
+
+
+```
+sudo dd if=/dev/zero of=/mnt/vdd/testfile bs=4k count=10000
+```
+4. 使用iostat工具查询结果。查看输出列`wMB/s`,如果被限制到10 MB/s,则表示cgroup writeback功能已生效。
+
+
+
+
+```
+iostat -xdm 1 vdd
+```
+
+
+
+
+
+
+# 增强容器资源可见性
+
+
+
+
+
+
+
+标准Linux的容器资源视图功能接口默认状态下是未启动的,当您在启动该功能后,如果在容器中使用top、free等命令,让容器读取以下接口的数据时,将直接获取容器资源信息,而不是获取容器所在的宿主机(即ECS实例)资源信息。
+* /proc/cpuinfo
+* /proc/meminfo
+* /sys/devices/system/cpu/online
+
+
+
+## 接口说明
+
+
+
+
+ | 接口 | 说明 |
+| --- | --- |
+| /proc/sys/kernel/rich\_container\_enable | 该接口控制容器资源视图功能是否开启。取值范围:
+* 0:关闭容器资源视图功能。
+* 1:开启容器资源视图功能。
+
+
+默认值:0 |
+| /proc/sys/kernel/rich\_container\_source | 该接口控制cgroup接口的数据源。取值范围:
+* 0:使用指针current所在的cgroup接口作为数据源。
+* 1:使用child reaper(即当前PID Namespace的1号进程)所在的cgroup作为数据源。
+
+
+默认值:0 |
+| /proc/sys/kernel/rich\_container\_cpuinfo\_source | 该接口控制/proc/cpuinfo接口以及/sys/devices/system/cpu/online接口显示的CPU数量。取值范围:
+* 0:使用Kubernetes的Request和Limit数据的比值(`Request/Limit`),即`quota`与`period`的比值(`quota/period`)。
+* 1:使用cpuset.cpus接口中的CPU数据源。
+* 2:使用`cpu.shares` 值除以 `/proc/sys/kernel/rich_container_cpuinfo_sharesbase`值的向上取整后的数据(原始数据如果包含小数,则整数位加1后,只取整数作为最终数据,例如:原始数据为1.1,则最终数据为2)。最终数据最多不超过实际在线CPU的数量。
+
+
+默认值:0 |
+| /proc/sys/kernel/rich\_container\_cpuinfo\_sharesbase | 当/proc/sys/kernel/rich\_container\_cpuinfo\_source接口的取值为2时,需要使用该接口作为计算公式的一部分获取最终数据。取值范围:大于等于2的整数值。
+默认值:1024 |
+
+
+## 接口使用示例
+
+
+本示例中,已在一台Linux实例中部署Docker,并创建了一个内存大小为1 GB的容器。
+
+
+* 如果您未开启容器资源视图功能,即/proc/sys/kernel/rich\_container\_enable接口的值为0。当您在容器中运行free -m命令时,查看到的资源信息如下图所示,该信息为容器所在的宿主机(Linux实例)资源信息。
+* 如果您在宿主机(Linux实例)中运行命令echo 1 > /proc/sys/kernel/rich\_container\_enable开启了容器资源视图功能,当您在容器中运行free -m命令时,查看到的资源信息如下图所示,该信息为容器资源信息。
+
+
+## 特殊场景说明
+
+
+一般情况下,开启容器资源视图功能后,使用相关接口的默认值即可满足常规需求,但您需要注意以下特殊场景的接口配置:
+
+
+对于非共享PID Namespace的Pod,其中的每一个容器都是独立的PID Namespace,如果使用systemd启动某个特权容器,容器的进程号为1号,则采集监控数据的任务可能位于容器的某个子cgroup中,而不是根cgroup。
+
+
+例如,当您通过SSH登录容器并运行cat /proc/cpuinfo命令后:
+* 如果/proc/sys/kernel/rich\_container\_source取值为默认值0,则指针current实际是位于容器的sshd.service所创建的子cgroup中,此时查看的结果为错误数据。
+* 如果您运行echo 1 > /proc/sys/kernel/rich\_container\_source命令,使用child reaper(即当前PID Namespace的1号进程)所在的cgroup作为数据源,即可查看到正确的数据。
+
+
+
+
+
+
+
+# 修改TCP TIME-WAIT超时时间
+
+
+
+
+在Linux的内核中,TCP/IP协议的TIME-WAIT状态持续60秒且无法修改。但在某些场景下,例如TCP负载过高时,适当调小该值有助于提升网络性能。ANCK新增内核接口用于修改TCP TIME-WAIT超时时间,本文主要介绍该接口的使用方法。
+
+
+
+## 背景信息
+
+
+
+TCP/IP协议的TIME-WAIT状态是指应用关闭用于通信的套接口(socket)之后,TCP/IP协议栈保持socket处于打开状态。该状态默认持续60秒,用来保证完成服务器和客户端的数据传输。当处于TIME-WAIT状态的连接数过多时,可能会影响到网络性能。因此ANCK提供了可修改TIME-WAIT超时时间的接口,用于在特定场景提高网络性能。例如,高并发业务场景。该接口的取值范围为[1, 600],单位为秒。如果不修改该接口,TIME-WAIT超时时间的默认值保持60秒不变。
+
+
+## 注意事项
+
+
+将TCP TIME-WAIT超时时间修改为小于60秒与TCP/IP协议quiet time概念相违背,可能导致您的系统将旧数据当做新数据接收,或者复制的新数据当做旧数据拒绝。因此请在网络专家建议下调整。了解TCP/IP协议quiet time的相关概念,请参见[IETF RFC 793标准](https://tools.ietf.org/html/rfc793)。
+
+
+## 配置方法
+
+
+您可以通过以下两种方式修改TIME-WAIT超时时间,其中参数[$TIME\_VALUE]为您修改的TIME-WAIT超时时间。
+
+
+* 通过`sysctl`命令修改TIME-WAIT超时时间。
+
+
+
+```
+sysctl -w "net.ipv4.tcp_tw_timeout=[$TIME_VALUE]"
+```
+* 以root权限使用`echo`命令,将值修改到`/proc/sys/net/ipv4/tcp_tw_timeout`接口中。
+
+
+
+```
+echo [$TIME_VALUE] > /proc/sys/net/ipv4/tcp_tw_timeout
+```
+
+
+例如,在Nginx配置7层代理等存在大量短连接的场景下,阿里云推荐您将TIME-WAIT超时时间修改为5s。运行以下任一命令修改超时时间:
+
+
+**说明** 服务器中是否存在大量短连接,您可以运行`netstat -ant | grep TIME_WAIT | wc -l`命令进行判断。
+
+
+
+
+```
+sysctl -w "net.ipv4.tcp_tw_timeout=5"
+```
+
+
+
+
+
+```
+echo 5 > /proc/sys/net/ipv4/tcp_tw_timeout
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210.md"
new file mode 100644
index 0000000000000000000000000000000000000000..f3563b40c6a0ec9514aeab101e06fdf089fa06df
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210.md"
@@ -0,0 +1,444 @@
+
+# 概述
+
+
+在本文中,我们基于社区DAMON设计用于跟踪实时内存热点数据的工具DATOP, 采用划分内存区域采样的方式,并自适应区域构建技术来获取极低的开销损耗,在此基础上,还增加了numa 仿真功能,用于收集任务跨numa访存情况,为了评估其准确性和低开销能力,我们选取和测试了多个benchmark,并与基线进行比较, 结果表明:**DATOP工具运行时开销非常小(保持在不到4%左右),此外开销不受负载大小的影响,仍然保持出色的监控质量,通过多方面测试,我们得出结论:DATOP工具在识别冷热内存以及跨numa访存方面具备优秀的表现能力。**
+
+
+# 背景:云计算大规模复杂场景下内存面临的挑战
+
+
+云计算领域场景下,海量用户数据的增长,对计算机软件和硬件设计都带来了巨大的挑战,尤其是内存设备如DRAM的速率提升并没有跟上这种高速增长趋势,在数据中心中,海量数据的处理,常常让服务器饱受内存不足之苦。
+
+
+为克服低内存容量,混合内存使用如DRAM搭配PMEM成为未来数据中心的主流方案,但是如何快速识别热点数据并让其准确保持在DRAM中运行是影响性能的关键因素,这就要求系统具备快速识别热点数据的能力,并能动态跟踪捕获热点数据的变化,让其处于高性能的DRAM中,但是不幸的是,现有工具为达到一定的准确度,通常会耗费大量的时间,并引入额外的overhead,造成性能回退。
+
+
+此外服务器硬件架构的快速迭代,cpu核数越来越多,numa节点也越来越多,例如amd服务器numa node数目达到8个,arm服务器飞腾s2500 numa节点达到16个,跨numa节点访存带来的性能影响日益突出,如何低开销高效的识别出跨numa热点数据,并优化之,对于提升系统服务质量,有着重要的意义。
+
+
+# datop:轻量级靶向热点内存扫描工具
+
+
+## 热点扫描原理及策略
+
+
+在内存领域,对内存进行优化其实依靠预测内存的行为而做的决策,但是能够高效准确的预测内存的走势,其实是非常困难的,此外内存的策略优化对于用户来说,是不透明的,因此现有内存领域的各种策略机制,在实际生产环境中,并未取得很好的效果,也正是基于这些原因,社区推出了一种新的内存调控机制DAMON(Data Access Monitor),它试图让向用户展示内存的动作行为,让用户可根据这些行为相应的调整内存管理策略。
+
+
+### 三大chunks
+
+
+服务器现有硬件能支持非常巨大的地址空间,内存容量动不动达到几个T的大小,工作负载耗用内存几个G也是很普遍的事,随机毫无规律的划分地址空间可肯定是不可取的,并且在实际使用中,只有小部分区域被实际映射到内存并被访问,DAMON通过分析和论证,先将地址分为三大chunks,这三个chunks区域之间的空隙是给定地址空间中两个最大的未映射区域。
+
+
+**图1:**
+
+
+
+
+
+在大多数情况下,两个最大的未映射区域是堆与最上层mmap() ed区域之间的空隙,以及最下层mmap() ed区域与堆栈之间的空隙, 因为这些间隙在通常的地址空间中是非常大的,排除这些就足够了,所以针对一个工作负载而言,DAMON只需要监控一下这些区域就足够了, 此外,随着工作负载的运行,映射区域发生变化,例如部分最大ummaped区域易主,所以damon设置了一个update周期,去周期性检测这些三大chunks的有效性,重新查找有效的三大chunks,并和现有监测得区域进行对比,删减或者增加。
+
+
+### region拆分与合并
+
+
+在获取三大chunks后,damon会按照设定规则,去将这三个chuns划分为不均等的若干分regions, 如下图2所示:
+
+
+**图2:**
+
+
+
+
+
+这些regions后面会随着热点频率去动态调整,进行拆分或者合并操作,其算法原理大致如下:
+
+
+**拆分原则:**
+
+
+1. 大于等于2倍 DAMON\_MIN\_REGION才能拆分;
+2. 才分region的size不能小于DAMON\_MIN\_REGION;
+3. region可以拆分为3个,当regions个数大于max\_nr\_regions的2/3后,降低拆分个数,由3变2;
+4. region个数必须保持在min\_nr\_regions和max\_nr\_regions范围内;
+
+
+**合并原则:**
+
+
+1. 两合并的regions必须收尾地址相等;
+2. 两者热点统计值之差必须小于设定阈值范围内;
+
+
+### region采样与热点统计
+
+
+“trace page access bit”技术作为跟踪热点内存通用那就的技术手段,被业界广泛使用,但是该技术有一个固有的缺陷,那就是随着工作负载耗用内存增加,自身带来的开销和跟踪质量都会变糟,而damon通过region划分, 再结合空间采样方式良好的解决了该缺陷:假设一个region中,所有page都有相同的访问模式,这样的话,只需要监控一个page就够了。这样一来,在每个region里面,会随机选择一个page,在bitmap中把它对应的“accessed(访问过)”bit先清零,然后时不时地检查一下,如果这个page被访问过了,那么就算作这个region都被访问过了,它不是监视所有的页面,而是只监视reigon里面随机抽取的一个页面,该页面在某个采样时刻代表着这个region, 并将该值记录下来, 随着采样的不断进行,该region的热点就被统计下来了。
+
+
+
+```
+void check_access(region ∗ r) {
+ if (!r−>sampled_page)
+ goto next ;
+ if (accessed(r−>sampled_page) )
+ r−>nr_accesses++;
+ next:
+ r−>sampled_page = rand_page(r->sampled_page);
+ clear_accessed(r−>sampled_page);
+}
+```
+
+上述伪代码只是介绍其采样和统计实现方法,其更复杂的逻辑处理关系,例如region合并和拆分后nr\_access的值处理,以及nr\_access周期性清零等本文不再介绍,有兴趣的读者可以依据damon实现源码自行分析。
+
+
+### numa仿真实现
+
+
+社区damon能有有效的识别工作负载内存的冷热情况,但是对于工作负载内存跨numa访存这块,是无法做出判断的, 然而在实际业务中,跨numa访问造成的性能衰退问题真实存在,尤其是现今服务硬件多numa架构numa数目越来越多,正式基于以上原因,我们丰富了damon kernel部分代码,增加了内存numa访存情况。
+
+
+和热点统计一样,numa仿真不会统计region中所有page的跨numa访问情况,而是利用damon空间采样方式,将damon获取的page在clear了access bit后,将其设置为pte none.
+
+
+
+```
+void check_numa(region ∗ r) {
+ if (!r−>sampled_page)
+ goto next ;
+ if (local_numa_node(r−>sampled_page) )
+ r−>nr_local++;
+ else
+ r->nr_remote++;
+ next:
+ r−>sampled_page = rand_page(r->sampled_page);
+ set_page_none(r−>sampled_page);
+}
+```
+
+同样该部分伪代码只是介绍其numa基本实现,在实际中我们需要考虑pte处于swap,和page属于大页的情况,此外在pte设置为none后,会造成再次访问该page时发生page\_fault和tlb miss的情况,我们测试发现,在某些频繁访问某块内存的工作负载中,造成一定的性能损耗,所以在实际使用中,我们增加了numa仿真开关,需要的时候去开启该功能。
+
+
+### 小结
+
+
+基于上述几小节对damon以及numa仿真在kernel部分的实现机制的介绍,让我们对datop工具的实现原理有了清楚的认识,datop包括内核态部分和用户态部分,用户态可以通过perf调用功能,将内核态通过trace统计的热点信息捕获,并排序显示出来,详细调用流程入下图3显示。
+
+
+**图3:**
+
+
+
+
+
+在用户态,DATOP通过trace\_event、damon dbgfs、以及numa switch接口和内核进行交互:
+
+
+**蓝色**绘制线部分:该部分是和用户态显示的核心, 通过内核kdamond线程将采样统计的相关值传递给trace接口, 用户态通过trace\_event方式获取region区域热点信息,包括区域大小,access统计,进程信息以及跨numa统计等,最终通过窗口向用户展示。
+
+
+**黑色**绘制线部分:该部分用于控制内核态线程kdamond的相关行为,通过damon dbfs接口,用于设置采样频率,更新周期,region个数划分,监控进程配置,kdamond线程的开启和关闭等。
+
+
+**绿色**绘制线部分用于设定numa仿真功能的开启和关闭,此功能针对支持多numa的场景。
+
+
+**红色**绘制线部分是热点工具的核心执行单元,用户态通过dbgfs接口开启监控后,kdamond线程被创建, 首先会查找被监控进程的三大chunks, 找到后,按照damon dbgfs接口设定的region个数方范围,对其进行拆分,此后按照设定好的采样频率进入周期性循环工作,直到被监控进程停止运行或用户操作dbgfs接口,停止监控,在周期性循环中,会对region热点进行随机采样并统计,此外还判定用户是否开启numa仿真功能,若开启还会对region跨numa情况进行统计,处理完成后,会更新采样结果,并通过trace event传递给用户,以上操作完成后,会依据kdamond线程运行时间,并在指定周期内,通过热点统计值对region进行拆分和合并操作,此外在更长的周期到来后,还会从新检查chunks的准确性,并按多加少减原则,修改region,以此保证热点内存跟踪的实时性和准确性。
+
+
+至此DATOP技术实现原理介绍完毕,后面会进入介绍使用和数据测试方面的介绍。
+
+
+## 使用
+
+
+在龙蜥社区 5.10版本内核支持damon代码以及自研的numa仿真部分代码,结合开源的用户态工具datop: 工具就可以运行起来了,datop工具支持单、多进程以及cgroup粒度内存热点监控以及跨numa访存监控 两种方式,详细使用可以参考源码readme部分。
+
+
+**注:**cgroup粒度监控功能会在近期开源。
+
+
+## DATOP工具对部分关联性能指标影响说明
+
+
+为评估了DATOP工具在使用中对系统造成的影响,此处采用lmbench作为作为被监控进程进行了测试。
+
+
+
+
+| | | |
+| --- | --- | --- |
+| 测试情况 | 虚拟机 32vCPU 4 node | 物理机 96cpu 4node |
+| | 被监控进程个数 | 未开numa仿真
+和base对比 | 开numa仿真功能 | base对比 | 未开numa仿真 | base对比 | 开numa仿真 | base对比 |
+|
+用户态overhead | 1 | 最高0.4%, | 稳定后0.1%不到 | 最高0.4% | 稳定后0.1%不到 | 最高0.2% | 稳定后不到0.1% | 0.2% | 稳定后不到0.1% |
+| 4 | 最高0.7% | 0.2% | 最高0.8% | 稳定后0.2% | 最高0.2% | 稳定后不到0.1% | 最高0.3 | 稳定后不到0.1% |
+|
+kernel overhead | 1 | 最高2% | 0.1% | 2.3% | 0.2% | 最高0.4% | 稳定后不到0.1% | 最高0.6% | 稳定后不到0.1% |
+| 4 | 最高2.5% | 0.2% | 2.8% | 0.2% | 最高0.6% | 稳定后不到0.1 | 最高0.7% | 稳定后不到0.2% |
+
+
+以上测试可能会存在一定的误差的,测试目主要是为了充分验证热点工具内核态代码引入,对内核以及应用程序的影响,通过测试,可以看出datop工具以及kernel部分,造成系统整机cpu使用率增加不超过1%。
+
+
+## 关于numa仿真测试统计正确性验证说明
+
+
+### 测试方法一
+
+
+构造一个执行程序,并创建两个线程a和b,这两个线程将会共享代码段部分代码,进行反复性读测试
+
+
+在测试前,将线程1和程序绑定在同一个numa节点,将线程2绑定在不同numa节点。
+
+
+在测试前先通过/proc/pid/smaps确认下代码段映射地址,如下图4所示。
+
+
+**图4:**
+
+
+
+
+
+通过perf工具在不通时刻抓取numa仿真统计相关值,如下所示:
+
+
+
+```
+kdamond.0 target_id=18446462601994805632 nr_regions=10 400000-402000: 12 5243 0
+kdamond.0 target_id=18446462601994805376 nr_regions=10 400000-402000: 8 0 5427
+...
+kdamond.0 target_id=18446462601994805632 nr_regions=10 400000-402000: 9 7669 0
+kdamond.0 target_id=18446462601994805376 nr_regions=10 400000-402000: 7 0 7913
+```
+
+从测试来看,虚拟地址0x400000-0x402000为属于代码段, 两线程共享该部分内存,通过perf采样统计可以看出, 本地线程1访问这块地址次数为5243次, 远端线程访问次数为5427次,隔一段时间后第二次统计本地线程1为7669,远端线程为7913,基本一致,说明numa仿真功能统计正确。
+
+
+### 测试方法二
+
+
+构造一个应用程序,申请1G左右大小的空间MSIZE,通过设置numa\_alloc等版本操作,将MSIZE绑定在node0和node1, 通过交叉访问,统计其跨numa的情况。
+
+
+下图是datop工具显示程序跨numa的情况,按照预定设置,两者访问占比50%,结果满足预期。
+
+
+
+```
+ INDEX TYPE START END SIZE(KiB) ACCESS AGE LOCAL REMOTE
+ 1 rw-p ffff49a34000 ffff515aa000 126424 2 0 50.02% 49.98%
+ 2 rw-p ffff4a636000 ffff52662000 131248 1 0 50.01% 49.99%
+ 3 rw-p ffff4f31d000 ffff52cb3000 58968 1 1 49.98% 50.02%
+ 4 rw-p ffff5704f000 ffff586f9000 23208 1 1 49.77% 50.23%
+ 5 rw-p ffff5b5a5000 ffff5cbd1000 22704 1 1 49.78% 50.22%
+ 6 rw-p ffff5cbd1000 ffff5ff58000 52764 2 0 49.71% 50.29%
+ 7 rw-p ffff5ff58000 ffff64ca4000 79152 1 0 49.71% 50.29%
+```
+
+同样采用numastat正是下该程序node访问情况,如下图所示:
+
+
+
+```
+Per-node process memory usage (in MBs) for PID 111676 (lt-numademo)
+ Node 0 Node 1 Node 2
+ --------------- --------------- ---------------
+Huge 0.00 0.00 0.00
+Heap 0.02 0.00 0.00
+Stack 0.01 0.00 0.00
+Private 565.24 564.00 0.00
+---------------- --------------- --------------- ---------------
+Total 565.27 564.00 0.00
+```
+
+从测试结果来看,node0和node1这块两者各自占比50%左右,复合预期,说明numa仿真统计这块正确性没有问题。
+
+
+## benchmark测试结果
+
+
+此处我们选取了几款常用的benchmark作为其测试,评估datop监控对其测试结果造成的影响。
+
+
+### unixbench
+
+
+选取unixbench中fstime和context1两者耗用内存较多的作为测试参考。
+
+
+
+
+| | | |
+| --- | --- | --- |
+| | 虚拟机 | 物理机 |
+| 测试类 | 关numa仿真 | 开numa仿真 | 关numa仿真 | 开numa仿真 |
+|
+
+fstime | 1573.6 | 1589.4 | 1955.6 | 1960.0 |
+| 1591.4 | 1574.2 | 1966.1 | 1960.7 |
+| 1575.6 | 1592.3 | 1963.5 | 1977.4 |
+|
+
+context1 | 475.4 | 473.3 | 556.5 | 557.4 |
+| 471.2 | 472.1 | 555.3 | 560.0 |
+| 473.4 | 474.6 | 557.6 | 558.2 |
+
+
+从以上测试数据来看,将unixbench作为被监控对象,在开和不开numa仿真功能下,不会造成其性能衰退。
+
+
+### stream
+
+
+stream通常用于内存带宽测试,会按照多种形式频繁访问内存,正好基于这一特性验证datop工具对其影响。
+
+
+测试指令:numactl -m 0 -C 5 ./stream
+
+
+
+
+| | | |
+| --- | --- | --- |
+| | 虚拟机 | 物理机 |
+| 测试项 | 关numa仿真 | 开numa仿真 | 关numa仿真 | 开numa仿真 |
+|
+Copy | 1499.4 | 1487.2 | 1678.0 | 1673.1 |
+| 1495.5 | 1493.5 | 1674.3 | 1665.5 |
+| 1473.0 | 1479.1 | 1675.2 | 1680.7 |
+|
+Scale | 1459.1 | 1483.9 | 1585.9 | 1588.5 |
+| 1490.9 | 1451.3 | 1590.0 | 1597.3 |
+| 1475.1 | 1472.1 | 1588.8 | 1595.6 |
+|
+Add | 1960.3 | 1937.0 | 1983.7 | 1974.6 |
+| 1962.2 | 1955.6 | 1991.9 | 1991.4 |
+| 1957.3 | 1944.9 | 1992.3 | 1996.2 |
+|
+Triad | 1867.8 | 1860.2 | 1976.6 | 2017.5 |
+| 1862.5 | 1873.1 | 2035.0 | 2025.3 |
+| 1852.1 | 1859.5 | 2011.9 | 1997.0 |
+
+
+从以上测试数据来看,将stream作为被监控对象,在开和不开numa仿真功能下,不会造成其性能衰退。
+
+
+### mbw
+
+
+测试指令:numactl -m 0 -C 5 ./mbw
+
+
+
+
+| | | |
+| --- | --- | --- |
+| | 虚拟机 | 物理机 |
+| 测试项 | 关numa仿真 | 开numa仿真 | 关numa仿真 | 开numa仿真 |
+|
+MEMCPY
+MiB/s | 2714.146 | 2627.115 | 2645.083 | 2621.095 |
+| 2713.336 | 2634.099 | 2643.614 | 2616.979 |
+| 2718.278 | 2625.363 | 2646.133 | 2629.780 |
+|
+DUMB
+MiB/s | 1019.456 | 1019.602 | 751.405 | 745.045 |
+| 1018.745 | 1018.746 | 768.279 | 763.038 |
+| 1018.080 | 1020.929 | 773.796 | 746.797 |
+|
+MCBLOCK
+MiB/s | 5139.354 | 5151.532 | 2668.374 | 2649.498 |
+| 5155.516 | 5150.471 | 2666.596 | 2650.973 |
+| 5148.191 | 5149.887 | 2667.449 | 2645.573 |
+
+
+通过测试发现mbw:
+
+
+在虚拟机测试时memcopy项时候存在3%左右性能衰退,其他测试项未见明显差异。
+
+
+在物理机测试时,三类测试项都存稍微的性能衰退, 其中MEMCPY衰退不到1%,DUMB衰退2.6%,MCBLOCK不到1%。
+
+
+
+
+
+### 小结
+
+
+在对比mbw和stream测试时,有个较为奇怪的问题了,steam测试copy并没有发生性能衰退,而mbw发生了3%的性能衰退,笔者通过分析其各自源码发现,发现stream copy测试过程中,每一次copy大小是小于4K的,而stream memcopy测试过程中每一次copy远大于4K,一个页的大小,这就导致stream memcpoy测试过程中会应为numa仿真设置pte表为空被命中的概率相比stream copy要大的多, 会造成更多的page fault问题,通过perf抓取分析也正好论证了这一点,所以mbw memcopy出现了性能衰退。
+
+
+这也充分说明,针对频繁访问一次超过4K大小的内存区域的应用程序,datop工具会造成一定的性能衰退影响,这也是numa仿真设置开关的原因,可根据实际情况按需打开。
+
+
+# 热点数据扫描试用
+
+
+我们可以对那些**内存访问密集模型进行简单的测试,获取到较稳定的热点**。例如redis get操作(测试命令:redis-benchmark -r 20000000 -n 20000000 -t get -d 1024 -c 32 -P 8)。
+
+
+**图5:**
+
+
+
+
+
+图5中INDEX:表示region索引,TYPE表示region的虚拟地址类型,START表示region的起始地址,END表示reigon结束地址,SIZE表示region大小为多少,单位KiB, ACCESS表示热点程度,值越大表示越热,AGE表示热点波动情况,值越大表示冷热状态稳定,波动小,LOCAL表示这段region区域本地numa访问占比,REMOTE表示远端numa访问占比。
+
+
+图5是按采集的ACCESS进行排序获取的热点较高的14个regions。目前测试,可以确定在一段时间内这些regions的统计基本稳定,并且存在大量的匿名页热点, 此外通过刻意numa本地绑定测试,也正确的统计numa访存情况。
+
+
+
+
+
+另外,我们以mysql为例,验证下跨代码端部分存在跨numa的情况。
+
+
+**图6:**
+
+
+
+
+
+上图6的热点监控命令为:datop -p 168368 -r 100,400。mysql中的热点显示与redis有些不同,存在大量属于"r-xp"的热点,并且存在跨numa访问的情况,我们之前测试中同样发现mysql的代码段热点高于匿名页,所以针对不同的场景,需要具体分析热点以及跨numa的内存段属性,然后做相应的优化措施。
+
+
+以上的测试数据表明:**该热点工具可以用于反映进程代码段、匿名段的相对热点,以及跨numa访存情况,用于判断进程使用大页,页迁移,冷内存回收等方面提供测试量化手段,进而达到有针对性优化的目的。**
+
+
+# 参考
+
+
+
+
+
+[Memory-management optimization with DAMON](https://lwn.net/Articles/812707/)
+
+
+[Using DAMON for proactive reclaim](https://lwn.net/Articles/863753/)
+
+
+[DAMON Extended To Offer Physical Memory Address Space Monitoring](https://www.phoronix.com/scan.php?page=news_item&px=DAMON-Physical-Monitoring)
+
+
+[Proactively reclaiming idle memory](https://lwn.net/Articles/787611/)
+
+
+[Intel® Optane™ Memory](https://www.intel.com/content/www/us/en/products/details/memory-storage/optane-memory.html)
+
+
+[damon用户态工具damo](https://github.com/awslabs/damo)
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/\351\241\271\347\233\256\347\256\200\344\273\213.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/\351\241\271\347\233\256\347\256\200\344\273\213.md"
new file mode 100644
index 0000000000000000000000000000000000000000..2c784154e3c39f8fc10ffd5e29d8a0c9fe98e7ff
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/\351\241\271\347\233\256\347\256\200\344\273\213.md"
@@ -0,0 +1,4 @@
+本项目聚焦于:
+- 龙蜥内核的基础能力建设,包括基础功能、兼容性、稳定性和性能,建立相关基线。
+- 跟踪行业和upstream发展动态,负责下一代龙蜥内核版本演进。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212.md"
new file mode 100644
index 0000000000000000000000000000000000000000..4ff5c36d16da8225d0a52c4ebf7bfdd7187d62e1
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212.md"
@@ -0,0 +1,449 @@
+from arm-sig:
+
+
+# 一、测试总结
+
+
+针对龙蜥 OS MPAM 特性的整体测试情况如下:
+
+
+* 经过对 MPAM 的功能性验证,目前 L3 cache 资源隔离和监控功能均正常,内存带宽隔离效果甚微,监控功能可用。
+* 测试用例覆盖 MPAM 接口读写测试、并发压力测试等多种类型,测试结果未发现问题。
+* 针对 MPAM ESR 中断,验证了 PARTID、PMG、monitor 相关异常能否触发中断、告知错误类型,中断监测功能正常可用。
+
+
+# 二、MPAM 功能验证
+
+
+## 2.1 cache 隔离功能验证
+
+
+### 2.1.1 不同配置对实际 cache 占有量的影响
+
+
+L3 cache 资源隔离以 ways 的方式进行配置。倚天机器共有 16 ways,测试对不同 ways 的隔离效果进行了验证。
+
+
+
+```
+numactl -m 0 -C 16 memhog -r10000000 100000m > /mnt/log
+```
+
+程序和资源隔离 group 绑定分别采用了 pid 绑定(tasks)和 cpu 绑定(cpus)两种方式。通过 schemata 接口设置程序所能够使用的 ways 数目,通过 mon\_data/mon\_L3\_0\*/llc\_occupancy 接口读取程序的 L3 cache 占用。多次读取取平均值,并与理想的 cache ways 大小进行对比。
+
+
+测试结果显示,L3 cache 隔离功能**效果显著**,无论是通过 tasks 绑定还是 cpus 绑定,均可以得到与理想值相接近的隔离效果。
+
+
+
+
+
+### 2.1.2 不同配置对 mem latency 的影响
+
+
+latency 作为一个重要的性能指标,在一些对时延敏感的场景来说,有很重要的参考作用,此处使用 lat\_mem\_rd 测试 cache 在不同的 ways 下,内存 latency 的分布情况,也从侧面验证 MPAM 对 cache 的隔离功能。
+
+
+
+```
+#设置步长为512字节
+numactl -C 10 -m 0 ./lat_mem_rd -N 1 -P 1 145M 512
+```
+
+测试结果显示,随着 cache way 数目的增加,加载相同内存的 latency 逐渐减小。
+
+
+
+
+
+### 2.1.3 L3 cache 抗干扰测试
+
+
+
+```
+# workload
+numactl -m 1 -C 64-127 memhog -r10000000 100000m > /mnt/log
+# distractor
+numactl -m 1 -C 64-127 memhog -r10000000 100000m > /mnt/log
+```
+
+workload:保持 L3:1=fff0 配置无变化
+
+
+distractor: 测试 L3:1=,mask 值分别为 0-f(无干扰)、0010-fff0(有干扰)
+
+
+测试结果显示:
+
+
+在无干扰情况下,workload 的 L3 cache 占用量基本无变化;
+
+
+随着干扰 way 数逐渐变多,workload 和 distractor 两者的 L3 cache占比逐渐趋同,总量不变。
+
+
+
+
+
+### 2.1.4 模拟混部 L3 cache 隔离测试
+
+
+分别以 SPECjbb 2015 和 stress-ng 程序模拟在线环境和离线环境,对L3 cache隔离功能进行测试。两个环境均运行在 NUMA node 1 上。
+
+
+在前 40s 的时间内,两个程序共享 L3 cache 资源。在约 40s 后,开始隔离在线和离线L3 cache资源的使用,在离线任务 L3 cache 的配比分别为 0xffff 和 0xf。
+
+
+
+
+
+通过实验结果可以看到,在 L3 cache 资源共享的情况下,离线资源对在线资源干扰和压制明显,L3 cache 竞争激烈,波动幅度很大;在对 L3 cache 资源进行隔离后,一方面离线得到了持续有效的压制,L3 cache 占有率大幅下降,另一方面在线性能提升明显,而且波动幅度变小。
+
+
+## 2.2 MB 隔离功能验证
+
+
+### 2.2.1 不同配置对内存带宽的影响
+
+
+
+```
+gcc -O3 -fopenmp -DSTREAM_ARRAY_SIZE=100000000 -DNTIMES=1000 stream.c -o stream
+# 单node测试
+numactl -m 1 -C 64-127 ./stream
+# 单CPU测试
+numactl -m 1 -C 72 ./stream
+```
+
+MB 资源隔离以百分比的方式进行配置。测试以 5% 为粒度,通过设置 schemata 接口让内存带宽从 5% 逐次递增到 100%,通过读取 mon\_data/mon\_MB\_0\*/mbm\_local\_bytes 接口读取带宽值,最终取多次测量的平均值。
+
+
+通过测试结果可以发现,不同百分比下的测试MB带宽值和100%带宽下的MB带宽值基本相等,倚天机器的 MB 带宽隔离**效果甚微**。
+
+
+#### 单 node(64 CPU) MB 配置结果
+
+
+
+
+| | | |
+| --- | --- | --- |
+| **percent** | **stream测试值[Copy] (MB/s)** | **mbm\_local\_bytes接口值 (MB/s)** |
+| 5 | 104808.5 | 104800.0 |
+| 10 | 105028.3 | 105730.5 |
+| 20 | 104459.3 | 104915.1 |
+| 40 | 105077.6 | 105852.0 |
+| 60 | 104980.6 | 105178.7 |
+| 80 | 104924.8 | 105182.8 |
+| 100 | 104828.1 | 105855.8 |
+
+
+#### 单 CPU MB 配置结果
+
+
+
+
+| | | |
+| --- | --- | --- |
+| **percent** | **stream测试值[Copy] (MB/s)** | **mbm\_local\_bytes接口值 (MB/s)** |
+| 5 | 25948.7 | 24147.7 |
+| 10 | 25934.0 | 24433.1 |
+| 20 | 25913.5 | 22771.2 |
+| 40 | 25897.9 | 24559.4 |
+| 60 | 25952.9 | 24079.7 |
+| 80 | 25866.5 | 24246.4 |
+| 100 | 25952.1 | 24171.9 |
+
+
+# 三、MPAM稳定性测试
+
+
+## 3.1 resctrl mount/umount
+
+
+**测试方法**
+
+
+挂载 resctrl 文件系统,设置 schemata 资源隔离接口,随机写 cpus/cpus\_list、tasks 接口,读取mon\_data 资源监控接口,最后卸载 resctrl 文件系统。重复 1000000 次。
+
+
+**测试结果**
+
+
+resctrl 文件系统相关接口仍可正常使用。
+
+
+## 3.2 接口写入测试
+
+
+### 3.2.1 schemata 写入
+
+
+**测试方法**
+
+
+创建两个 group,生成随机 L3 cache mask 和 MB 内存带宽值,并分别写入两个 group 的 schemata 接口,之后读取 schemata 接口,验证当前值是否与写入值相同。重复测试 1000000 次。
+
+
+**测试结果**
+
+
+schemata 均可正常写入。
+
+
+### 3.2.2 schemata 错误写入
+
+
+对 schemata 接口写入多种错误参数,验证 schemata 是否可以正确识别处理。
+
+
+验证的错误类型及验证结果如下:
+
+
+
+
+| | | |
+| --- | --- | --- |
+| **错误写入示例** | **last\_cmd\_status输出** | **测试结果** |
+| L3:0=10000 | Mask out of range | PASS |
+| L3:2=ff;3=ff | Unknown domain | PASS |
+| L3 | Missing ':' | PASS |
+| L3: | Missing 'L3' value | PASS |
+| L3:0 | Missing '=' or non-numeric domain | PASS |
+| L30:0=fff | Unknown or unsupported resource name 'L30' | PASS |
+| L3:0=fghi | Non-hex character in the mask fghi | PASS |
+| L3:1=ff;1=f4 | Duplicate domain 1 | PASS |
+| MB:0=150 | MB value 150 out of range 5-100 | PASS |
+| MB:0=4 | MB value 4 out of range 5-100 | PASS |
+| MB:0=FOO | Non-decimal digit in MB | PASS |
+| MB | Missing ':' | PASS |
+| MB:0 | Missing 'MB' value | PASS |
+| MB:2=55 | Unknown domain | PASS |
+| MB:1=23;1=56 | Duplicate domain 1 | PASS |
+| L3:0=ff (with cdp) | Unknown or unsupported resource name 'L3' | PASS |
+
+
+### 3.2.3 cpus/cpus\_list 写入
+
+
+测试方法
+
+
+随机写入 cpus/cpus\_list 接口 1000000 次,验证是否写入成功,并且 cpus 接口和 cpus\_list 接口的值是否相对应。
+
+
+测试结果
+
+
+cpus/cpus\_list 均可正常写入,并保持值的相等。
+
+
+### 3.2.4 cpus/cpus\_list 错误写入
+
+
+
+
+| | | |
+| --- | --- | --- |
+| **错误写入示例** | **last\_cmd\_status输出** | **测试结果** |
+| echo 156 > cpus\_list | Can only assign online CPUs | PASS |
+| echo 4096 > cpus\_list | Bad CPU list/mask | PASS |
+| echo ffff > cpus\_list | Bad CPU list/mask | PASS |
+| echo 3-12 > cpus | Bad CPU list/mask | PASS |
+
+
+### 3.2.5 tasks 写入
+
+
+**测试方法**
+
+
+创建 500 个进程,并将其 pid 写入 tasks 接口,验证进程对应 pid 是否存在。之后 kill 掉所有进程,验证其 pid 是否已从 tasks 文件中移除。重复 1000000 次。
+
+
+**测试结果**
+
+
+tasks 接口均可正常写入和移除。
+
+
+### 3.2.6 tasks 错误写入
+
+
+
+
+| | | |
+| --- | --- | --- |
+| **错误示例** | **stderr** | **测试结果** |
+| 将不存在pid写入tasks | echo: write error: No such process | PASS |
+| echo hello > tasks | echo: write error: Invalid argument | PASS |
+
+
+### 3.2.7 mode 写入
+
+
+mode 接口默认值为 shareable,当前MPAM接口暂不支持 mode 接口值的修改。
+
+
+
+
+| | |
+| --- | --- |
+| **Mode** | **支持情况** |
+| shareable | 支持 |
+| exclusive | 不支持 |
+| pseudo-locksetup | 不支持 |
+| pseudo-locked | 不支持 |
+
+
+## 3.3 group mkdir/rmdir 测试
+
+
+### 3.3.1 max group 创建
+
+
+**测试方法**
+
+
+以 info/\*/num\_closids 为基准,创建所能达到的最多 group。重复 1000000 次。
+
+
+**测试结果**
+
+
+倚天 PARTID 数目为 64 个,因此除了 default group 外,最多能够创建 63 个 group。一般情况下均可达到最大值。但在部分 group 被使用过的情况下,由于其对应的 PARTID 在 L3 cache中占用量可能超过 /sys/fs/resctrl/info/L3\_MON/max\_threshold\_occupancy,从而导致该 PARTID 在一定时间内不可用。
+
+
+### 3.3.2 group 随机创建/删除
+
+
+**测试方法**
+
+
+随机创建/删除 group 共计 2000\*(num\_closids-1),验证 group 分配和回收功能是否正常。
+
+
+**测试结果**
+
+
+group 随机创建和删除,group 分配/回收接口仍可正常运作。
+
+
+### 3.3.3 mon\_group 创建/删除
+
+
+当前社区版本MPAM代码下 num\_rmids 均为 1,暂不支持 mon\_groups 目录下 mon group 的创建和删除。
+
+
+## 3.4 并发读写测试
+
+
+### 3.4.1 L3 cache 监控接口并发读取
+
+
+**测试方法**
+
+
+创建 5 个 group,每个 group 中写入 10 个进程:memhog -r1000000000 1m > /mnt/log
+
+
+同时 10 个进程并发读 mon\_data/L3\_MON/llc\_occupancy,持续时间 60 min。
+
+
+**测试结果**
+
+
+测试过程中未出现resctrl接口崩溃或不可用问题。
+
+
+### 3.4.2 MB 监控接口并发读取
+
+
+**测试方法**
+
+
+创建 5 个 group,每个 group 中写入 10 个进程:memhog -r1000000000 1m > /mnt/log
+
+
+同时 10 个进程并发读 mon\_data/mon\_MB\_\*/mbm\_local\_bytes,持续时间 60 min。
+
+
+**测试结果**
+
+
+测试过程中未出现 resctrl 接口崩溃或不可用问题。
+
+
+### 3.4.3 schemata 接口并发写入
+
+
+**测试方法**
+
+
+创建 5 个 group,每个 group 中写入 10 个进程:memhog -r1000000000 1m > /mnt/log
+
+
+同时 10 个进程并发随机写入 schemata,持续时间 60 min。
+
+
+**测试结果**
+
+
+测试过程中未出现 resctrl 接口崩溃或不可用问题。
+
+
+### 3.4.4 cpus/cpus\_list 接口并发写入
+
+
+**测试方法**
+
+
+创建 1 个 group,10 个进程并发写入随机 cpus/cpus\_list,持续时间 60 min。
+
+
+**测试结果**
+
+
+测试过程未出现接口崩溃或不可用问题。
+
+
+### 3.4.5 tasks 接口并发写入
+
+
+**测试方法**
+
+
+创建 1 个 group,10 个进程并发创建 300 个 task 并写入 tasks 接口。
+
+
+**测试结果**
+
+
+测试过程未出现接口崩溃或不可用问题。
+
+
+# 四、MPAM 错误中断验证
+
+
+## 4.1 L3 cache 资源错误中断验证
+
+
+
+
+| | | | |
+| --- | --- | --- | --- |
+| 错误码 | 描述 | 结果 | 备注 |
+| 0 | No error captured in MPAMF\_ESR | 无 | 非异常情况 |
+| 1 | MPAMCFG\_PART\_SEL out of range | 可触发 | |
+| 2 | Request PARTID out of range | 可触发 | |
+| 3 | MSMON out of range PARTID/PMG | 可触发 | |
+| 4 | Request PMG out of range | 不可触发 | PMG>1时无法写入 |
+| 5 | MSMON\_CFG\_MON\_SEL out of range | 可触发 | |
+| 6 | MPAMCFG\_INTPARTID out of range | 未测试 | 暂不支持PARTID narrowing |
+| 7 | INTERNAL unexpected | 未测试 | 暂不支持PARTID narrowing |
+| 8 | MPAMCFG\_PART\_SEL.RIS unimplemented | 不可触发 | RIS>1时无法写入 |
+| 9 | MPAMCFG\_PART\_SEL.RIS no control | 不可触发 | RIS>1时无法写入 |
+| 10 | MSMON\_CFG\_MON\_SEL.RIS unimplemented | 不可触发 | RIS>1时无法写入 |
+| 11 | MSMON\_CFG\_MON\_SEL.RIS no monitor | 不可触发 | RIS>1时无法写入 |
+| 12:18 | Reserved |
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214.md"
new file mode 100644
index 0000000000000000000000000000000000000000..917ca23cdee68096e992a6be8ba697c009e4c010
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214.md"
@@ -0,0 +1,374 @@
+from arm-sig:
+
+
+# 一、引言
+
+
+MPAM(Memory System Resource Partitioning and Monitoring)是 ARM v8 引入的新特性,对标 x86 的 RDT 特性,可以实现对 Cache、内存带宽、SMMU 等资源的分配及监控功能。该特性可以从硬件层面减少不同工作负载之间的性能干扰,确保高优先级任务性能的稳定性,在虚拟化、混部等业务中取得了良好的效果。
+
+
+# 二、MPAM特性简介
+
+
+## 2.1 MPAM整体框架
+
+
+MPAM 特性的整体框架如图1所示。其中,MPAM 硬件上是通过 MSC(Memory System Component)实现的。MPAM 将提供资源管理功能组件称为 MSC,可以对资源请求进行处理。完整的系统模型中一般拥有多个 MSC,分别负责管理不同资源。MPAM 为资源访问请求添加了 PARTID 和 PMG 标识,MSC 可以对该标识进行区分处理,进而实现资源的隔离和监控功能。
+
+
+根据 MPAM 手册的介绍,除了基本的 Cache 和内存带宽资源隔离和监控外,MPAM 可以实现比 Intel RDT 更为丰富的资源隔离和监控特性,包括:
+
+
+* 提供对 SMMU 资源的支持
+* 提供对 Cache 和内存带宽资源进行最大最小值限制
+* 提供基于优先级的资源隔离支持
+
+
+
+
+
+MPAM 驱动作为核心部分,对下完成了 MPAM 硬件功能的访问和设置,包括 MPAM 资源的获取和初始化、MPAM 中断初始化以及对 MPAM 相关寄存器的读写,对上则与 resctrl fs 用户态接口层进行交互。
+
+
+resctrl fs 接口层以资源调配 group 为单位提供了资源隔离和监控的用户态接口,并通过 info 接口暴露 MPAM 硬件相关信息。此外,其底层还完成了 PARTID 和 PMG 的分配和回收。
+
+
+## 2.2 MPAM资源隔离特性
+
+
+MPAM 资源隔离特性的关键是由 MSC 组件维护的资源配置表。资源配置表中包含了不同 PARTID 和对应资源分配方案的映射。
+
+
+
+
+
+对于每一次资源请求,该资源对应的 MSC 会通过请求中的 PARTID 查找自身的配置表,然后按照表中与该 PARTID 相对应的方案进行资源分配。这样,通过将不同业务应用或VM与不同PARTID相绑定,就可以达到资源隔离的目的。
+
+
+通过图2左侧部分可以看到,不同资源分配方案的表示方法是有所区别的,这与资源的拆分方式不同有关。Cache 资源使用了 Bit Map,每一bit表示了对应的 Cache way 是否能够被分配;内存带宽资源则使用了百分比,表示该方案能够分配的内存带宽比例。
+
+
+## 2.3 MPAM资源监控特性
+
+
+资源监控可以看做是 MPAM 在支持资源隔离功能后的附加功能。MPAM 除了拥有资源隔离组件外,还拥有一定数目的资源 monitor。资源 monitor 可以实现对特定标识的资源使用情况的监控。
+
+
+为了实现对使用同一个 PARTID 的不同 task 分别进行资源监控,MPAM引入了PMG(Performance Monitoring Group)的概念。资源监控接口通过选取对应的 PARTID 和 PMG,即可获取到对应的资源使用情况。
+
+
+
+
+
+## 2.4 龙蜥 OS 对倚天 MPAM 特性的支持
+
+
+龙蜥 OS 5.10.134-12.al8 版本基于 resctrl 文件系统实现了对倚天芯片的 MPAM 特性的支持,同时保证了对 x86 RDT 特性和鲲鹏的 MPAM 特性的兼容。对应的代码仓库在 中。其中,MPAM 支持相关代码路径包括:
+
+
+* drivers/platform/mpam —— MPAM 驱动代码
+* drivers/acpi/arm64 —— MPAM ACPI 解析代码
+* fs/resctrl —— 用户态接口实现代码
+* arch/x86/kernel/cpu/resctrl —— x86 RDT 特性架构相关代码
+* drivers/staging/kunpeng/mpam —— 鲲鹏 MPAM 特性相关代码
+
+
+目前,龙蜥 OS 针对倚天芯片提供了 L3 Cache 和内存带宽两种资源的资源隔离和监控接口。接口的主要特性如下:
+
+
+* 提供最大 64 个 PARTID 支持
+* 提供 4 个 monitor 支持
+* 支持 per-numa 的 16 way L3 CAT(Cache Allocation Technology)特性
+* 支持 per-numa 的 16 way L3 CDP(Code and Data Prioritization)特性
+* 支持 per-numa 的 L3 Cache 资源监控特性
+* 支持 per-numa 的粒度为 5% 的 MBA(Memory Bandwidth Allocation)特性(受硬件限制,该特性目前效果较差)
+* 支持 per-numa 的内存带宽资源监控特性
+* 支持 MPAM 寄存器错误中断检测
+
+
+对应测试文档在。
+
+
+# 三、MPAM的使用
+
+
+## 3.1 开启MPAM
+
+
+1. 首先需要确保当前内核支持 MPAM 功能,需要设置`CONFIG_ARM64_MPAM`和`CONFIG_RESCTRL`;
+2. 在 cmdline 或 grub.cfg 文件中添加`mpam=acpi`,使能 MPAM 功能;
+3. 系统启动后,需要手动挂载 resctrl 文件系统到 /sys/fs/resctrl 目录。
+
+
+
+```
+mount -t resctrl resctrl /sys/fs/resctrl
+```
+
+## 3.2 MPAM 用户态接口
+
+
+MPAM 的用户态接口复用了 Intel RDT 功能的 resctrl 文件系统。resctrl 文件系统的目录结构如下图。
+
+
+
+
+
+### 3.2.1 资源调配 group
+
+
+开启 MPAM 功能后,操作系统中的每个进程(线程)都会与 resctrl 文件系统中的一个资源调配 group 相绑定。每个资源调配 group 在 MPAM 中对应着一个 PARTID。在 /sys/fs/resctrl 下新创建的每个目录将分别对应一个新的资源调配 group,每个资源调配 group 中会自动添加以下文件和目录:
+
+
+
+```
+|-- cpus
+|-- cpus_list
+|-- id
+|-- mode
+|-- mon_data
+|-- mon_groups
+|-- schemata
+|-- size
+`-- tasks
+```
+
+其中各文件和目录的作用为:
+
+
+**schemata**:表示该 group 对各个资源的分配方案,可读写。
+
+
+**mon\_data**:该目录中各个文件包含了对各个资源的监控值,只读。
+
+
+**cpus**:以 bitmask 的形式表示该 group 所控制的逻辑 CPU,可读写。
+
+
+**cpus\_list**: 与 cpus 含义一致,但以 range 的形式(如0-63)表示该 group 所控制的逻辑 CPU,可读写。
+
+
+**tasks**:表示该 group 所控制的 task pid,可读写。
+
+
+**id**:创建 group 时随机生成,用于唯一标识一个 group,只读。
+
+
+**mode**:表示当前 group 的分配方式,目前仅支持 shareable 方式。
+
+
+**mon\_groups**: 该目录用于创建仅用于监控功能的子 group,暂不可用。
+
+
+**size**:表示该 group 下各个资源所能使用的资源大小,只读。
+
+
+观察 /sys/fs/resctrl 目录可以发现,该目录自带了一个资源调配 group。这个 group 是作为 MPAM 开启后各 cpu 和 task 使用的默认 group 使用的。该 group 默认可以实现对各资源 100% 的占用。
+
+
+### 3.2.2 资源隔离与schemata文件
+
+
+使用资源隔离特性的关键是 schemata 文件,schemata 中包含了对该 group 的资源分配方案。其基本格式为如下:
+
+
+
+```
+MB:0= 100;1= 80
+L3:0=ffff;1=fff0
+```
+
+其中,
+
+
+* L3 cache 资源的分配以 bit mask 进行表示,`L3:0=ffff;1=fff0`表示所属该 group 的 cpu 和 task 可以分配到 NUMA 0 的 L3 cache 的完整 16 way,NUMA 1 的 L3 cache 的高 12 way。
+* 内存带宽资源的分配以百分比进行表示,`MB:0=100;1=80`表示所属该 group 的 cpu 和 task 可以分配到 NUMA 0 最多 100% 的内存带宽,NUMA 1 最多 80% 的内存带宽。
+
+
+### 3.2.3 资源监控与mon\_data目录
+
+
+mon\_data 目录下相关文件完成了 MPAM 的资源监控特性,倚天中 mon\_data 目录结构如下:
+
+
+
+```
+mon_data
+|-- mon_L3_00
+| `-- llc_occupancy
+|-- mon_L3_01
+| `-- llc_occupancy
+|-- mon_MB_00
+| `-- mbm_local_bytes
+`-- mon_MB_01
+ `-- mbm_local_bytes
+```
+
+其中,
+
+
+* L3 cache 资源监控对应着 mon\_L3\_ 目录,该目录下包含了对应 NUMA 节点下 L3 cache 资源的当前使用情况。目前该目录下只有 llc\_occupancy 一个文件,该文件以byte为单位显示了当前 group 各个 task 的 L3 cache 用量。
+* 内存带宽资源监控对应着 mon\_MB\_ 目录,该目录下包含了对应 NUMA 节点下内存带宽资源的当前使用情况。目前该目录下只有 mbm\_local\_bytes 一个文件,该文件以 byte/s 为单位显示了当前 group 各个 task 的内存带宽统计值。
+
+
+### 3.2.4 info目录
+
+
+/sys/fs/resctrl 目录下除了包含一个默认 group 所需要的相关文件和目录外,还有一个 info 目录。info 目录中包含了当前机器能够支持 MPAM 扩展中资源分配和监测功能的详细信息。目前倚天机器上该目录中有以下内容:
+
+
+
+```
+info/
+|-- L3
+| |-- bit_usage
+| |-- cbm_mask
+| |-- min_cbm_bits
+| |-- num_closids
+| `-- shareable_bits
+|-- L3_MON
+| |-- max_threshold_occupancy
+| |-- mon_features
+| `-- num_rmids
+|-- MB
+| |-- bandwidth_gran
+| |-- delay_linear
+| |-- min_bandwidth
+| `-- num_closids
+|-- MB_MON
+| |-- mon_features
+| `-- num_rmids
+`-- last_cmd_status
+```
+
+* L3 目录包含了 L3 cache 资源隔离特性的相关信息,其中各文件及其含义为
+
+
++ **bit\_usaged**:以 bitmask 的形式表示 L3 各 way 当前的使用情况,在倚天机器中,默认为`0=XXXXXXXXXXXXXXXX;1=XXXXXXXXXXXXXXXX`。
++ **cbm\_mask**:对应着 L3 cache 资源可以设置的最大 bitmask,同时该 mask 也对应着 100% 的 cache 资源占用。
++ **min\_cbm\_bit**:对 L3 cache 资源可以设置的最小 bit 数。
++ **num\_closids**:L3 cache 资源所能够创建的最大 group 数目,该值包含了 resctrl 文件系统挂载后自带的默认group。
++ **shareable\_bits**:以 bitmask 的形式表示 L3 cache 资源与其他实体(例如I/O)的共享情况。
+
+
+* L3\_MON 目录包含了 L3 cache 资源监控特性的相关信息,其中各文件及其含义为
+
+
++ **max\_threshold\_occupancy**:资源监控 monitor 被释放之后可能无法立即使用,因为之前的 cache 占用会影响 monitor 结果的准确性。max\_threshold\_occupancy 用于配置可以真正释放 monitor 的 cache占用。
++ **mon\_features**:显示 L3 cache 有哪些资源监控特性,与 mon\_data/mon\_L3\_xx 中文件相对应。
++ **num\_rmids**:可用的 monitor 数目,倚天机器该值为 4。
+
+
+* MB 目录包含了内存带宽资源隔离特性相关信息,其中各文件及其含义为:
+
+
++ **bandwidth\_gran**:内存带宽设置的百分比粒度,倚天机器该值为 5。
++ **delay\_linear**:与 Intel 机器中内存带宽资源隔离特性相关的值,倚天机器中默认为 true,即 1。
++ **min\_bandwidth**:内存带宽百分比设置的最小值,与 bandwidth\_gran 相等,倚天机器中该值为 5。
++ **num\_closids**:内存带宽资源所能够创建的最大 group,该数目包含了 resctrl 文件系统的默认 group。
+
+
+* MB\_MON 目录包含了内存带宽资源监控特性相关信息,其中各文件及其含义为:
+
+
++ **mon\_features**:显示内存带宽有哪些资源监控特性,与 mon\_data/mon\_MB\_xx 中文件相对应。
++ **num\_rmids**:可用的 monitor 数目,倚天机器该值为 4。
+
+
+* **last\_cmd\_status**:文件中包含了相关指令所出现的问题,可以通过读取该指令获取 resctrl 文件系统中相关操作失败的原因。
+
+
+## 3.3 MPAM 使用示例
+
+
+### 3.3.1 配置两个资源调配 group
+
+
+
+```
+mount -t resctrl resctrl /sys/fs/resctrl
+cd /sys/fs/resctrl
+# 创建两个资源调配group p0和p1
+mkdir p0 p1
+# 令p0使用Node0的高12路L3 Cache,Node1的低12路L3 Cache
+echo "L3:0=0xfff0;1=0x0fff" > /sys/fs/resctrl/p0/schemata
+# 令p1使用Node0的低12路L3 Cache,Node1的高12路L3 Cache
+echo "L3:0=0x0fff;1=0xfff0" > /sys/fs/resctrl/p1/schemata
+# 限制p0和p1的MB上限不超过50%
+echo "MB:0=50;1=50" > /sys/fs/resctrl/p0/schemata
+echo "MB:0=50;1=50" > /sys/fs/resctrl/p1/schemata
+# 读取两个文件
+cat /sys/fs/resctrl/p0/schemata
+cat /sys/fs/resctrl/p1/schemata
+```
+
+此时 /sys/fs/resctrl/p0/schemata 和 /sys/fs/resctrl/p1/schemata 两个文件中的内容分别为:
+
+
+
+```
+MB:0=50;1=50
+L3:0=fff0;1=0fff
+```
+
+
+```
+MB:0=50;1=50
+L3:0=0fff;1=fff0
+```
+
+### 3.3.2 为指定进程/线程分配资源调配 group
+
+
+以 3.3.1 中已创建的 p0 资源调配 group 为例,此处限制 pid 为 12345 的进程/线程使用 p0 资源调配 group 所限定的资源。需要注意的是,新创建的子进程将继承父进程的 PARTID 和 PMG 信息,但已创建的子进程将不受影响。
+
+
+
+```
+# 将pid 12345加入p0资源调配group
+echo 12345 > /sys/fs/resctrl/p0/tasks
+```
+
+之后,pid 为 12345 的进程/线程将自动从 /sys/fs/resctrl/tasks 移动到 /sys/fs/resctrl/p0/tasks 文件中。
+
+
+### 3.3.3 为指定cpu分配资源调配 group
+
+
+
+```
+# 将cpu 99、100、101移入p1资源调配group
+echo "99-101" > /sys/fs/resctrl/p1/cpus_list
+# 或者
+echo "38,00000000,00000000,00000000" > /sys/fs/resctrl/p1/cpus_list
+```
+
+之后,cpu 99-101 将从 /sys/fs/resctrl/cpus\_list 中移动到 /sys/fs/resctrl/p1/cpus\_list 中。
+
+
+### 3.3.4 读取 cache/内存带宽 的 monitor 值
+
+
+仍然以 3.3.1 中创建的 p0 资源调配group为例,要获取 p0 资源组各进程的资源占用值,通过 cat 即可得到实时监控结果。
+
+
+
+```
+cat /sys/fs/resctrl/p0/mon_data/mon_L3_0*/llc_occupancy
+cat /sys/fs/resctrl/p0/mon_data/mon_MB_0*/mbm_local_bytes
+```
+
+## 3.4 模拟混部L3 cache隔离
+
+
+混部是 MPAM 资源隔离的一个重要应用场景。此处分别以 SPECjbb 2015 和 stress-ng 程序分别模拟云环境上广泛使用的 java 类在线作业上和离线作业,对 MPAM 的 L3 cache 隔离功能进行验证。
+
+
+在前 40s 的时间内,两个程序共享L3 cache所有资源。在约 40s 后,开始隔离在线和离线L3 cache资源的使用,在离线任务 L3 cache 的配比分别为 0xffff 和 0xf。
+
+
+
+
+
+通过实验结果可以看到,在 L3 cache 资源共享的情况下,离线资源对在线资源干扰明显,L3 cache 竞争激烈,波动幅度很大;在对 L3 cache 资源进行隔离后,一方面离线得到了持续有效的压制,L3 cache 占有率大幅下降,另一方面在线性能提升明显,平均 L3 cache 占用提升了约 78%,且波动幅度变小,L3 cache 占用更加稳定。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247.md" "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247.md"
new file mode 100644
index 0000000000000000000000000000000000000000..897bbc104b8fc169729a65eabe73dc3a1a04b1d3
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247.md"
@@ -0,0 +1,223 @@
+
+文/龙蜥社区内核开发人员 陈善佩、吴一昊、邓二伟
+
+# Plugsched 是什么
+Plugsched 是 Linux 内核调度器子系统热升级的 SDK, **它可以实现在不重启系统、应用的情况下动态替换调度器子系统,毫秒级 downtime** 。Plugsched 可以对生产环境中的内核调度特性动态地进行增、删、改,以满足不同场景或应用的需求,且支持回滚。
+
+基于 plugsched 实现的调度器热升级,不修改现有内核代码,就能获得较好的可修改能力,天然支持线上的老内核版本。如果提前在内核调度器代码的关键数据结构中加入 Reserve 字段,可以额外获得修改数据结构的能力,进一步提升可修改能力。
+
+Plugsched 开源链接:https://gitee.com/anolis/plugsched
+
+
+
+# Plugsched 可以解决什么问题
+那么 Plugsched 诞生的背景或者想要解决的问题是什么?我们认为有以下 4 点:
+
+* **应用场景不同,最佳调度策略不同:** 应用种类极大丰富,应用特征也是千变万化 (throughput-oriented workloads, us-scale latency critical workloads, soft real-time, and energy efficiency requirements),使得调度策略的优化比较复杂,不存在“一劳永逸”的策略。因此,允许用户定制调度器满足不同的场景是必要的。
+* **调度器迭代慢:** Linux 内核经过很多年的更新迭代,代码变得越来越繁重。调度器是内核最核心的子系统之一,它的结构复杂,与其它子系统紧密耦合,这使得开发和调试变得越发困难。此外,Linux 很少增加新的调度类,尤其是不太可能接受非通用或场景针对型的调度器,上游社区在调度领域发展缓慢。
+* **内核升级困难:** 调度器内嵌 (built-in)在内核中,上线调度器的优化或新特性需要升级内核版本。内核发布周期通常是数月之久,这将导致新的调度器无法及时应用在生产系统中。再者,要在集群范围升级新内核,涉及业务迁移和停机升级,对业务方来说代价昂贵。
+* **无法升级子系统。** kpatch 和 livepatch 是函数粒度的热升级方案,可修改能力较弱,不能实现复杂的逻辑改动; eBPF 技术在内核网络中广泛应用,但现在调度器还不支持 ebpf hook,将来即使支持,也只是实现局部策略的灵活修改,可修改能力同样较弱。
+
+Plugsched 能将调度器子系统从内核中提取出来,以模块的形式对内核调度器进行热升级。通过对调度器模块的修改,能够针对不同业务定制化调度器,而且使用模块能够更敏捷的开发新特性和优化点,并且可以在不中断业务的情况下上线。
+
+
+图1 plugsched:业务不中断
+
+
+
+**使用 plugsched 具有以下 6 大优势:**
+* **与内核发布解耦:** 调度器版本与内核版本解耦,不同业务可以使用不同调度策略;建立持续运维能力,加速调度问题修复、策略优化落地;提升调度领域创新空间,加快调度器技术演进和迭代;
+* **可修改能力强:** 可以实现复杂的调度特性和优化策略,能人之所不能;
+* **维护简单:** 不修改内核代码,或少量修改内核代码,保持内核主线干净整洁;在内核代码 Tree 外独立维护非通用调度策略,采用 RPM 的形式发布和上线;
+* **简单易用:** 容器化的 SDK 开发环境,一键生成 RPM,开发测试简洁高效;
+* **向下兼容:** 支持老内核版本,使得存量业务也能及时享受新技术红利;
+* **高效的性能:** 毫秒级 downtime,可忽略的 overhead。
+
+
+
+# Plugsched 应用案例
+Plugsched 相比 kpatch 和 livepatch 可修改能力更强,热升级范围更广,plugsched 是子系统范围的热升级,而后者是函数级别的热升级。**对于 plugsched 而言,无论是 bugfix,还是性能优化,甚至是特性的增、删、改,都可胜任**。鉴于 plugsched 较强的可修改能力,它可应用到以下场景:
+
+* **快速开发、验证、上线新特性,稳定后放入内核主线;**
+* **针对不同业务场景做定制优化,以 RPM 包的形式发布和维护非通用调度器特性;**
+* **统一管理调度器热补丁,避免多个热补丁之间的冲突而引发故障。**
+
+
+
+**应用案例1:新增 Group Identity 调度特性**
+Group Identity 是阿里云用于混部场景的调度特性,它基于 CFS 调度器增加了一颗存储低优先级任务的红黑树,而且会对每一个 cgroup 分配一个默认优先级,用户也可自行配置其优先级,当队列中存在高优先级任务时,低优先级任务会停止运行。我们利用 plugsched 对 anck 4.19 的一个老版本内核(没有该调度特性)进行调度器热升级,并将 Group Identity 调度特性移植到生成的调度器模块中,涉及 7 个文件,2500+ 行的修改量。
+
+安装该调度器模块后,在系统中创建两个 cpu cgroup A 和 B,并绑定同一个 CPU,分别设置最高和最低优先级,然后各自创建一个 busy loop 任务。理论上,当 A 中有任务执行时,B 中的任务会停止运行。此时用 top 工具查看该 CPU 利用率,发现只有一个利用率是 100% 的 busy loop 任务,说明模块中的 Group Identity 特性已生效;而动态卸载该模块后,出现了两个各占 50% CPU 的 busy loop 任务,说明模块已经失效。
+
+
+
+**应用案例2:与内核发布解耦及定制化调度器**
+阿里云某客户使用的旧版本内核,由于该内核调度器对 load 的统计算法不合理,导致 CPU 利用率过高,虽然修复补丁已经合入内核主线,但是新内核版本还未发布,而且业务方也不打算更换内核,因为集群中部署了大量的业务,升级内核成本较高。
+
+除此之外,客户的内核开发人员对其混部业务场景(Group Identity 调度特性)进行了针对性的优化,想将优化内容合入内核主线。但是,阿里云内核开发人员发现,该优化内容在其它场景中有性能回退,属于非通用优化,因此不允许将优化内容合入主线。
+
+于是,客户的内核开发人员使用 plugsched 将优化修复内容全部移植到调度器模块中,最后规模部署。该案例可以体现出 plugsched 的与内核发布解耦、定制化调度器的优势。
+
+
+
+# 如何使用 Plugsched
+目前,plugsched 默认支持 Anolis OS 7.9 ANCK 系统发行版,其它系统需要[调整边界配置](./docs/Support-various-Linux-distros.md)。为了减轻搭建运行环境的复杂度,我们提供了的容器镜像和 Dockerfile,开发人员不需要自己去搭建开发环境。为了方便演示,这里购买了一台阿里云 ECS(64CPU + 128GB),并安装 Anolis OS 7.9 ANCK 系统发行版,我们将会对内核调度器进行热升级。
+
+1. 登陆云服务器后,先安装一些必要的基础软件包:
+```shell
+# yum install anolis-repos -y
+# yum install podman kernel-debuginfo-$(uname -r) kernel-devel-$(uname -r) --enablerepo=Plus-debuginfo --enablerepo=Plus -y
+```
+
+2. 创建临时工作目录,下载系统内核的 SRPM 包:
+```shell
+# mkdir /tmp/work
+# uname -r
+4.19.91-25.2.an7.x86_64
+# cd /tmp/work
+# wget https://mirrors.openanolis.cn/anolis/7.9/Plus/source/Packages/kernel-4.19.91-25.2.an7.src.rpm
+```
+
+3. 启动并进入容器:
+```shell
+# podman run -itd --name=plugsched -v /tmp/work:/tmp/work -v /usr/src/kernels:/usr/src/kernels -v /usr/lib/debug/lib/modules:/usr/lib/debug/lib/modules docker.io/plugsched/plugsched-sdk
+# podman exec -it plugsched bash
+# cd /tmp/work
+```
+
+4. 提取 4.19.91-25.1.al7.x86_64 内核源码:
+```shell
+# plugsched-cli extract_src kernel-4.19.91-25.2.an7.src.rpm ./kernel
+```
+
+5. 进行边界划分与提取:
+```shell
+# plugsched-cli init 4.19.91-25.2.an7.x86_64 ./kernel ./scheduler
+```
+
+6. 提取后的调度器模块代码在 ./scheduler/kernel/sched/mod 中, 新增一个 sched\_feature 并打包生成 rpm 包:
+```diff
+diff --git a/scheduler/kernel/sched/mod/core.c b/scheduler/kernel/sched/mod/core.c
+index 9f16b72..21262fd 100644
+--- a/scheduler/kernel/sched/mod/core.c
++++ b/scheduler/kernel/sched/mod/core.c
+@@ -3234,6 +3234,9 @@ static void __sched notrace __schedule(bool preempt)
+ struct rq *rq;
+ int cpu;
+
++ if (sched_feat(PLUGSCHED_TEST))
++ printk_once("I am the new scheduler: __schedule\n");
++
+ cpu = smp_processor_id();
+ rq = cpu_rq(cpu);
+ prev = rq->curr;
+diff --git a/scheduler/kernel/sched/mod/features.h b/scheduler/kernel/sched/mod/features.h
+index 4c40fac..8d1eafd 100644
+--- a/scheduler/kernel/sched/mod/features.h
++++ b/scheduler/kernel/sched/mod/features.h
+@@ -1,4 +1,6 @@
+ /* SPDX-License-Identifier: GPL-2.0 */
++SCHED_FEAT(PLUGSCHED_TEST, false)
++
+ /*
+ * Only give sleepers 50% of their service deficit. This allows
+ * them to run sooner, but does not allow tons of sleepers to
+```
+```shell
+# plugsched-cli build /tmp/work/scheduler
+```
+
+7. 将生成的 rpm 包拷贝到宿主机,退出容器,查看当前 sched\_features:
+```text
+# cp /usr/local/lib/plugsched/rpmbuild/RPMS/x86_64/scheduler-xxx-4.19.91-25.2.an7.yyy.x86_64.rpm /tmp/work
+# exit
+exit
+# cat /sys/kernel/debug/sched_features
+GENTLE_FAIR_SLEEPERS START_DEBIT NO_NEXT_BUDDY LAST_BUDDY CACHE_HOT_BUDDY WAKEUP_PREEMPTION NO_HRTICK NO_DOUBLE_TICK NONTASK_CAPACITY TTWU_QUEUE NO_SIS_AVG_CPU SIS_PROP NO_WARN_DOUBLE_CLOCK RT_PUSH_IPI RT_RUNTIME_SHARE NO_LB_MIN ATTACH_AGE_LOAD WA_IDLE WA_WEIGHT WA_BIAS NO_WA_STATIC_WEIGHT UTIL_EST ID_IDLE_AVG ID_RESCUE_EXPELLEE NO_ID_EXPELLEE_NEVER_HOT NO_ID_LOOSE_EXPEL ID_LAST_HIGHCLASS_STAY
+```
+
+8. 安装调度器包,且新增了一个 PLUGSCHED\_TEST sched\_feature(关闭状态):
+```text
+# rpm -ivh /tmp/work/scheduler-xxx-4.19.91-25.2.an7.yyy.x86_64.rpm
+# lsmod | grep scheduler
+scheduler 503808 1
+# dmesg | tail -n 10
+[ 2186.213916] cni-podman0: port 1(vethfe1a04fa) entered forwarding state
+[ 6092.916180] Hi, scheduler mod is installing!
+[ 6092.923037] scheduler: total initialization time is 6855921 ns
+[ 6092.923038] scheduler module is loading
+[ 6092.924136] scheduler load: current cpu number is 64
+[ 6092.924137] scheduler load: current thread number is 667
+[ 6092.924138] scheduler load: stop machine time is 249471 ns
+[ 6092.924138] scheduler load: stop handler time is 160616 ns
+[ 6092.924138] scheduler load: stack check time is 85916 ns
+[ 6092.924139] scheduler load: all the time is 1097321 ns
+# cat /sys/kernel/debug/sched_features
+NO_PLUGSCHED_TEST GENTLE_FAIR_SLEEPERS START_DEBIT NO_NEXT_BUDDY LAST_BUDDY CACHE_HOT_BUDDY WAKEUP_PREEMPTION NO_HRTICK NO_DOUBLE_TICK NONTASK_CAPACITY TTWU_QUEUE NO_SIS_AVG_CPU SIS_PROP NO_WARN_DOUBLE_CLOCK RT_PUSH_IPI RT_RUNTIME_SHARE NO_LB_MIN ATTACH_AGE_LOAD WA_IDLE WA_WEIGHT WA_BIAS NO_WA_STATIC_WEIGHT UTIL_EST ID_IDLE_AVG ID_RESCUE_EXPELLEE NO_ID_EXPELLEE_NEVER_HOT NO_ID_LOOSE_EXPEL ID_LAST_HIGHCLASS_STAY
+```
+
+9. 打开新的 sched\_feature,“I am the new scheduler: \_\_schedule” 信息出现在 dmesg 日志中:
+```text
+# echo PLUGSCHED_TEST > /sys/kernel/debug/sched_features
+# dmesg | tail -n 5
+[ 6092.924138] scheduler load: stop machine time is 249471 ns
+[ 6092.924138] scheduler load: stop handler time is 160616 ns
+[ 6092.924138] scheduler load: stack check time is 85916 ns
+[ 6092.924139] scheduler load: all the time is 1097321 ns
+[ 6512.539300] I am the new scheduler: __schedule
+```
+
+10. 卸载调度器包后,新的 sched\_feature 被删除:
+```text
+# rpm -e scheduler-xxx
+# dmesg | tail -n 8
+[ 6717.794923] scheduler module is unloading
+[ 6717.809110] scheduler unload: current cpu number is 64
+[ 6717.809111] scheduler unload: current thread number is 670
+[ 6717.809112] scheduler unload: stop machine time is 321757 ns
+[ 6717.809112] scheduler unload: stop handler time is 142844 ns
+[ 6717.809113] scheduler unload: stack check time is 74938 ns
+[ 6717.809113] scheduler unload: all the time is 14185493 ns
+[ 6717.810189] Bye, scheduler mod has be removed!
+#
+# cat /sys/kernel/debug/sched_features
+GENTLE_FAIR_SLEEPERS START_DEBIT NO_NEXT_BUDDY LAST_BUDDY CACHE_HOT_BUDDY WAKEUP_PREEMPTION NO_HRTICK NO_DOUBLE_TICK NONTASK_CAPACITY TTWU_QUEUE NO_SIS_AVG_CPU SIS_PROP NO_WARN_DOUBLE_CLOCK RT_PUSH_IPI RT_RUNTIME_SHARE NO_LB_MIN ATTACH_AGE_LOAD WA_IDLE WA_WEIGHT WA_BIAS NO_WA_STATIC_WEIGHT UTIL_EST ID_IDLE_AVG ID_RESCUE_EXPELLEE NO_ID_EXPELLEE_NEVER_HOT NO_ID_LOOSE_EXPEL ID_LAST_HIGHCLASS_STAY
+```
+**注意:不可以用“rmmod”命令直接卸载调度器模块,应使用“rpm 或 yum”标准命令卸载调度器包。**
+
+
+
+# Plugsched 实现原理
+**我们通过以上知道了 Plugsched 是什么、应用案例,那它实现原理是什么?**
+
+调度器子系统在内核中并非是一个独立的模块,而是内嵌在内核中,与内核其它部分紧密相连。
+
+**Plugsched 采用“模块化”的思想**:它提供了边界划分程序,确定调度器子系统的边界,把调度器从内核代码中提取到独立的目录中,开发人员可对提取出的调度器代码进行修改,然后编译成新的调度器内核模块,动态替换内核中旧的调度器。对子系统进行边界划分和代码提取,需要处理函数和数据,而后生成一个独立的模块。
+
+**对于函数而言**,调度器模块对外呈现了一些关键的函数,以这些函数为入口就可以进入模块中,我们称之为接口函数。通过替换内核中的这些接口函数,内核就可以绕过原有的执行逻辑进入新的调度器模块中执行,即可完成函数的升级。模块中的函数,除了接口函数外,还有内部函数,其它的则是外部函数。
+
+**对于数据**,调度器模块默认使用并继承内核中原有的数据,对于调度器重要的数据,比如运行队列状态等,可以通过状态重建技术自动重新初始化,这类数据属于私有数据,而其它则是共享数据。为了灵活性,plugsched 允许用户手动设置私有数据,手动设置的私有数据会在模块中保留定义,但需要对它们进行初始化。对于结构体而言,plugsched 将只被调度器访问的结构体成员分类为内部成员,其它为非内部成员。调度器模块允许修改内部成员的语义,禁止修改非内部成员的语义。如果结构体所有成员都是内部成员,则调度器模块允许修改整个结构体。但是,建议优先使用结构体中的保留字段,而不是修改现有成员。
+
+
+
+# Plugsched 设计方案
+Plugsched 主要包含两大部分,第一部分是调度器模块边界划分与代码提取部分,第二部分是调度器模块热升级部分,这两部分是整个方案的核心。其整体设计方案如下:
+
+
+图2 plugsched 整体架构
+
+
+
+首先进行的是调度器模块边界划分和代码提取流程,由于调度器本身并不是模块,因此需要明确调度器的边界才能将它模块化。边界划分程序会根据边界配置信息(主要包含代码文件、接口函数等信息)从内核源代码中将调度器模块的代码提取到指定目录,然后开发人员可在此基础上进行调度器模块的开发,最后编译生成调度器 RPM 包,并可安装在对应内核版本的系统中。安装后会替换掉内核中原有的调度器,安装过程会经历以下几个关键过程:
+
+* **符号重定位**:解析模块对部分内核符号的访问;
+* **栈安全检查**:类似于 kpatch,函数替换前必须进行栈安全检查,否则会出现宕机的风险。plugsched 对栈安全检查进行了并行和二分优化,提升了栈安全检查的效率,降低了停机时间;
+* **接口函数替换**:用模块中的接口函数动态替换内核中的函数;
+* **调度器状态重建**:采用通用方案自动同步新旧调度器的状态,极大的简化数据状态的一致性维护工作。
+
+
+
+# 总结
+Plugsched 使得调度器从内核中解放出来,开发人员可以对调度器进行专项定制,而不局限于内核通用调度器;内核维护也变得更加轻松,因为开发人员只需要关注通用调度器的开发与迭代,定制化调度器可通过 RPM 包的形式进行发布;内核调度器代码也会变得简洁,无需再被各个场景的优化混淆起来。
+
+未来,plugsched 会支持新版本内核和其它平台,持续对其易用性进行优化,并提供更多的应用案例。最后,欢迎更多的开发者能参与到 plugsched 中。
\ No newline at end of file
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG01/sig-info.yaml" "b/sig/Anolis\350\277\201\347\247\273SIG02/sig-info.yaml"
similarity index 88%
rename from "sig/Anolis\350\277\201\347\247\273SIG01/sig-info.yaml"
rename to "sig/Anolis\350\277\201\347\247\273SIG02/sig-info.yaml"
index d378c0668c8a5c9f8d7578560e8cd4f43b3a080d..2721eeef2210878acfd937c5ab5417254cf35903 100644
--- "a/sig/Anolis\350\277\201\347\247\273SIG01/sig-info.yaml"
+++ "b/sig/Anolis\350\277\201\347\247\273SIG02/sig-info.yaml"
@@ -1,11 +1,11 @@
-name: aaa
-en_name: Anolis迁移SIG01
-home_page: https://openanolis.cn/sig/migration01
+name: Anolis迁移SIG02
+en_name: Anolis迁移SIG02
+home_page: https://openanolis.cn/sig/migration02
description: OpenAnolis作为一个新的OS开源社区,为了用户能够更好的使用Anolis OS,需要提供从别的OS迁移到Anolis OS的迁移指导和迁移工具,降低用户的迁移成本。
en_description: As a new OS open source community, Anolis OS needs to provide migration guidance and migration tools for migrating from other OS to Anolis OS i
mailing_list: os@lists.openanolis.cn
meeting_url: https://openanolis.cn
-maintainers:
+maintainers:
- openanolis_id:ceshi002
gitee_id:
name:
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/README.en.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/README.en.md"
new file mode 100644
index 0000000000000000000000000000000000000000..be0e6a29693481155b507426cc7cde9f5c199b36
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/README.en.md"
@@ -0,0 +1,24 @@
+# Group goals
+
+Provide migration guidance and migration tools from CentOS to Anolis OS, users can use Anolis OS simply and efficiently.
+
+1. Provide in-place migration tool from CentOS 8 to Anolis OS 8
+2. Provide in-place migration tool from CentOS 7 to Anolis OS 7
+3. Provide in-place upgrade tool from CentOS 7 to Anolis OS 8
+
+# Ongoing project
+
+1. OS Migration Tool
+
+Provide CentOS 8 to Anolis OS 8 and CentOS 7 to Anolis OS 7 in-place migration tool, users can use the migration script to migrate to Anolis OS in place.
+
+Open source: [https://gitee.com/anolis/centos2anolis](https://gitee.com/anolis/centos2anolis)
+
+1. 7 to 8 migration tool
+
+Provide CentOS 7 to Anolis OS 8 upgrade evaluation and in-place upgrade tool, users can use this tool to achieve CentOS7 to Anolis OS 8 in-place upgrade.
+
+Open source:
+
+* [https://gitee.com/src-anolis-sig/leapp](https://gitee.com/src-anolis-sig/leapp)
+* [https://gitee.com/src-anolis-sig/leapp-repository](https://gitee.com/src-anolis-sig/leapp-repository)
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/README.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/README.md"
new file mode 100644
index 0000000000000000000000000000000000000000..55d122e6ee48f214926ca2eca37d3e962427cbbb
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/README.md"
@@ -0,0 +1,24 @@
+# 小组目标
+
+提供从CentOS迁移到Anolis OS的迁移指导和迁移工具,用户能够简单高效的使用到Anolis OS。
+
+1. 提供从CentOS 8迁移到Anolis OS 8的一键式迁移工具
+2. 提供从CentOS 7迁移到Anolis OS 7的一键式迁移工具
+3. 提供从CentOS 7升级到Anolis OS 8的一键式升级工具
+
+# 正在进行的项目
+
+1. OS迁移工具
+
+提供CentOS 8到Anolis OS8,CentOS 7到Anolis OS 7一键式迁移工具,用户可使用迁移脚本就地迁移到Anolis OS。
+
+已开源: [https://gitee.com/anolis/centos2anolis](https://gitee.com/anolis/centos2anolis)
+
+1. 7迁8迁移工具
+
+提供CentOS 7到Anolis OS 8的升级评估和就地升级工具,用户可使用该工具实现CentOS 7到Anolis OS 8的就地升级。
+
+已开源:
+
+* [https://gitee.com/src-anolis-sig/leapp](https://gitee.com/src-anolis-sig/leapp)
+* [https://gitee.com/src-anolis-sig/leapp-repository](https://gitee.com/src-anolis-sig/leapp-repository)
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/Cloud_Kernel_\344\272\247\345\223\201\347\256\200\344\273\213/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/Cloud_Kernel_\344\272\247\345\223\201\347\256\200\344\273\213/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..8e463b096dfb28b1ad1697b2ee4ea21fbc80e846
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/Cloud_Kernel_\344\272\247\345\223\201\347\256\200\344\273\213/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/dingding_group_qa.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/dingding_group_qa.png"
new file mode 100644
index 0000000000000000000000000000000000000000..c5b855ba68d171d8ff86213120b6db9abb79bcf8
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/dingding_group_qa.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.11.14\343\200\221Cloud_Kernel\344\273\243\347\240\201\345\220\210\345\271\266\346\265\201\347\250\213\345\217\230\346\233\264/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.11.14\343\200\221Cloud_Kernel\344\273\243\347\240\201\345\220\210\345\271\266\346\265\201\347\250\213\345\217\230\346\233\264/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..62dc7b6b0032e519b579904258e138907fd55970
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.11.14\343\200\221Cloud_Kernel\344\273\243\347\240\201\345\220\210\345\271\266\346\265\201\347\250\213\345\217\230\346\233\264/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b3d694d5986e8236c6689d2576c38dc8aef02474
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..89e8edb07188edf919b880e5caf9bad3cb072d1e
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..0ea00c803d57b2689cd4a5edcce4de3c35b62e7b
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..0457558710f096384b44c13d0390ad788b0db560
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\205\254\345\221\212/\343\200\220\345\205\254\345\221\212-2022.7.22\343\200\221Cloud_Kernel\345\274\200\345\217\221\346\265\201\347\250\213\345\217\230\346\233\264/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..380ae5996919384b397842341f37a4698d1109cf
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9304c3aebcd602970c06d5fdfbdd326cbadee253
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f0782be572dff8e4befca5989fb7f32feaae883f
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\344\273\243\347\240\201\345\210\206\346\236\220/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..1e0d3c14fcded55abd4f2ad39479abb5c76f0050
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..fa7da5d383820ff2a6d0ddaff29938e36fb360e7
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..80187bd3d11a7edb94ab2237e0c30dc217eb0c83
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f2bb4248a9386583e637d85d8009b4e28a21a722
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Ftrace\357\274\232_osnoise_\346\200\273\350\247\210/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..fddcb74f5c9a9e7b6ae714d7527695b8af147661
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..a841c6380b4c5ac16d172b524940b5fd030b3927
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232CONSOLE_\344\273\243\347\240\201\345\210\206\346\236\220/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232DMESG_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232DMESG_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..dec01fec232e11cca5e54a6ccc32e21b199575cb
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\211\215\347\253\257\357\274\232DMESG_\344\273\243\347\240\201\345\210\206\346\236\220/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..ab5f3485686d34b385b7706bfb22a28259777941
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..8416444ae596818142b187f27a5895531e155e63
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..bb5c37e746e0b78a77903d6b279b9d351aa32922
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\345\244\232\345\220\216\347\253\257\346\224\257\346\214\201\350\241\245\344\270\201/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..ca310e0f41e61f3e0964ac19704fd07af704fe7e
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..7324b7e19438810c058546a055c640be709f4843
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..2af59d1371fb10ecaa3324e5aa4f746d1008c783
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..4527db2df8937827d6fd7876e0382533ef0e69e9
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..cd6474e495ea5ab1483f9ee937b6f4d5c39062a5
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_5.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..da4ad25a7cca35fc9876d6ff26879246fbbe7586
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/Pstore\346\200\273\350\247\210/img_5.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..47b10a693407189e1e7703c470b51df2e2048013
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..a47ed97da917f61f81b8c28c0174d9e4479b8fa3
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..ba86bbe47e77a4b3dd6b48493c289b1ddd20040f
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..49048ef55c3ff70684bf0f0f35b9d8b365384be9
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f59092869cc9c39b595c95109b7d84117f66b9ea
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\350\260\203\346\265\213/\345\237\272\344\272\216pstore\347\232\204kdump\350\260\203\346\265\213\345\267\245\345\205\267/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..74072b56ea1bb7cba1eb3f03ba735fb70627abf7
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..248e6445b9869598280f71ea4c43c880be85533e
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_10.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_10.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9d2cee1c3836c8da875c7baf12a890a4e59365fd
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_10.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_11.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_11.png"
new file mode 100644
index 0000000000000000000000000000000000000000..dfe650b0c62a67a8500cb5f65daf0e99fefe8663
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_11.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..3b16ced8c3e1ff7d506c40d37d66c5c86dce9382
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b986cb29b49d6dad487ae789c5fcfa58ff76e6fb
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..05753d4cc7cb7f87f81b93eaa010cb9ac9850b11
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_5.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..85bc9f951e34353ac0c023e58f2fc336475f2f63
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_5.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_6.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_6.png"
new file mode 100644
index 0000000000000000000000000000000000000000..45282ecfb0c0d2d8fe1c4f919e09a04a8a2f5547
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_6.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_7.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_7.png"
new file mode 100644
index 0000000000000000000000000000000000000000..45282ecfb0c0d2d8fe1c4f919e09a04a8a2f5547
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_7.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_8.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_8.png"
new file mode 100644
index 0000000000000000000000000000000000000000..7af6ece254049856eeab8bb11ff3e19ab332fdfa
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_8.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_9.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_9.png"
new file mode 100644
index 0000000000000000000000000000000000000000..a7104e9b46e0f6e24b72020d653e3140fede8eda
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\206\205\346\240\270\351\251\261\345\212\250/OOT\351\251\261\345\212\250\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/img_9.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..369ef9d313640f62bba3459944af705a3365f75a
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..83526fa8cf9970957ce61102244f0dd759a70cf3
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_ARM64_RAS\346\234\272\345\210\266\347\256\200\344\273\213/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..95472b08774a80401adc22b5701848d397c3c909
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..efacbe74a8b24f0969a4245002cc3fd75f3c92b1
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK_boot_cmdline_\345\237\272\347\272\277\346\216\250\350\215\220/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..44799418f12fd06d4922fcb7740a8bf6367e753d
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..727fb493b49b429143195a68ef00d4d3406d41cd
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f05d93a1edc145b8c315cbd62f4084c36708122c
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f6c03f4ce83423ee42454a2027b99a8bb71b16ef
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/ANCK\345\206\205\346\240\270\345\212\237\350\203\275\344\270\216\346\216\245\345\217\243\344\273\213\347\273\215/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..a798ff256c3f6abc0b1dfaa200bab76962adbb3b
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..bb5c5e8ec2ee954701e0c49a2b7209462b5fe610
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f863b7c1a111f35db9fc16742807cbf611520b29
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..e9c0f9d166126e8fde6cd3d822cd982a38fef0f5
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..0f3a2dd7b0c1d288b5673f0e37d4f005113ef4a9
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_5.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..0bddeb4655513c3a1dd7291d4c29e5092c4734ff
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\237\272\347\241\200\350\203\275\345\212\233\345\222\214\347\211\210\346\234\254\346\274\224\350\277\233/datop\346\212\200\346\234\257\346\226\271\346\241\210/img_5.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..7f37c60b633e2dd00d64a2a4efafc88a0447c32b
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..2145aec1966cfbc621be0efa9eaa865abb517c59
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..a0af706ace2308e440a572caffcdfbdd3d2d0a97
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..7cbcbc9dce3471d2404f2f5d923c195a2c3de2b2
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d5c16cc68db0638fb6eae6d42ab0c751fcc79dd8
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2201\343\200\221Anolis_OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..59ebe6c002c5994c6084e7af37152d6ae226928f
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..e7f35b123c413f2f023e4c83f9129812cb7ea674
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d37b6c3d8e347bb277f4036910acc10d7b72f756
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d2d969a0f704ee9268077b9ea3f7cd227ae480a9
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..a5499779a58080c817c8ff36d8064c495ac1e5b6
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_5.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..43959c1a7372c156ae31431fd7725dc19dc7577d
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2202\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_Make\346\226\271\345\274\217/img_5.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..4d3c493790bdc85217baadab774837db8174b1c5
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..209fc652359363a47a41ec2218fd8bc173baf27f
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2203\343\200\221\345\206\205\346\240\270\347\274\226\350\257\221\345\256\211\350\243\205_-_RPM\345\214\205\346\226\271\345\274\217/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..691cc43166d4c318395cd51b1e0fecbbe98274a7
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..413371b395a8f3c1b791f2a1dd0edaaf0832c15f
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..01d195ccff245f413daaa53619e9586d9af29037
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..a526e09cca6111af785c2eb4ef8bd013c091a1d4
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..31f6d007f009bcc149452e15fefcd16fff0bf5f5
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_5.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d7cf172a4603d4613e9700e81420563cf8747ba4
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_5.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_6.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_6.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f80f8094a9b3398ccba84fc258522191857ee6d3
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204-1\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212BUG/img_6.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..cd4e2172e8b9225fa5843634ec8b38778e32cf5b
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..54c06edbd4dda8bcf171eb06bbf0eb274623a2ed
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b7c769b0ad81dfa9720abd13839b38cd7f37a2b8
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..c93631f36ea52dc552571594af9c14445b58bf36
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..3a2b0b7f3590b03626f0cf287a5b7fb51b71e4a0
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_5.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..184e9226627bcea1d2b40b749ba5fdebb35f7b13
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_5.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_6.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_6.png"
new file mode 100644
index 0000000000000000000000000000000000000000..93b0c090d2a688b08de89c82ba4ce26dc138ec54
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_6.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_7.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_7.png"
new file mode 100644
index 0000000000000000000000000000000000000000..2eb64a4df5cdda266178b2575c88ef1da134d200
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_7.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_8.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_8.png"
new file mode 100644
index 0000000000000000000000000000000000000000..e8065d561c7ad9c7bdd4d47b398befe6234d6ac7
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_8.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_9.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_9.png"
new file mode 100644
index 0000000000000000000000000000000000000000..51a44717b0d1347a64a6721304a301d63aaf372a
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2204\343\200\221Cloud_Kernel\345\274\200\345\217\221\345\237\272\346\234\254\346\265\201\347\250\213/img_9.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..4adf2fd8ec3b352a1eef36a715895b59472fd0c4
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..501748e393b27959d95ddf79066a2c9c1c840db2
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2205\343\200\221\345\220\221Cloud_Kernel\346\212\245\345\221\212CVE/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b88cf41c53388655041dbec55f3c7d6094c1f959
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..30b5718cf47bd0a7604c4febe56ad8c5b6b3f67e
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..e9d50acfa8c565b1731e4355999efa1a4efa08eb
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..88d9e372a0ddd57408e351ba5391faac0358ba73
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\343\200\2206\343\200\221\350\256\242\351\230\205Cloud_Kernel\351\202\256\344\273\266\345\210\227\350\241\250/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..2b698da7f47590295eb2fc53179c64bdcfe4ed55
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..7c37a1db235aa78013ca7faaf1158263ff0579ea
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9c47e4e9b8bee43d6b33f01345a6ea2d6c585e49
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d68ee6d6911568f4952bb704ced2bd7426578374
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\346\265\213\350\257\225\346\212\245\345\221\212/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..c257a26648e809c2e37549e2fe4472300e6a9d1a
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..be45fa1e21ea22de702cafabaa8b8467084a066c
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b1bed8770605d31e48a5184beb182ed6e53f4695
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..2704bb5aaac5e2a48480b1174ad4db673358e3be
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d68ee6d6911568f4952bb704ced2bd7426578374
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\347\241\254\350\265\204\346\272\220\351\232\224\347\246\273mpam\347\211\271\346\200\247\344\273\213\347\273\215/\351\276\231\350\234\245_ANCK_5.10_\345\200\232\345\244\251\345\271\263\345\217\260_MPAM_\347\224\250\346\210\267\346\211\213\345\206\214/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..1bbd3dd0a6d3b53d767f4f5f508a7cb0ef717b30
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..e791ecb3d3090cf1efc8e562a2af9e9fe7a2d100
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..500f8c9925971c4b339cc352fc4cec6b59229220
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/Plugsched_\342\200\224\342\200\224_Linux_\345\206\205\346\240\270\350\260\203\345\272\246\345\231\250\347\203\255\345\215\207\347\272\247/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..507c5552e047b1736fd0f9397a20887b48be99c2
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..f32a0710752c6a24215173b87c50ede8fcdf109e
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9c254f32e4f0a102a34e1d06514fd1687d06b40d
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..3d4f4bc5faba39a5348d69eea8aa0837fb7912a4
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9df092e6163a19c483dba4489eac80133465bae1
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245OS\350\265\204\346\272\220\351\232\224\347\246\273\346\212\200\346\234\257\344\273\213\347\273\215/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_0.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_0.png"
new file mode 100644
index 0000000000000000000000000000000000000000..bc14d4826022d43df35532aa87777614833dda1e
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_0.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_1.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_1.png"
new file mode 100644
index 0000000000000000000000000000000000000000..ebbe779d6f5a95407dd5c8af2346711f288fc181
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_1.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_10.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_10.png"
new file mode 100644
index 0000000000000000000000000000000000000000..98fb21bb72a93b3e5870a8dbcbc069d818dda134
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_10.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_11.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_11.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b1cfe176f26af9e796127777138f1e0f94517687
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_11.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_12.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_12.png"
new file mode 100644
index 0000000000000000000000000000000000000000..3dabd3ed4a8a1498a14b49afa2bc268b720d61ab
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_12.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_13.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_13.png"
new file mode 100644
index 0000000000000000000000000000000000000000..2cea85e41767e9d3801c8404f359b5b0c535c8a6
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_13.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_14.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_14.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9dd713591c6162ea15de1b29976fcde489231d91
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_14.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_2.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_2.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d0eef93ec6f877248caa01ac0c06595a9fe56fea
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_2.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_3.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_3.png"
new file mode 100644
index 0000000000000000000000000000000000000000..2bc13bf9842fe6f61b8e9bb3f2c528d145b2187d
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_3.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_4.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_4.png"
new file mode 100644
index 0000000000000000000000000000000000000000..3d4f4bc5faba39a5348d69eea8aa0837fb7912a4
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_4.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_5.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_5.png"
new file mode 100644
index 0000000000000000000000000000000000000000..d936ddf9426f2062c5b78608ce22b8f9484a17ef
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_5.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_6.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_6.png"
new file mode 100644
index 0000000000000000000000000000000000000000..580695a971df01c9b6226c96ca9bcebc7e5fa133
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_6.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_7.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_7.png"
new file mode 100644
index 0000000000000000000000000000000000000000..9df092e6163a19c483dba4489eac80133465bae1
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_7.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_8.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_8.png"
new file mode 100644
index 0000000000000000000000000000000000000000..074c12d51cfd861b15939f35b135c447338fd5f7
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_8.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_9.png" "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_9.png"
new file mode 100644
index 0000000000000000000000000000000000000000..b206604394f29a4c6efc41a01d0cbd18247b6288
Binary files /dev/null and "b/sig/Anolis\350\277\201\347\247\273SIG03/assets/\350\265\204\346\272\220\351\232\224\347\246\273\344\270\216\346\267\267\351\203\250/\351\276\231\350\234\245os\350\265\204\346\272\220\351\232\224\347\246\273\344\275\277\347\224\250\347\256\200\344\273\213/img_9.png" differ
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/2021.11.01~2021.11.14.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/2021.11.01~2021.11.14.md"
new file mode 100644
index 0000000000000000000000000000000000000000..8836ff2b507693190017a459eb94c992dad7b341
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/2021.11.01~2021.11.14.md"
@@ -0,0 +1,81 @@
+### 会议主题
+
+
+首次非正式会议, 自由讨论的形式, 聊聊龙蜥内核版本计划, 研发流程及后续双周会主题等
+
+
+### 会议时间
+
+
+2021.11.03 15:00-17:00
+
+
+### 与会人
+
+
+* 会议主持: Shiloong
+* 来自统信,龙芯, 阿里云的龙蜥社区爱好者
+
+
+### 会议纪要
+
+
+* 会议由 Shioong 发起主持, 开场简单介绍了龙蜥 ANCK 版本情况及当前基本研发流程.
+
+
+* 自由讨论中, 谢仲天提出如何尽快参与到内核社区共建的问题. 讨论认为,
+
+
+* + 1) 主动参与: 可通过向社区贡献开源特性参与社区内核研发; 可通过积极关注 kernel-sig bug 管理平台, 积极承担特性/bug 研发任务来参与;
+ + 2) 被动参考: 确定统一接口人, 由社区统一分派研发任务.
+
+
+* + 总之社区是极其开放的, 欢迎大家积极参与其中.
+
+
+* 卢彦表示关注内核性能测试相关 benchmark 评价与测试验收标准
+
+
+* + 阿里云在这一块有多年积累, 一些成熟经验计划在社区推广;
+ + 这块建议放到社区相应的 [QA Sig](https://openanolis.cn/sig/QA) 进一步深入交流.
+
+
+* 李雪峰介绍了龙芯内核同源异构相关进展:
+
+
+* + 表示龙芯内部已经有相关计划;
+ + 因这块工作量较大, 涉及内核及工具链; 且与架构相关的bug 一般难度较大.
+ + 龙芯内部还需要进一步讨论, 以确定排期等相关事项.
+
+
+* + 会上讨论认为这块可以在龙芯 sig 里进一步对齐.
+ + 当前ANCK 已经推出5.10内核, 希望能在这个内核尽快做起来.
+
+
+* 最后大家讨论了 kernel-sig 双周会的相关问题:
+
+
+* + 目前暂定双周会固定时间为第一周周三下午3:00-5:00; 下一次双周会时间 2021.11.17 15:00-17:00;
+ + 疫情期间以线上会议为主, 待国家放开后考虑线下会议;
+
+
+* + 会上头脑风暴了双周会话题:
+
+
+* + - 双周会会有一些例行事项: 1) kernel-sig 双周大事回顾; 2) kernel-sig 相关事项决策等等;
+ - 客户现场案例分享相关: 如在真实客户现场遇到的问题, 解决方案, 经验等分享交流;
+
+
+* + - 内核子系统相关: 如内核子系统相关新特性技术分享, 实例业务应用案例等;
+ - 内核相关业界软硬技术热点研讨: 如 eBPF 应用等等;
+
+
+* + - 客户解决方案相关话题: 如1)客户具体案例分享; 2) 应用软件生态适配相关话题;
+ - ANCK 内核历史经典问题,案例分享;
+
+
+* + - 软硬件协同, 跨平台支持技术等;
+ - 内核相关系列技术讲座;
+
+
+* + - 会上大家提议后面可以发起 ACK (Anolis Cloud Kernel 开发者大会); 待国内疫情放开后, 可以考虑先搞起线下 meetup.
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\344\273\243\347\240\201\345\244\247\351\241\265-mysql\346\200\247\350\203\275\346\265\213\350\257\225.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\344\273\243\347\240\201\345\244\247\351\241\265-mysql\346\200\247\350\203\275\346\265\213\350\257\225.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ec8e22ac006bf2e176d9e7f7890c4f2de8420eaf
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\344\273\243\347\240\201\345\244\247\351\241\265-mysql\346\200\247\350\203\275\346\265\213\350\257\225.md"
@@ -0,0 +1,205 @@
+# 背景
+代码大页特性将应用程序代码段 (.text) 通过file THP映射,减少TLB entry开销,以此减低整个系统中TLB entry的资源竞争。对于MySQL、JAVA等应用,能显著减少iTLB miss,提升E2E性能。下面会采用hugetext来代表代码大页。
+
+
+我们在本地基准测试以及业务真实压力测试都验证了hugetext性能效果。对于数据库类业务(例如 MySQL),x86物理机/虚拟机上hugetext提升性能2\~4%,ARM物理机/虚拟机上hugetext提升性能6\~10%;
+
+
+本文档主要用于展示**透明代码大页**使用、mysql相关测试数据,平台涉及x86和arm物理机。最后将代码大页、THP以及4k在mysql上进行性能对比。
+
+作者:王荣巍(雨庭) 徐宇(弃余) 邓刚(据德)
+
+# hugetext使用
+
+## 使用开关
+
+- 启动参数
+
+打开:hugetext=1 or 2 or 3
+关闭:缺省即为关闭
+
+
+
+- sysfs接口
+
+仅打开二进制和动态库大页:echo 1 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+仅打开可执行匿名大页:echo 2 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+打开以上两类大页:echo 3 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+关闭:echo 0 > /sys/kernel/mm/transparent\_hugepage/hugetext\_enabled
+
+
+## 回退
+在打开hugetext\_enabled后,若关闭hugetext\_enabled并且完全消除hugetext\_enabled影响,可以下面几种方式:
+
+- 清理整个系统的page cache:echo 3 > /proc/sys/vm/drop\_caches
+- 清理单个文件的page cache:vmtouch -e /\/target
+
+
+
+## 注意事项
+打开、关闭并不意味着立即合并、拆散大页,hugetext是异步的。
+如果一段代码曾经被整理成大页,即使关闭hugetext功能,还是会大页映射。
+
+
+在测试性能时,为了消除这些影响,可以通过 `echo 3 > /proc/sys/vm/drop\_caches` 来回收整理的大页,以保证下次是普通页映射。
+
+
+想确认代码段是否大页映射,可以通过 `grep FilePmdMapped /proc/$(pidof mysqld)/smaps` 来确认。
+
+# mysql测试准备
+
+创建用户以及修改密码:
+```c
+mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '123';
+```
+
+
+创建数据库:
+```
+CREATE DATABASE hugepages;
+show databases;
+```
+所创建的数据库hugepages需要与下面的步骤保持一直。
+
+
+开始为创建的数据库准备数据,执行以下命令(**进行该步骤前需要安装sysbench**):
+```
+sysbench --test=/usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --oltp-tables-count=200 --oltp-table-size=100000 --report-interval=2 prepare
+```
+其中,prepare表示准备数据,在的sbtest库生成测试数据,
+创建200张表,每张表10万条数据,每2秒显示一次报告。
+
+# 代码大页 - mysql数据库测试
+
+下面是代码大页的测试数据。
+
+## arm平台mysql性能测试
+
+测试说明:
+测试过程中需要对mysqld进行**绑核**,并显示指定内存分配节点为local node。
+
+
+测试命令:
+sysbench /usr/local/share/sysbench/tests/include/oltp\_legacy/oltp.lua --mysql-db=hugepages --mysql-host=localhost --mysql-port=3306 --mysql-user=root --mysql-password=123 --oltp-test-mode=complex --time=300 --threads=1 --report-interval=5 run
+
+
+
+测试过程中,mysql并发数分别是1、8(25%)、16(50%)、32(100%)。测试结果与普通的4K代码页数据对比如下:
+
+
+
+**图1:arm平台mysql TPS测试数据对比**
+
+
+上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有:
+
+- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%;
+- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上;
+- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右;
+
+另外,还有RT的对比,如下图:
+
+
+
+**图2:arm平台mysql RT数据对比**
+
+
+RT的数据主要是前95%的请求的最大响应时间(**95th percentile**)。代码大页在RT上的表现与图1一致,大约提升在5.7%~11.4%之间。
+
+## x86平台mysql性能测试
+
+测试方法以及测试数据与arm平台一致。
+
+该测试主要在Intel(R) Xeon(R) Platinum 8163平台下完成。
+
+TPS、RT对比图如下:
+
+
+
+**图3(a、b)为TPS、RT对比图**
+
+
+由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。
+
+
+除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。
+
+
+
+**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据**
+
+
+上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%;
+
+## 微架构测试数据
+
+除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。
+x86和arm平台的数据如下:
+
+
+x86平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图5 x86平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- 从iTLB miss的数据看,代码大页相比4k代码页大约下降了1.5-2.3倍左右;
+- 从iTLB MPKI的数据看,代码大页相比4k代码页大约下降了1.6-2.3倍之间,与iTLB miss效果相似;
+
+测试iTLB MPKI使用的工具可以从下面的链接获取:
+https://github.com/intel/iodlr
+
+arm平台下的iTLB miss和iTLB MPKI数据:
+
+
+
+**图6 arm平台使用代码大页前后iTLB miss和iTLB MPKI数据对比图**
+
+
+上图数据显示:
+
+- mysql使用代码大页后,iTLB miss大约下降了10倍左右,数值大小从原来的1%下降到0.08%左右;
+- 在iTLB MPKI上,大约下降了6倍左右;
+
+**此外,可以看出在使用代码大页后,性能提升存在平台差异。图6和图7的iTLB miss差异主要是x86和arm的TLB entry差异。**
+
+## 代码大页 vs THP和4k
+
+这里将代码大页和目前比较熟知的THP进行对比,对比中将4k测试数据作为baseline。
+
+对比数据主要包括mysql单线程、4线程和8线程测试。数据如下:
+
+**图7 arm虚拟机中代码大页、THP和4k baseline数据对比**
+
+
+在图7中最后一列为性能与4k base相比提升的百分比,如代码大页和THP在单线程测试中,相比4k页,性能提升分别是12.7%和4.47%(本数据为虚拟机下测试数据,数值大小不能代表物理机下测试数据)。
+
+
+根据图7,可以大致得出以下结论:
+**代码大页的性能以及稳定性远优于anon THP;其性能存在以下规律:**
+**收益:代码大页 > anon THP > 4k**
+
+# 代码大页 - 达梦数据库测试
+
+达梦数据库安装测试文档:https://openanolis.cn/sig/third\_software\_compatibility/doc/390232652013568029
+
+下图为在x86 skylake平台上,关闭THP,分别设置hugetext=0,1或者2对达梦数据库进行测试:
+
+
+**图8 代码大页+达梦数据库性能测试对比**
+
+
+根据图中的数据,大致可以得出以下结论:
+
+(1)在x86 skylake平台上,当磁盘I/O利用率峰值在94%左右时,hugetext对于达梦数据库的提升大约在3.86%左右(如图最后一行数据显示);
+
+(2)当磁盘I/O成为瓶颈,利用率100%,代码大页无法提升性能;
+
+
+
+
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\351\276\231\350\234\245\345\206\205\346\240\270\347\232\204_Load_Averages_\345\211\226\346\236\220(\344\270\212).md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\351\276\231\350\234\245\345\206\205\346\240\270\347\232\204_Load_Averages_\345\211\226\346\236\220(\344\270\212).md"
new file mode 100644
index 0000000000000000000000000000000000000000..68caa548fbe3da879182beb14461ad4b49d4953e
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\351\276\231\350\234\245\345\206\205\346\240\270\347\232\204_Load_Averages_\345\211\226\346\236\220(\344\270\212).md"
@@ -0,0 +1,4 @@
+/img1.jpeg)
+
+点击[这里](https://www.bilibili.com/video/BV1R34y197Lw/)参看.
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\351\276\231\350\234\245\345\206\205\346\240\270\347\232\204_Load_Averages_\345\211\226\346\236\220(\344\270\213).md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\351\276\231\350\234\245\345\206\205\346\240\270\347\232\204_Load_Averages_\345\211\226\346\236\220(\344\270\213).md"
new file mode 100644
index 0000000000000000000000000000000000000000..e68954407328329fce3f3769179cae89ffbd8b1f
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\206\205\346\240\270\346\212\200\346\234\257\345\210\206\344\272\253/\351\276\231\350\234\245\345\206\205\346\240\270\347\232\204_Load_Averages_\345\211\226\346\236\220(\344\270\213).md"
@@ -0,0 +1,4 @@
+/img1.jpeg)
+
+视频回放正在准备中, 敬请期待...
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2021.11.01~2021.11.14.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2021.11.01~2021.11.14.md"
new file mode 100644
index 0000000000000000000000000000000000000000..8836ff2b507693190017a459eb94c992dad7b341
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2021.11.01~2021.11.14.md"
@@ -0,0 +1,81 @@
+### 会议主题
+
+
+首次非正式会议, 自由讨论的形式, 聊聊龙蜥内核版本计划, 研发流程及后续双周会主题等
+
+
+### 会议时间
+
+
+2021.11.03 15:00-17:00
+
+
+### 与会人
+
+
+* 会议主持: Shiloong
+* 来自统信,龙芯, 阿里云的龙蜥社区爱好者
+
+
+### 会议纪要
+
+
+* 会议由 Shioong 发起主持, 开场简单介绍了龙蜥 ANCK 版本情况及当前基本研发流程.
+
+
+* 自由讨论中, 谢仲天提出如何尽快参与到内核社区共建的问题. 讨论认为,
+
+
+* + 1) 主动参与: 可通过向社区贡献开源特性参与社区内核研发; 可通过积极关注 kernel-sig bug 管理平台, 积极承担特性/bug 研发任务来参与;
+ + 2) 被动参考: 确定统一接口人, 由社区统一分派研发任务.
+
+
+* + 总之社区是极其开放的, 欢迎大家积极参与其中.
+
+
+* 卢彦表示关注内核性能测试相关 benchmark 评价与测试验收标准
+
+
+* + 阿里云在这一块有多年积累, 一些成熟经验计划在社区推广;
+ + 这块建议放到社区相应的 [QA Sig](https://openanolis.cn/sig/QA) 进一步深入交流.
+
+
+* 李雪峰介绍了龙芯内核同源异构相关进展:
+
+
+* + 表示龙芯内部已经有相关计划;
+ + 因这块工作量较大, 涉及内核及工具链; 且与架构相关的bug 一般难度较大.
+ + 龙芯内部还需要进一步讨论, 以确定排期等相关事项.
+
+
+* + 会上讨论认为这块可以在龙芯 sig 里进一步对齐.
+ + 当前ANCK 已经推出5.10内核, 希望能在这个内核尽快做起来.
+
+
+* 最后大家讨论了 kernel-sig 双周会的相关问题:
+
+
+* + 目前暂定双周会固定时间为第一周周三下午3:00-5:00; 下一次双周会时间 2021.11.17 15:00-17:00;
+ + 疫情期间以线上会议为主, 待国家放开后考虑线下会议;
+
+
+* + 会上头脑风暴了双周会话题:
+
+
+* + - 双周会会有一些例行事项: 1) kernel-sig 双周大事回顾; 2) kernel-sig 相关事项决策等等;
+ - 客户现场案例分享相关: 如在真实客户现场遇到的问题, 解决方案, 经验等分享交流;
+
+
+* + - 内核子系统相关: 如内核子系统相关新特性技术分享, 实例业务应用案例等;
+ - 内核相关业界软硬技术热点研讨: 如 eBPF 应用等等;
+
+
+* + - 客户解决方案相关话题: 如1)客户具体案例分享; 2) 应用软件生态适配相关话题;
+ - ANCK 内核历史经典问题,案例分享;
+
+
+* + - 软硬件协同, 跨平台支持技术等;
+ - 内核相关系列技术讲座;
+
+
+* + - 会上大家提议后面可以发起 ACK (Anolis Cloud Kernel 开发者大会); 待国内疫情放开后, 可以考虑先搞起线下 meetup.
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2021.11.15~2021.11.28.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2021.11.15~2021.11.28.md"
new file mode 100644
index 0000000000000000000000000000000000000000..c7c29a7bfe95059ba72fcf5fcd937c03c820ac6c
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2021.11.15~2021.11.28.md"
@@ -0,0 +1,52 @@
+## 会议主题
+
+
+技术分享:<龙蜥内核 load average 剖析(上)>及龙蜥内核自由讨论
+
+
+## 会议时间
+
+
+2021.11.17 15:00-17:00
+
+
+## 与会人
+
+
+会议主持: Shiloong
+
+
+技术分享人: xunlei
+
+
+参与人: 龙蜥社区
+
+
+## 会议纪要
+
+
+* 会议前1小时庞训磊带来了精彩的技术分享<龙蜥内核 load averages 剖析> 上半部分直播;
+
+
++ 感兴趣的社区爱好者可以到[这里](https://openanolis.cn/video/440158297192218780)(https://openanolis.cn/video/440158297192218780)观看回放.
+
+
+* 直播结束后, 大家就分享的内容及龙蜥内核相关话题自由讨论; 大家对这次技术分享反馈相当不错, 并积极互动讨论.
+
+
++ 社区爱好者陈国斌(音)提出希望技术分享能增加一些实操性的演示; 这部分会在下次分享中安排;
++ 社区爱好者耕深提到是否能搞几次虚拟化相关的技术分享; 这部分后续可以与龙蜥社区的"虚拟化 SIG"组合作推出. 也欢迎大家积极参加龙蜥社区共建中来;
+
+
++ 有社区爱好者提到对调度器及其优化感兴趣, 希望能安排分享龙蜥内核在调度器相关的优化; 这个后面会考虑安排;
++ 有社区爱好者对 eBPF 技术落地龙蜥内核感兴趣, 希望能有相关分享; 龙蜥内核在 eBPF 邻域是有一些创新与积累的, 后面计划安排;
+
+
+* 自由讨论时, 统信参与龙蜥 kernel-sig 研发的同学反馈目前的 Bug Tracker 状态更新不及时, 造成有些信息不对称.
+
+
++ 这个情况基本属实, 目前正在改进中, 后续会把 kernel-sig 相关的 bug 管理迁移至新的平台. 届时也会加强 bug 管理.
+
+
+感谢庞训磊为大家带来精彩讲解, 也感谢芹菜,邢秀帮忙筹划本次技术分享!
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2021.11.29~2021.12.12.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2021.11.29~2021.12.12.md"
new file mode 100644
index 0000000000000000000000000000000000000000..cc693bec33f50f25d178039e043baf9dabbf3c13
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2021.11.29~2021.12.12.md"
@@ -0,0 +1,21 @@
+## 会议主题
+技术分享:及龙蜥内核动态更新
+
+## 会议时间
+2021.12.1 15:00-17:00
+
+## 与会人
+会议主持: Shiloong
+技术分享人: Xunlei
+参与人: 龙蜥社区
+
+## 会议纪要
++ 前半段直播技术分享, 感谢庞训磊为大家带来精彩讲解, 感兴趣或错过的, 可以到观看[回放](https://www.bilibili.com/video/BV1R34y197Lw/).
++ 会议传达了龙蜥内核 cloud-kernel 基础设施迁移的最新情况:
+ + 代码托管平台已经迁移至Gitee: https://gitee.com/anolis/cloud-kernel;
+ + 缺陷与需求管理平台已经迁移到 Bugzilla: https://bugzilla.openanolis.cn;
+ + 相关的开发流程也已经更新;
++ 会议传达了最新龙蜥内核版本发布情况:
+ + ANCK-4.19 内核发布最新版本4.19.91-25, 已经同步到 yum 源支持更新安装;
+ + ANCK-5.10 内核最新版本研发中, 预计2022.1.17发布.
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2021.12.13~2021.12.26.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2021.12.13~2021.12.26.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e1ef7d82d40c50f34644b9c91acf1c1f25539500
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2021.12.13~2021.12.26.md"
@@ -0,0 +1,16 @@
+## 会议主题
++ 龙蜥内核新研发流程讲解
++ 龙蜥内核 kernel-sig 自由讨论
+## 会议时间
+2021.12.15 15:00-17:00
+## 与会人
++ 会议主持: Shiloong
++ 参与人: 龙蜥社区kernel-SIG
+## 会议记要
+1. 龙蜥内核新研发流程讲解.
+2. 龙蜥社区 kernel-sig 补丁规范答疑: 对首次通过龙蜥社区公开的补丁, 需要加上 anolis 标签, 以龙蜥自研补丁发布;
+3. 龙蜥内核社区公开征召技术分享, 以增加社区技术分享活跃度;
+4. 前期推广以技术分享为主, 后面增加技术 workshop, 技术讨论等形式, 丰富 kernel-sig 的技术研讨及新技术孵化.
+5. 鼓励更多内核相关的理事单位参加双周会.
+6. kernel-sig 技术分享主题征集.
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.01.10~2022.01.23.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.01.10~2022.01.23.md"
new file mode 100644
index 0000000000000000000000000000000000000000..3e4c0e6b49e9f47a71447d482a8a0baaf12fbb3d
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.01.10~2022.01.23.md"
@@ -0,0 +1,16 @@
+本期双周会为技术分享
+
+## 分享主题
+系统性能监控工具ssar使用介绍和案例分享
+
+## 直播内容
+ssar整机指标功能使用介绍,ssar进程级指标使用介绍,ssar的load特色指标使用介绍。ssar解决单机生产问题案例剖析。[直播回放](https://www.bilibili.com/video/BV19S4y157Xa?spm\_id\_from=333.999.0.0)
+## 听众收益
+了解ssar的基本功能和使用,初步学习用ssar解决单机OS问题的诊断。
+## 适合人群
+系统运维工程师、linux系统编程工程师、内核爱好者。
+## 讲师头衔
+闻茂泉(广成)龙蜥社区跟踪诊断SIG核心成员,阿里云运维专家。
+## 讲师介绍
+负责阿里云计算平台事业部的基础运维相关工作,目前是龙蜥社区ssar和iodump开源诊断工具的maintainer。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.03.07~2022.03.20.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.03.07~2022.03.20.md"
new file mode 100644
index 0000000000000000000000000000000000000000..534454b3eb62499e70db0418097ff860f30d6344
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.03.07~2022.03.20.md"
@@ -0,0 +1,4 @@
+本期技术分享《datop -- 轻量级靶向内存热点扫描工具介绍与入门》
+
+欢迎到 OpenAnolis Kernel SIG 钉群收看直播回放。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.03.21~2022.04.03.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.03.21~2022.04.03.md"
new file mode 100644
index 0000000000000000000000000000000000000000..976065ee9a2c3643867e712bb7b830f724c5dc46
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.03.21~2022.04.03.md"
@@ -0,0 +1,7 @@
+本期技术分享
+1. 《通过sealer实现整个集群Build&Share&Run》
+
+2. 《硬件兼容性 SIG 分享》
+
+欢迎到 OpenAnolis Kernel SIG 钉群收看直播回放。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.04.04~2022.04.17.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.04.04~2022.04.17.md"
new file mode 100644
index 0000000000000000000000000000000000000000..b7d2cce980ecfc4378940c4469cd2e24d7866014
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.04.04~2022.04.17.md"
@@ -0,0 +1,4 @@
+本期技术分享《内核内存被改和内存泄漏难题的线上解决方案》
+
+欢迎到 OpenAnolis Kernel SIG 钉群收看直播回放。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.04.18~2022.05.01.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.04.18~2022.05.01.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.07.20~2022.08.03.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.07.20~2022.08.03.md"
new file mode 100644
index 0000000000000000000000000000000000000000..b07d6e40219c62e1766ac42a351f41f0651a458d
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.07.20~2022.08.03.md"
@@ -0,0 +1,4 @@
+与会人: 卢彦 道引 落盘 子札
+
+主题:讨论了ANCK-5.10对ARMv9的支持情况,以及ANCK-5.10的分支管理和版本发布计划。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.08.04~2022.08.24.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.08.04~2022.08.24.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e4cd765f488d13c958d7efc53af68663d1da7ab4
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.08.04~2022.08.24.md"
@@ -0,0 +1,4 @@
+与会人:卢彦 王晓华 道引 落盘 行信 王帅
+
+主题:分享了ARMv9 MPAM的龙蜥内核方案,基于/sys/fs/resctrl/实现的LLC和MB的隔离方案,并做了实际案例分享和效果演示。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.08.25~2022.09.07.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.08.25~2022.09.07.md"
new file mode 100644
index 0000000000000000000000000000000000000000..fc4abb36858a52fae2da85021d9ff7db045af4ba
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.08.25~2022.09.07.md"
@@ -0,0 +1,18 @@
+与会人:卢彦 王晓华 道引 落盘 要麻 半叶
+
+主题:
+
+1)要麻分享了ARM64 RAS的龙蜥内核方案,并做了实际案例分享和测试用例建议。
+ - RAS错误处理流程
+
+ UE non fatal类型错误是不可纠正但可恢复的错误,例如出现错误的内存存储的非内核使用的数据结构,后续不再使用对应内存即可,或者是非关键数据在cache中,将对应cache内容丢弃即可,都不会也不必要导致crash。
+ - RAS错误注入流程
+ https://gitee.com/anolis/ras-tools 可用于错误注入的工具
+ - Rasdaemon工具解读日志方法
+
+2)半叶对OS Noise背景噪声检测机制及检测工具进行介绍
+ - ANCK 5.10 支持该功能,在进行benchmark跑分时可以先提前检测包括中断、软中断、NMI、硬件自身 干扰、其他任务干扰等噪声,避免噪声对benchmark跑分结果的准确性造成干扰
+ - OS Noise的trace机制在正常的生产环境中部署会有一定开销,可以使用用户态的检测工具(无法统 计硬件噪声),该工具开销低,可用于生产部署。同时,使用该工具对调度指标进行监控可分析
+ benchmark运行行为,排查干扰运行的因素。
+ - 硬件噪声主要包括会陷入BIOS的硬件中断,在新机型验证方面比较有用。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.09.08~2022.09.21.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.09.08~2022.09.21.md"
new file mode 100644
index 0000000000000000000000000000000000000000..2c04b50983c970d96b7dab2533807ce4b46d5a56
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.09.08~2022.09.21.md"
@@ -0,0 +1,12 @@
+与会人:卢彦 、焦芬芳、王毅博、苟浩、道引、行信、半叶、谷米、落盘
+
+主题:
+- datop工具介绍
+ - ANCK 5.10 已支持该功能,分析内存冷热和跨numa访问,工具开销低,可常态化部署
+ - 工具地址 https://gitee.com/anolis/data-profile-tools
+ - 跨numa访问统计准确性
+ 工具通过仿真统计跨numa访问,存在一定的定量误差,但是不存在定性误差
+- ancert-m工具介绍和演示
+- APP Noise用户态工具演示
+- 介绍了kdump可调可测能力的研发。
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.09.22~2022.10.12.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.09.22~2022.10.12.md"
new file mode 100644
index 0000000000000000000000000000000000000000..648b6616934ffefaaa46b60836267aea0d2efec0
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.09.22~2022.10.12.md"
@@ -0,0 +1,11 @@
+# 与会人
+卢彦、焦芬芳、咸正、彧斌、云里、道引、落盘
+
+
+# 主题
+ARM64 PMU相关内容介绍,对ARM64 PMU进行了讲解,PMU从机制都进行了覆盖,并就perf使用问题,以及发生任务迁移时的场景进行了互动交流。
+- PMU的基本原理
+- ARM64 SPE 功能介绍
+- perf相关功能介绍
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.10.13~2022.10.26.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.10.13~2022.10.26.md"
new file mode 100644
index 0000000000000000000000000000000000000000..8f5f78b1a082d09c2c065216b929156cef3e05b6
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\344\274\232/2022.10.13~2022.10.26.md"
@@ -0,0 +1,9 @@
+# 与会人
+卢彦、焦芬芳、苟浩、道引、落盘
+
+
+# 主题
+- 交流了ARM baseos部分需要关注的包。
+- ras-tools是基于APEI的通用工具,服务器需要更新配套的BIOS版本才能使用。
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\346\212\245/2021.10.18~2021.10.31.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\346\212\245/2021.10.18~2021.10.31.md"
new file mode 100644
index 0000000000000000000000000000000000000000..ff1cb9a0546b95d630b6512bab635c0b33774ed2
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\346\212\245/2021.10.18~2021.10.31.md"
@@ -0,0 +1,27 @@
+
+**内核研发**
+
+
+* ANCK-4.19 CK25 代码本周(11.30)冻结, 新特性需求研发代码基本完成合入, 主要特性:
+
+
++ 支持商密特性更新及 bugfix;
++ 支持代码段大页优化;
+
+
++ 支持 SM2/SM3加密算法组合签名;
++ fs/buffer 性能优化;
+
+
++ 支持内核 SM4算法的 AVX/AVX2指令集优化;
+
+
+* ANCK-5.10 下一个版本开发中, 预计11.30代码冻结, 12.30日发布;
+
+
+**SIG运作**
+
+
+* 讨论决定下周三(暂定11.3下午3:00-5:00)召开第一次 kernel-sig 双周会, 主题暂定为;
+
+
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\346\212\245/2021.11.01~2021.11.14.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\346\212\245/2021.11.01~2021.11.14.md"
new file mode 100644
index 0000000000000000000000000000000000000000..b024c157bcbd7852404b4388babf1113afa979ae
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\346\212\245/2021.11.01~2021.11.14.md"
@@ -0,0 +1,14 @@
+**内核研发**
+
+
+* ANCK-4.19 下一个版本 4.19.91-25 rc1 已经开始发布测试;
+
+
+* ANCK-5.10 下一个版本开发路线图有调整, 代码冻结时间调整为2021.12.10, 发布日期调整为 2022.1.17;
+
+
+**SIG运作**
+
+
+* 顺利招开了龙蜥社区 kernel-SIG 第一期双周会, 统信, 龙芯及阿里云社区爱好者在一起自由畅谈龙蜥内核发展, 头脑风暴了内核相关的技术话题, 为后续双周会技术分享做准备.
+ + 详细周会纪要请参看[这里](https://openanolis.cn/sig/Cloud-Kernel/doc/426213132286165112).
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\346\212\245/2021.11.15~2021.11.28.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\346\212\245/2021.11.15~2021.11.28.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\346\212\245/2021.11.29~2021.12.12.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\346\212\245/2021.11.29~2021.12.12.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\346\212\245/2021.12.13~2021.12.26.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\346\212\245/2021.12.13~2021.12.26.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\346\212\245/2021.12.27~2022.1.9.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\346\212\245/2021.12.27~2022.1.9.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\346\212\245/2022.1.10~2022.1.23.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\346\212\245/2022.1.10~2022.1.23.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\346\212\245/2022.1.24~2022.2.6.md" "b/sig/Anolis\350\277\201\347\247\273SIG03/content/\345\217\214\345\221\250\346\212\245/2022.1.24~2022.2.6.md"
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG03/sig-info.yaml" "b/sig/Anolis\350\277\201\347\247\273SIG03/sig-info.yaml"
new file mode 100644
index 0000000000000000000000000000000000000000..cfb62f6c4020e1f2b25d084ccb218e6f55c9f7c3
--- /dev/null
+++ "b/sig/Anolis\350\277\201\347\247\273SIG03/sig-info.yaml"
@@ -0,0 +1,35 @@
+name: Anolis迁移SIG03
+en_name: Anolis迁移SIG03
+home_page: https://openanolis.cn/sig/migration03
+description: OpenAnolis作为一个新的OS开源社区,为了用户能够更好的使用Anolis OS,需要提供从别的OS迁移到Anolis OS的迁移指导和迁移工具,降低用户的迁移成本。
+en_description: As a new OS open source community, Anolis OS needs to provide migration guidance and migration tools for migrating from other OS to Anolis OS i
+mailing_list: os@lists.openanolis.cn
+meeting_url: https://openanolis.cn
+maintainers:
+- openanolis_id: ceshi002
+ gitee_id:
+ name:
+ organization:
+ email:
+- openanolis_id: ceshi001
+ gitee_id:
+ name:
+- openanolis_id: ceshi004
+ gitee_id:
+ name:
+- openanolis_id: abc123
+ gitee_id:
+ name:
+contributors:
+repositories:
+- repo:
+ - anolis/testfarm
+ - anolis/testfarm-front
+ - anolis/tone-web
+ - anolis/tone-runner
+ - anolis/tone-agent
+ - anolis/tone-agent-proxy
+ - anolis/tone-agent-front
+ - anolis/community
+ - anolis-challenge/activity-docs-test
+ - anolis-challenge/activity-common-task
\ No newline at end of file
diff --git a/sig/CXL/README.md b/sig/CXL/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..7ad9e2ae87b8a2383d62de3ad219011cbf0fe3c4
--- /dev/null
+++ b/sig/CXL/README.md
@@ -0,0 +1,32 @@
+## SIG主页
+
+https://openanolis.cn/sig/cxl
+
+## SIG目标
+CXL (Compute Express Link) 技术是一种新型的高速互联技术,旨在提供更高的数据吞吐量和更低的延迟,以满足现代计算系统对于内存的需求。CXL SIG会以intel平台结合Agilex CXL为基点并逐渐支持其他架构和平台,通过提供支持CXL的内存管理系统以助力用户对于CXL的直接使用。如图所示,通过CXL SIG,以当前的CXL-SHM和CXL-SDK开源项目为中心,底层以海光/浪潮/Intel等设备生产厂家为底座,结合龙蜥现有生态环境,从多角度出发强化生态领域,多层次满足社区开发者广泛的业务场景需要。1
+
+## SIG组技术方向
+基于目前的CXL硬件(Intel Agilex FPGA或者澜起/三星CXL)进行开发,从以下几个方面对CXL进行支持:
+1. Anolis OS中CXL1.1/2.0相关驱动,以及对于CXL不同类型硬件的支持。
+2. 面向CXL共享内存的内存管理系统,这里我们主要从用户态分布式内存管理的角度,为用户提供一套语义一致的分布式管理机制和语义。
+3. 面向CXL不同类型内存的SDK,支持对异构内存进行管理,支持PMEM等内存。
+
+## 成员列表
+| 成员 | 角色 |
+| ------------ | ------------ |
+| [stmatengss](https://gitee.com/stmatengss) | maintainer |
+
+## SIG仓库
+
+Source code repositories:
+- https://gitee.com/anolis/cxl-shm
+
+
+## 小组例会
+月会,采用线上会议形式
+
+## 钉钉群
+
+欢迎使用钉钉扫码入群
+
+
diff --git a/sig/CXL/sig-info.yaml b/sig/CXL/sig-info.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..d7d39cb8b8b6e1f612a59bd6080ef21a12af7ccc
--- /dev/null
+++ b/sig/CXL/sig-info.yaml
@@ -0,0 +1,18 @@
+name: CXL
+en_name: CXL
+home_page: https://openanolis.cn/sig/cxl
+description: CXL (Compute Express Link) 技术是一种新型的高速互联技术,旨在提供更高的数据吞吐量和更低的延迟,以满足现代计算系统对于内存的需求。
+en_description: Leveraging CXL-SHM, we have established the CXL Special Interest Group (SIG) within the Anolis Community.
+
+maintainers:
+- openanolis_id: stmatengss
+ gitee_id: stmatengss
+
+
+contributors:
+- openanolis_id: stmatengss
+ gitee_id: stmatengss
+
+repositories:
+- repo:
+ - anolis/cxl-shm
diff --git "a/sig/Cloud Kernel/content/Cloud Kernel \344\272\247\345\223\201\347\256\200\344\273\213.md" "b/sig/Cloud Kernel/content/Cloud Kernel \344\272\247\345\223\201\347\256\200\344\273\213.md"
index 207ae878e14f14bb645757a110344e569f3d914b..3ea08e7b1cba094d16bf28005babf0691c09a454 100644
--- "a/sig/Cloud Kernel/content/Cloud Kernel \344\272\247\345\223\201\347\256\200\344\273\213.md"
+++ "b/sig/Cloud Kernel/content/Cloud Kernel \344\272\247\345\223\201\347\256\200\344\273\213.md"
@@ -33,3 +33,7 @@
您有任何有关龙蜥操作系统内核的问题, 缺陷, 特性, 需求等, 都欢迎您报告给我们。您可以按照以下教程报告一个问题.
[https://openanolis.cn/sig/Cloud-Kernel/doc/607601736106142822](https://openanolis.cn/sig/Cloud-Kernel/doc/607601736106142822)
+
+
+
+sssssssssssssssssssssssssss
\ No newline at end of file
diff --git "a/sig/Cloud Kernel/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227\347\233\256\345\275\225.md" "b/sig/Cloud Kernel/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227\347\233\256\345\275\225.md"
new file mode 100644
index 0000000000000000000000000000000000000000..fa1839816559ebe8b3d4dcd5ad0e3bc3525f54e2
--- /dev/null
+++ "b/sig/Cloud Kernel/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227\347\233\256\345\275\225.md"
@@ -0,0 +1,30 @@
+
+### [【1】Anolis OS环境搭建教程](https://openanolis.cn/sig/Cloud-Kernel/doc/721476209221304399)
+
+### [【2】订阅Cloud Kernel邮件列表](https://openanolis.cn/sig/Cloud-Kernel/doc/721476296169226335)
+
+### [【3-1】内核编译安装 - Make方式](https://openanolis.cn/sig/Cloud-Kernel/doc/721476224463405137)
+
+### [【3-2】内核编译安装 - RPM包方式](https://openanolis.cn/sig/Cloud-Kernel/doc/721476230897467475)
+
+### [【3-3】内核编译安装 - intree模块编译](https://openanolis.cn/sig/Cloud-Kernel/doc/796036400039221309)
+
+### [【4-0】Cloud Kernel开发基本流程](https://openanolis.cn/sig/Cloud-Kernel/doc/721476280021155931)
+
+### [【4-1】向Cloud Kernel报告BUG](https://openanolis.cn/sig/Cloud-Kernel/doc/721476248891031637)
+
+### [【4-2】Cloud Kernel补丁规范](https://openanolis.cn/sig/Cloud-Kernel/doc/721476251004960855)
+
+### [【4-3】PR(Pull Request)规范](https://openanolis.cn/sig/Cloud-Kernel/doc/721476253496377433)
+
+### [【4-4】Cloud Kernel 研发规约(必读)](https://openanolis.cn/sig/Cloud-Kernel/doc/860616877348361648)
+
+### [【5】向Cloud Kernel报告CVE](https://openanolis.cn/sig/Cloud-Kernel/doc/721476285859627101)
+
+### [【6】Cloud Kernel仓库代码管理](https://openanolis.cn/sig/Cloud-Kernel/doc/721476298165715041)
+
+### [【7】从Cloud Kernel cherry-pick补丁的要求](https://openanolis.cn/sig/Cloud-Kernel/doc/831592015795327880)
+
+
+swwsww333
+ssssss
\ No newline at end of file
diff --git "a/sig/Cloud Kernel/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\351\276\231\350\234\245 ANCK 5.10 \345\200\232\345\244\251\345\271\263\345\217\260 MPAM \346\265\213\350\257\225\346\212\245\345\221\212.md" "b/sig/Cloud Kernel/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\351\276\231\350\234\245 ANCK 5.10 \345\200\232\345\244\251\345\271\263\345\217\260 MPAM \346\265\213\350\257\225\346\212\245\345\221\212.md"
index b3230c28ce258110ce76f3dd8cbfa7c1c036a7e2..d6a6aadf61d207615311318a8344f13efe94e4d0 100644
--- "a/sig/Cloud Kernel/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\351\276\231\350\234\245 ANCK 5.10 \345\200\232\345\244\251\345\271\263\345\217\260 MPAM \346\265\213\350\257\225\346\212\245\345\221\212.md"
+++ "b/sig/Cloud Kernel/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/\351\276\231\350\234\245 ANCK 5.10 \345\200\232\345\244\251\345\271\263\345\217\260 MPAM \346\265\213\350\257\225\346\212\245\345\221\212.md"
@@ -998,4 +998,22 @@ RIS>1时无法写入
-Reserved
\ No newline at end of file
+Reserved
+
+---------------------------------------------------------------------
+
+
+333333333333333333333333333333
+
+
+T-One 系统的相关材料:
+
+部署手册(SIG):https://openanolis.cn/sig/t-one/doc/477143281756406096
+
+社区版系统链接:https://tone.openanolis.cn/
+
+T-One 帮助文档:https://tone.openanolis.cn/help_doc/2
+
+
+
+BIANJI
\ No newline at end of file
diff --git a/sig/Cloud Kernel/sig-info.yaml b/sig/Cloud Kernel/sig-info.yaml
index cb917ea79940d89b2558af6f8aefd4923e61ddaa..a407663008e23d413e5e5af3ab398a504e0531f7 100644
--- a/sig/Cloud Kernel/sig-info.yaml
+++ b/sig/Cloud Kernel/sig-info.yaml
@@ -11,9 +11,12 @@ maintainers:
name:
organization:
email:
-- openanolis_id:
- gitee_id:
- name:
+- openanolis_id: ceshi001
+ gitee_id: ceshi001
+ name: ceshi001
+- openanolis_id: hahahaha
+ gitee_id: yutting123
+ name: yutt
- openanolis_id:
gitee_id:
name:
diff --git a/sig/CodeOneOne/sig-info.yaml b/sig/CodeOneOne/sig-info.yaml
deleted file mode 100644
index aa78014cad9c095f1416766fd4f888c2f867117e..0000000000000000000000000000000000000000
--- a/sig/CodeOneOne/sig-info.yaml
+++ /dev/null
@@ -1,14 +0,0 @@
-name: CodeOneOne
-en_name: CodeOneOne
-home_page: https://openanolis.cn/sig/CodeOneOne
-description: CodeOneOne description modify
-en_description: CodeOneOne english description modify
-mailing_list: CodeOneOne@lists.openanolis.cn
-meeting_url:
-maintainers:
-- openanolis_id: ceshi009
- gitee_id: coder-one-one
-contributors:
-repositories:
-- repo:
- - anolis/testfarm
\ No newline at end of file
diff --git a/sig/Intel Arch SIG02/README.en.md b/sig/CoderOneOne/README.en.md
similarity index 100%
rename from sig/Intel Arch SIG02/README.en.md
rename to sig/CoderOneOne/README.en.md
diff --git a/sig/CoderOneOne/README.md b/sig/CoderOneOne/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..1125ee24ccf0e8e6948e8559bf4088ae80dc4f8a
--- /dev/null
+++ b/sig/CoderOneOne/README.md
@@ -0,0 +1,2 @@
+#readme
+ readme
\ No newline at end of file
diff --git "a/sig/CoderOneOne/assets/assets/Anolis OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213.md" "b/sig/CoderOneOne/assets/assets/Anolis OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213.md"
new file mode 100644
index 0000000000000000000000000000000000000000..a9f7ecb382957f8fb98b0d231d69b48f1efed377
--- /dev/null
+++ "b/sig/CoderOneOne/assets/assets/Anolis OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213.md"
@@ -0,0 +1,268 @@
+# 写在前面
+
+Anolis OS 是 OpenAnolis 社区推出的完全开源、中立、开放的发行版,它支持多计算架构,也面向云端场景优化。
+
+在您使用Anolis OS之前,我们提供了一个预装Anolis OS的在线机器资源服务。我们**强烈建议**您访问[**龙蜥实验室**](https://lab.openanolis.cn/#/apply/home),使用Web页面及机器人等形式自动创建和管理机器资源,以此来对Anolis OS进行体验。
+
+您可以访问[龙蜥实验室使用指南](https://www.yuque.com/anolis-docs/community/peng85),来进行**一键申请**和 **免费试用** 。
+
+
+
+我们提供两种方式安装Anolis OS:
+
+* ISO镜像安装
+* qcow虚拟机镜像安装
+
+## 一、通过ISO进行安装
+
+### 1.1 ISO镜像下载
+
+登陆下载界面获取Anolis OS最新iso镜像文件
+
+[https://openanolis.cn/download](https://openanolis.cn/download)
+
+
+
+### 1.2 镜像安装
+
+参考该文档,通过图形化安装接口部署Anolis8/7至目标平台:
+
+[https://www.yuque.com/anolis-docs/manual/installation](https://www.yuque.com/anolis-docs/manual/installation)
+
+## 二、 通过qcow虚拟机镜像安装
+
+首先,验证CPU是否支持KVM;
+
+`egrep '(vmx|svm)' /proc/cpuinfo`
+
+如果结果中有vmx(Intel)或svm(AMD)字样,就说明CPU是支持的。
+
+如果您是买的ECS,或者已经开了虚拟机,那大概率没办法再通过KVM的方式进行安装。
+
+### 2.1 虚拟机镜像下载
+
+登陆下载界面获取Anolis OS最新qcow2镜像文件
+
+[https://openanolis.cn/download](https://openanolis.cn/download)
+
+这里以7.9为例:点击网址中的下载按钮后,选择相应架构的文件夹进入,既可以看到对应的下载列表,请选择**AnolisOS-7.9-GA-x86_64-ANCK.qcow2**文件进行下载。
+
+
+
+### 2.2 安装依赖包
+
+`sudo yum install -y qemu-kvm libvirt virt-install bridge-utils`
+
+### 2.3 启动前配置
+
+#### 2.3.1 libvirt服务
+
+开启libvirt服务
+
+`systemctl start libvirtd`
+
+设置开机启动
+
+`systemctl enable libvirtd`
+
+查看状态操作结果
+
+`systemctl status libvirtd`
+
+
+
+`systemctl is-enabled libvirtd`
+
+
+
+#### 2.3.2 打开虚拟化的网络支持
+
+`sudo virsh net-autostart default`
+
+`sudo virsh net-start default`
+
+`sudo sysctl -w net.ipv4.ip_forward=1` # 也可以写到配置文件里持久化
+
+**TIPS:**
+
+`sudo virsh net-autostart default` 执行过程中可能会卡住,此时将 `/etc/modprobe.d/blacklist.conf` 文件中的 "blacklist nf_conntrack_ipv4" 语句注释掉,例如
+
+```
+...
+#blacklist nf_conntrack_ipv4
+```
+
+之后再执行 `sudo virsh net-autostart default`
+
+#### 2.3.3 修改kvm权限
+
+直接设置成root启动
+
+```
+cat >> /etc/libvirt/qemu.conf << EOF
+user = "root"
+group = "root"
+EOF
+systemctl restart libvirtd.service
+```
+
+#### 2.3.4 建立链接
+
+查看qemu-kvm路径
+
+`whereis qemu-kvm`
+
+```
+qemu-kvm: /etc/qemu-kvm /usr/libexec/qemu-kvm /usr/share/qemu-kvm /usr/share/man/man1/qemu-kvm.1.gz
+```
+
+建立软连接
+
+`ln -s /usr/libexec/qemu-kvm /usr/bin/qemu-kvm`
+
+#### 2.3.5 创建xml配置文件
+
+示例文件的名称为anolis.xml,请根据提示修改您的镜像路径
+
+您可以按照注释自己酌情修改。
+
+```
+
+ anolis
+ 16777216
+ 8
+
+
+
+
+ hvm
+
+
+
+
+
+
+
+
+
+
+
+ destroy
+ restart
+ restart
+
+
+ /usr/bin/qemu-kvm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### 2.4 虚拟机的启动与管理
+
+#### 2.4.1 使用virsh命令启动虚拟机
+
+新机器执行virsh命令可能会有setlocale: No such file or directory的警告,可安装语言包
+
+`yum install -y glibc-langpack-zh`
+
+`sudo virsh define 虚拟机名.xml`
+
+`sudo virsh start 虚拟机名` # 请修改为KVM虚拟机的真实名称。
+
+vm 默认的账户和密码为:
+
+* 用户名:`anuser`
+* 密码:`anolisos`
+
+#### 2.4.2 切换root用户并允许ssh root登录
+
+1. `sudo su`
+2. 输入密码`anolisos`
+3. 修改root密码:`passwd root`
+4. 修改`/etc/ssh/sshd_config`:
+
+```
+PasswordAuthentication yes
+
+PermitRootLogin yes
+```
+
+#### 2.4.3 虚拟机的访问
+
+可以通过下列方式访问VM:
+
+* 通过 vnc 访问宿主机的 IP,登录VM,查看 IP
+* 通过 `sudo virsh console 虚拟机名` 登录 VM(请注意可能会有一段时间的黑屏,VM启动过程没有输出到屏幕),查看 IP
+* 获取到 Guest IP 之后,通过 `ssh root@` 登录 VM.
+
+#### 2.4.3 查询虚拟机在宿主机对应串口设备
+
+`virsh ttyconsole 虚拟机名`
+
+#### 2.4.4 其余virsh命令
+
+`virsh list` #显示本地活动虚拟机
+
+`virsh list –-all ` #显示本地所有的虚拟机(活动的+不活动的)
+
+`virsh define 虚拟机名.xml` #通过配置文件定义一个虚拟机(这个虚拟机还不是活动的)
+
+`virsh undefine 虚拟机名.xml` #删除虚拟机配置
+
+`virsh start 虚拟机名` #启动名字为ubuntu的非活动虚拟机
+
+`virsh create 虚拟机名.xml ` # 创建虚拟机(创建后,虚拟机立即执行,成为活动主机)
+
+`virsh suspend 虚拟机名` # 暂停虚拟机
+
+`virsh resume 虚拟机名 ` # 启动暂停的虚拟机
+
+`virsh shutdown 虚拟机名` # 正常关闭虚拟机
+
+`virsh destroy 虚拟机名` # 强制关闭虚拟机
+
+`virsh dominfo 虚拟机名` #显示虚拟机的基本信息
+
+`virsh domname 2` # 显示id号为2的虚拟机名
+
+`virsh domid 虚拟机名` # 显示虚拟机id号
+
+`virsh domuuid 虚拟机名` # 显示虚拟机的uuid
+
+`virsh domstate 虚拟机名` # 显示虚拟机的当前状态
+
+`virsh dumpxml 虚拟机名` # 显示虚拟机的当前配置文件(可能和定义虚拟机时的配置不同,因为当虚拟机启动时,需要给虚拟机分配id号、uuid、vnc端口号等等)
+
+`virsh setmem 虚拟机名 512000` #给不活动虚拟机设置内存大小
+
+`virsh setvcpus 虚拟机名 4` # 给不活动虚拟机设置cpu个数
+
+`virsh edit 虚拟机名` # 编辑配置文件(一般是在刚定义完虚拟机之后)
diff --git "a/sig/Anolis\350\277\201\347\247\273SIG/assets/dingding_group.jpeg" b/sig/CoderOneOne/assets/dingding_group.jpeg
similarity index 100%
rename from "sig/Anolis\350\277\201\347\247\273SIG/assets/dingding_group.jpeg"
rename to sig/CoderOneOne/assets/dingding_group.jpeg
diff --git "a/sig/CoderOneOne/content/Bugzilla\347\263\273\347\273\237/Bugzilla\347\224\250\346\210\267\346\226\207\346\241\243.md" "b/sig/CoderOneOne/content/Bugzilla\347\263\273\347\273\237/Bugzilla\347\224\250\346\210\267\346\226\207\346\241\243.md"
new file mode 100644
index 0000000000000000000000000000000000000000..65e2b7500efe889e7c95c74eef35ffdd0383ef4f
--- /dev/null
+++ "b/sig/CoderOneOne/content/Bugzilla\347\263\273\347\273\237/Bugzilla\347\224\250\346\210\267\346\226\207\346\241\243.md"
@@ -0,0 +1,7 @@
+### Bugzilla用户文档
+文档内容
+
+
+撒礼品券五六千【为了钱王拳王劳务派遣【
+
+我问问我
\ No newline at end of file
diff --git a/sig/CoderOneOne/content/RAS/Anolis OS Cloud Kernel RAS White Paper.md b/sig/CoderOneOne/content/RAS/Anolis OS Cloud Kernel RAS White Paper.md
new file mode 100644
index 0000000000000000000000000000000000000000..aff77f788cd9a721b818e696bcaadfd047222640
--- /dev/null
+++ b/sig/CoderOneOne/content/RAS/Anolis OS Cloud Kernel RAS White Paper.md
@@ -0,0 +1,982 @@
+# Anolis OS Cloud Kernel: RAS White Paper
+
+## REVISION HISTORY
+
+| DATE | VERSION | DESCRIPTION | AUTHOR | APPROVER |
+| ---------- | ------- | --------------- | ----------------------- | ----------- |
+| 2022/12/31 | 1.0 | Initial version | Shuai Xue, Ruidong Tian | Baolin Wang |
+
+## Terms and Abbreviations
+
+| Abbreviation | Definition |
+| ------------ | ----------------------------------------------------------------------------- |
+| RAS | Reliability, Availability and Serviceability |
+| SLA | Service Level Agreement |
+| CE | Correctable Error |
+| UCE | Uncorrected Correctable Error |
+| MCA | Machine-Check Architecture |
+| CMCI | Corrected Machine Check Interrupt |
+| MCE | Machine-Check Exception |
+| SEA | Synchronous External Abort |
+| ELx | Exception levels are referred to as EL, with x as a number between 0 and 3 |
+| ECC | Error Correction Code |
+| SECDED | Single-bit Error Correction and Double-bit Error Detection |
+| TF-A | Trusted Firmware-A |
+| HEST | Hardware Error Source Table |
+| GHES | Generic Hardware Error Source |
+
+## Abstract
+
+Reliability, availability and serviceability (RAS) is a computer hardware engineering term referring to the elimination of hardware failures to ensure maximum system uptime.
+
+This document describes the memory RAS features in detail, explaining how server availability is enhanced with the memory RAS features on Yitian 710 servers running Anolis OS Cloud Kernel.
+
+## Introduction
+
+The server is one of the key components of any modern data center infrastructure. It consists of a variety of hardware parts, including processors, storage devices, PCIe devices, power supplies, and fans.
+
+In today’s hyper scale Cloud Data centers, correct server operation and data integrity are critical to ensure service continuity. In other words, we must avoid data corruption no matter data is stored in any server component (memory, cache, or processor registers) or transmitted through any platform links (Intel®UPI, PCI Express, or DMI).
+
+Server reliability, availability, and serviceability (RAS) are crucial issues for modern enterprise IT shops that deliver mission-critical applications and services, as application delivery failures can be extremely costly per hour of system downtime. Although hardware failures are rare, they are inevitable but random events, especially for large scale data centers. If such incidents are not efficiently diagnosed, the consequences may be very serious and sometimes even catastrophic, such as data corruption or server crash. which are top concerns to meet SLAs (Service Level Agreement) for cloud end users. The likelihood of such failures increases statistically with the size of the servers, data, and memory required for these deployments. Furthermore, considering today’s server system with more and more CPU cores shipped on hundreds of Virtual Machines (VM) and DDR DIMMs operating on it, the impact of server crash caused by hardware failures is much bigger than before.
+
+Modern CPU offers an extensive and robust set of RAS features in silicon to provide error detection, correction, containment, and recovery in all processors, memory, and I/O data paths based on Intel Machine Check Architecture (MCA) Recovery mechanism or ARM v8.2 RAS Extension. When a server component fails, OS with such RAS features is capable of recovery from hardware error, maximizing service availability and maintaining data integrity.
+
+## RAS Mechanism Overview
+
+### Error categories
+
+One of the most popular RAS schemes used in the memory subsystem is Error Correction Code (ECC) SECDED (Single-bit Error Correction and Double-bit Error Detection), which as its name indicates, the DDR controller can correct single-bit errors and detect double-bit errors on the received data from the DRAMs.
+
+Talking about detected hardware errors, we can classify memory errors as either corrected errors (CE) or uncorrected errors (UCE).
+
+- **Correctable Error (CE)** - the hardware error detection mechanism detected and automatically corrected the error.
+- **Uncorrected errors (UCE)** - are severe enough, hardware detects but cannot correct.
+
+
+
+Typically, uncorrectable errors further fall into three categories:
+
+- **Uncorrected Recoverable Errors (UCR)** - are uncorrected errors that have been detected and signaled but have not corrupted the processor context. For certain UCR errors, this means that once system software has performed a certain recovery action, it is possible to continue execution on this processor. UCR error reporting provides an error containment mechanism for data poisoning. It can be further divided into:
+ - **Action Required (AR)**: The error occurs in execution context. If such an error is detected, and the memory access has been architecturally executed, that error is considered “consumed”. CPU will signal a synchronous exception when an error is detected and the processor already consumes the memory. OS requires to take action (for example, offline failure page/kill failure thread) to recover this uncorrectable error.
+ - **Action Optional (AO)**: The error is detected out of processor execution context, e.g. when detected by a background scrubber or accessed by prefetch instruction. In this scenario, the data in the memory are corrupted, but OS is optional to take action to recover this uncorrectable error.
+- **Uncorrected Error (UC)** - 2 bit (uncorrectable) error occurs and can not be corrected by hardware. The processor context is corrupted and cannot continue to operate the system. OS requires to panic immediately.
+
+OS will take specific actions based on the above failures. Handling CEs is done in silicon, e.g. using ECCs and can be made transparent to system. Handling DUEs, however, can require collaboration from higher layers in the hardware-software stack, from silicon to virtual memory manager, to the operating system (OS), and sometimes even the application layer.
+
+### X86 MCA Recovery
+
+The new Intel Xeon Scalable Family processors support recovery from some memory errors based on the Machine Check Architecture (MCA) Recovery mechanism. The figure shows a basic workflow with legacy MCA or EMCA.
+
+Prior to enhanced machine check architecture (EMCA), IA32-legacy version of Machine Check Architecture (MCA) implemented error handling where all the errors were logged in architected registers (MC banks) and signaled to OS/hypervisor. CMCI is signaled only when CE is over threshold and OS CMCI handler, aka, `threshold_interrupt` read MC Banks and other HW registers for further error handling. MCE is signaled when uncorrected or fatal errors are detected and its handler `do_machine_check` will poison the page and then kill current thread in memory failure.
+
+EMCA enables BIOS-based recovery from errors which redirects MCE and CMCI to firmware first (via SMI) before sending it to the OS error handler. It allows firmware first to handle, collect, and build enhanced error logs then report to system software.
+
+
+
+### ARM v8.2 RAS Extension
+
+The RAS Extension is a mandatory extension to the Armv8.2 architecture, and it is an optional extension to the Armv8.0 and Armv8.1 architectures. The figure shows a basic workflow with Firmware First mode.
+
+
+- Prerequisite: System boot and init
+
+ - Platform RAS driver init: BL31 initializes SPM (includes MM dispatcher) and SDEI dispatcher, UEFI query and update error source info in HEST
+ - OS RAS driver init: HEST driver scans HEST table and registers error handlers by APEI notification, e.g. SDEI, SEA, GPIO, etc.
+
+1. RAS event (UE or CE) occurred, the event will be routed to EL3 (SPM).
+2. SPM routes the event to RAS error handler in S-EL0 (MM Foundation).
+3. MM Foundation creates the CPER blobs by the info from RAS Extension.
+4. SPM notifies RAS event through APEI notification, e.g. SDEI, SEA, etc. to call the corresponding OS registered handler.
+5. OS gets the CPER blobs by Error Status Address block, processes the error, and tries to recover.
+6. OS reports the error event by RAS tracepoints.
+7. rasdaemon log error info from RAS event to recorder.
+
+For example, the platform specifies SDEI as an APEI notification to handle RAS events. As part of initialization, the kernel registers a handler for a platform event, enables the event, and unmasks the current PE. At a later point in time, a critical event, e.g. DDR UE interrupt is trapped into EL3. EL3 performs a first-level triage of the event, and a RAS component assumes further handling. The dispatch completes, but intends to involve Non-secure world UEFI in further handling, and therefore decides to explicitly dispatch an event (which the kernel had already registered for).
+
+## RAS Solution on ANCK
+
+Modern CPU offers an extensive and robust set of RAS features in silicon to provide error detection, correction, containment, and recovery in all processors, memory, and I/O data paths based on Intel Machine Check Architecture (MCA) Recovery mechanism or ARM v8.2 RAS Extension. The RAS mechanism is intended to assist CPU designers and CPU debuggers in diagnosing, isolating, and understanding processor failures. It is also intended to help system administrators detect transient and age-related failures, suffered during long-term operation of the server.
+
+To reduce systems downtime, the OS recovery process for ensuring reliable hardware performance is to detect and correct errors where possible, recover from uncorrectable errors through either physical or logical replacement of a failing component or data path, and prevent future errors by replacing in timely fashion components most likely to fail.
+
+The figure shows the system error handling flow with Anolis OS.
+
+
+
+### Memory Failure Recovery
+
+The RAS mechanism is used to detect, signal, and record machine fault information. Some of these faults are correctable, whereas others are uncorrectable. The Memory Failure Recovery capabilities of RAS mechanism allow systems to continue to operate when an uncorrected error is detected in the system. If not for these capabilities, the system would crash and might require hardware replacement or a system reboot.
+
+When an uncorrectable error is detected on a requested memory address, data poisoning is used to inform the CPU that the data requested has an uncorrectable error. When the hardware detects an uncorrectable memory error, it routes a poison bit along with the data to the CPU. For the Intel architecture, when the CPU detects this poison bit, it sends a processor interrupt signal to the operating system to notify it of this error. The operating system can then examine the uncorrectable memory error, determine if the software can recover, and perform recovery actions via an interrupt handler.
+
+Memory Failure Recovery handles UCR errors including:
+
+- AR are synchronous Errors. There are two types of such errors signaled as data abort or instruction abort. For example, data abort is detected by Data Cache Unit (DCU) and instruction abort is detected by Instruction Fetch Unit (IFU) which are both signaled as Machine Check Exception. The analogy exception is Synchronous External Abort in Arm64 platform.
+
+- AO are asynchronous Errors. Such errors are detected by memory patrol scrub, prefetch, Last Level Cache (LLC) explicit writeback transaction for X86 platform or store less than ECC protection granularity, e.g. per 64 bit on Neoverse N1 and N2.
+
+The kernel will attempt to hard-offline the page, by trying to unmap the page or killing any owner, or triggering IO errors if needed. This may kill any processes accessing the page. The kernel will avoid to access this page assuming it's poisoned by the hardware.
+Let's dive into more details about Anolis OS Cloud Kernel running on Severs capable of Intel MCA Recovery or ARM v8.2 RAS Extension.
+
+#### User Space Action Required Recovery
+
+In Linux, user memory and kernel memory are independent and implemented in separate address spaces. The address spaces are virtualized, meaning that the addresses are abstracted from physical memory (through a process detailed shortly). In fact, the kernel itself resides in one address space, and each process resides in its own address space, so each process can be isolated completely and protected by the paging mechanism. These address spaces consist of virtual memory addresses, permitting many processes with independent address spaces to refer to a considerably smaller physical address space (the physical memory in the machine). Not only is this convenient, but it's also secure, because each address space is independent and isolated and therefore secure. One isolated address space per process is the basis of preventing the fault from being propagated to the enclosing scope or process.
+
+Without OS memory failure recovery and hardware data poisoning support, once a process is consuming poison, it will be regarded as a fatal event and the kernel will crash immediately. When the OS kernel receives the UCE events, the `memory_failure` function (HWPoison handler) analyzes the log to verify if recovery is feasible. It then takes actions to offline the affected memory page and logs the event in the
+mcelog or RAS tracepoint, and the possible results of the actions appear to be ignoring, recovery, delay, and failure.
+
+The HWPoison handler starts the recovery action by isolating the affected page and declaring it with a “poisoned” tag to disallow any reuse of the page. In the case of an AR-instruction abort event, the HWPoison handler then reloads the 4KB page containing the instruction to a new physical page and resumes normal operation. In the case of an AR-data abort event, the HWPoison handler triggers a “SIGBUS” event to take further recovery action by notifying only the accessing process or any owner process which is configured by hwpoison-aware technique like prctl or early kill. The application has a choice to either reload the data and resume normal execution, or terminate the application to avoid crashing the entire system.
+
+
+
+#### Kernel Space Action Required Recovery
+
+The kernel itself resides in one address space, and contains a process scheduler, networking stack, virtual file system, and device drivers for hardware support, to name just a few, shared by all user space processes. When a user space application requires the services provided by the kernel, it will signal the kernel to execute a syscall, and switch to kernel mode for the duration of the syscall execution. In principle, if any UCE error was triggered while executing OS kernel code, then the UCE error will be fatal.
+Kernel also provides user space memory access APIs for cross-space data movement from or to user memory. Cross-space data movements are limited to perform in Linux by special functions, defined in ``. Such a movement is either performed by a generic (memcpy-like) function or by functions optimized for a specific data size (char, short, int, long); The role of the data-movement functions is shown in following figure as it relates to the types involved for copy (simple vs. aggregate), note, not all user access API is showed.
+
+
+
+For example, when a user process tries to write a buffer to a file, kernel will copy the data from userspace and then write them to disk. If a UCE error occurs in the userspace buffer, kernel will consume the poison data while copying data from userspace. In such case, a system wide reboot is not unnecessary. The point behind Kernel Space Action Required Recovery is that the poison data manipulated by kernel is owned by the user process. If the application that initiated the copy and owned corrupt data can be easily identified by the kernel, it is possible to isolate the corrupt data by marking the affected page with the ‘poison’ tag and terminating the initiator/impacted applications to stop the corrupt data from spreading.
+
+The mechanism is to track uaccess in extable in advance and change pc to fixup handler while handling synchronous Errors. Then the uaccess will jump to fixup handler which then endups the uaccess process. If the exception is fixuped correctly, the kernel can avoid panic. In the copy from user case, e.g. initiated by write(2), it is not even necessary to send a SIGBUS. System calls should return -EFAULT or a short count for write(2). The Figure shows the basic workflow for Arm64 platform and the implementation of the X86 platform is similar.
+
+
+
+#### Action Optional Recovery: Patrol Scrub
+
+ECC Patrol Scrubber is a common block in DDR Controller (DDRC) capable of generating initialization write commands, periodic read commands, periodic RMW commands, and correction RMW commands. It proactively searches the system memory, repairing correctable errors. Periodic scrubbing is performed by the ECC Patrol Scrubber to prevent the accumulation of single-bit errors and increase the reliability of the system by correcting single-bit ECC errors in time, before they turn into uncorrectable 2-bit errors.
+When an uncorrectable 2-bit error is detected by Patrol Scrubber, an interrupt will be signaled. In such case, kernel will just unmap the poisoned page because no process is accessing the poison data by default.
+
+On X86 old generation platform, after the patrol scrub detects memory uncorrected data errors, it will report the OS by MCE. The new generation like Intel® Xeon® Processor-based platforms have an `UCE_TO_CE_DOWNGRAGE` mode where the users can request the memory controller to report UCE found by the patrol scrubber as a corrected type. It is also called ‘downgrading patrol scrub CE/SRAO to CE’. Those errors are signaled by using CMCI, a process less disruptive than a machine check and thus helps avoid double MCE interrupts to crash the system. We recommend setting it on.
+
+
+
+#### Action Optional Recovery: Prefetch
+
+Many modern processors implement implicit hardware prefetching and support software prefetching. With software prefetching the programmer or compiler inserts prefetch instructions into the program. For example, Prefetch from Memory (`PRFM`) enables code to provide a hint to the memory system that data from a particular address will be used by the program soon. While for implicit hardware prefetching, the processor monitors the memory access pattern of the running program and tries to predict what data the program will access next and prefetches that data.
+
+If a prefetch request accesses to poison data, an asynchronous error will be detected and an interrupt will be signaled, e.g. CMCI on Intel Icelake and SPI on Yitian 710. In such case, kernel will just unmap the poison page like Patrol Scrub error.
+
+Another prefetch scenario we observed is that the poisoned page may still be accessed even though all its owned user processes are killed. After a page is poisoned, it will never be reused, e.g. reallocated to other processes. The problem is that the poisoned page is only unmapped from the page table of user-space process, the kernel page table of the linear mapping range is not considered. It requires dynamically splitting the target linear mapping into PTE granularity and then clearing the PTE valid attribute of the related virtual address while processing memory failure. As a result, the poisoned page will be marked as not-present, which avoids speculative and prefetch access.
+
+#### Action Optional Recovery: Store
+
+Write is another type of request which may read the poison data from DDR controller. On Yitian 710, L2 cache is protected by a per 64-bit ECC scheme, a write less than 64bit will trigger asynchronous External Aborts, signaled as SErrors. Similarly, an asynchronous interrupt CMCI is signaled on X86 platform. In such case, it requires firmware to take extra care that does not notify kernel as a fatal error to avoid a system wide reboot.
+
+Unlike read access, write access does not cause error propagation. When such an error is detected, kernel will regard it as AO asynchronous error and only unmap the poisoned page. However, the write did not take effect, resulting in data loss. A subsequent 64-bit write access has the opportunity to correct this error. When the process trie to consume the poisoned page, the HWPoison handler triggers a “SIGBUS” event to take further recovery action by notifying only the accessing process or any owner process which is configured by hwpoison-aware technique like prctl or early kill.
+
+#### HWPoison-aware Strategy
+
+There are in principle two hwpoison-aware strategies to kill processes on poison:
+
+- just unmap the data and wait for an actual reference before killing
+- kill all processes that have the corrupted and not reloadable page mapped as soon as the corruption is detected.
+
+Both have advantages and disadvantages and should be used in different situations. **Right now both are implemented and can be switched** with a new sysctl vm.memory_failure_early_kill. The default is late kill. Applications can override this setting individually with the PR_MCE_KILL prctl. For example, if early kill is set by `sysctl -w vm.memory_failure_early_kill=1`, kernel will kill any process which mapped the poison page when an uncorrectable 2-bit error is detected by Patrol Scrubber.
+
+Note, the kill is done using a catchable SIGBUS with BUS_MCEERR_AO, so processes can handle this if they want to. While for AR synchronous errors, the kill is done using a catchable SIGBUS with BUS_MCEERR_AR.
+
+### Memory Predictive Failure Analysis with Rasdeamon
+
+When a 1-bit error is detected, it is transparently corrected by the hardware ECC mechanism, and internal counters are updated. If a correctable fault occurs in the memory, we don't need to perform any recovery action on the OS. However, if we continue to see correctable errors, then perhaps the memory is failing. To avoid the possibility of future uncorrectable faults on the same page, we can copy the data to a different page and mark the page as offline. This is the mechanism used by Memory Predictive Failure Analysis (PFA).
+
+The PFA is powered by the userspace rasdaemon package. Rasdaemon written by Mauro Carvalho Chehab is one of the tools to gather MCE information. Previously, the task was performed by the mcelog package. However, the driver it depends on has been deprecated after kernel 4.12, we recommend switching to the new generation rasdaemon solution.
+
+If a memory error is detected and signaled, the OS related handler reports them to userspace through RAS tracepoints with EDAC decoded DIMM statistics for accounting and predictive failure analysis. Rasdeamon runs as a daemon that monitors the platform RAS reports from the Linux kernel trace events. And it optionally records RAS events via Sqlite3 which has the benefit of keeping a persistent record of the RAS events. Based on statistical results, some actions can be configured and taken to prevent corrected errors from evoluting into uncorrected errors. For example, specify soft offline action or hard offline action when exceeding a page error threshold within refresh cycles, e.g. 50 CEs perf 24 hours. When a soft action is specified, the kernel will then attempt to soft-offline it, by moving the contents elsewhere or dropping it if possible. The kernel will then be placed on the bad page list and never be reused. The page is still accessible, not poisoned. The kernel will never kill anything for this, but rather fail the offline.
+
+Note, the RAS feature is only covered but not limited to memory, the processor, PCIe, and Platform(e.g. CMN, GIC, SMMU, etc) RAS are also supported on Anolis OS Cloud Kernel.
+
+## RAS Validation Guide
+
+EINJ provides a hardware error injection mechanism. It is very useful for debugging and testing APEI and RAS features in general. In this white paper, we take Yitian 710 running Anolis OS as an example. Note that this guide is also suitable for other platforms with advanced RAS features.
+
+### Prerequisite
+
+#### BIOS Requirement
+
+You need to check whether your BIOS supports EINJ first. For Panjiu M Series equipped with Yitian 710, make ensure to set the following configuration properly.
+
+```bash
+[Platform Configuration][Processor Configuration][CPU Poison]
+[Platform Configuration][Memory RAS Configuration][Poison]
+[Platform Configuration][Memory RAS Configuration][CE threshold ]<0>
+[Platform Configuration][Memory RAS Configuration][Ecc]
+[Platform Configuration][PCI-E Configuration][PCIe RAS Support]
+[Platform Configuration][PCI-E Configuration][AER CE]
+[Platform Configuration][Advance Configuration][Global RAS Enable]
+[Platform Configuration][Advance Configuration][EINJ Enable]
+[Platform Configuration][Advance Configuration][Route EA to El3]
+```
+
+#### OS Requirement
+
+Then, you need to check whether your BIOS supports EINJ. For that, look for early boot messages similar to this one, e.g. on Yitian 710 :
+
+```bash
+#dmesg | grep EINJ
+[ 0.000000] ACPI: EINJ 0x00000000F8FAFE18 000150 (v01 PTG PTG01 00000000 PTG 20200717)
+```
+
+which shows that the BIOS is exposing an EINJ table - it is the mechanism through which the injection is done.
+
+By default, the EINJ driver is built-in on Anolis OS. If you build kernel from scratch, make sure the following are options enabled in your kernel configuration:
+
+```shell
+CONFIG_DEBUG_FS
+CONFIG_ACPI_APEI
+CONFIG_ACPI_APEI_EINJ
+```
+
+Check if the einj module is loaded:
+
+```shell
+$ lsmod | grep einj
+einj 16384 0
+```
+
+If not, load the einj modules by yourself
+
+```shell
+modprobe einj
+```
+
+### EINJ Interface
+
+The EINJ user interface is in \/apei/einj, by default, `/sys/kernel/debug/apei/einj`.
+
+```bash
+#ls /sys/kernel/debug/apei/einj/
+available_error_type error_inject error_type flags notrigger param1 param2 param3 param4 vendor vendor_flags
+```
+
+The standard error types for the EINJ interface include Processor, Memory, PCIe, and Platform. The file `available_error_type`displays the supported standard error types and their severities, e.g.
+
+```bash
+#cat /sys/kernel/debug/apei/einj/available_error_type
+0x00000001 Processor Correctable
+0x00000002 Processor Uncorrectable non-fatal
+0x00000004 Processor Uncorrectable fatal
+0x00000008 Memory Correctable
+0x00000010 Memory Uncorrectable non-fatal
+0x00000020 Memory Uncorrectable fatal
+0x00000040 PCI Express Correctable
+0x00000080 PCI Express Uncorrectable non-fatal
+0x00000100 PCI Express Uncorrectable fatal
+0x00000200 Platform Correctable
+0x00000400 Platform Uncorrectable non-fatal
+0x00000800 Platform Uncorrectable fatal
+```
+
+The error injection mechanism is a two-step process.
+
+- First select an error specified all necessary error parameters including`error_type`,`flags`,`param{1-4}`and `notrigger`,then write any integer to `error_inject` to inject the error.
+- The second step performs some actions to trigger it. Setting `notrigger` to 1 skips the trigger phase, which may allow the user to cause the error in some other context by a simple access to the CPU, memory location, or device that is the target of the error injection. Setting `notrigger` to 0, the BIOS should trigger the error internally, e.g. by kicking the patrol scrubber. Whether this actually works depends on what operations the BIOS actually includes in the trigger phase.
+
+Please refer to the kernel document for more details about EINJ user interface format.
+
+#### Error Injection Examples with APEI Debugfs
+
+In this section, we show examples to inject errors with APEI Debugfs on Yitian 710.
+
+##### Processor Uncorrectable non-fatal
+
+```bash
+APEI_IF=/sys/kernel/debug/apei/einj
+echo 33 > $APEI_IF/param3 # APIC ID
+echo 0x1 > $APEI_IF/flags
+echo 0x00000002 > $APEI_IF/error_type
+echo 1 > $APEI_IF/error_inject
+```
+
+The dmesg log:
+
+```bash
+[ 1820.578688] {3}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 4
+[ 1820.589434] {3}[Hardware Error]: event severity: recoverable
+[ 1820.595078] {3}[Hardware Error]: precise tstamp: 2023-01-02 17:23:02
+[ 1820.601503] {3}[Hardware Error]: Error 0, type: recoverable
+[ 1820.607147] {3}[Hardware Error]: section_type: ARM processor error
+[ 1820.613485] {3}[Hardware Error]: MIDR: 0x00000000410fd490
+[ 1820.619041] {3}[Hardware Error]: Multiprocessor Affinity Register (MPIDR): 0x0000000081210000
+[ 1820.627723] {3}[Hardware Error]: running state: 0x1
+[ 1820.632759] {3}[Hardware Error]: Power State Coordination Interface state: 0
+[ 1820.639965] {3}[Hardware Error]: Error info structure 0:
+[ 1820.645435] {3}[Hardware Error]: num errors: 1
+[ 1820.650037] {3}[Hardware Error]: error_type: 0, cache error
+[ 1820.655854] {3}[Hardware Error]: error_info: 0x0000000000800015
+[ 1820.662019] {3}[Hardware Error]: transaction type: Instruction
+[ 1820.668183] {3}[Hardware Error]: cache level: 2
+[ 1820.673045] {3}[Hardware Error]: the error has not been corrected
+[ 1820.679470] {3}[Hardware Error]: type: CORE (0x41), ras_count:1
+[ 1820.685461] {3}[Hardware Error]: sub_type: 0x0
+[ 1820.689977] {3}[Hardware Error]: fr: 0x10a9a2, ctrl: 0x0, status: 0x44800007, addr: 0x800e9f716acea53d
+[ 1820.699352] {3}[Hardware Error]: misc0: 0x4, misc1: 0x0, misc2: 0x0, misc3: 0x0
+```
+
+##### Processor Uncorrectable fatal
+
+Script to inject and trigger processor uncorrectable fatal error. Note, a fatal error will cause the kernel to panic.
+
+```bash
+APEI_IF=/sys/kernel/debug/apei/einj
+echo 33 > $APEI_IF/param3 # APIC ID
+echo 0x1 > $APEI_IF/flags
+echo 0x00000004 > $APEI_IF/error_type
+echo 1 > $APEI_IF/error_inject
+```
+
+The dmesg log:
+
+```bash
+[10862.838686] {10}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 3
+[10862.838687] {10}[Hardware Error]: event severity: fatal
+[10862.838688] {10}[Hardware Error]: precise tstamp: 2023-01-02 19:53:43
+[10862.838688] {10}[Hardware Error]: Error 0, type: fatal
+[10862.838688] {10}[Hardware Error]: section_type: ARM processor error
+[10862.838689] {10}[Hardware Error]: MIDR: 0x00000000410fd490
+[10862.838689] {10}[Hardware Error]: Multiprocessor Affinity Register (MPIDR): 0x0000000081210000
+[10862.838689] {10}[Hardware Error]: running state: 0x1
+[10862.838690] {10}[Hardware Error]: Power State Coordination Interface state: 0
+[10862.838690] {10}[Hardware Error]: Error info structure 0:
+[10862.838691] {10}[Hardware Error]: num errors: 1
+[10862.838691] {10}[Hardware Error]: error_type: 0, cache error
+[10862.838691] {10}[Hardware Error]: error_info: 0x0000000000800015
+[10862.838692] {10}[Hardware Error]: transaction type: Instruction
+[10862.838692] {10}[Hardware Error]: cache level: 2
+[10862.838693] {10}[Hardware Error]: the error has not been corrected
+[10862.838693] {10}[Hardware Error]: type: CORE (0x41), ras_count:1
+[10862.838693] {10}[Hardware Error]: sub_type: 0x0
+[10862.838694] {10}[Hardware Error]: fr: 0x10a9a2, ctrl: 0x0, status: 0x74000007, addr: 0x800e9f716acea53d
+[10862.838694] {10}[Hardware Error]: misc0: 0x4, misc1: 0x0, misc2: 0x0, misc3: 0x0
+[10862.838695] Kernel panic - not syncing: Fatal hardware error!
+```
+
+#### Memory
+
+##### Correctable
+
+Firstly, run a `victim` program in the background. The `victim` is one of the ras-tools which allocates a page in userspace and dumps the virtual and physical address of the page, and then holds on to trigger.
+
+```bash
+#victim -d &
+[1] 12472
+physical address of (0xffff87fb2000) = 0x89a0f8000
+Hit any key to trigger error:
+[1]+ Stopped victim -d
+```
+
+Then run the bellow script to inject and trigger memory correct error. Note, the CE recovery is usually implemented as a threshold based error reporting mechanism. The default threshold for CE is 5000, in other words, the hardware only signal interrupt per 5000 CE errors. To test the feature, we configure CE threshold as 0.
+
+```bash
+echo 0x89a0f8000 > $APEI_IF/param1
+echo 0xfffffffffffff000 > $APEI_IF/param2
+echo 0x1 > $APEI_IF/flags
+echo 0x00000008 > $APEI_IF/error_type
+echo 1 > $APEI_IF/error_inject
+```
+
+The dmesg log:
+
+```bash
+[ 1555.991595] EDAC MC0: 1 CE single-symbol chipkill ECC on unknown memory (node:0 card:0 module:0 rank:0 bank_group:4 bank_address:2 device:0 row:616 column:1024 chip_id:0 page:0x89a0f8 offset:0x0 grain:1 syndrome:0x0 - APEI location: node:0 card:0 module:0 rank:0 bank_group:4 bank_address:2 device:0 row:616 column:1024 chip_id:0 status(0x0000000000000400): Storage error in DRAM memory)
+[ 1555.991600] {1}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 2
+[ 1555.991602] {1}[Hardware Error]: It has been corrected by h/w and requires no further action
+[ 1555.991602] {1}[Hardware Error]: event severity: corrected
+[ 1555.991604] {1}[Hardware Error]: precise tstamp: 2023-01-02 17:18:38
+[ 1555.991604] {1}[Hardware Error]: Error 0, type: corrected
+[ 1555.991606] {1}[Hardware Error]: section_type: memory error
+[ 1555.991606] {1}[Hardware Error]: error_status: Storage error in DRAM memory (0x0000000000000400)
+[ 1555.991607] {1}[Hardware Error]: physical_address: 0x000000089a0f8000
+[ 1555.991608] {1}[Hardware Error]: node:0 card:0 module:0 rank:0 bank_group:4 bank_address:2 device:0 row:616 column:1024 chip_id:0
+[ 1555.991609] {1}[Hardware Error]: error_type: 4, single-symbol chipkill ECC
+[ 1555.991610] {1}[Hardware Error]: type: DDR (0x50), ras_count:1
+[ 1555.991611] {1}[Hardware Error]: sub_type: 0x0
+[ 1555.991612] {1}[Hardware Error]: fr: 0x1000200000022, ctrl: 0x0, status: 0x0, addr: 0x0
+[ 1555.991612] {1}[Hardware Error]: misc0: 0x0, misc1: 0x0, misc2: 0x200000000000000, misc3: 0x900000000000000
+```
+
+##### Memory UnCorrectable Non-fatal
+
+Firstly, run a `victim` program in the background as the last section described.
+
+```bash
+#victim -d &
+physical address of (0xffff962d0000) = 0x9f8acb000
+Hit any key to trigger error:
+[1]+ Stopped victim -d
+```
+
+Then run the bellow script to inject and trigger memory correct error. Here, we specify `notrigger` to 0 to let the firmware kick the DDRC scrubber to trigger the error.
+
+```bash
+APEI_IF=/sys/kernel/debug/apei/einj
+echo 0x400a4919000 > $APEI_IF/param1
+echo 0xfffffffffffff000 > $APEI_IF/param2
+echo 0x1 > $APEI_IF/flags
+echo 0x00000010 > $APEI_IF/error_type
+echo 0x0 > $APEI_IF/notrigger
+echo 1 > $APEI_IF/error_inject
+```
+
+The dmesg log:
+
+```bash
+[ 211.121855] {1}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 2
+[ 211.132646] {1}[Hardware Error]: event severity: recoverable
+[ 211.138292] {1}[Hardware Error]: precise tstamp: 2022-12-30 15:26:40
+[ 211.144717] {1}[Hardware Error]: Error 0, type: recoverable
+[ 211.150362] {1}[Hardware Error]: section_type: memory error
+[ 211.156096] {1}[Hardware Error]: error_status: Storage error in DRAM memory (0x0000000000000400)
+[ 211.165125] {1}[Hardware Error]: physical_address: 0x00000400a4919000
+[ 211.171725] {1}[Hardware Error]: node:0 card:7 module:0 rank:0 bank_group:7 bank_address:0 device:0 row:146 column:1152 chip_id:0
+[ 211.183619] {1}[Hardware Error]: error_type: 14, scrub uncorrected error
+[ 211.190479] {1}[Hardware Error]: type: DDR (0x50), ras_count:1
+[ 211.196383] {1}[Hardware Error]: sub_type: 0x0
+[ 211.200899] {1}[Hardware Error]: fr: 0x1000200000353, ctrl: 0x0, status: 0x0, addr: 0x0
+[ 211.208974] {1}[Hardware Error]: misc0: 0x0, misc1: 0x0, misc2: 0x0, misc3: 0x200000000000500
+[ 211.218375] Memory failure: 0x400a4919: recovery action for dirty LRU page: Recovered
+```
+
+At this point, the allocated physical page is unmapped and poisoned, any read access will trigger a page fault.
+If we move the background process `victim`on current Linux shell to the foreground and hit any key, the victim will trigger a page fault and receive a SIGBUS signal due to the poisoned PTE entry. Because the `victim`process does not register the SIGBUS handler, it will be killed.
+
+```bash
+#fg
+victim -d
+
+Access time at Fri Dec 30 15:38:14 2022
+
+Bus error
+```
+
+We can also specify `notrigger` to 1 to let the firmware skip the trigger phase and allow the `victim` process to access the target of the error injection so that the error will be detected in execution context.
+
+Firstly, select a page and inject an error to it, while explicitly skipping the firmware trigger phase.
+
+```bash
+#victim -d &
+[1] 9522
+physical address of (0xffffaed6d000) = 0x400aa6dd000
+Hit any key to trigger error:
+[1]+ Stopped victim -d
+
+APEI_IF=/sys/kernel/debug/apei/einj
+
+echo 0x400aa6dd000 > $APEI_IF/param1
+echo 0xfffffffffffff000 > $APEI_IF/param2
+echo 0x1 > $APEI_IF/flags
+echo 0x00000010 > $APEI_IF/error_type
+echo 0x1 > $APEI_IF/notrigger
+echo 1 > $APEI_IF/error_inject
+```
+
+Then move the background process `victim` on current Linux shell to the foreground and hit any key, so that the error will be triggered in execution context. The kernel will poison the page and unmap it, then send SIGBUS to the process which accesses the page.
+
+```bash
+#fg
+victim -d
+
+Access time at Fri Dec 30 15:39:26 2022
+
+Bus error
+```
+
+The dmesg log:
+
+```bash
+[ 799.958832] {3}[Hardware Error]: Hardware error from APEI Generic Hardware Error Source: 2
+[ 799.969533] {3}[Hardware Error]: event severity: recoverable
+[ 799.975179] {3}[Hardware Error]: precise tstamp: 2022-12-30 15:36:29
+[ 799.981603] {3}[Hardware Error]: Error 0, type: recoverable
+[ 799.987248] {3}[Hardware Error]: section_type: memory error
+[ 799.992978] {3}[Hardware Error]: error_status: Storage error in DRAM memory (0x0000000000000400)
+[ 800.002007] {3}[Hardware Error]: physical_address: 0x00000400aa6dd000
+[ 800.008607] {3}[Hardware Error]: node:0 card:5 module:0 rank:1 bank_group:1 bank_address:0 device:0 row:169 column:1664 chip_id:0
+[ 800.020500] {3}[Hardware Error]: error_type: 5, multi-symbol chipkill ECC
+[ 800.027446] {3}[Hardware Error]: type: DDR (0x50), ras_count:1
+[ 800.033351] {3}[Hardware Error]: sub_type: 0x0
+[ 800.037866] {3}[Hardware Error]: fr: 0x1001000100000000, ctrl: 0xf000000000920004, status: 0xd800000Cor0040](0xadd040000d0receiveaecntr=526(d1.subch3), cnt=0x1
+[ 800.060436] {3}[Hardware Error]: misc0: 0x3f00000000040307, misc1: 0xd00000000030cd18, misc2: 0x4015, misc3: 0x200000000000100
+[ 800.072366] Memory failure: 0x400aa6dd: recovery action for dirty LRU page: Recovered
+```
+
+### RAS-tools
+
+We can also test and validate RAS features of whole system stack across hardware, firmware and OS via ras-tools. Ras-tools are an excellent set of tools to inject and test RAS ability on X86 and Arm64 platforms based on the APEI EINJ interface.
+
+| tools | fatal | arch | Description | Usage |
+| ----------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------ |
+| einj_mem_uc | See help | x86、Arm | inject an error and then trigger it in one of a variety of ways. | ./einj_mem_uc # See help for testname |
+| cmcistorm | No | x86 | use EINJ to inject a bunch of soft errors, then consume them all as fast as possible. | ./cmcistorm # e.g./cmcistorm 20 1 |
+| hornet | No | x86、Arm | Start a process (or point to an existing one) and inject an uncorrectable memory error to a targeted or randomly chosen memory address | ./hornet -p PID |
+| lmce | No | x86 | local mce | ./lmce |
+| mca-recover | No | x86、Arm | Set up to get zapped by a machine check (injected elsewhere) recovery function reports physical address of new page - so we can inject to that and repeat over and over. | ./mca-recover |
+| rep_ce_page | No | x86、Arm | loop using EINJ to inject a soft error, consuming after each until the page is taken offline. | ./rep_ce_page |
+| vtop | No | x86、Arm | Given a process if and virtual address, dig around in /proc/id/pagemap to find the physical address (if present) behind the virtual one. | ./vtop |
+| memattr | No | Arm | Example of the Linux kernel driver that allows a user-space program to mmap a buffer of contiguous physical memory with specific memory attribute. | cd pgprot-drv