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 首页** + +![image.png](https://oss.openanolis.cn/blog/vnyrodeytjdirmwvclsl) +## 二. Bug生命周期 + +- **2.1 新建Bug** + - **2.1.1 路径** + + 首页->New/File a Bug->Select a classification->Select a product->Bug创建页面。具体如下:首先,在首页点击New或File a Bug按钮,进行创建Bug。 + ![image.png](https://oss.openanolis.cn/blog/wzzgfkzzdtcjdszhtitj) + 然后会提示让选择一个classification, classification是Bug的一级分类。 + ![image.png](https://oss.openanolis.cn/blog/jhezhtkdurrdfdemionv) + 选择完classification分类后会提示选择一个product,product是Bug的二级分类。 + ![image.png](https://oss.openanolis.cn/blog/jgnutqwmfwiamimclhvv) + + - **2.1.2 创建页面** + + 选择完product产品后会进入Bug创建页面,创建页面有一些参数需要填充,具体参数含义如下图所示: + ![image.png](https://oss.openanolis.cn/blog/qhsbjoqiqjqyjzjsvwpc) + +- **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 列表页。 + ![image.png](https://oss.openanolis.cn/blog/lbgdrwslbapzgoanzmez) + 然后在Bug List列表页点击Bug ID或Summary进入Bug编辑页面。 + ![image.png](https://oss.openanolis.cn/blog/jjcaxwoopxfdqkupkvqm) + + - **2.2.2 编辑页面** + + Bug编辑页面也进行Bug一些字段的修改,编辑页面的字段同Bug创建。 + ![image.png](https://oss.openanolis.cn/blog/oekldlyxclvagcqlejru) + +- **2.3 关闭Bug** + - **2.3.1 路径** + - Bug编辑页面->Status->Resolved、Fixed->Save Changes + + 在Bug页面编辑Status状态,当状态被修改为[RESOLVED,FIXED]时表示Bug关闭,至此Bug的生命周期结束。 + ![image.png](https://oss.openanolis.cn/blog/fghfimqbzadgazdcnspj) + +## 三. 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、评论、组件、产品等的操作,具体如下: + ![image.png](https://oss.openanolis.cn/blog/hhlrvwjkwfhderonmtqa) + +- **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/) + + ![image.png](https://oss.openanolis.cn/blog/havgigzzthanbpnspetz) + +- 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权限 和当前帐号权限一致。 + + ![image.png](https://oss.openanolis.cn/blog/qzupjlpwybxcfynwaryo) + + - 配置bugzillarc文件,配置url和api_key,python-bugzilla-cli插件可自动读取配置的参数,在使用命令时无需额外携带参数,bugzillarc文件内容如下: + + ![image.png](https://oss.openanolis.cn/blog/qlvjgwoqhaxvzolnyuzw) + +- 3.3 插件使用: + - 配置好bugzillarc文件之后,就可以使用bugzilla-anolis命令操作Bugzilla了,使用bugzilla-anolis命令查看当前支持的所有参数: + + ![image.png](https://oss.openanolis.cn/blog/bujocdnxusyfpvgslvxz) + + - 执行sub component相关命令: + - 查询: + ```json + bugzilla-anolis getsubcomponent --ids=10 --ids=11 + ``` + ![image.png](https://oss.openanolis.cn/blog/rdzzgstvtvxddhixabgx) + + - 添加: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" + + ![image.png](https://oss.openanolis.cn/blog/jdhfqzdhqnxvcizrrrsn) + + - 删除:bugzilla-anolis deletesubcomponent --ids=39 --product=testfarm --component=user + + ![image.png](https://oss.openanolis.cn/blog/jwdznaajpwrcmxhmhicw) 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 技术、拥有更好的性能、可靠的稳定性、丰富成熟的透明替换方案和及时的更新维护。 + +![](https://oss.openanolis.cn/sig/mvhfmmhwckaninvsrfda) 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 资源,同时也提高了网络吞吐量、降低了网络通信时延。 + +![](https://oss.openanolis.cn/sig/tmcyoeavfcpgonchogda) + +在过去,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 链路这条高速公路上飞驰起来。 + +![](https://oss.openanolis.cn/sig/clnlgbfummdpuseebadv) + +然而,仅本地一厢情愿的使用 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 连接完成后续的数据传输,保证网络的可靠稳定。 + +![](https://oss.openanolis.cn/sig/lyulsaymttjhauujxpsf) + +数据传输的高速公路建立起来后,交通规则也要安排妥当。顾名思义,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 上你追我赶,贯穿网络数据传输的始终,确保传输的安全与可靠。 + +![](https://oss.openanolis.cn/sig/fcxggqhikevmhifnwzug) + +最后,数据在高速公路上飞驰难免会遇到差错,为了保证一切都在掌控之中,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) 拷贝到用户态内存中,完成一次数据传输。 + +![](https://oss.openanolis.cn/sig/hlwaeufmvjquifrkzexx) + +在这一过程中,CPU 需要负责: +- 用户态与内核态间的数据拷贝。 +- 网络报文的封装、解析工作。 + +这些工作“重复低级”,占用了大量 CPU 资源 (如 100 Gb/s 的网卡跑到满带宽需要打满多个 CPU 核资源),使得 CPU 在数据密集型场景下无法将算力用到更有益的地方。 +所以,解决网络性能与 CPU 算力失配问题成为了高性能网络发展的关键。考虑到摩尔定律逐渐失效,CPU 性能短时间内发展缓慢,将网络数据处理工作从 CPU 卸载到硬件设备的思路就成为了主流解决方案。这使得以往专用于特定高性能领域的 RDMA 在通用场景下得到愈来愈多的应用。 + + +### 1.2 RDMA 的优势 + +RDMA (Remote Direct Memory Access) 是一种远程内存直接访问技术,自提出以来经过 20 余年的发展已经成为了高性能网络的重要组成。那么 RDMA 是如何完成一次数据传输的呢? + +![](https://oss.openanolis.cn/sig/gvomsutwtstpebknksly) + +RDMA 网络 (用户态模式) 中,具备 RDMA 能力的网卡 RNIC 直接从发送端用户态内存中取得数据,在网卡中完成数据封装后传输到接收端,再由接收端 RNIC 将数据解析剥离,将有效负载 (payload) 直接放入用户态内存中完成数据传输。 +这一过程中 CPU 除了必要的控制面功能外,几乎不用参与数据传输。数据就像是通过 RNIC 直接写入到远程节点的内存中一样。因此,与传统网络相比,RDMA 将 CPU 从网络传输中解放了出来,使得网络传输就像是远程内存直接访问一样方便快捷。 + +![](https://oss.openanolis.cn/sig/uhithopldznnojbtlcnt) + +对比传统网络协议,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 协议非常简单。总体来说有两个方法: + +![](https://oss.openanolis.cn/sig/hkvozwaygbobwvmfcurs) + +- 其一,使用 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 架构 + +![](https://oss.openanolis.cn/sig/pwnpzgbdxcansfqjpmen) + +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 拷贝到接收端应用缓冲区中。 +![](https://oss.openanolis.cn/sig/scdbjenfcrwxhzsenbum) + +显然,SMC-R 名称中的共享内存通信指的就是基于远程节点 RMB 进行通信。与传统的本地共享内存通信相比,SMC-R 将通信两端拓展为了两个分离的节点,利用 RDMA 实现了基于“远程”共享内存的通信。 + +![](https://oss.openanolis.cn/sig/wacftxofvtwvovlglrov) + +目前,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 选项。 +![](https://oss.openanolis.cn/sig/ecdvckhvsusfsugrnnbb) + +- 回退 + +若在上述过程中,通信两端其一无法支持 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 连接。 + +![](https://oss.openanolis.cn/sig/fxxmjraklmtvbovyhtej) + +在 TCP 连接三次握手中,使用 SMC-R 协议的一端发送的 SYN/ACK 中携带了特殊的 TCP 选项 (Kind = 254,Magic Number = 0xe2d4),用于表明自身支持 SMC-R。通过检查对端发送的 SYN/ACK,通信节点得知其 SMC-R 能力,进而决定是否继续使用 SMC-R 通信。 + +![](https://oss.openanolis.cn/sig/wlyvwtzyhrjtnvcgwjiv) + +![](https://oss.openanolis.cn/sig/gtxycbdryqrwjkqlvzbe) + +### 2.2 协议回退 + +若在上述 TCP 握手过程中,通信两端其一表示无法支持 SMC-R,则进入协议回退 (fallback) 流程。 + +协议回退时,应用程序所持有的 fd 对应的 smc socket 将被替换为 clcsock。从此,应用程序将使用 TCP 协议通信,从而确保数据传输不会因为协议兼容问题而中断。 + +需要注意的是,协议回退仅发生在通信协商过程中,如前文提到的 TCP 握手阶段,或是下文提到的 SMC-R 建连阶段。为便于跟踪诊断,SMC-R 协议详细分类了潜在的回退可能,用户可以通过用户态工具 smc-tools 观测到协议回退事件及原因。 + +![](https://oss.openanolis.cn/sig/wjykmqpfzlhucufgxcei) + +### 2.3 建立 SMC-R 连接 + +若在 TCP 握手中,两端均表示支持 SMC-R,则进入 SMC-R 建连流程。SMC-R 连接的建立依赖 TCP 连接传递控制消息,这种控制消息被称为 Connection Layer Control (CLC) 消息。 + +![使用 CLC 消息建立 SMC-R 连接](https://oss.openanolis.cn/sig/tgiruolgpebxuqleeyri) + +CLC 消息的主要职责是同步通信两端的 RDMA 资源以及共享内存等信息。使用 CLC 消息建立 SMC-R 连接的过程与 SSL 握手类似,主要包含 Proposal、Accept、Decline、Confirm 等语义。在建连过程中,若遇到不可恢复的异常 (如 RDMA 资源失效) 导致后续 SMC-R 通信无法继续,也将触发前文所述的协议回退流程。 + +First contact 场景下,由于通信两端首次接触,两者间尚不存在使用 RDMA 通信的条件。所以,在建立首个 SMC-R 连接时,还将创建 SMC-R 通信所需的 RDMA 资源,建立 RDMA 链路,申请 RDMA 内存。 + +![SMC-R 握手过程](https://oss.openanolis.cn/sig/chcbtjzeynaeerbzceia) + +#### 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。 + +![](https://oss.openanolis.cn/sig/hygrnecybugcvmxmcoyb) + +#### 2.3.2 建立 RDMA 链路 + +通信两端将已创建的 RDMA 资源通过 CLC 消息同步到对端,进而在两端之间建立起基于 RC (Reliable Connection) QP 的 RDMA 链路。SMC-R 中将这种点对点逻辑上的 RDMA 链路称为 SMC-R Link。一条 SMC-R Link 承载着多条 SMC-R 连接的数据流量。 + +![](https://oss.openanolis.cn/sig/xgvatpvjpzgpnsdmxnxw) + +若通信节点之间存在不止一对可用的 RNIC,则会建立不止一条 Link。这些 Link 在逻辑上组成一个小组,称为 SMC-R Link Group。 + +![](https://oss.openanolis.cn/sig/bayvhqfogkbqcnufortz) + +在 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。 + +![](https://oss.openanolis.cn/sig/baxigyfuygoloyffpssz) + +其中,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 内存创建/销毁对建连性能的影响。 + +![](https://oss.openanolis.cn/sig/fykrmvbdtqgkikkptkul) + +### 2.4 验证 SMC-R Link + +由于 first contact 场景下新建立的 SMC-R Link 尚未经过验证,所以在正式使用 Link 传输应用数据前,通信两端会基于 Link 发送 Link Layer Control (LLC) 消息,用于检验 Link 是否可用。 + +![](https://oss.openanolis.cn/sig/splciwevvdazqnmqogko) + +LLC 消息通常为请求-回复模式,用于传输 Link 层面的控制信息,如添加/删除/确认 Link,确认/删除 r_key 等。 + +![](https://oss.openanolis.cn/sig/rnhpbmvabjixlljebcij) + +| 类型 | 说明 | +|--------------|-----------------------------------------| +| 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 操作。 + +![](https://oss.openanolis.cn/sig/uvuoftktaxeugmeldmgr) + +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 连接传输数据。 + +![](https://oss.openanolis.cn/sig/qjvqktbvyxgzgdpwftws) + +应用程序下发到 SMC-R 连接中的数据由关联的 Link 通过 RDMA WRITE 操作写入远程节点 RMB 中。 + +![](https://oss.openanolis.cn/sig/cedjbejvpiklydtfuwtz) + +与上文提到的 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 的共享内存通信流程可以总结为: + +![](https://oss.openanolis.cn/sig/bhkofbyxsxetppagzcsf) + + - 发送端的数据通过 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) + +## 机器规格 + +![](https://oss.openanolis.cn/sig/khzymelkgxainqbxmvva) + +为了能够对 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数据性能进行了多次测试,稳定的测试结果如下: + +![](https://oss.openanolis.cn/sig/nxagksyxajdvmlroriob) + +![](https://oss.openanolis.cn/sig/tcskypcbdeoqqerbuysu) + +从测试结果可以看出,无论是GET测试还是SET测试,SMC-R相对于TCP都带来了至少40%+的性能测试数据提升. +但如果CPU开销也额外花费了40%,数据就没有显著意义了,因此CPU开销也是及其重要的数据,接下来我们将在同样的测试条件下对SMC-R和TCP的CPU开销数据进行对比。 + +### CPU 开销 + +![](https://oss.openanolis.cn/sig/wafkqyxsbubwjpojllio) + +从测试结果可以看出,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开销情况没有单独列出。 + +### 时延收益 + +这里展示了在不同文件大小,不同线程数以及不同连接数下的时延数据情况: + +![](https://oss.openanolis.cn/sig/hxlwsxavjwuohhfeknup) + +我们可以看到,SMC-R在优化请求的时延上也有显著收益,在不同请求数据大小下,相对于TCP减少了20%到40%左右的时延,受益于ERDMA快速的协议栈处理和更短的数据路径,显著的时延收益也不足为奇了。 +因此,即使您的RPC应用不太关心吞吐的收益,SMC-R也可以帮助你在优化请求的时延上大做文章,在不需要任何代码改动的情况下,便可以使用SMC-R来获得收益。 + +### 吞吐收益 + +![](https://oss.openanolis.cn/sig/xlluifunfureocmdguuk) + +同样的,在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 资源,进而提高了网络吞吐、降低了网络时延。 + +![](https://oss.openanolis.cn/sig/ogivttvkizwrxxmvhltg) + +因此,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 实体。 + +![](https://oss.openanolis.cn/sig/odsxqmylydvjaufgkqbs) + +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://oss.openanolis.cn/sig/nwcyhydqswkpvarkqhgj) + +
(图片来自于 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 充当传输过程中的共享内存。 + +![](https://oss.openanolis.cn/sig/rlxxabffbvvnikjxuvey) + +# 四、应用场景 + +## 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。 + + +![](https://oss.openanolis.cn/sig/kmlhvlzhyaiiuragpofq) + +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”中所述。 + +![](https://oss.openanolis.cn/sig/xmjtsvlwrgbnigtfeqmf) + +利用 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 高性能网络协议栈。 + +![](https://oss.openanolis.cn/sig/lyzfztfmqfoguaoxelzx) + +接下来在“网络和安全组”页面,弹性网卡中勾选“弹性 RDMA 接口”。 + +![](https://oss.openanolis.cn/sig/jyltbebwahuwdcuduexn) + +对于已经创建的 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]文档。 + +![](https://oss.openanolis.cn/sig/ydxsbbgdyctbcxluaehq) + +![](https://oss.openanolis.cn/sig/oxoayutodtdympzxkpew) + +从测试结果可以看出,无论是 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 技术、拥有更好的性能、可靠的稳定性、丰富成熟的透明替换方案和及时的更新维护。 + +![](https://oss.openanolis.cn/sig/mvhfmmhwckaninvsrfda) + +# 组织原则 + +共赢、平等、开源 + +# 目标愿景 + +- 探索 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 总览 + + + + + + + + +![](assets/Ftrace:_osnoise_总览/img_0.png) + + +## 一、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)。 + + +如图所示: + + +![](assets/Ftrace:_osnoise_总览/img_1.png) + + +在一段时间内,采样线程不断的去循环读取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` + + + + + +![](assets/Ftrace:_osnoise_总览/img_2.png) + + +这里显示的是系统整体采样的结果各个字段的含义如下: + + +* 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` + + +输出如下所示: + + +![](assets/Ftrace:_osnoise_总览/img_3.png) + + + +日志中包含了所有噪声的详细信息,包括其名字,开始事件,持续时间等等。关于其输出的具体格式可以查看对应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 @@ +![](assets/Pstore前端:DMESG_代码分析/img_0.png) + + +作者:新绎 + + + +## 写在前面 + + +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 @@ +![](assets/Ftrace:_osnoise_代码分析/img_0.png) + + +前面一篇文章中,我们简要的介绍了一下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。** + + +![](assets/Ftrace:_osnoise_代码分析/img_1.png) + +因此,需要高优先级的对低优先级的事件的时间进行校准。 + + ++ 对于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; + + ... +} +``` + + + +分析采样函数的主体逻辑流程图如下所示: + + +![](assets/Ftrace:_osnoise_代码分析/img_2.png) + + +即通过不断的轮询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 总览 + + + + + + + + +![](assets/Ftrace:_osnoise_总览/img_0.png) + + +## 一、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)。 + + +如图所示: + + +![](assets/Ftrace:_osnoise_总览/img_1.png) + + +在一段时间内,采样线程不断的去循环读取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` + + + + + +![](assets/Ftrace:_osnoise_总览/img_2.png) + + +这里显示的是系统整体采样的结果各个字段的含义如下: + + +* 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` + + +输出如下所示: + + +![](assets/Ftrace:_osnoise_总览/img_3.png) + + + +日志中包含了所有噪声的详细信息,包括其名字,开始事件,持续时间等等。关于其输出的具体格式可以查看对应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 @@ +![](assets/Ftrace:_osnoise_代码分析/img_0.png) + + +前面一篇文章中,我们简要的介绍了一下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。** + + +![](assets/Ftrace:_osnoise_代码分析/img_1.png) + +因此,需要高优先级的对低优先级的事件的时间进行校准。 + + ++ 对于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; + + ... +} +``` + + + +分析采样函数的主体逻辑流程图如下所示: + + +![](assets/Ftrace:_osnoise_代码分析/img_2.png) + + +即通过不断的轮询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 @@ +![](assets/Pstore前端:CONSOLE_代码分析/img_0.png) + + +作者:新绎 + + + +# 写在前面 + + +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总览 + + +![](assets/Pstore前端:CONSOLE_代码分析/img_1.png) + + + +# 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 @@ +![](assets/Pstore前端:CONSOLE_代码分析/img_0.png) + + +作者:新绎 + + + +# 写在前面 + + +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总览 + + +![](assets/Pstore前端:CONSOLE_代码分析/img_1.png) + + + +# 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 @@ +![](assets/Pstore前端:DMESG_代码分析/img_0.png) + + +作者:新绎 + + + +## 写在前面 + + +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 @@ + +![](assets/Pstore多后端支持补丁/img_0.png) + + +作者:新绎 + + +## 写在前面 + + +目前,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; +}; +``` + + +### 前端复用 + + +为了防止每注册一个后端就要注册相应的前端造成过多开销,我们选择对已经注册好的前端进行复用。如果当多个后端同时使能了同一前端,那么这个前端将会把自己收集的信息多写到这几个后端当中。 + + +![image.png](../../../assets/内核调测/Pstore多后端支持补丁/img_1.png) + + + +代码实现: + + + +``` +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`下建立相应后端的子文件夹,实现文件归类 + + +![](../../../assets/内核调测/Pstore多后端支持补丁/img_2.png) + + + +## 总结 + + +多后端支持的引入让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顺带进行保存,如下图所示: + + +![](assets/基于pstore的kdump调测工具/img_0.png) + + +但是,这样的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存储逻辑如下: + + +![](assets/基于pstore的kdump调测工具/img_1.png) + + +对于用户态信息,pmsg只会接受用户对其的输入信息,而不会主动获取。而可以产生用户态输出的程序和服务有许多,包括各种service以及dump相关脚本,如果想采用这样一个方案进行用户态信息的收集,我们需要对用户态的输出进行重定向到pmsg。这样的操作有两个比较大的问题: + + +1、重定向后原有的串口将不显示输出 + + +2、如果想cover所有用户态输出,需要在用户态进行大量的修改 + + +所以,我们希望从根源上高效地解决问题。我们注意到所以用户态向串口输出都会走tty驱动,那么我们可以实现一个新的pstore前端,该前端在tty驱动前有一个hook点,我们可以直接获取到用户态向tty驱动的输出,从而获取相关的log信息。 + + +![](assets/基于pstore的kdump调测工具/img_2.png) + + +## 工具流程 + + +基于pstore的kdump调测工具主要工作在crash kernel中,在crash kernel中配置好pstore后端ramoops相应的参数(内存地址,预留空间大小等),在crash kernel启动过程中会使能pstore并且获取内核态以及用户态的信息,实时输出到ramoops配置好的持久化内存当中。 + + +由于机器重启不会掉电(正常情况下),当我们重回第一个kernel的之后,我们对那块内存进行解析,就可以获取crash kernel相应的log输出。 + + +![](assets/基于pstore的kdump调测工具/img_3.png) + + +## 使用 + + +我们对工具进行了包装,与kdump进行融合,pstore相关的配置将由相应的脚本自动实现,使用者无需进行配置。在正常使用过程中,我们将工具包装进了kdumpctl命令。 + + +只需要在crash kernel执行过后输入kdumpctl showdebug,就可以很方便地对crash kernel的log输出进行查看。 + + +![](assets/基于pstore的kdump调测工具/img_4.png) + 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镜像」,进入新建页面。 +![输入图片说明](../../assets/构建平台ABS/image9.png) + +根据需求填写对应的设置参数。 +![输入图片说明](../../assets/构建平台ABS/image8.png) + +配置参数: + +| 名称 |描述 | +|---|---| +| 镜像名称 | 该产出物为镜像所用名的名称,支持自定义命名。产出物可用于后续部署任务。 | +| 描述 | 概述镜像的内容。 | +| 仓库地址 | 用户所用的仓库地址 | +| 分支名称 | 用户所用的分支 | +| Dockerfile文件路径 | Dockerfile存放的路径URL。| + +##### 删除 +点击镜像详情,右侧的「删除」按钮,即可完成删除。 +![输入图片说明](../../assets/构建平台ABS/image12.png) + + +### 云原生ACNS版本 +龙蜥云原生套件是龙蜥社区社区云原生SIG输出的基于kubernetes发行版本为基础而集成的套件能力,可以提供一键式部署、开箱即用、以及丰富的云原生基础能力。 +##### 新建 +点击 「+ 新建」>「云原生ACNS版本」,进入新建页面。 +![输入图片说明](../../assets/构建平台ABS/image10.png) +根据需求填写对应的设置参数。 + +![输入图片说明](../../assets/构建平台ABS/image11.png) + +配置参数: + +| 名称 |描述 | +|---|---| +| 构建名称 | 该产出物为构建所用名的名称。 | +| 描述 | 概述构建的内容。 | +| 产品及版本 | 目前仅支持基于anolis-cloud-native仓库产品的ACNS构建。| +| 镜像名称 | 默认:anolis-cloud-native | +| 架构 | 目前仅支持x86_84。 | +| 仓库地址 | 使用默认。 | +| 分支名称 | 使用默认。 | + +##### 删除 +点击镜像详情,右侧的「删除」按钮,即可完成删除。 +![输入图片说明](../../assets/构建平台ABS/image13.png) + + + 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平台。 +![输入图片说明](../../assets/构建平台ABS/image14.png) + +Tips:\ + a. 目前只支持Gitee仓库的单个软件包导入。\ + b. 不可重复的导入相同分支下的软件包。\ + c. 软件包描述暂不支持后期修改内容。请项目拥有者谨慎填写。 + +#### 从平台上选择 + 点击 「+ 添加软件包」>「从外部导入」,项目拥有者可以从ABS平台上公开软件包导入。 +![输入图片说明](../../assets/构建平台ABS/image15.png) + + +### 构建软件包 +#### 需要完成基础设置 +创建项目,并将软件包添加到该项目。 +![输入图片说明](../../assets/构建平台ABS/image15.png) +#### 项目配置产品和OS架构 +![输入图片说明](../../assets/构建平台ABS/image16.png) +#### 开始构建 +##### 测试构建 +准备阶段完成后,在软件包详情页右上角点击「测试构建」即可开始。 + +![输入图片说明](../../assets/构建平台ABS/image17.png) + +##### 生产构建 +准备阶段完成后,在软件包详情页右上角点击「生产构建」即可开始。 + +![输入图片说明](../../assets/构建平台ABS/image19.png) +然后,选择配置的产品类型。 + +![输入图片说明](../../assets/构建平台ABS/image21.png)\ +确定后,跳到官方项目下构建。结束后,可查看构建结果。 + +Tips:\ +个人项目的构建默认属于**测试构建**,rpm包如果有maintainer/contributor权限可以提交**生产构建**。 + +#### 构建结果 +构建结束后,可查看构建结果。 + +![输入图片说明](../../assets/构建平台ABS/image18.png)\ +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. **镜像总览:** 主要提供了镜像维度和构建状态总览两个视角。 +![输入图片说明](../../assets/构建平台ABS/image1.jpg) + + +#### 二.如何新建镜像和删除 + +##### 新建 +点击 「+ 新建Rebrand镜像」 ,可以进入表单填写页,根据需求填写对应的设置参数。 +![输入图片说明](../../assets/构建平台ABS/image2.jpg) + +基本格式如下: + +| 名称 | 描述 | +|------|------| +| 镜像名称 | 生成镜像文件的名称。 | +| 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个构建一个镜像同时构建,如需构建多个镜像,请在上一个镜像构建完成后,再次进行构建镜像。 + +##### 删除 +选择要删除的镜像,在详情页右上角选择「删除」即可。 + +![输入图片说明](../../assets/构建平台ABS/image3.jpg) + + +### 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/),如果没有注册过龙蜥社区需要先进行注册。实验室首页如下图所示: +![image.png](https://oss.openanolis.cn/blog/qjoovhpirjgpxbvwcarp) +二、打开创作中心,把鼠标放在右上角个人头像上会出现下拉选择框,选择【创作中心】 +![image.png](https://oss.openanolis.cn/blog/iuhzoxmcziyxdqalmkcx) +三、创作课程,点击右上角【创作课程】按钮 +![image.png](https://oss.openanolis.cn/blog/grnbwrykgbilbnqsdpsr) +打开创作课程后填写课程信息,其中字段描述如下: + +1. 课程名称:课程展示的标题;2. 课程描述:课程描述;3. 课程分类:选择课程学习;4. 课程难度:分为初级、中级、高级等,选择对应的课程难度;5: 课程总时长:输入一个数字,比如30,代表用户学习完课程需要花费30min;6:课程封面图:可以上传自定义的课程封面,如果不上传则有默认封面图提供;7. 课程领域: 目前提供内核、编译器、云原生、CentOS 迁移、算法、IO、DDE等领域分类,选择一个课程所属的领域。 + +![image.png](https://oss.openanolis.cn/blog/zagpbtiwqioabfmwecsr) +填完课程基本信息后添加保存即可。 + +三、添加章节,创作完课程之后为课程添加一个章节,在课程最后侧点击【添加章节】按钮 +![image.png](https://oss.openanolis.cn/blog/rddrdzvroktifkvfugwf) +打开添加章节后填写章节信息,其中字段描述如下: + +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等。 + +![image.png](https://oss.openanolis.cn/blog/hoqhmeqwianznppvlndk) +四、添加步骤,填写完章节信息之后,点击【添加 Steps】按钮,为章节添加一个步骤,其中 +步骤类型分为START、STEPS、FINISH, START表示步骤开始,顺序为1,STEPS 为步骤正文,FINISH 为步骤结束。右侧是一个 Markdown 输入框,用于输入步骤内容,支持预览,上传图片等操作。 +![image.png](https://oss.openanolis.cn/blog/uzneppbbgxzttulkvqiz) +添加完步骤后点击保存即可,如果步骤内容中有 shell 命令, 请使用 [[ ]] 替代markdown中的代码格式,这样审核通过后可以在页面上直接点击命令将命令自动粘贴到右侧的终端内。 + +五、提交审核,课程编写完成之后可以通过【预览】功能进行预览,没有问题之后点击【下载配置】按钮进行配置下载,下载完之后点击【提交审核】按钮 +![image.png](https://oss.openanolis.cn/blog/syvxymjumleeyarstugz) +点击完提交审核按钮之后,将下载下来的配置在gitee仓库(https://gitee.com/anolis/anolis-lab-courses),anolis-courses 目录下提交一个课程pr,并将pr链接填进输入框,点击确定即可。 +![image.png](https://oss.openanolis.cn/blog/xxstihbdkpgnyoseuclf) +![image.png](https://oss.openanolis.cn/blog/ezsreejpfrukrvlxlkth) +六、提交审核之后等待管理员审核,管理员审核通过之后在实验室课程中心就能看到了 +![image.png](https://oss.openanolis.cn/blog/anamxvcefkymizldwtel) +以上就是龙蜥实验室创作中心创作课程的完整过程,如使用过程中有问题,欢迎联系[基础设施 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. + +![](../../assets/MCA_categories_2.png) + +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. + +![ras_x86.png](../../assets/ras_x86.png) + +### 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. +![m1_ras_flow.png](../../assets/m1_ras_flow.png) + +- 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. + +![RAS_OS_Error_Flow.png](../../assets/RAS_OS_Error_Flow.png) + +### 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. + +![EL0_Recovery.png](../../assets/EL0_Recovery.png) + +#### 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. + +![uaccess.png](../../assets/uaccess.png) + +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. + +![EL2_Recovery_x86.png](../../assets/EL2_Recovery_x86.png) + +#### 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. + +![scrub_recovery](../../assets/Scrub_Recovery.png) + +#### 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 首页** + +![image.png](../../assets/bugzilla/mainpage1.png) +## 二. Bug生命周期 + +- **2.1 新建Bug** + - **2.1.1 路径** + + 首页->New/File a Bug->Select a classification->Select a product->Bug创建页面。具体如下:首先,在首页点击New或File a Bug按钮,进行创建Bug。 + ![image.png](../../assets/bugzilla/new.png) + 然后会提示让选择一个classification, classification是Bug的一级分类。 + ![image.png](../../assets/bugzilla/classification.png) + 选择完classification分类后会提示选择一个product,product是Bug的二级分类。 + ![image.png](../../assets/bugzilla/product.png) + + - **2.1.2 创建页面** + + 选择完product产品后会进入Bug创建页面,创建页面有一些参数需要填充,具体参数含义如下图所示: + ![image.png](../../assets/bugzilla/param-info.png) + +- **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 列表页。 + ![image.png](../../assets/bugzilla/bug-list.png) + 然后在Bug List列表页点击Bug ID或Summary进入Bug编辑页面。 + ![image.png](../../assets/bugzilla/bug-list-2.png) + + - **2.2.2 编辑页面** + + Bug编辑页面也进行Bug一些字段的修改,编辑页面的字段同Bug创建。 + ![image.png](../../assets/bugzilla/edit-param.png) + +- **2.3 关闭Bug** + - **2.3.1 路径** + - Bug编辑页面->Status->Resolved、Fixed->Save Changes + + 在Bug页面编辑Status状态,当状态被修改为[RESOLVED,FIXED]时表示Bug关闭,至此Bug的生命周期结束。 + ![image.png](../../assets/bugzilla/bugstatus.png) + +## 三. 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、评论、组件、产品等的操作,具体如下: + ![image.png](../../assets/bugzilla/api.png) + +- **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/) + + ![image.png](../../assets/bugzilla/plugin.png) + +- 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权限 和当前帐号权限一致。 + + ![image.png](../../assets/bugzilla/api-key.png) + + - 配置bugzillarc文件,配置url和api_key,python-bugzilla-cli插件可自动读取配置的参数,在使用命令时无需额外携带参数,bugzillarc文件内容如下: + + ![image.png](../../assets/bugzilla/bugzillarc.png) + +- 3.3 插件使用: + - 配置好bugzillarc文件之后,就可以使用bugzilla-anolis命令操作Bugzilla了,使用bugzilla-anolis命令查看当前支持的所有参数: + + ![image.png](../../assets/bugzilla/bugzilla-anolis.png) + + - 执行sub component相关命令: + - 查询: + ```json + bugzilla-anolis getsubcomponent --ids=10 --ids=11 + ``` + ![image.png](../../assets/bugzilla/sub component.png) + + - 添加: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" + + ![image.png](../../assets/bugzilla/addsubcomponent.png) + + - 删除:bugzilla-anolis deletesubcomponent --ids=39 --product=testfarm --component=user + + ![image.png](../../assets/bugzilla/deletesubcomponent.png) 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 的生命周期重要指标之一)。 +大致原理图如下: +![](https://intranetproxy.alipay.com/skylark/lark/0/2021/png/65019/1634611841498-077bbdf1-7867-471c-9a0f-385726a16317.png#crop=0&crop=0&crop=1&crop=1&from=url&id=ubwMo&margin=%5Bobject%20Object%5D&originHeight=472&originWidth=752&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=) +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文件。 +![image.png](https://intranetproxy.alipay.com/skylark/lark/0/2022/png/337836/1661235609734-7ba8d8fa-ad68-48ab-b4dd-d5067bfbe1f8.png#clientId=u03c343e1-5eb0-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=208&id=u38b8d83b&margin=%5Bobject%20Object%5D&name=image.png&originHeight=415&originWidth=750&originalType=binary&ratio=1&rotation=0&showTitle=false&size=50664&status=done&style=none&taskId=uae858605-9a2f-42f2-b4fd-a200b49becc&title=&width=375) +这些IR文件再次并发经过优化器优化后,生成真正的二进制对象文件并传递给真正的链接器进行链接,最后得到可执行文件。 +![image.png](https://intranetproxy.alipay.com/skylark/lark/0/2022/png/337836/1661235644272-166afe2c-01ca-4321-9cff-32cb57d98471.png#clientId=u03c343e1-5eb0-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=144&id=ub8d56a1c&margin=%5Bobject%20Object%5D&name=image.png&originHeight=287&originWidth=750&originalType=binary&ratio=1&rotation=0&showTitle=false&size=37694&status=done&style=none&taskId=ue2789136-02a4-4e5b-9b29-83087681c78&title=&width=375) +# 使用方法 +举例说明如何使用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 +``` +如下图: + +![bootloader_info1](../../assets/bootloader_info_4.jpg) +## 国产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 +``` +效果如下图: + +![enable-smee](../../assets/enable-smee.png) + +海光C86-4G配置 +``` +Advanced -> HYGON CBS -> Core Common Options +``` +效果如下图: + +![enable-smee](../../assets/enable-smee_4.png) +### 2. DCU直通功能 + +要使用DCU直通功能,必须进入BIOS设置,通过以下路径打开IOMMU功能。 + +#### CPU BIOS配置参考 +海光2号配置 +``` +HYGON CBS -> NBIO Common Options -> NB Configuration -> IOMMU +``` +``` +Setup Utility -> Advanced -> HYGON CBS -> NBIO Common Options +``` + +效果如下图: + +![enable-iommu](../../assets/enable-iommu.png) + +海光C86-4G配置 +``` +Advanced -> HYGON CBS -> NBIO Common Options +``` +效果如下图: + +![enable-iommu](../../assets/enable-iommu_4.png) \ 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实体通信过程: + +![单机测试拓扑](../../assets/VPP-IPSec/single_machine_topology.png "单机测试拓扑") + +#### 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. 测试拓扑 + +下图所示为多机测试的拓扑连接: + +![双机测试拓扑](../../assets/VPP-IPSec/dual_machine_topology.png "双机测试拓扑测") + +图中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”命令,如下图所示: + +![worker绑定](../../assets/VPP-IPSec/worker_bound_to_nic.png "选取worker与网卡绑定测") + +上图中,“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实体通信过程: + +![单机测试拓扑](../../assets/VPP-IPSec/single_machine_topology.png "单机测试拓扑") + +#### 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. 测试拓扑 + +下图所示为多机测试的拓扑连接: + +![双机测试拓扑](../../assets/VPP-IPSec/dual_machine_topology.png "双机测试拓扑测") + +图中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”命令,如下图所示: + +![worker绑定](../../assets/VPP-IPSec/worker_bound_to_nic.png "选取worker与网卡绑定测") + +上图中,“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实体通信过程: + +![单机测试拓扑](../../assets/VPP-IPSec/single_machine_topology.png "单机测试拓扑") + +#### 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. 测试拓扑 + +下图所示为多机测试的拓扑连接: + +![双机测试拓扑](../../assets/VPP-IPSec/dual_machine_topology.png "双机测试拓扑测") + +图中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”命令,如下图所示: + +![worker绑定](../../assets/VPP-IPSec/worker_bound_to_nic.png "选取worker与网卡绑定测") + +上图中,“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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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系统。 - -![alt text](https://oss.openanolis.cn/fragment/dziozbchprwncwzhfyhw) - -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,但并不是一个最终的状态。 + + +![](../../assets/公告/【公告-2022.11.14】Cloud_Kernel代码合并流程变更/img_0.png) + + +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规范四篇。 + + +![](../../assets/公告/【公告-2022.7.22】Cloud_Kernel开发流程变更/img_0.png) + + +## 2.2 已熟悉原有提交流程 + + +如果您已经熟悉原来的那套流程,即:制作补丁、开bugzilla、提PR。 + + +那么,**以下步骤需要注意**: + + +**1. 提交PR时,请按照规定格式来写**,而不像之前那样很随意。**该规则已纳入门禁检测**。 + + +PR格式要求带上bugzilla链接和**技术背景描述**(不低于10个字)。请把PR的正文当做向linux社区发送补丁的时候cover-letter那样对待,以便让龙蜥社区开发者了解技术背景。 + + +参考链接:。 + +[参考链接](https://openanolis.cn/sig/Cloud-Kernel/doc/607605992881480196) + + +![](../../assets/公告/【公告-2022.7.22】Cloud_Kernel开发流程变更/img_1.png) + + +**2.** 在PR review完毕,准备添加reviewer的签名后/merge合并时,原来只需要在commit log里面加上reviewed-by即可,现在**要求还要加上PR链接**。**该规则已纳入门禁检测。** + + +参考链接:。 + + +![](../../assets/公告/【公告-2022.7.22】Cloud_Kernel开发流程变更/img_2.png) + + +具体案例您可以参考[这个PR](https://gitee.com/anolis/cloud-kernel/commit/4a1a5547bd7ec65d734368ac8e93e415c52220f0): + + +![](../../assets/公告/【公告-2022.7.22】Cloud_Kernel开发流程变更/img_3.png) + + 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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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 @@ +![](assets/龙蜥内核的_Load_Averages_剖析(上)/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 @@ +![](assets/龙蜥内核的_Load_Averages_剖析(下)/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),来进行**一键申请**和**免费试用**。 + + + +![](assets/【1】Anolis_OS环境搭建教程/img_0.png) + + +  + + +我们提供两种方式安装Anolis OS: + + +* ISO镜像安装 +* qcow虚拟机镜像安装 + + + + +## 一、通过ISO进行安装 + + +### 1.1 ISO镜像下载 + + +登陆下载界面获取Anolis OS最新iso镜像文件 + + + + + +![](assets/【1】Anolis_OS环境搭建教程/img_1.png) + + + + + +### 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**文件进行下载。 + + +![](assets/【1】Anolis_OS环境搭建教程/img_2.png) + + +### 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` + + +![](assets/【1】Anolis_OS环境搭建教程/img_3.png) + + +`systemctl is-enabled libvirtd` + + +![](assets/【1】Anolis_OS环境搭建教程/img_4.png) + + + +#### 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`列出支持的默认配置, 如下: + + +![](assets/【2】内核编译安装_-_Make方式/img_0.png) + + + +### 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) + + +![](assets/【2】内核编译安装_-_Make方式/img_1.png) + + +### 4.2 内核安装 + + +内核编译完成后,我们可以通过执行以下命令对编译好的内核进行安装。 + + + +编译完成后执行make modules\_install 安装内核模块 + + +`make modules_install` + + +安装内核核心文件 + + +`make install` + + +如需将新版本内核设置为默认启动内核,可以使用此命令 + + +`grub2-set-default 0` + + +重启 + + +`reboot` + + + +重启进入系统后,查看内核版本 + + +`uname -a` + + +成功安装。 + + +![](assets/【2】内核编译安装_-_Make方式/img_2.png) + + + +## 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` + + + +![](assets/【2】内核编译安装_-_Make方式/img_3.png) + + +在menuconfig图形界面,我们能够更加清晰地看到各个config相关的详细描述信息,来对各个config的管理的功能有进一步的了解。 + + +在对信息修改后,记住将修改保存到.config + + +![](assets/【2】内核编译安装_-_Make方式/img_4.png) + + + +### 5.3 修改内核名称 + + +在menuconfig界面中,我们还能对编译的内核名称进行修改: + + + +General setup --->local version -append to kernel release + + +此处修改内核名称为5.10.112-001.my\_test\_kernel.x86\_64 + + +![](assets/【2】内核编译安装_-_Make方式/img_5.png) + + +  + + + + +## 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包时,发现有该报错信息: +![](assets/【3】内核编译安装_-_RPM包方式/img_0.png) + + +请使用该命令: + + +`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包如下: + + +![](assets/【3】内核编译安装_-_RPM包方式/img_1.png) + + + + + + + + +### + + 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** 项目】 + + +![](assets/【4-1】向Cloud_Kernel报告BUG/img_0.png) + + +**step 2:** + + +选择bug所属版本 + + +PS: 如果在5.10和4.19上**都存在相应的Bug**,选择5.10并且在描述或者评论中说明相应情况即可。 + + +![](assets/【4-1】向Cloud_Kernel报告BUG/img_1.png) + + +**step 3:** + + +填写Bug详细信息, + + +- 带红色星号(\*)的为**必填/选**内容 +- 点击每个字段的名称,即可跳转该字段的详细介绍 +- 请尽可能的按照bugzilla所提供的描述模版详细描述您的问题。 + + +![](assets/【4-1】向Cloud_Kernel报告BUG/img_2.png) + + +  + + +**step 4:** + + +在完成基本信息的填写之后,需要点击左上角的**【Show Advanced Fields】**,展开进阶选项,如图所示: + + +![](assets/【4-1】向Cloud_Kernel报告BUG/img_3.png) + + +然后在**keyword字段**选择您的工单类型: + + +![](assets/【4-1】向Cloud_Kernel报告BUG/img_4.png) + + +![](assets/【4-1】向Cloud_Kernel报告BUG/img_5.png) + + +**step 5:** + + +当您填写完相关信息之后,点击**【Submit Bug】**即可生成对应的bugzilla工单,每个bugzilla工单都有一个独一无二的ID。 + + +此ID会用于后续您提交patch的一系列流程中。 + + +![](assets/【4-1】向Cloud_Kernel报告BUG/img_6.png) + + + +# + + 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 账号. + + +![](assets/【4】Cloud_Kernel开发基本流程/img_0.png) + + + +### 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仓库至个人账号下。 + + +![](assets/【4】Cloud_Kernel开发基本流程/img_1.png) + + +  + + +2. 克隆完毕之后,git clone 您个人账号下的内核代码库到您的开发环境,进行开发。 + + +![](assets/【4】Cloud_Kernel开发基本流程/img_2.png) + + + +## 二、[bugzilla](https://bugzilla.openanolis.cn/) 确认 + + +1. 提交代码前,根据[**bugzilla教程**](https://openanolis.cn/sig/Cloud-Kernel/doc/607601736106142822)进入bugzilla查看是否有对应的**bugzilla**,如果没有则需要根据教程创建新的bugzilla工单。 +2. 获取**bugzilla ID**。 + + +示例:图中 **1461** 即为bugzilla ID + + +![](assets/【4】Cloud_Kernel开发基本流程/img_3.png) + + +## 三、补丁制作 + + +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】** 创建合并请求; + + +![image.png](assets/【4】Cloud_Kernel开发基本流程/img_4.png) + + +   3. 填写PR信息: + + ++ 选择目标库为 **【kernel/cloud-kernel】** ++ 选取正确的**源及目标分支** ++ 选择合适的**评审人**。自动指定评审人的功能正在开发,目前您可以通过加入[Cloud Kernel Sig 钉钉群](https://openanolis.cn/sig/Cloud-Kernel)与我们取得联系。 + + +![](assets/【4】Cloud_Kernel开发基本流程/img_5.png) + + +  + + +4. 根据[**Cloud-Kernel PR规范**](https://openanolis.cn/sig/Cloud-Kernel/doc/607603338330374166)中的要求,编辑好补丁描述,提交PR请求。[PR示例](https://gitee.com/anolis/cloud-kernel/pulls/449)。 + + +5. 当您提交完PR后,会有机器人自动帮您进行代码审核验证。 + + ++ 代码**检测通过**,会有如下提示: + + +![](assets/【4】Cloud_Kernel开发基本流程/img_6.png) + + ++ 代码**检测未通过**: + + 1. 请自行修改代码后,使用 **`git push --force`** 重新push至个人仓库下 + 2. 在pr链接下评论 **`/retest`** 重新触发代码检测。 + 3. 若因为某些特殊原因导致无法通过检测,可联系maintainer回复 **`/skip-test`** 跳过检测。详见: + + +![](assets/【4】Cloud_Kernel开发基本流程/img_7.png) + + +6. 评审人回复通过并附上签名。 + + +![](assets/【4】Cloud_Kernel开发基本流程/img_8.png) + + + +7. 评审人评论 **`/merge`** 合入代码 + + +![](assets/【4】Cloud_Kernel开发基本流程/img_9.png) + + + + + + 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】** 创建合并请求; + + +![](assets/【5】向Cloud_Kernel报告CVE/img_0.png) + + +3. 填写PR信息: + + ++ 选择目标库为 **【kernel/cloud-kernel】** ++ 选取正确的**源及目标分支** ++ 选择合适的**评审人**。目前自动指定评审人的功能正在开发,您现在可以通过加入[Cloud Kernel Sig 钉钉群](https://openanolis.cn/sig/Cloud-Kernel)与我们取得联系。 + + +![](assets/【5】向Cloud_Kernel报告CVE/img_1.png) + + +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. 填写邮箱地址以及您的名称 + + +![](assets/【6】订阅Cloud_Kernel邮件列表/img_0.png) + + +  + + +3. 点击 **【Subscribe】** 即可完成订阅,您将收到该邮件: + + +![](assets/【6】订阅Cloud_Kernel邮件列表/img_1.png) + + +4. 点击 **【Manage Subscription】** 进入订阅配置 + + +![](assets/【6】订阅Cloud_Kernel邮件列表/img_2.png) + + +  + + +5. 根据提示个人喜好配置**Global Mailman Settings**。 + + +**注意:Delivery status需要Enable**,否则您无法收到我们的邮件。 + + +![](assets/【6】订阅Cloud_Kernel邮件列表/img_3.png) + + 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切换,而是需要从集群迁移视角来看待,做好全局评估与实施方案,做好灾备,灰度,回滚方案,并结合上层业务调度来进行迁移的系统工程。 + +## 方案特色 + +迁移方法论:评估,决策,实施,优化四步迁移法。 + +![迁移方法论(绿色标记)](../../../assets/solution/theory.png) + +迁移评估的5个维度及其关键的决策信息: + +![5个纬度(绿色标记)](../../../assets/solution/5_phases.png) + +迁移实施也是业务迁移实现平稳交付的关键环节,其阶段详细的流程要经过实施方案制定、基础设施准备、业务适配改造、迁移试点、迁移批量实施、割接护航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 +``` +如下图: + +![bootloader_info1](../../assets/bootloader_info_4.jpg) +## 国产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 +``` +效果如下图: + +![enable-smee](../../assets/enable-smee.png) + +海光C86-4G配置 +``` +Advanced -> HYGON CBS -> Core Common Options +``` +效果如下图: + +![enable-smee](../../assets/enable-smee_4.png) +### 2. DCU直通功能 + +要使用DCU直通功能,必须进入BIOS设置,通过以下路径打开IOMMU功能。 + +#### CPU BIOS配置参考 +海光2号配置 +``` +HYGON CBS -> NBIO Common Options -> NB Configuration -> IOMMU +``` +``` +Setup Utility -> Advanced -> HYGON CBS -> NBIO Common Options +``` + +效果如下图: + +![enable-iommu](../../assets/enable-iommu.png) + +海光C86-4G配置 +``` +Advanced -> HYGON CBS -> NBIO Common Options +``` +效果如下图: + +![enable-iommu](../../assets/enable-iommu_4.png) \ 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 @@ ​ ### 平台架构 -![](../../assets/dingding_group.jpeg) +![](assets/jiagou.jpeg) ### 核心特点 - 一站式质量平台:平台打通了测试准备、测试执行、测试分析、测试计划、测试报告、覆盖率检测、智能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!") + +![示例图片](https://pic.rmb.bdstatic.com/bjh/gallery/03e17cba710868d9153176b50a5fca0d1090.jpeg#pic_center=100x100) + +| 列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 +![测试外链图片](https://up.enterdesk.com/2021/edpic/0a/13/7a/0a137aaa28f48af0349cee1e568c0a57_1.jpg) \ 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) +![图片](http://url/a.png) +> 引用 +* 第一项 +* 第二项 +* 第三项 + ++ 第一项 ++ 第二项 ++ 第三项 + +- 第一项 +- 第二项 +- 第三项 +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!") + +![示例图片](https://pic.rmb.bdstatic.com/bjh/gallery/03e17cba710868d9153176b50a5fca0d1090.jpeg#pic_center=100x100) + +| 列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!") + +![示例图片](https://pic.rmb.bdstatic.com/bjh/gallery/03e17cba710868d9153176b50a5fca0d1090.jpeg#pic_center=100x100) +| 列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!") + +![示例图片](https://pic.rmb.bdstatic.com/bjh/gallery/03e17cba710868d9153176b50a5fca0d1090.jpeg#pic_center=100x100) + +| 列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!") + +![示例图片](https://pic.rmb.bdstatic.com/bjh/gallery/03e17cba710868d9153176b50a5fca0d1090.jpeg#pic_center=100x100) + +| 列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 +![测试外链图片](https://up.enterdesk.com/2021/edpic/0a/13/7a/0a137aaa28f48af0349cee1e568c0a57_1.jpg) \ 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 @@ +![](assets/Ftrace:_osnoise_代码分析/img_0.png) + + +前面一篇文章中,我们简要的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。** + + +![](assets/Ftrace:_osnoise_代码分析/img_1.png) + +因此,需要高优先级的对低优先级的事件的时间进行校准。 + + ++ 对于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; + + ... +} +``` + + + +分析采样函数的主体逻辑流程图如下所示: + + +![](assets/Ftrace:_osnoise_代码分析/img_2.png) + + +即通过不断的轮询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 总览 + + + + + + + + +![](assets/Ftrace:_osnoise_总览/img_0.png) + + +## 一、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)。 + + +如图所示: + + +![](assets/Ftrace:_osnoise_总览/img_1.png) + + +在一段时间内,采样线程不断的去循环读取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` + + + + + +![](assets/Ftrace:_osnoise_总览/img_2.png) + + +这里显示的是系统整体采样的结果各个字段的含义如下: + + +* 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` + + +输出如下所示: + + +![](assets/Ftrace:_osnoise_总览/img_3.png) + + + +日志中包含了所有噪声的详细信息,包括其名字,开始事件,持续时间等等。关于其输出的具体格式可以查看对应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 @@ +![](assets/Ftrace:_osnoise_代码分析/img_0.png) + + +前面一篇文章中,我们简要的介绍了一下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。** + + +![](assets/Ftrace:_osnoise_代码分析/img_1.png) + +因此,需要高优先级的对低优先级的事件的时间进行校准。 + + ++ 对于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; + + ... +} +``` + + + +分析采样函数的主体逻辑流程图如下所示: + + +![](assets/Ftrace:_osnoise_代码分析/img_2.png) + + +即通过不断的轮询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 总览 + + + + + + + + +![](assets/Ftrace:_osnoise_总览/img_0.png) + + +## 一、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)。 + + +如图所示: + + +![](assets/Ftrace:_osnoise_总览/img_1.png) + + +在一段时间内,采样线程不断的去循环读取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` + + + + + +![](assets/Ftrace:_osnoise_总览/img_2.png) + + +这里显示的是系统整体采样的结果各个字段的含义如下: + + +* 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` + + +输出如下所示: + + +![](assets/Ftrace:_osnoise_总览/img_3.png) + + + +日志中包含了所有噪声的详细信息,包括其名字,开始事件,持续时间等等。关于其输出的具体格式可以查看对应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 @@ +![](assets/Pstore前端:CONSOLE_代码分析/img_0.png) + + +作者:新绎 + + + +# 写在前面 + + +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总览 + + +![](assets/Pstore前端:CONSOLE_代码分析/img_1.png) + + + +# 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 @@ +![](assets/Pstore前端:DMESG_代码分析/img_0.png) + + +作者:新绎 + + + +## 写在前面 + + +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 @@ +![](assets/Pstore前端:CONSOLE_代码分析/img_0.png) + + +作者:新绎 + + + +# 写在前面 + + +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总览 + + +![](assets/Pstore前端:CONSOLE_代码分析/img_1.png) + + + +# 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 @@ +![](assets/Pstore前端:DMESG_代码分析/img_0.png) + + +作者:新绎 + + + +## 写在前面 + + +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 @@ + +![](assets/Pstore多后端支持补丁/img_0.png) + + +作者:新绎 + + +## 写在前面 + + +目前,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; +}; +``` + + +### 前端复用 + + +为了防止每注册一个后端就要注册相应的前端造成过多开销,我们选择对已经注册好的前端进行复用。如果当多个后端同时使能了同一前端,那么这个前端将会把自己收集的信息多写到这几个后端当中。 + + +![image.png](../../../assets/内核调测/Pstore多后端支持补丁/img_1.png) + + + +代码实现: + + + +``` +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`下建立相应后端的子文件夹,实现文件归类 + + +![](../../../assets/内核调测/Pstore多后端支持补丁/img_2.png) + + + +## 总结 + + +多后端支持的引入让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 @@ +![](assets/Pstore总览/img_0.png) + + +作者:新绎 + + +## 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/*` + + +![](../../../assets/内核调测/Pstore总览/img_1.png) + + + +如图配置,backend = ramoops,compress = deflate,update\_ms = -1 + + +检查相关预留 size 是否配置成功(这里以ramoops后端为例) +`ls /sys/module/ramoops/parameters` +`cat /sys/module/ramoops/parameters/*` + + +![](../../../assets/内核调测/Pstore总览/img_2.png) + + +## pstore使用 + + +pstore使用十分简单,只要我们使能成功,并且检查各项配置都正确,那么pstore已经可以正常工作了。 + + +我们可以通过手动触发crash来查看pstore捕获的日志。 + + +`echo c > /proc/sysrq-trigger` + + +在重启之后,我们可以在`/sys/fs/pstore/*` 看到加载的 pstore 数据 + + +`ls /sys/fs/pstore/` + + +![](../../../assets/内核调测/Pstore总览/img_3.png) + + +## pstore框架梳理 + + +这里后端以ramoops为例,kernel version = 5.10 + + +**【右键-在新标签页中打开图片】[查看原图](https://oss.openanolis.cn/fragment/uqbmggfmkvyziugluctq)** + + +![](../../../assets/内核调测/Pstore总览/img_4.png) + + + +### pstore初始化 + + +pstore的初始化分为两步,首先是pstore前端和后端的初始化,接着是pstore文件系统的初始化 + + +pstore前后端:`postcore_initcall(ramoops_init);` + + +pstore文件系统:`late_initcall(pstore_init);` + + +![](../../../assets/内核调测/Pstore总览/img_5.png) + + +通过查看相关模块初始化定义,我们发现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顺带进行保存,如下图所示: + + +![](assets/基于pstore的kdump调测工具/img_0.png) + + +但是,这样的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存储逻辑如下: + + +![](assets/基于pstore的kdump调测工具/img_1.png) + + +对于用户态信息,pmsg只会接受用户对其的输入信息,而不会主动获取。而可以产生用户态输出的程序和服务有许多,包括各种service以及dump相关脚本,如果想采用这样一个方案进行用户态信息的收集,我们需要对用户态的输出进行重定向到pmsg。这样的操作有两个比较大的问题: + + +1、重定向后原有的串口将不显示输出 + + +2、如果想cover所有用户态输出,需要在用户态进行大量的修改 + + +所以,我们希望从根源上高效地解决问题。我们注意到所以用户态向串口输出都会走tty驱动,那么我们可以实现一个新的pstore前端,该前端在tty驱动前有一个hook点,我们可以直接获取到用户态向tty驱动的输出,从而获取相关的log信息。 + + +![](assets/基于pstore的kdump调测工具/img_2.png) + + +## 工具流程 + + +基于pstore的kdump调测工具主要工作在crash kernel中,在crash kernel中配置好pstore后端ramoops相应的参数(内存地址,预留空间大小等),在crash kernel启动过程中会使能pstore并且获取内核态以及用户态的信息,实时输出到ramoops配置好的持久化内存当中。 + + +由于机器重启不会掉电(正常情况下),当我们重回第一个kernel的之后,我们对那块内存进行解析,就可以获取crash kernel相应的log输出。 + + +![](assets/基于pstore的kdump调测工具/img_3.png) + + +## 使用 + + +我们对工具进行了包装,与kdump进行融合,pstore相关的配置将由相应的脚本自动实现,使用者无需进行配置。在正常使用过程中,我们将工具包装进了kdumpctl命令。 + + +只需要在crash kernel执行过后输入kdumpctl showdebug,就可以很方便地对crash kernel的log输出进行查看。 + + +![](assets/基于pstore的kdump调测工具/img_4.png) + 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 账号。 + + +          ![](../../../assets/内核驱动/OOT驱动开发者指南/img_0.png) + + +签署CLA +向龙蜥OOT贡献代码,必须先签署 CLA。 可以登录龙蜥社区后, 打开[CLA页面](https://openanolis.cn/pact/contributor) 进行 CLA 签署。 + + +注意: + + +* 以人个名义贡献的,可签署个人 CLA; +* 以公司名义贡献的,需要签署公司 CLA; +* 详情请咨询贵公司相关法务。 + + +#### fork代码仓库 + + +1、将maintainer创建好的source tree仓库fork到自己的账户,龙蜥采用PR(Pull Request)的方式合并源码。 + + + ![](../../../assets/内核驱动/OOT驱动开发者指南/img_1.png) + + +2、将fork到个人账号的source tree仓库clone到本地的开发环境。 + + +![](../../../assets/内核驱动/OOT驱动开发者指南/img_2.png) + + +#### 补丁制作 + + +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,进入个人账户下的仓库页面。 + + +![](../../../assets/内核驱动/OOT驱动开发者指南/img_3.png) + + +2、在「Pull Request栏」点击「新建Pull Request」,创建PR。 + + +![](../../../assets/内核驱动/OOT驱动开发者指南/img_4.png) + + +3、填写PR信息: + + +* 选择目标仓库为被fork的source tree仓库。 +* 选择正确的**源及目标分支**。 +* 选择合适的评审人即maintainer,maintainer会将他的账号同步到bugzilla或者钉钉群。 +* 「标题」和「说明」请参考[PR(Pull Request)规范](https://openanolis.cn/sig/Cloud-Kernel/doc/607605992881480196)填写。 + + +![](../../../assets/内核驱动/OOT驱动开发者指南/img_5.png) + + +4、当您提交完PR后,会有机器人自动帮您进行代码审核验证。 + + +* 代码**检测通过**,会有如下提示: + + +![](../../../assets/内核驱动/OOT驱动开发者指南/img_6.png) + + +* 代码**检测未通过**: + + 请自行修改代码后,使用**git push --force**重新push至个人仓库下。 + + 在pr链接下评论 **/retest** 重新触发代码检测。 + + 若因为某些特殊原因导致无法通过检测,可联系maintainer回复**/skip-test**跳过检测。详见:[龙蜥内核代码门禁系统](https://openanolis.cn/sig/SIG-Infra/doc/594387296754325258)。 + + +![](../../../assets/内核驱动/OOT驱动开发者指南/img_7.png) + + +5、评审人(maintainer)回复通过并附上签名。 + + +![](../../../assets/内核驱动/OOT驱动开发者指南/img_8.png) + + +6、依次将PR链接和评审人签名添加到相应 commit log 末尾处,并且使用git push --force 提交更新。 + + +注意:PR链接放在评审人签名前面 + + +格式: + + +Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx Reviewed-by: xxx <邮箱> + + +![](../../../assets/内核驱动/OOT驱动开发者指南/img_9.png) + + +让最后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链接检查命令。 + + +![](../../../assets/内核驱动/OOT驱动开发者指南/img_10.png) + + +8、联系maintainer评论**/merge** 即可进入代码合入流程。 + + +![](../../../assets/内核驱动/OOT驱动开发者指南/img_11.png) + + +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」以保证社区能够第一时间看到。 + +![](https://oss.openanolis.cn/sig/barzdgeglncfymauwenf) + 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。 + + +![](assets/ANCK_ARM64_RAS机制简介/img_0.png) + + +# 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表示由用户自行触发)。 + + +![](assets/ANCK_ARM64_RAS机制简介/img_1.png) + + +上述流程比较简要地介绍了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 +``` + +脚本执行前: + + +![](assets/ANCK_boot_cmdline_基线推荐/img_0.png) + + +脚本执行后: + + +![](assets/ANCK_boot_cmdline_基线推荐/img_1.png) + + +但是在执行脚本后,查看/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功能已开启。![开启THP功能](../../../assets/基础能力和版本演进/ANCK内核功能与接口介绍/img_0.png) +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 +``` + + +查看结果如下图所示:![异步回收机制](../../../assets/基础能力和版本演进/ANCK内核功能与接口介绍/img_1.png) +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实例)资源信息。![free](../../../assets/基础能力和版本演进/ANCK内核功能与接口介绍/img_2.png) +* 如果您在宿主机(Linux实例)中运行命令echo 1 > /proc/sys/kernel/rich\_container\_enable开启了容器资源视图功能,当您在容器中运行free -m命令时,查看到的资源信息如下图所示,该信息为容器资源信息。![free](../../../assets/基础能力和版本演进/ANCK内核功能与接口介绍/img_3.png) + + +## 特殊场景说明 + + +一般情况下,开启容器资源视图功能后,使用相关接口的默认值即可满足常规需求,但您需要注意以下特殊场景的接口配置: + + +对于非共享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:** + + +![](assets/datop技术方案/img_0.png) + + +在大多数情况下,两个最大的未映射区域是堆与最上层mmap() ed区域之间的空隙,以及最下层mmap() ed区域与堆栈之间的空隙, 因为这些间隙在通常的地址空间中是非常大的,排除这些就足够了,所以针对一个工作负载而言,DAMON只需要监控一下这些区域就足够了, 此外,随着工作负载的运行,映射区域发生变化,例如部分最大ummaped区域易主,所以damon设置了一个update周期,去周期性检测这些三大chunks的有效性,重新查找有效的三大chunks,并和现有监测得区域进行对比,删减或者增加。 + + +### region拆分与合并 + + +在获取三大chunks后,damon会按照设定规则,去将这三个chuns划分为不均等的若干分regions, 如下图2所示: + + +**图2:** + + +![](assets/datop技术方案/img_1.png) + + +这些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:** + + +![](../../../assets/基础能力和版本演进/datop技术方案/img_2.png) + + +在用户态,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:** + + +![](../../../assets/基础能力和版本演进/datop技术方案/img_3.png) + + +通过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:** + + +![](../../../assets/基础能力和版本演进/datop技术方案/img_4.png) + + +图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:** + + +![](../../../assets/基础能力和版本演进/datop技术方案/img_5.png) + + +上图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 绑定,均可以得到与理想值相接近的隔离效果。 + + +![](assets/龙蜥_ANCK_5.10_倚天平台_MPAM_测试报告/img_0.png) + + +### 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 逐渐减小。 + + +![](assets/龙蜥_ANCK_5.10_倚天平台_MPAM_测试报告/img_1.png) + + +### 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占比逐渐趋同,总量不变。 + + +![](assets/龙蜥_ANCK_5.10_倚天平台_MPAM_测试报告/img_2.png) + + +### 2.1.4 模拟混部 L3 cache 隔离测试 + + +分别以 SPECjbb 2015 和 stress-ng 程序模拟在线环境和离线环境,对L3 cache隔离功能进行测试。两个环境均运行在 NUMA node 1 上。 + + +在前 40s 的时间内,两个程序共享 L3 cache 资源。在约 40s 后,开始隔离在线和离线L3 cache资源的使用,在离线任务 L3 cache 的配比分别为 0xffff 和 0xf。 + + +![](assets/龙蜥_ANCK_5.10_倚天平台_MPAM_测试报告/img_3.png) + + +通过实验结果可以看到,在 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 和内存带宽资源进行最大最小值限制 +* 提供基于优先级的资源隔离支持 + + +![](assets/龙蜥_ANCK_5.10_倚天平台_MPAM_用户手册/img_0.png) + + +MPAM 驱动作为核心部分,对下完成了 MPAM 硬件功能的访问和设置,包括 MPAM 资源的获取和初始化、MPAM 中断初始化以及对 MPAM 相关寄存器的读写,对上则与 resctrl fs 用户态接口层进行交互。 + + +resctrl fs 接口层以资源调配 group 为单位提供了资源隔离和监控的用户态接口,并通过 info 接口暴露 MPAM 硬件相关信息。此外,其底层还完成了 PARTID 和 PMG 的分配和回收。 + + +## 2.2 MPAM资源隔离特性 + + +MPAM 资源隔离特性的关键是由 MSC 组件维护的资源配置表。资源配置表中包含了不同 PARTID 和对应资源分配方案的映射。 + + +![](assets/龙蜥_ANCK_5.10_倚天平台_MPAM_用户手册/img_1.png) + + +对于每一次资源请求,该资源对应的 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,即可获取到对应的资源使用情况。 + + +![](assets/龙蜥_ANCK_5.10_倚天平台_MPAM_用户手册/img_2.png) + + +## 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 文件系统的目录结构如下图。 + + +![](assets/龙蜥_ANCK_5.10_倚天平台_MPAM_用户手册/img_3.png) + + +### 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。 + + +![](assets/龙蜥_ANCK_5.10_倚天平台_MPAM_用户手册/img_4.png) + + +通过实验结果可以看到,在 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 @@ +![](assets/Plugsched_——_Linux_内核调度器热升级/img_0.png) +文/龙蜥社区内核开发人员 陈善佩、吴一昊、邓二伟 + +# 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 能将调度器子系统从内核中提取出来,以模块的形式对内核调度器进行热升级。通过对调度器模块的修改,能够针对不同业务定制化调度器,而且使用模块能够更敏捷的开发新特性和优化点,并且可以在不中断业务的情况下上线。 + +![](assets/Plugsched_——_Linux_内核调度器热升级/img_1.png) +图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 主要包含两大部分,第一部分是调度器模块边界划分与代码提取部分,第二部分是调度器模块热升级部分,这两部分是整个方案的核心。其整体设计方案如下: + +![](assets/Plugsched_——_Linux_内核调度器热升级/img_2.png) +图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已经申请对应的专利,有独立的知识产权。这些关键的技术使客户有能力在云原生混部场景中根据业务特点给出最优解决方案,可有效提高用户的资源使用率并最终降低用户资源的使用成本,非常适用于容器云混部场景,同时也是大规模化混合部署方案所强依赖的关键技术。 + + +下图是资源隔离能力在整个混部方案中的位置:![](../../../assets/社区研发项目/资源隔离与混部/龙蜥OS资源隔离技术介绍/img_0.png) + + +# 为什么需要资源隔离:**资源隔离会遇到哪些拦路虎** + + +假设我们现在有一台服务器,上面运行了高优的在线业务,以及离线任务也在上面运行运行。在线任务对响应时间 (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) 以及资源竞争分析工具等,提供一整套集监控、告警、运维、诊断等整套的资源隔 离和混部解决方案,如下图所示 + + +![](../../../assets/社区研发项目/资源隔离与混部/龙蜥OS资源隔离技术介绍/img_1.png) + + +## 弹性容器场景的调度器优化 + + +如何保证计算服务质量的同时尽可能提高计算资源利用率,是容器调度的经典问题。随着 CPU 利用率不断 提升,CPU 带宽控制器暴露出弹性不足的问题日趋严重,面对容器的短时间 CPU 突发需求,带宽控制器需要对容器的 CPU 使用进行限流,避免影响负载延迟和吞吐。 + + +Anolis OS 中的 CPU Burst 技术是一种弹性容器带宽控制技术,在满足平均 CPU 使用率低于一定限制的条件下,CPU Burst 允许短时间的 CPU 突发使用,实现服务质量提升和容器负载加速。 + + +在容器场景中使用 CPU Burst 之后,测试容器的服务质量显著提升,如下图所示,在实测中可以发现使用该特性技术以后,RT长尾问题几乎消失。 + + +![](../../../assets/社区研发项目/资源隔离与混部/龙蜥OS资源隔离技术介绍/img_2.png) + + +## 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的异步回收策略,用于按照用户需求提前进行容器级别的内存回收机制,做到提前内存释压。 + + +具体的异步回收过程可以通过下面这幅图进行描述: + + +![](../../../assets/社区研发项目/资源隔离与混部/龙蜥OS资源隔离技术介绍/img_3.png) + + +## Memcg 全局水位线分级 + + +通常资源消耗型的离线任务可能会时常瞬间申请大量的内存,使得系统的空闲内存触及全局min水线,引发系统所有任务进入直接内存回收的慢速流程,时延敏感型的在线业务很容易发生性能抖动。此场景下,无论是全局kswapd后台回收还是memcg级别的后台回收机制,都是无能为力的。 + + +我们基于"内存消耗型的离线任务通常对时延不敏感"这样一个事实,设计了"memcg的全局min水线分级功能"来解决上述抖动难题。在标准upstream全局共享min水线的基础上,将离线任务的全局min水线上移让其提前进入直接内存回收,同时将时延敏感的在线任务的全局min水线下移,在一定程度上实现了离线任务和在线任务的min水线隔离。这样当离线任务瞬间大量内存申请的时候,会将离线任务抑制在其上移的min水线,避免了在线任务发生直接内存回收,随后当全局kswapd回收一定量的内存后,离线任务的短时间抑制得以解除。 + + +我们的核心思想就是通过为在离线容器设置不同标准的全局水位线来控制在离线容器申请内存的动作,这样能让离线容器的任务在申请内存时先与在线业务进入直接内存回收,用于解决离线容器瞬间申请大量内存引发的问题。 + + +对linux内存管理有一定基础的同学也可以查阅下面这幅图,他详细的记录了在离线容器混部过程中在多种水位线的作用下的一个走势图: + + +![](../../../assets/社区研发项目/资源隔离与混部/龙蜥OS资源隔离技术介绍/img_4.png) + + +## 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已经被打满: + + +![](../../../assets/社区研发项目/资源隔离与混部/龙蜥os资源隔离使用简介/img_0.png) + + +而此时,我们可以通过查看 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 +``` + +![](../../../assets/社区研发项目/资源隔离与混部/龙蜥os资源隔离使用简介/img_1.png) + + +可以看到,计算机的 CPU 使用率立刻降到了 20%. + + +除 CPU 子系统外,Cgroups 的每一个子系统都有其独有的资源限制能力,比如: + + ++ blkio,为块设备设定I/O 限制,一般用于磁盘等设备; ++ cpuset,为进程分配单独的 CPU 核和对应的内存节点; ++ memory,为进程设定内存使用的限制。 + + +Linux Cgroups 的设计还是比较易用的,简单粗暴地理解呢,它就是一个子系统目录加上一组资源限制文件的组合。而对于 Docker 等 Linux 容器项目来说,它们只需要在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录),然后在启动容器进程之后,把这个进程的 PID 填写到对应控制组的 tasks 文件中就可以了。 + + +# 特别提醒 + + +Alinux内核完全兼容对应的centos的原生内核,所以这意味着所有centos内核中自带的资源隔离方法在Alinux中都有,阿里云在各个资源维度有针对云原生场景下的各种需要进行资源隔离的场景做了额外的优化,这部分的优化内容并不能方向从centos中找到,属于阿里云的核心资源隔离能力,详细使用细节可以参见各个资源的指导手册。 + + +# 内存资源隔离使用指导 + + +![](../../../assets/社区研发项目/资源隔离与混部/龙蜥os资源隔离使用简介/img_2.png) + + +* 频繁的全局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水位线时,此时回收线程就会停止回收。 + + +![](../../../assets/社区研发项目/资源隔离与混部/龙蜥os资源隔离使用简介/img_3.png) + + +具体的异步回收过程可以通过下面这幅图进行描述: + + +![](../../../assets/社区研发项目/资源隔离与混部/龙蜥os资源隔离使用简介/img_4.png) + + +### 使用说明 + + + + +| | | +| --- | --- | +| 接口 | 简介 | +| 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,你可以理解为这个水线下的内存是禁止被回收的。 | + + +  + + +我们这边通过下面这幅图来举例说明这个过程: + + +![](../../../assets/社区研发项目/资源隔离与混部/龙蜥os资源隔离使用简介/img_5.png) + + +我们假设整个系统只有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进行直接内存回收,此时在线容器的服务质量才会受到影响。很明显,这种多标准的水位线可以为我们解决"需求背景"中描述的问题,防止离线容器由于瞬间申请大量内存而把系统内存耗尽而影响在线业务。 + + +![](../../../assets/社区研发项目/资源隔离与混部/龙蜥os资源隔离使用简介/img_6.png) + + +  + + +对linux内存管理有一定基础的同学也可以查阅下面这幅图,他详细的记录了在离线容器混部过程中在多种水位线的作用下的一个走势图: + + +![](../../../assets/社区研发项目/资源隔离与混部/龙蜥os资源隔离使用简介/img_7.png) + + +### 使用说明 + + +这里主要通过配置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的概率。 + + +![](../../../assets/社区研发项目/资源隔离与混部/龙蜥os资源隔离使用简介/img_8.png) + + +### 使用说明 + + +通过按需配置/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为通用的内核资源隔离技术,这里不做使用说明介绍,有兴趣的同学可以参考网上相关资料。 + + +![](../../../assets/社区研发项目/资源隔离与混部/龙蜥os资源隔离使用简介/img_9.png) + + +## CPU Burst-弹性CPU带宽控制技术 + + +### 需求来源 + + +我们的服务宗旨是让客户花最少的钱获得最好的服务质量,或者让单个容器在保证业务服务质量的同时尽量提高容器的cpu使用率,让用户在有限的资源下运行更多的任务,等于降低了用户的使用成本,但是在现实的场景中,在业务的视角可能会出现容器的cpu平均使用率并不高,但是业务的容器却时不时的会出现短时间内的throttle现象,由于容器被限流最终导致业务延迟等问题。比如如下图所示: + + +![](../../../assets/社区研发项目/资源隔离与混部/龙蜥os资源隔离使用简介/img_10.png) + + +从图中可以看到在一个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的风险。 + + +这边通过场景演示来说明一下这个原理: + + +![](../../../assets/社区研发项目/资源隔离与混部/龙蜥os资源隔离使用简介/img_11.png) + + +### 使用说明 + + +* 如果要使用此功能,首先要确保以下配置是否打开,默认是打开状态。 + + + +``` +[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资源隔离使用指导 + + +![](../../../assets/社区研发项目/资源隔离与混部/龙蜥os资源隔离使用简介/img_12.png) + + +## 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 +* ![](../../../assets/社区研发项目/资源隔离与混部/龙蜥os资源隔离使用简介/img_13.png) + + +## 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,它就被激活,此时会计算在整棵层级树中的权重比例。以如下层级为例: + + +![](../../../assets/社区研发项目/资源隔离与混部/龙蜥os资源隔离使用简介/img_14.png) + + +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,但并不是一个最终的状态。 + + +![](../../assets/公告/【公告-2022.11.14】Cloud_Kernel代码合并流程变更/img_0.png) + + +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规范四篇。 + + +![](../../assets/公告/【公告-2022.7.22】Cloud_Kernel开发流程变更/img_0.png) + + +## 2.2 已熟悉原有提交流程 + + +如果您已经熟悉原来的那套流程,即:制作补丁、开bugzilla、提PR。 + + +那么,**以下步骤需要注意**: + + +**1. 提交PR时,请按照规定格式来写**,而不像之前那样很随意。**该规则已纳入门禁检测**。 + + +PR格式要求带上bugzilla链接和**技术背景描述**(不低于10个字)。请把PR的正文当做向linux社区发送补丁的时候cover-letter那样对待,以便让龙蜥社区开发者了解技术背景。 + + +参考链接:。 + + +![](../../assets/公告/【公告-2022.7.22】Cloud_Kernel开发流程变更/img_1.png) + + +**2.** 在PR review完毕,准备添加reviewer的签名后/merge合并时,原来只需要在commit log里面加上reviewed-by即可,现在**要求还要加上PR链接**。**该规则已纳入门禁检测。** + + +参考链接:。 + + +![](../../assets/公告/【公告-2022.7.22】Cloud_Kernel开发流程变更/img_2.png) + + +具体案例您可以参考[这个PR](https://gitee.com/anolis/cloud-kernel/commit/4a1a5547bd7ec65d734368ac8e93e415c52220f0): + + +![](../../assets/公告/【公告-2022.7.22】Cloud_Kernel开发流程变更/img_3.png) + + 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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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 @@ +![](assets/龙蜥内核的_Load_Averages_剖析(上)/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 @@ +![](assets/龙蜥内核的_Load_Averages_剖析(下)/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),来进行**一键申请**和**免费试用**。 + + + +![](assets/【1】Anolis_OS环境搭建教程/img_0.png) + + +  + + +我们提供两种方式安装Anolis OS: + + +* ISO镜像安装 +* qcow虚拟机镜像安装 + + + + +## 一、通过ISO进行安装 + + +### 1.1 ISO镜像下载 + + +登陆下载界面获取Anolis OS最新iso镜像文件 + + + + + +![](assets/【1】Anolis_OS环境搭建教程/img_1.png) + + + + + +### 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**文件进行下载。 + + +![](assets/【1】Anolis_OS环境搭建教程/img_2.png) + + +### 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` + + +![](assets/【1】Anolis_OS环境搭建教程/img_3.png) + + +`systemctl is-enabled libvirtd` + + +![](assets/【1】Anolis_OS环境搭建教程/img_4.png) + + + +#### 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`列出支持的默认配置, 如下: + + +![](assets/【2】内核编译安装_-_Make方式/img_0.png) + + + +### 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) + + +![](assets/【2】内核编译安装_-_Make方式/img_1.png) + + +### 4.2 内核安装 + + +内核编译完成后,我们可以通过执行以下命令对编译好的内核进行安装。 + + + +编译完成后执行make modules\_install 安装内核模块 + + +`make modules_install` + + +安装内核核心文件 + + +`make install` + + +如需将新版本内核设置为默认启动内核,可以使用此命令 + + +`grub2-set-default 0` + + +重启 + + +`reboot` + + + +重启进入系统后,查看内核版本 + + +`uname -a` + + +成功安装。 + + +![](assets/【2】内核编译安装_-_Make方式/img_2.png) + + + +## 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` + + + +![](assets/【2】内核编译安装_-_Make方式/img_3.png) + + +在menuconfig图形界面,我们能够更加清晰地看到各个config相关的详细描述信息,来对各个config的管理的功能有进一步的了解。 + + +在对信息修改后,记住将修改保存到.config + + +![](assets/【2】内核编译安装_-_Make方式/img_4.png) + + + +### 5.3 修改内核名称 + + +在menuconfig界面中,我们还能对编译的内核名称进行修改: + + + +General setup --->local version -append to kernel release + + +此处修改内核名称为5.10.112-001.my\_test\_kernel.x86\_64 + + +![](assets/【2】内核编译安装_-_Make方式/img_5.png) + + +  + + + + +## 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包时,发现有该报错信息: +![](assets/【3】内核编译安装_-_RPM包方式/img_0.png) + + +请使用该命令: + + +`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包如下: + + +![](assets/【3】内核编译安装_-_RPM包方式/img_1.png) + + + + + + + + +### + + 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** 项目】 + + +![](assets/【4-1】向Cloud_Kernel报告BUG/img_0.png) + + +**step 2:** + + +选择bug所属版本 + + +PS: 如果在5.10和4.19上**都存在相应的Bug**,选择5.10并且在描述或者评论中说明相应情况即可。 + + +![](assets/【4-1】向Cloud_Kernel报告BUG/img_1.png) + + +**step 3:** + + +填写Bug详细信息, + + +- 带红色星号(\*)的为**必填/选**内容 +- 点击每个字段的名称,即可跳转该字段的详细介绍 +- 请尽可能的按照bugzilla所提供的描述模版详细描述您的问题。 + + +![](assets/【4-1】向Cloud_Kernel报告BUG/img_2.png) + + +  + + +**step 4:** + + +在完成基本信息的填写之后,需要点击左上角的**【Show Advanced Fields】**,展开进阶选项,如图所示: + + +![](assets/【4-1】向Cloud_Kernel报告BUG/img_3.png) + + +然后在**keyword字段**选择您的工单类型: + + +![](assets/【4-1】向Cloud_Kernel报告BUG/img_4.png) + + +![](assets/【4-1】向Cloud_Kernel报告BUG/img_5.png) + + +**step 5:** + + +当您填写完相关信息之后,点击**【Submit Bug】**即可生成对应的bugzilla工单,每个bugzilla工单都有一个独一无二的ID。 + + +此ID会用于后续您提交patch的一系列流程中。 + + +![](assets/【4-1】向Cloud_Kernel报告BUG/img_6.png) + + + +# + + 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 账号. + + +![](assets/【4】Cloud_Kernel开发基本流程/img_0.png) + + + +### 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仓库至个人账号下。 + + +![](assets/【4】Cloud_Kernel开发基本流程/img_1.png) + + +  + + +2. 克隆完毕之后,git clone 您个人账号下的内核代码库到您的开发环境,进行开发。 + + +![](assets/【4】Cloud_Kernel开发基本流程/img_2.png) + + + +## 二、[bugzilla](https://bugzilla.openanolis.cn/) 确认 + + +1. 提交代码前,根据[**bugzilla教程**](https://openanolis.cn/sig/Cloud-Kernel/doc/607601736106142822)进入bugzilla查看是否有对应的**bugzilla**,如果没有则需要根据教程创建新的bugzilla工单。 +2. 获取**bugzilla ID**。 + + +示例:图中 **1461** 即为bugzilla ID + + +![](assets/【4】Cloud_Kernel开发基本流程/img_3.png) + + +## 三、补丁制作 + + +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】** 创建合并请求; + + +![image.png](assets/【4】Cloud_Kernel开发基本流程/img_4.png) + + +   3. 填写PR信息: + + ++ 选择目标库为 **【kernel/cloud-kernel】** ++ 选取正确的**源及目标分支** ++ 选择合适的**评审人**。自动指定评审人的功能正在开发,目前您可以通过加入[Cloud Kernel Sig 钉钉群](https://openanolis.cn/sig/Cloud-Kernel)与我们取得联系。 + + +![](assets/【4】Cloud_Kernel开发基本流程/img_5.png) + + +  + + +4. 根据[**Cloud-Kernel PR规范**](https://openanolis.cn/sig/Cloud-Kernel/doc/607603338330374166)中的要求,编辑好补丁描述,提交PR请求。[PR示例](https://gitee.com/anolis/cloud-kernel/pulls/449)。 + + +5. 当您提交完PR后,会有机器人自动帮您进行代码审核验证。 + + ++ 代码**检测通过**,会有如下提示: + + +![](assets/【4】Cloud_Kernel开发基本流程/img_6.png) + + ++ 代码**检测未通过**: + + 1. 请自行修改代码后,使用 **`git push --force`** 重新push至个人仓库下 + 2. 在pr链接下评论 **`/retest`** 重新触发代码检测。 + 3. 若因为某些特殊原因导致无法通过检测,可联系maintainer回复 **`/skip-test`** 跳过检测。详见: + + +![](assets/【4】Cloud_Kernel开发基本流程/img_7.png) + + +6. 评审人回复通过并附上签名。 + + +![](assets/【4】Cloud_Kernel开发基本流程/img_8.png) + + + +7. 评审人评论 **`/merge`** 合入代码 + + +![](assets/【4】Cloud_Kernel开发基本流程/img_9.png) + + + + + + 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】** 创建合并请求; + + +![](assets/【5】向Cloud_Kernel报告CVE/img_0.png) + + +3. 填写PR信息: + + ++ 选择目标库为 **【kernel/cloud-kernel】** ++ 选取正确的**源及目标分支** ++ 选择合适的**评审人**。目前自动指定评审人的功能正在开发,您现在可以通过加入[Cloud Kernel Sig 钉钉群](https://openanolis.cn/sig/Cloud-Kernel)与我们取得联系。 + + +![](assets/【5】向Cloud_Kernel报告CVE/img_1.png) + + +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. 填写邮箱地址以及您的名称 + + +![](assets/【6】订阅Cloud_Kernel邮件列表/img_0.png) + + +  + + +3. 点击 **【Subscribe】** 即可完成订阅,您将收到该邮件: + + +![](assets/【6】订阅Cloud_Kernel邮件列表/img_1.png) + + +4. 点击 **【Manage Subscription】** 进入订阅配置 + + +![](assets/【6】订阅Cloud_Kernel邮件列表/img_2.png) + + +  + + +5. 根据提示个人喜好配置**Global Mailman Settings**。 + + +**注意:Delivery status需要Enable**,否则您无法收到我们的邮件。 + + +![](assets/【6】订阅Cloud_Kernel邮件列表/img_3.png) + + 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 @@ +![](assets/Ftrace:_osnoise_代码分析/img_0.png) + + +前面一篇文章中,我们简要的介绍了一下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。** + + +![](assets/Ftrace:_osnoise_代码分析/img_1.png) + +因此,需要高优先级的对低优先级的事件的时间进行校准。 + + ++ 对于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; + + ... +} +``` + + + +分析采样函数的主体逻辑流程图如下所示: + + +![](assets/Ftrace:_osnoise_代码分析/img_2.png) + + +即通过不断的轮询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 总览 + + + + + + + + +![](assets/Ftrace:_osnoise_总览/img_0.png) + + +## 一、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)。 + + +如图所示: + + +![](assets/Ftrace:_osnoise_总览/img_1.png) + + +在一段时间内,采样线程不断的去循环读取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` + + + + + +![](assets/Ftrace:_osnoise_总览/img_2.png) + + +这里显示的是系统整体采样的结果各个字段的含义如下: + + +* 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` + + +输出如下所示: + + +![](assets/Ftrace:_osnoise_总览/img_3.png) + + + +日志中包含了所有噪声的详细信息,包括其名字,开始事件,持续时间等等。关于其输出的具体格式可以查看对应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 @@ +![](assets/Ftrace:_osnoise_代码分析/img_0.png) + + +前面一篇文章中,我们简要的介绍了一下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。** + + +![](assets/Ftrace:_osnoise_代码分析/img_1.png) + +因此,需要高优先级的对低优先级的事件的时间进行校准。 + + ++ 对于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; + + ... +} +``` + + + +分析采样函数的主体逻辑流程图如下所示: + + +![](assets/Ftrace:_osnoise_代码分析/img_2.png) + + +即通过不断的轮询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 总览 + + + + + + + + +![](assets/Ftrace:_osnoise_总览/img_0.png) + + +## 一、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)。 + + +如图所示: + + +![](assets/Ftrace:_osnoise_总览/img_1.png) + + +在一段时间内,采样线程不断的去循环读取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` + + + + + +![](assets/Ftrace:_osnoise_总览/img_2.png) + + +这里显示的是系统整体采样的结果各个字段的含义如下: + + +* 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` + + +输出如下所示: + + +![](assets/Ftrace:_osnoise_总览/img_3.png) + + + +日志中包含了所有噪声的详细信息,包括其名字,开始事件,持续时间等等。关于其输出的具体格式可以查看对应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 @@ +![](assets/Pstore前端:CONSOLE_代码分析/img_0.png) + + +作者:新绎 + + + +# 写在前面 + + +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总览 + + +![](assets/Pstore前端:CONSOLE_代码分析/img_1.png) + + + +# 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 @@ +![](assets/Pstore前端:DMESG_代码分析/img_0.png) + + +作者:新绎 + + + +## 写在前面 + + +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 @@ +![](assets/Pstore前端:CONSOLE_代码分析/img_0.png) + + +作者:新绎 + + + +# 写在前面 + + +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总览 + + +![](assets/Pstore前端:CONSOLE_代码分析/img_1.png) + + + +# 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 @@ +![](assets/Pstore前端:DMESG_代码分析/img_0.png) + + +作者:新绎 + + + +## 写在前面 + + +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 @@ + +![](assets/Pstore多后端支持补丁/img_0.png) + + +作者:新绎 + + +## 写在前面 + + +目前,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; +}; +``` + + +### 前端复用 + + +为了防止每注册一个后端就要注册相应的前端造成过多开销,我们选择对已经注册好的前端进行复用。如果当多个后端同时使能了同一前端,那么这个前端将会把自己收集的信息多写到这几个后端当中。 + + +![image.png](../../../assets/内核调测/Pstore多后端支持补丁/img_1.png) + + + +代码实现: + + + +``` +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`下建立相应后端的子文件夹,实现文件归类 + + +![](../../../assets/内核调测/Pstore多后端支持补丁/img_2.png) + + + +## 总结 + + +多后端支持的引入让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 @@ +![](assets/Pstore总览/img_0.png) + + +作者:新绎 + + +## 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/*` + + +![](../../../assets/内核调测/Pstore总览/img_1.png) + + + +如图配置,backend = ramoops,compress = deflate,update\_ms = -1 + + +检查相关预留 size 是否配置成功(这里以ramoops后端为例) +`ls /sys/module/ramoops/parameters` +`cat /sys/module/ramoops/parameters/*` + + +![](../../../assets/内核调测/Pstore总览/img_2.png) + + +## pstore使用 + + +pstore使用十分简单,只要我们使能成功,并且检查各项配置都正确,那么pstore已经可以正常工作了。 + + +我们可以通过手动触发crash来查看pstore捕获的日志。 + + +`echo c > /proc/sysrq-trigger` + + +在重启之后,我们可以在`/sys/fs/pstore/*` 看到加载的 pstore 数据 + + +`ls /sys/fs/pstore/` + + +![](../../../assets/内核调测/Pstore总览/img_3.png) + + +## pstore框架梳理 + + +这里后端以ramoops为例,kernel version = 5.10 + + +**【右键-在新标签页中打开图片】[查看原图](https://oss.openanolis.cn/fragment/uqbmggfmkvyziugluctq)** + + +![](../../../assets/内核调测/Pstore总览/img_4.png) + + + +### pstore初始化 + + +pstore的初始化分为两步,首先是pstore前端和后端的初始化,接着是pstore文件系统的初始化 + + +pstore前后端:`postcore_initcall(ramoops_init);` + + +pstore文件系统:`late_initcall(pstore_init);` + + +![](../../../assets/内核调测/Pstore总览/img_5.png) + + +通过查看相关模块初始化定义,我们发现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顺带进行保存,如下图所示: + + +![](assets/基于pstore的kdump调测工具/img_0.png) + + +但是,这样的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存储逻辑如下: + + +![](assets/基于pstore的kdump调测工具/img_1.png) + + +对于用户态信息,pmsg只会接受用户对其的输入信息,而不会主动获取。而可以产生用户态输出的程序和服务有许多,包括各种service以及dump相关脚本,如果想采用这样一个方案进行用户态信息的收集,我们需要对用户态的输出进行重定向到pmsg。这样的操作有两个比较大的问题: + + +1、重定向后原有的串口将不显示输出 + + +2、如果想cover所有用户态输出,需要在用户态进行大量的修改 + + +所以,我们希望从根源上高效地解决问题。我们注意到所以用户态向串口输出都会走tty驱动,那么我们可以实现一个新的pstore前端,该前端在tty驱动前有一个hook点,我们可以直接获取到用户态向tty驱动的输出,从而获取相关的log信息。 + + +![](assets/基于pstore的kdump调测工具/img_2.png) + + +## 工具流程 + + +基于pstore的kdump调测工具主要工作在crash kernel中,在crash kernel中配置好pstore后端ramoops相应的参数(内存地址,预留空间大小等),在crash kernel启动过程中会使能pstore并且获取内核态以及用户态的信息,实时输出到ramoops配置好的持久化内存当中。 + + +由于机器重启不会掉电(正常情况下),当我们重回第一个kernel的之后,我们对那块内存进行解析,就可以获取crash kernel相应的log输出。 + + +![](assets/基于pstore的kdump调测工具/img_3.png) + + +## 使用 + + +我们对工具进行了包装,与kdump进行融合,pstore相关的配置将由相应的脚本自动实现,使用者无需进行配置。在正常使用过程中,我们将工具包装进了kdumpctl命令。 + + +只需要在crash kernel执行过后输入kdumpctl showdebug,就可以很方便地对crash kernel的log输出进行查看。 + + +![](assets/基于pstore的kdump调测工具/img_4.png) + 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 账号。 + + +          ![](../../../assets/内核驱动/OOT驱动开发者指南/img_0.png) + + +签署CLA +向龙蜥OOT贡献代码,必须先签署 CLA。 可以登录龙蜥社区后, 打开[CLA页面](https://openanolis.cn/pact/contributor) 进行 CLA 签署。 + + +注意: + + +* 以人个名义贡献的,可签署个人 CLA; +* 以公司名义贡献的,需要签署公司 CLA; +* 详情请咨询贵公司相关法务。 + + +#### fork代码仓库 + + +1、将maintainer创建好的source tree仓库fork到自己的账户,龙蜥采用PR(Pull Request)的方式合并源码。 + + + ![](../../../assets/内核驱动/OOT驱动开发者指南/img_1.png) + + +2、将fork到个人账号的source tree仓库clone到本地的开发环境。 + + +![](../../../assets/内核驱动/OOT驱动开发者指南/img_2.png) + + +#### 补丁制作 + + +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,进入个人账户下的仓库页面。 + + +![](../../../assets/内核驱动/OOT驱动开发者指南/img_3.png) + + +2、在「Pull Request栏」点击「新建Pull Request」,创建PR。 + + +![](../../../assets/内核驱动/OOT驱动开发者指南/img_4.png) + + +3、填写PR信息: + + +* 选择目标仓库为被fork的source tree仓库。 +* 选择正确的**源及目标分支**。 +* 选择合适的评审人即maintainer,maintainer会将他的账号同步到bugzilla或者钉钉群。 +* 「标题」和「说明」请参考[PR(Pull Request)规范](https://openanolis.cn/sig/Cloud-Kernel/doc/607605992881480196)填写。 + + +![](../../../assets/内核驱动/OOT驱动开发者指南/img_5.png) + + +4、当您提交完PR后,会有机器人自动帮您进行代码审核验证。 + + +* 代码**检测通过**,会有如下提示: + + +![](../../../assets/内核驱动/OOT驱动开发者指南/img_6.png) + + +* 代码**检测未通过**: + + 请自行修改代码后,使用**git push --force**重新push至个人仓库下。 + + 在pr链接下评论 **/retest** 重新触发代码检测。 + + 若因为某些特殊原因导致无法通过检测,可联系maintainer回复**/skip-test**跳过检测。详见:[龙蜥内核代码门禁系统](https://openanolis.cn/sig/SIG-Infra/doc/594387296754325258)。 + + +![](../../../assets/内核驱动/OOT驱动开发者指南/img_7.png) + + +5、评审人(maintainer)回复通过并附上签名。 + + +![](../../../assets/内核驱动/OOT驱动开发者指南/img_8.png) + + +6、依次将PR链接和评审人签名添加到相应 commit log 末尾处,并且使用git push --force 提交更新。 + + +注意:PR链接放在评审人签名前面 + + +格式: + + +Link: https://gitee.com/anolis/cloud-kernel/pulls/xxx Reviewed-by: xxx <邮箱> + + +![](../../../assets/内核驱动/OOT驱动开发者指南/img_9.png) + + +让最后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链接检查命令。 + + +![](../../../assets/内核驱动/OOT驱动开发者指南/img_10.png) + + +8、联系maintainer评论**/merge** 即可进入代码合入流程。 + + +![](../../../assets/内核驱动/OOT驱动开发者指南/img_11.png) + + +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」以保证社区能够第一时间看到。 + +![](https://oss.openanolis.cn/sig/barzdgeglncfymauwenf) + 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。 + + +![](assets/ANCK_ARM64_RAS机制简介/img_0.png) + + +# 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表示由用户自行触发)。 + + +![](assets/ANCK_ARM64_RAS机制简介/img_1.png) + + +上述流程比较简要地介绍了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 +``` + +脚本执行前: + + +![](assets/ANCK_boot_cmdline_基线推荐/img_0.png) + + +脚本执行后: + + +![](assets/ANCK_boot_cmdline_基线推荐/img_1.png) + + +但是在执行脚本后,查看/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功能已开启。![开启THP功能](../../../assets/基础能力和版本演进/ANCK内核功能与接口介绍/img_0.png) +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 +``` + + +查看结果如下图所示:![异步回收机制](../../../assets/基础能力和版本演进/ANCK内核功能与接口介绍/img_1.png) +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实例)资源信息。![free](../../../assets/基础能力和版本演进/ANCK内核功能与接口介绍/img_2.png) +* 如果您在宿主机(Linux实例)中运行命令echo 1 > /proc/sys/kernel/rich\_container\_enable开启了容器资源视图功能,当您在容器中运行free -m命令时,查看到的资源信息如下图所示,该信息为容器资源信息。![free](../../../assets/基础能力和版本演进/ANCK内核功能与接口介绍/img_3.png) + + +## 特殊场景说明 + + +一般情况下,开启容器资源视图功能后,使用相关接口的默认值即可满足常规需求,但您需要注意以下特殊场景的接口配置: + + +对于非共享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:** + + +![](assets/datop技术方案/img_0.png) + + +在大多数情况下,两个最大的未映射区域是堆与最上层mmap() ed区域之间的空隙,以及最下层mmap() ed区域与堆栈之间的空隙, 因为这些间隙在通常的地址空间中是非常大的,排除这些就足够了,所以针对一个工作负载而言,DAMON只需要监控一下这些区域就足够了, 此外,随着工作负载的运行,映射区域发生变化,例如部分最大ummaped区域易主,所以damon设置了一个update周期,去周期性检测这些三大chunks的有效性,重新查找有效的三大chunks,并和现有监测得区域进行对比,删减或者增加。 + + +### region拆分与合并 + + +在获取三大chunks后,damon会按照设定规则,去将这三个chuns划分为不均等的若干分regions, 如下图2所示: + + +**图2:** + + +![](assets/datop技术方案/img_1.png) + + +这些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:** + + +![](../../../assets/基础能力和版本演进/datop技术方案/img_2.png) + + +在用户态,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:** + + +![](../../../assets/基础能力和版本演进/datop技术方案/img_3.png) + + +通过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:** + + +![](../../../assets/基础能力和版本演进/datop技术方案/img_4.png) + + +图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:** + + +![](../../../assets/基础能力和版本演进/datop技术方案/img_5.png) + + +上图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 绑定,均可以得到与理想值相接近的隔离效果。 + + +![](assets/龙蜥_ANCK_5.10_倚天平台_MPAM_测试报告/img_0.png) + + +### 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 逐渐减小。 + + +![](assets/龙蜥_ANCK_5.10_倚天平台_MPAM_测试报告/img_1.png) + + +### 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占比逐渐趋同,总量不变。 + + +![](assets/龙蜥_ANCK_5.10_倚天平台_MPAM_测试报告/img_2.png) + + +### 2.1.4 模拟混部 L3 cache 隔离测试 + + +分别以 SPECjbb 2015 和 stress-ng 程序模拟在线环境和离线环境,对L3 cache隔离功能进行测试。两个环境均运行在 NUMA node 1 上。 + + +在前 40s 的时间内,两个程序共享 L3 cache 资源。在约 40s 后,开始隔离在线和离线L3 cache资源的使用,在离线任务 L3 cache 的配比分别为 0xffff 和 0xf。 + + +![](assets/龙蜥_ANCK_5.10_倚天平台_MPAM_测试报告/img_3.png) + + +通过实验结果可以看到,在 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 和内存带宽资源进行最大最小值限制 +* 提供基于优先级的资源隔离支持 + + +![](assets/龙蜥_ANCK_5.10_倚天平台_MPAM_用户手册/img_0.png) + + +MPAM 驱动作为核心部分,对下完成了 MPAM 硬件功能的访问和设置,包括 MPAM 资源的获取和初始化、MPAM 中断初始化以及对 MPAM 相关寄存器的读写,对上则与 resctrl fs 用户态接口层进行交互。 + + +resctrl fs 接口层以资源调配 group 为单位提供了资源隔离和监控的用户态接口,并通过 info 接口暴露 MPAM 硬件相关信息。此外,其底层还完成了 PARTID 和 PMG 的分配和回收。 + + +## 2.2 MPAM资源隔离特性 + + +MPAM 资源隔离特性的关键是由 MSC 组件维护的资源配置表。资源配置表中包含了不同 PARTID 和对应资源分配方案的映射。 + + +![](assets/龙蜥_ANCK_5.10_倚天平台_MPAM_用户手册/img_1.png) + + +对于每一次资源请求,该资源对应的 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,即可获取到对应的资源使用情况。 + + +![](assets/龙蜥_ANCK_5.10_倚天平台_MPAM_用户手册/img_2.png) + + +## 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 文件系统的目录结构如下图。 + + +![](assets/龙蜥_ANCK_5.10_倚天平台_MPAM_用户手册/img_3.png) + + +### 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。 + + +![](assets/龙蜥_ANCK_5.10_倚天平台_MPAM_用户手册/img_4.png) + + +通过实验结果可以看到,在 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 @@ +![](assets/Plugsched_——_Linux_内核调度器热升级/img_0.png) +文/龙蜥社区内核开发人员 陈善佩、吴一昊、邓二伟 + +# 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 能将调度器子系统从内核中提取出来,以模块的形式对内核调度器进行热升级。通过对调度器模块的修改,能够针对不同业务定制化调度器,而且使用模块能够更敏捷的开发新特性和优化点,并且可以在不中断业务的情况下上线。 + +![](assets/Plugsched_——_Linux_内核调度器热升级/img_1.png) +图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 主要包含两大部分,第一部分是调度器模块边界划分与代码提取部分,第二部分是调度器模块热升级部分,这两部分是整个方案的核心。其整体设计方案如下: + +![](assets/Plugsched_——_Linux_内核调度器热升级/img_2.png) +图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代码页数据对比如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img1.png) + + +**图1:arm平台mysql TPS测试数据对比** + + +上图TPS对比可以看出:代码大页的性能始终高于普通的代码页。关于这张图中其他的结论,还有: + +- 并发数为1时,外在的影响因素最小,此时,代码大页相比普通代码页,性能提升大约在6.9%; +- 并发数8、16基本可以保证没有cpu的竞争,代码大页的性能提升大约也在6.5%以上; +- 并发数32时,由于总核数为32,存在于其他应用竞争cpu,所以TPS较低于前面的测试结果。但是代码大页的鲁棒性更好,此时相比普通代码页,性能提升大约在11%左右; + +另外,还有RT的对比,如下图: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img2.png) + + +**图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对比图如下: +![图片 4-x86-TPS和RT.png](../../assets/内核技术分享/代码大页-mysql性能测试/img3.png) + + +**图3(a、b)为TPS、RT对比图** + + +由于TLB硬件的差异,代码大页在x86和arm上性能提升存在差异,根据图6(a、b)中的测试数据,代码大页在x86上,对TPS的提升大致在3%-5之间,在RT上大致有5%-7.5%的收益。 +​ + +除intel Xeon平台,在海光的机器上对mysql数据库+代码大页进行了性能测试。 +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img4.png) + + +**图4 海光平台测试数据。图左为并发数为1的测试(上为普通,下为开启hugetext),图右为并发数为4的测试数据** + + +上图代码大页性能结论为:单核提升6.5%,4并发数提升3.9%; + +## 微架构测试数据 + +除前面展示的mysql数据库中的TPS和RT数据,我们也记录了在测试过程中iTLB miss,以及换算后的iTLB MPKI数据。 +x86和arm平台的数据如下: +​ + +x86平台下的iTLB miss和iTLB MPKI数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img5.png) + + +**图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数据: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img6.png) + + +**图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线程测试。数据如下: +![image.png](../../assets/内核技术分享/代码大页-mysql性能测试/img7.png) +**图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对达梦数据库进行测试: + +![](../../assets/内核技术分享/代码大页-mysql性能测试/img8.png) +**图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 @@ +![](assets/龙蜥内核的_Load_Averages_剖析(上)/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 @@ +![](assets/龙蜥内核的_Load_Averages_剖析(下)/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 + + +## 小组例会 +月会,采用线上会议形式 + +## 钉钉群 + +欢迎使用钉钉扫码入群 + +![](assets/cxl_sig.png) 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),来进行**一键申请**和 **免费试用** 。 + +![](https://intranetproxy.alipay.com/skylark/lark/0/2022/png/63156315/1656644119956-01a1cabe-eb42-4c64-82d8-902d01afb26d.png) + +我们提供两种方式安装Anolis OS: + +* ISO镜像安装 +* qcow虚拟机镜像安装 + +## 一、通过ISO进行安装 + +### 1.1 ISO镜像下载 + +登陆下载界面获取Anolis OS最新iso镜像文件 + +[https://openanolis.cn/download](https://openanolis.cn/download) + +![](https://intranetproxy.alipay.com/skylark/lark/0/2022/png/63156315/1656504756808-2cdce132-2ff8-4d66-a96d-18cd6525601a.png) + +### 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**文件进行下载。 + +![](https://intranetproxy.alipay.com/skylark/lark/0/2022/png/63156315/1656574325523-958feb42-fbbf-4974-9bd9-9d6827dd99db.png) + +### 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` + +![](https://intranetproxy.alipay.com/skylark/lark/0/2022/png/63156315/1656557798218-65ab7a31-63e2-4200-bca5-2ed9f65a169e.png) + +`systemctl is-enabled libvirtd` + +![](https://intranetproxy.alipay.com/skylark/lark/0/2022/png/63156315/1656557863822-cec7389f-3748-43c9-8878-e03fe5906f4f.png) + +#### 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. + +![](../../assets/MCA_categories_2.png) + +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. + +![ras_x86.png](../../assets/ras_x86.png) + +### 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. +![m1_ras_flow.png](../../assets/m1_ras_flow.png) + +- 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. + +![RAS_OS_Error_Flow.png](../../assets/RAS_OS_Error_Flow.png) + +### 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. + +![EL0_Recovery.png](../../assets/EL0_Recovery.png) + +#### 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. + +![uaccess.png](../../assets/uaccess.png) + +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. + +![EL2_Recovery_x86.png](../../assets/EL2_Recovery_x86.png) + +#### 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. + +![scrub_recovery](../../assets/Scrub_Recovery.png) + +#### 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/CoderOneOne/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/Anolis OS\347\216\257\345\242\203\346\220\255\345\273\272\346\225\231\347\250\213.md" "b/sig/CoderOneOne/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/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/content/\345\274\200\345\217\221\350\200\205\346\214\207\345\215\227/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),来进行**一键申请**和 **免费试用** 。 + +![](https://intranetproxy.alipay.com/skylark/lark/0/2022/png/63156315/1656644119956-01a1cabe-eb42-4c64-82d8-902d01afb26d.png) + +我们提供两种方式安装Anolis OS: + +* ISO镜像安装 +* qcow虚拟机镜像安装 + +## 一、通过ISO进行安装 + +### 1.1 ISO镜像下载 + +登陆下载界面获取Anolis OS最新iso镜像文件 + +[https://openanolis.cn/download](https://openanolis.cn/download) + +![](https://intranetproxy.alipay.com/skylark/lark/0/2022/png/63156315/1656504756808-2cdce132-2ff8-4d66-a96d-18cd6525601a.png) + +### 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**文件进行下载。 + +![](https://intranetproxy.alipay.com/skylark/lark/0/2022/png/63156315/1656574325523-958feb42-fbbf-4974-9bd9-9d6827dd99db.png) + +### 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` + +![](https://intranetproxy.alipay.com/skylark/lark/0/2022/png/63156315/1656557798218-65ab7a31-63e2-4200-bca5-2ed9f65a169e.png) + +`systemctl is-enabled libvirtd` + +![](https://intranetproxy.alipay.com/skylark/lark/0/2022/png/63156315/1656557863822-cec7389f-3748-43c9-8878-e03fe5906f4f.png) + +#### 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/CoderOneOne/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/CoderOneOne/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" new file mode 100644 index 0000000000000000000000000000000000000000..b3230c28ce258110ce76f3dd8cbfa7c1c036a7e2 --- /dev/null +++ "b/sig/CoderOneOne/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" @@ -0,0 +1,1001 @@ +from arm-sig: https://openanolis.cn/sig/ARM_ARCH_SIG/doc/657742613244594693 + +一、测试总结 + +针对龙蜥 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 \ No newline at end of file diff --git a/sig/CoderOneOne/sig-info.yaml b/sig/CoderOneOne/sig-info.yaml new file mode 100644 index 0000000000000000000000000000000000000000..484a24099686af3b42474542fee88733647849c7 --- /dev/null +++ b/sig/CoderOneOne/sig-info.yaml @@ -0,0 +1,19 @@ +name: CoderOneOne +en_name: CoderOneOne +home_page: https://openanolis.cn/sig/CoderOneOne +description: 中文描述 +en_description: English description +mailing_list: intel-kernel@lists.openanolis.cn +meeting_url: https://openanolis.cn +maintainers: +- openanolis_id: ceshi002 + gitee_id: coder-one-one + name: + organization: + email: +contributors: +- openanolis_id: ceshi005 + gitee_id: +repositories: +- repo: + - anolis/coder-one-one/ \ No newline at end of file diff --git a/sig/HighPerfStorageSIG/README.en.md b/sig/HighPerfStorageSIG/README.en.md new file mode 100644 index 0000000000000000000000000000000000000000..2c82b33d9b4871067d5f67c6f7dbbe2905dab451 --- /dev/null +++ b/sig/HighPerfStorageSIG/README.en.md @@ -0,0 +1,56 @@ +# SIG Homepage +https://openanolis.cn/sig/high-perf-storage + +# SIG Objectives +There are many applications still relying on standard storage IO interfaces, e.g. standard system calls. High Performance Storage Technologies SIG is focusing on those technologies providing high IO performance for end users. Currently we mainly focus on the next asynchronous IO standard io_uring, and persistent memory related topic, container storage technologes, etc. + +Through community cooperation, we expect to build a standard high performance IO stack, and promote the collaborative development of software and hardware. + +# SIG Members +| ID | Role | +| ------ | ------ | +| josephqi | Maintainer | +| gaoxiang | Maintainer | +| xiaoguangwang | Maintainer | +| wangleic | Maintainer | +| HanGuangyu | Maintainer | +| yxpeng | Maintainer | +| Jingbo Xu | Contributor | +| ZiyangZhang | Contributor | +| hongnan_Li | Contributor | +| HaoXu | Contributor | +| anuo | Contributor | + +# SIG Projects +- io_uring +- virtio-fs +- Container Image Acceleration +- Database Optimization +- Userspace Block Device +- DSMS + +# SIG Repositories +https://gitee.com/anolis/storage-cloud-kernel
+https://gitee.com/anolis/liburing
+https://gitee.com/anolis/fio
+https://gitee.com/anolis/perf-test-for-io_uring
+https://gitee.com/anolis/io_uring-echo-server
+https://gitee.com/anolis/nginx
+https://gitee.com/anolis/redis
+https://gitee.com/anolis/storage-test-scripts
+https://gitee.com/anolis/xfsprogs-dev
+https://gitee.com/anolis/mariadb-server
+https://gitee.com/anolis/erofs-utils
+https://gitee.com/anolis/sealer
+https://gitee.com/anolis/image-service
+https://gitee.com/anolis/libubd
+https://gitee.com/anolis/ubdsrv
+https://gitee.com/anolis/e2fsprogs
+https://gitee.com/anolis/dsms
+ +# SIG Contacts +## Maillist +storage@lists.openanolis.cn + +## DingTalk +![](assets/dingtalk.png) diff --git a/sig/HighPerfStorageSIG/README.md b/sig/HighPerfStorageSIG/README.md new file mode 100644 index 0000000000000000000000000000000000000000..0182e3b2f715e3e3e39dbd8772e34a3d80383956 --- /dev/null +++ b/sig/HighPerfStorageSIG/README.md @@ -0,0 +1,56 @@ +# SIG 主页 +https://openanolis.cn/sig/high-perf-storage + +# SIG 目标 +存储领域的发展历程,本质上是存储介质与软件栈相互促进发展的过程。高性能存储 SIG 致力于存储栈性能挖掘,当前主要聚焦内核 io_uring 技术优化异步 IO 性能,使用持久化内存提升业务单成本性能,容器场景存储技术优化等课题。 + +高性能存储 SIG 期望通过社区合作,打造标准的高性能存储技术软件栈,推动软硬件协同发展。 + +# SIG 成员 +| 成员 | 角色 | +| ------ | ------ | +| josephqi | Maintainer | +| gaoxiang | Maintainer | +| xiaoguangwang | Maintainer | +| wangleic | Maintainer | +| HanGuangyu | Maintainer | +| yxpeng | Maintainer | +| Jingbo Xu | Contributor | +| ZiyangZhang | Contributor | +| hongnan_Li | Contributor | +| HaoXu | Contributor | +| anuo | Contributor | + +# 项目清单 +- io_uring +- virtio-fs +- 容器镜像加速 +- 数据库优化 +- 用户态存储 +- DSMS + +# 代码仓库 +https://gitee.com/anolis/storage-cloud-kernel
+https://gitee.com/anolis/liburing
+https://gitee.com/anolis/fio
+https://gitee.com/anolis/perf-test-for-io_uring
+https://gitee.com/anolis/io_uring-echo-server
+https://gitee.com/anolis/nginx
+https://gitee.com/anolis/redis
+https://gitee.com/anolis/storage-test-scripts
+https://gitee.com/anolis/xfsprogs-dev
+https://gitee.com/anolis/mariadb-server
+https://gitee.com/anolis/erofs-utils
+https://gitee.com/anolis/sealer
+https://gitee.com/anolis/image-service
+https://gitee.com/anolis/libubd
+https://gitee.com/anolis/ubdsrv
+https://gitee.com/anolis/e2fsprogs
+https://gitee.com/anolis/dsms
+ +# 联系方式 +## 邮件列表 +storage@lists.openanolis.cn + +## 钉钉群 +![](assets/dingtalk.png) diff --git a/sig/HighPerfStorageSIG/assets/4k-rand-read-moc.png b/sig/HighPerfStorageSIG/assets/4k-rand-read-moc.png new file mode 100644 index 0000000000000000000000000000000000000000..e57b4b02d5b60a8bd27a5e2d941f87b621b62540 Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/4k-rand-read-moc.png differ diff --git a/sig/HighPerfStorageSIG/assets/4k-rand-read.png b/sig/HighPerfStorageSIG/assets/4k-rand-read.png new file mode 100644 index 0000000000000000000000000000000000000000..d5114f185130af8a4cfacbd8184cc44f2a30aebc Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/4k-rand-read.png differ diff --git a/sig/HighPerfStorageSIG/assets/4k-rand-write.png b/sig/HighPerfStorageSIG/assets/4k-rand-write.png new file mode 100644 index 0000000000000000000000000000000000000000..638675189708c6ce711ccf00f8f081fb6a4234ea Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/4k-rand-write.png differ diff --git a/sig/HighPerfStorageSIG/assets/4k-seq-read.png b/sig/HighPerfStorageSIG/assets/4k-seq-read.png new file mode 100644 index 0000000000000000000000000000000000000000..87485418f513d8b44e04e46591decad9ea5a74f2 Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/4k-seq-read.png differ diff --git a/sig/HighPerfStorageSIG/assets/4k-seq-write.png b/sig/HighPerfStorageSIG/assets/4k-seq-write.png new file mode 100644 index 0000000000000000000000000000000000000000..2e7edf84d33477a93cc3958f43c149e48e10ab61 Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/4k-seq-write.png differ diff --git a/sig/HighPerfStorageSIG/assets/dingtalk.png b/sig/HighPerfStorageSIG/assets/dingtalk.png new file mode 100644 index 0000000000000000000000000000000000000000..33cb8ac45eb340e28f363df868171d8836d15018 Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/dingtalk.png differ diff --git a/sig/HighPerfStorageSIG/assets/double-write.png b/sig/HighPerfStorageSIG/assets/double-write.png new file mode 100644 index 0000000000000000000000000000000000000000..a3a21ce81735a8dda69cb0fd8af0256bc6a41538 Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/double-write.png differ diff --git a/sig/HighPerfStorageSIG/assets/echo-server-qps.png b/sig/HighPerfStorageSIG/assets/echo-server-qps.png new file mode 100644 index 0000000000000000000000000000000000000000..378c5e8a6036495d0ee9f2266cec8da6f3c2b2fc Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/echo-server-qps.png differ diff --git a/sig/HighPerfStorageSIG/assets/echo-server-syscalls.png b/sig/HighPerfStorageSIG/assets/echo-server-syscalls.png new file mode 100644 index 0000000000000000000000000000000000000000..5b45613286a719622b91709d3be6f8c96367b737 Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/echo-server-syscalls.png differ diff --git a/sig/HighPerfStorageSIG/assets/io_uring-arch.png b/sig/HighPerfStorageSIG/assets/io_uring-arch.png new file mode 100644 index 0000000000000000000000000000000000000000..b89adf17f0eb5ade0e2c90eb8f8d2bf75cab944f Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/io_uring-arch.png differ diff --git a/sig/HighPerfStorageSIG/assets/nginx-arch.png b/sig/HighPerfStorageSIG/assets/nginx-arch.png new file mode 100644 index 0000000000000000000000000000000000000000..1030aae9938e4ee2fabab2ec4b9e69d6d6a9582a Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/nginx-arch.png differ diff --git a/sig/HighPerfStorageSIG/assets/nginx-multi-worker-qps.png b/sig/HighPerfStorageSIG/assets/nginx-multi-worker-qps.png new file mode 100644 index 0000000000000000000000000000000000000000..21a14cb70e1dcde1a962726974e24fcaed3b5f48 Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/nginx-multi-worker-qps.png differ diff --git a/sig/HighPerfStorageSIG/assets/nginx-qps.png b/sig/HighPerfStorageSIG/assets/nginx-qps.png new file mode 100644 index 0000000000000000000000000000000000000000..0fc22e2d9639ccaf78827f5ebfdf4cb86467cc5b Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/nginx-qps.png differ diff --git a/sig/HighPerfStorageSIG/assets/nginx-single-worker-qps.png b/sig/HighPerfStorageSIG/assets/nginx-single-worker-qps.png new file mode 100644 index 0000000000000000000000000000000000000000..2b276d414bb2a2d059272ff171ffbd4b5aae1928 Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/nginx-single-worker-qps.png differ diff --git a/sig/HighPerfStorageSIG/assets/redis-epoll-flow.png b/sig/HighPerfStorageSIG/assets/redis-epoll-flow.png new file mode 100644 index 0000000000000000000000000000000000000000..7c3da7d1b26b4f7d8aae62c8013b6ec159beca69 Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/redis-epoll-flow.png differ diff --git a/sig/HighPerfStorageSIG/assets/redis-get-qps.png b/sig/HighPerfStorageSIG/assets/redis-get-qps.png new file mode 100644 index 0000000000000000000000000000000000000000..79ede008bccdc1d94732826828d91727ef76c10b Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/redis-get-qps.png differ diff --git a/sig/HighPerfStorageSIG/assets/redis-iouring-flow.png b/sig/HighPerfStorageSIG/assets/redis-iouring-flow.png new file mode 100644 index 0000000000000000000000000000000000000000..244a201b356f7ae6fc621d498f91bfb456f3b771 Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/redis-iouring-flow.png differ diff --git a/sig/HighPerfStorageSIG/assets/redis-ping_bulk-qps.png b/sig/HighPerfStorageSIG/assets/redis-ping_bulk-qps.png new file mode 100644 index 0000000000000000000000000000000000000000..54dc4f7d592feeae551890a3fe256cf039a71586 Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/redis-ping_bulk-qps.png differ diff --git a/sig/HighPerfStorageSIG/assets/redis-ping_inline-qps.png b/sig/HighPerfStorageSIG/assets/redis-ping_inline-qps.png new file mode 100644 index 0000000000000000000000000000000000000000..fb386b96aa2b3907cc3cc428e6917426653077b2 Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/redis-ping_inline-qps.png differ diff --git a/sig/HighPerfStorageSIG/assets/redis-set-qps.png b/sig/HighPerfStorageSIG/assets/redis-set-qps.png new file mode 100644 index 0000000000000000000000000000000000000000..9d3cf53953ce54f71d40adc71c348648b92723eb Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/redis-set-qps.png differ diff --git a/sig/HighPerfStorageSIG/assets/sealer-nydus-test.png b/sig/HighPerfStorageSIG/assets/sealer-nydus-test.png new file mode 100644 index 0000000000000000000000000000000000000000..2621be8173cdbceb806ba432bd3dd410ccaf69b7 Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/sealer-nydus-test.png differ diff --git a/sig/HighPerfStorageSIG/assets/virtiofs-dax.png b/sig/HighPerfStorageSIG/assets/virtiofs-dax.png new file mode 100644 index 0000000000000000000000000000000000000000..bebc4c43605d935b225f81b94afee63f9c788bb7 Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/virtiofs-dax.png differ diff --git a/sig/HighPerfStorageSIG/assets/virtiofs-perfile-dax.png b/sig/HighPerfStorageSIG/assets/virtiofs-perfile-dax.png new file mode 100644 index 0000000000000000000000000000000000000000..07bd3047a9e1bdb84dd08c930d31c76ffb5e640a Binary files /dev/null and b/sig/HighPerfStorageSIG/assets/virtiofs-perfile-dax.png differ diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2021/2021.10.27.md b/sig/HighPerfStorageSIG/content/meetingminutes/2021/2021.10.27.md new file mode 100644 index 0000000000000000000000000000000000000000..1334b88f103b0e0cc14c32c4c5c95d8f6f41d87e --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2021/2021.10.27.md @@ -0,0 +1,44 @@ +# 会议时间 +2021.10.27 15:00 ~ 16:00 + +# 与会人 +wangleic,HanGuangyu,liuzhentao,gaoxiang,xiaoguangwang,josephqi + +# 会议纪要 +1、mysql 16k 原子写 POC + +统信计划 11 月中旬基于 UOS 龙蜥版完成评测,对应为 openstack 私有云场景; + +mysql 版本基于 mysql-5.7 和 mariadb-10.3; + +需要重点关注下 guest 磁盘的性能指标; + +特性代码分支是 UOS 龙蜥版内核基线 + 特性新增补丁。 + +@HanGuangyu,@wangleic,@gaoxiang,@josephqi + +2、glusterfs io_uring 优化 + +目前已经进 gluster 9.0,但从 PR 的描述来看,没有明显的性能优化数据; + +从代码上看,主要是 readv/writev/fsync 的替换,理论上性能优化效果与 batch 的数量,以及存储的性能强相关; + +统信相关团队可以通过实际测试数据来判断最终的优化效果。 + +@HanGuangyu,@wangleic + +3、redis 社区推进 + +整理下社区 PR 反馈的 8 个问题,需要结合整体代码逐个答复; + +确认下 redis-benchmark 的默认测试包大小; + +AnolisOS 和 UOS 的性能测试数据差异,可以深入分析下原因。 + +@HanGuangyu,@xiaoguangwang,@maomao123 + +4、容器存储 + +目前 SIG 有结合 kata 做容器存储方向的优化,如容器镜像加速等,需要进一步交流合作的可能性。 + +@HanGuangyu,@wangleic,@gaoxiang diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2021/2021.11.10.md b/sig/HighPerfStorageSIG/content/meetingminutes/2021/2021.11.10.md new file mode 100644 index 0000000000000000000000000000000000000000..d35db6c4fddc5835880e9b0bd634d709f5fdb980 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2021/2021.11.10.md @@ -0,0 +1,25 @@ +# 会议时间 +2021.11.10 15:00 ~ 16:00 + +# 与会人 +wangleic,HanGuangyu,wangbo,gaoxiang,xiaoguangwang,Jingbo Xu,maomao123,josephqi,Xianting Tian,dust-li + +# 会议纪要 + +1、社区项目进展 + +社区目前进行的主要由四个项目:16k 原子写,virtiofs per-file dax,容器存储镜像加速,io_uring,相关进展已经在 10 月份 SIG 月报中总结: + +https://openanolis.cn/sig/high-perf-storage/doc/424181960756938643 + +其中 16k 原子写统信正在协调环境 POC。 + +2、介绍 erofs + nydus 容器镜像加速方案,目前已申报 2021.12.9 OSS 议题: + +https://www.lfasiallc.com/kubecon-cloudnativecon-open-source-summit-china/program/schedule/ + +统信同学会尝试将 nydus 应用到 k8s,相关反馈在钉钉群跟进; + +另外需要调研下与集群镜像管理 sealer 的结合的可行性: + +https://openanolis.cn/sig/sealer diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2021/2021.11.24.md b/sig/HighPerfStorageSIG/content/meetingminutes/2021/2021.11.24.md new file mode 100644 index 0000000000000000000000000000000000000000..bf870ce09d17a58c058d00551e074abc0b20c9da --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2021/2021.11.24.md @@ -0,0 +1,37 @@ +# 会议时间 +2021.11.24 15:00 ~ 16:00 + +# 与会人 +wangleic,HanGuangyu,wangbo,gaoxiang,josephqi + +# 会议纪要 + +1、16k 原子写 POC 更新 + +统信同学基于物理机 NVMe 盘的测试结果,写入数据量优化 30% ~ 60%,但 tps 存在 5% ~ 30% 的下降; + +初步怀疑是物理机盘的顺序与随机性能存在差异导致,需要分析确认;后续需要针对实际应用场景调整策略,使用随机 IO 转顺序等方案优化。 + +Action: + +a)提供物理机测试环境分析确认; + +b)与业务应用确认典型应用场景,作为后续优化方向。 + +2、nydus 对接 k8s 更新 + +统信同学反馈行业更注重标准,对新镜像格式接受度会比较慢,初步想法是作为一个新特性选项; + +nydus 计划推进到 kata 社区成为事实标准,后续可作为社区标准案例引用; + +需要确认统信 kata 团队是否有诉求,可以拉到 SIG 中一起合作交流; + +阿里目前已经有做过一些工作,相关信息尽量与统信共享。 + +3、nydus 对接 sealer 更新 + +与 sealer 团队进行了一次共创交流会,sealer 确认有镜像加速的诉求(当前使用远程拷贝); + +已经启动将 nydus 集成到 sealer 的 POC,后续会基于 POC 效果决策落地计划; + +如果顺利,后续会通过 openanolis 社区 sealer sig 输出,统信可基于该成果集成。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2021/2021.12.08.md b/sig/HighPerfStorageSIG/content/meetingminutes/2021/2021.12.08.md new file mode 100644 index 0000000000000000000000000000000000000000..49b065314884dc377b6c2fb414cdbc05b7020827 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2021/2021.12.08.md @@ -0,0 +1,39 @@ +# 会议时间 +2021.12.08 15:00 ~ 16:00 + +# 与会人 +wangleic,HanGuangyu,wangbo,gaoxiang,josephqi,xiaoguangwang + +# 会议纪要 + +1、16k 原子写 POC 更新 + +抓了统信物理机 POC 环境的 trace,单纯从数据结果肉眼没有发现明显的规律,可能需要对 trace 可视化一下才能看出实际IO pattern。 + +本地能复现 insert 场景差异,并尝试做随机转顺序的优化;从本地的验证效果上,180s 固定时间测试,前 100s 左右 tps 效果较好,后面 80s 左右 tps 有较明显回落,目前怀疑跟元数据的开销有关,还需要进一步调查。 + +待本地优化验证通过后,发出新版本提供给统信同学 POC。 + +2、nydus 对接 k8s 更新 + +统信同学测试了 containerd 和 docker 两种场景。 + +对于containerd,发行版 containerd 版本较低,需要确认低版本(具体版本待确认)下使用 nydus-snapshotter 的方式。 + +对于 docker,需要确认集成 nydus 后,CRI 的方式是否会影响原有OCI v1 格式镜像的拉取。 + +3、nydus 对接 sealer 更新 + +与 sealer 团队正在 POC,当前测试 k8s 基础镜像,相比原 sealer scp 目录方式,nydus 镜像加速比在 15% ~30%。 + +目前对比方式,nydus 使用 oss 方式在远端,scp 方式是内网同集群,因此理论上要更优。 + +需要确认下后续项目运作的方式,建议通过龙蜥社区透出。 + +4、redis io_uring 更新 + +io_uring sqpoll 与 redis 自身 io 线程池方案思路比较类似,都是通过将 io 开销使用独立的 cpu。两者相比,redis 自身线程池可以用更多的线程。 + +从我们之前的分析来看,socket 读写 cpu 约占主线程 70%,所以理论上使用 sqpoll 后可以提升 40% 的性能。 + +目前 io_uring 社区在尝试 zero copy,这个不依赖 sqpoll,实现后在非 sqpoll 模式会有明显优势。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2021/2021.12.22.md b/sig/HighPerfStorageSIG/content/meetingminutes/2021/2021.12.22.md new file mode 100644 index 0000000000000000000000000000000000000000..a945e6ec54c403f2be9a79c317e4b2d5b47ed2bf --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2021/2021.12.22.md @@ -0,0 +1,27 @@ +# 会议时间 +2021.12.22 15:00 ~ 16:00 + +# 与会人 +wangleic,HanGuangyu,wangbo,gaoxiang,hongnan_Li + +# 会议纪要 + +1、16k 原子写 + +目前物理盘 insert tps 性能回退基本锁定在大文件的元数据更新开销上,这两周无投入。 + +统信目前还是关注物理盘的场景,不过后续也有基于 cinder 即 ceph rbd 分布式盘的场景。 一月份如果可以的话,可以协调 openstack + ceph 的环境做测试。 + +2、Kata Containers + Nydus + +统信目前没有强需求场景,一个 node 节点运行容器 10 ~ 20 个 runC + k8s。 + +3、Sealer + Nydus + +介绍了最新 Sealer 的 POC 进展和协作情况。统信内部需要跨团队对齐一下,另外需要了解阿里云内部使用的场景的实际数据。 + +4、Lifsea OS (Ostree -> Nydus) + +统信在轻量级 OS 方向也有计划,主要是想替代红帽 CoreOS,在云场景推统信容器云平台 + 轻量级 OS。涉及包的二次定制,容器的镜像,容器云适配轻量级 OS 等。 + +差异点主要是在原有 Lifsea OS 云场景的基础上增加物理机和裸金属的情况。Nydus 替换 Ostree 的事情需要三方对齐一下。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.01.05.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.01.05.md new file mode 100644 index 0000000000000000000000000000000000000000..8b7f574ae945f55e5c10a9b77d9abdb51bda342d --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.01.05.md @@ -0,0 +1,34 @@ +# 会议时间 +2022.1.5 15:00 ~ 16:00 + +# 与会人 +wangleic,HanGuangyu,wangbo,gaoxiang,josephqi,denggang,yummypeng + +# 会议纪要 + +1、16k 原子写 +除先前讨论的可能原因与读写随机/顺序性能差异以外,云盘与本地 NVMe 盘的时延差异也可能有影响; + +目前对 oltp insert 单线程用例抓取 on cpu 火焰图分析发现在元数据操作上的确存在比较大的差异,但还无法确认是否为造成物理机 tps 性能回退的根因,还在想方案优化中。 + +2、sealer + nydus + +POC 已完成,测试结果显示整体时间降低了约 33%,已更新到 SIG 文档中; + +目前已经进入正式方案的开发,第一阶段集成预计 1 月份完成; + +统信将跟随社区开发节奏,待社区发布后测试并使用。 + +3、代码段大页优化 + +介绍了代码段大页项目的背景,以及 POC 的效果; + +目前该特性代码已经进入 anolis cloud kernel 主线,通过配置启动参数或开关即可启用; + +需要提供一份操作文档,统信同学基于该文档做 POC 评估。 + +4、lifseaos + +需要确认下物理机不重启的实际需求; + +计划于 3 月份先基于 ostree 方案提供第一个版本,6 月份提供基于 nydus + erofs 的更新版本。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.01.19.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.01.19.md new file mode 100644 index 0000000000000000000000000000000000000000..037d8ca8c893eccb048c0a85440cd1fbf2253eee --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.01.19.md @@ -0,0 +1,47 @@ +# 会议时间 +2022.1.19 15:00 ~ 16:00 + +# 与会人 +wangleic,HanGuangyu,wangbo,gaoxiang,josephqi,hliang + +# 会议纪要 + +1、16k 原子写 + +经过多机型的对比和不同存储盘(云盘、SATA SSD 和 NVMe 物理盘)的测试,目前物理盘的 tps 性能问题锁定在元数据更新增加的延迟上,因此在云盘和 SATA SSD 上由于 IO 延迟相对较高,元数据更新的延迟就变得不这么敏感。 + +因此接下来的优化方向主要是尽可能减少元数据的操作。 + +另外,统信同学后续也会协调 SATA SSD 和 ceph 存储测试,验证 ceph 云盘的效果。 + +2、代码段大页优化 + +代码段大页 POC 文档已经更新在 cloud kernel sig: + +https://openanolis.cn/sig/Cloud-Kernel/doc/475049355931222178 + +统信反馈目前 arm 机器还没到位,待机器到位后会统一安排 POC 测试,确认效果后会在 UOS 中作为解决方案提供。 + +3、fuse 优化 + +sig 后续会起一个 fuse 优化项目,以解决当前开源 fuse 模块的问题,如并发性能存在瓶颈等。 + +openstack 存储后端 cephfs(ceph-fuse)可能存在应用场景,后续可以调研下结合点。 + +4、sealer + nydus + +sealer 单节点和多节点流程已初步调通,收益数据还需进一步收集和确认。开发完成后将在 github 上发起 PR 合并。 + +合并后知会到统信开始 POC 验证。 + +5、container os + +确认了物理机场景升级版本后可以重启。 + +第一阶段基于 ostree lifseaos 可能会延期到 4 月份;nydus + lifseaos 相应往后延,开发计划待后续排期。 + +6、Intel WSR + +WSR(Write Shaping RAID)是 SPDK 的一个子项目,其构建了一个介质感知的混合存储软件框架,有着完整的 FTL 实现,可以创建一个巨大的虚拟 SSD。 + +计划节后邀请 Intel 的同学在 SIG 例会上进行介绍。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.02.16.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.02.16.md new file mode 100644 index 0000000000000000000000000000000000000000..610258d8bf1f14ae35adc4f2fc4ee7cf473d1402 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.02.16.md @@ -0,0 +1,39 @@ +# 会议时间 +2022.2.16 15:00 ~ 16:00 + +# 与会人 +HanGuangyu,wangbo,gaoxiang,josephqi,Hongnan Li,xiaoguangwang + +# 会议纪要 + +1、16k 原子写 + +在 xfs end cow 路径上增加 fast path,已将该优化同步发到上游社区。目前根据讨论发出 v2 版本,待继续跟进。 + +insert 用例在合入优化后,在本地 nvme 盘场景仍然存在一定差异,需要继续分析下是否还有优化点。 + +统信同学在下周例会前评估下当前版本在 sata ssd 和 ceph 云盘场景的效果。 + +2、代码段大页优化 + +因设备和当前项目排期原因,该 poc 还未进行,待后续跟进。 + +3、sealer + +社区 pr 已经发出,目前根据 review 意见已发出 v2 版本,预计会在 sealer 下个版本支持。 + +到时需要整理提供使用文档,放到 sig 当中。 + +4、erofs over fscache + +已发出 v3 版本,fscache maintainer 当前主要精力在重构版本的稳定上,没有太多的精力 review,接下来需要继续跟进。 + +5、tcmu 优化 + +介绍了 sig 新增项目 tcmu 优化的背景,目前在性能上取得了约一倍的提升,具体信息可参阅 sig 1 月份月报。 + +6、其他 + +1)约了 intel 同学在下次例会(3.2)上作介绍。 + +2)建议后续例会轮流主持,提升 sig 成员的参与度,例会动作包括:邮件列表议题征集,例会主持,会议纪要等。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.03.02.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.03.02.md new file mode 100644 index 0000000000000000000000000000000000000000..9e22800eb2686db74d3c496b91d4e70c7901970d --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.03.02.md @@ -0,0 +1,44 @@ +# 会议时间 +2022.03.02 15:00 ~ 16:00 + +# 与会人 +josephqi,gaoxiang,xiaoguangwang,Xianting Tian,wangleic,HanGuangyu + +# 会议纪要 +1、16K 原子写 + +统信在 OpenStack 虚拟机中完成了 Cinder 卷场景(卷位于 nvme 物理盘)的测试。总体符合预期,少部分不符合预期的是:单线程时,关双写(不安全)和原子写比开双写 tps 存在下降。 统信后续复现单线程测试,确认是否 tps 下降为稳定出现,而后进一步判断原因。对加入新优化补丁的分支进行测试。 + +2、代码段大页优化 + +统信在完成 16K 原子写测试后,进行此项的 POC 测试。 + +3、fuse 优化 + +此项目为阿里云存储团队同学实现。目前已发布第一个补丁。计划下一步实现 fuse 性能优化,如目并发优化等。同时也在进行加入 Anolis 内核主线的过程,社区的诉求是:需要考虑兼容性,在性能优化的同时,也需要保留原有 fuse 特性。当前正在实现中。 + +4、sealer + nydus + +sealer 的 PR 已经合并,nydus http-server 部分还在做局部重构。后续 POC 验证的时候 sig 将提供指导手册。 + +5、container os + +已经集成 IOS。目前 nydus 的合入还没有纳入正式规划;周四负责同学在 container os 会议提出此项,再同步进度。 + +6、Intel WSR + +上午 Intel 同学进行了分享,相关工作计划 Q2 后开源。 + +7、erofs over fscache + +提出了一套新的方案,完全脱离对 fscache 格式的依赖,目标是内核能够完全开箱使用,可以做到按需加载。上周与上游社区做了新的一轮沟通,正在努力能在 5.19 版本落地。 + +8、tcmu 优化 + +介绍其作用及项目进展。分布式文件系统需要有对外提供块设备的能力,需要一个用户态的块设备方案。普通的访问请求发送到块设备后,后端的 tcmu 驱动拿到请求,tcmu 会把请求透传到用户态程序,让容器、虚拟机可以方便地使用分布式文件系统提供的能力。 + +近期增加了对零拷贝的支持,大块 IO 性能提升明显。测试中:256KB 的 IO,写性能从大约 3.6GB 提升到 11.5GB 左右。目前主要是阿里内部业务在使用,统信调研下是否存在相关应用场景。 + +9、ceph 优化 + +此前与 Intel、Xsky 的同学进行了交流。目前讨论到的主要结合点是把 io_uring 应用到 ceph。从 Intel ceph 团队测试来看,io_uring性能出乎意料的好,后续会再进行确认。SIG 以前尝试过把 io_uring 做 epoll 的替换,Xsky 的同学对这方面感兴趣。后续可能推动在 SIG 内成立一个优化 ceph 存储场景的项目。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.03.16.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.03.16.md new file mode 100644 index 0000000000000000000000000000000000000000..031837aae0f345bdcb871db79d4858c94a0530ac --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.03.16.md @@ -0,0 +1,33 @@ +# 会议时间 +2022.03.16 15:00 ~ 16:00 + +# 与会人 +josephqi,gaoxiang,xutao, wangleic,HanGuangyu + +# 会议纪要 + +1、16K 原子写 + +当前测试了 mysql 5.7、8.0 和 mariadb 5.5、10.3 等版本,除了写入量均有所优化外,在 mysql 5.7 和 mariadb 5.5 上,单、多线程均体现 tps 优化;mariadb 10.3 上,单线程 tps 下降(关双写而不开启原子写场景便已出现 tps 下降),多线程同样体现 tps 优化。 + +统信整体策略是跟着主线走,不单独出版本,mysql 目前的主要应用版本为 mysql 5.7 和 mariadb 10.3(基于 mysql 5.7)。根据某个操作系统版本例如 UOS 1020a 优化,目前选定的还是 mariadb 10.3,后续给出最佳实践。 + +继续调查基于 mysql 5.7 的 mariadb 10.3 的性能问题。 统信会将内核切换脚本合入到龙蜥测试脚本仓库中,并继续补测 mariadb 10.3 较多线程的情况。 + +2、代码段大页优化 + +16k 原子写测试完毕告一段落后测试。 + +3、sealer + nydus + +同步了 sealer 研发的最新进展,即后面会把 nydus 加速从 k8s + nydus 基础镜像转为 nydus 组件,这样可与任意镜像 merge。 + +统信对目前的使用方式有疑问,下次参会希望邀请对应统信负责 sealer 的同学。 + +4、container os + +刚刚验证完 container os 的物理机环境和其他场景。目前计划月底做 nydus 集成这个事情。 + +5、其他 + +为迎合 sig 主要同学的时间,经讨论后决定,后续会议时间统一改到双周周三上午 11:00 ~ 12:00。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.03.30.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.03.30.md new file mode 100644 index 0000000000000000000000000000000000000000..503fba06d8137eb7679c058a9343004ff2a2260f --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.03.30.md @@ -0,0 +1,23 @@ +# 会议时间 +2022.03.30 11:00 ~ 12:00 + +# 与会人 +josephqi,gaoxiang,hongnan_Li,xutao, wangleic,mahmut_,HanGuangyu + +# 会议纪要 + +1、16K 原子写 + +统信与内核同事沟通确认落地UOS的版本,后续向社区提需求,将此特性合入Anolis内核主线。 默认不开启,mysql场景可以手动打开。阿里同学会出配套用户态工具。 + +2、代码段大页优化 + +本阶段在OpenStack实例(8C16G,物理机为海光cpu)中进行了测试,关闭THP场景,目前数据中tps在1、4、8线程提升5.19%、2.66%、2.09%。目前正在测试实例中的iTLB miss数据,以辅助判断当前提升是否受到干扰。下一步计划在物理机场景进行测试。 原理上而言,代码大页和16K原子写对mariadb数据库的优化是可叠加的,计划后续对此进行测试。 + +3、sealer + nydus + +统信测试中,存在部署不成功情况;部署成功时,单节点部署速度提升10%,不符合预期。经沟通,单节点本机master场景,无法利用优化效果,缺少文件传输过程。部署不成功情况,由相关同学会后单独沟通排查。 + +4、container os + +container os 已可以开始 nydus 集成。高性能存储SIG首先内部讨论决定人力投入情况,而后与container os进一步沟通。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.04.13.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.04.13.md new file mode 100644 index 0000000000000000000000000000000000000000..b78b541a7c14657d1bd10e96ff697788e7df563d --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.04.13.md @@ -0,0 +1,27 @@ +# 会议时间 +2022.04.13 11:00 ~ 12:00 + +# 与会人 +wangleic,HanGuangyu,gaoxiang,hongnan_Li + +# 会议纪要 + +1、16k 原子写 + +根据上次的沟通,该特性先在 anolis 5.10 内核中落地,待足够稳定后再回合到 4.19 内核; + +目前 5.10 内核的代码正在适配中,计划 6.30 前提供版本先测试。 + +2、代码段大页优化 + +物理机场景还在测试中,相关进展钉钉群及时同步。 + +3、sealer + nydus + +nydus 服务存在问题,由于 sealer 版本更新后需要同步更新镜像,怀疑是不匹配导致,需要获取新版本再验证。 + +4、container os + nydus + +完成了一次技术方案交流,目前来看工作量还比较大,需要进一步梳理明确。 + +另外,针对额外安装包的生命周期上,目前存在一定的分歧。是否需要通过新版本切换后丢弃来达成最终一致,需要进一步明确。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.04.27.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.04.27.md new file mode 100644 index 0000000000000000000000000000000000000000..afa373cff7f5b29b622ce38d6764885ede34cd0d --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.04.27.md @@ -0,0 +1,27 @@ +# 会议时间 +2022.04.27 11:00 ~ 12:00 + +# 与会人 +josephqi,gaoxiang,wangleic,HanGuangyu + +# 会议纪要 + +1、16k 原子写 + +基于Mariadb 10.3.28的代码原型基本完成。后续会基于增加适配补丁的5.10内核,进行相关测试。预计下次例会同步测试结果。 如果在Mysql上使用此特性,内核接口统一,可直接使用,Mariadb上支持原子写的相关框架需要移植到Mysql。 + +2、代码段大页优化 + +海光物理机测试数据异常,排查到部分环境binutils包有影响,增加“-z noseparate-code”cmake参数,手动编译安装,复现测试中。 + +3、sealer + nydus + +测试中存在docker丢失问题。后续由相关同学沟通细节,并在群里同步进展。 + +4、container os + nydus + +经沟通,container os先优先实现易用性,后续再考虑对ostree的替换,此议题暂时封存。 + +5、virtiofs + +统信提出需求,希望将特性加入商业版本,后续由统信内核部门同学和阿里同学对接。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.05.11.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.05.11.md new file mode 100644 index 0000000000000000000000000000000000000000..af68458f90acc277c857f5985cac26d3356421ec --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.05.11.md @@ -0,0 +1,23 @@ +# 会议时间 +2022.05.11 11:00 ~ 12:00 + +# 与会人 +wangleic,HanGuangyu,mahmut_,josephqi,gaoxiang,hongnan_Li + +# 会议纪要 + +1、16k 原子写 + +5.10 版本的性能测试数据已经出来,跟先前在 4.19 上的 POC 数据基本一致,需要再补充下联合代码段大页的数据; 初步跑了下xfstests 回归,合入原子写特性前后有一些小的差异,需要进一步确认;计划后续再补充下 mariadb 自身的测试用例回归; 待合入主线后,提供相关的 patchs 清单。 + +2、代码段大页优化 + +目前已基于龙蜥内核完成相关测试,结果符合预期:单线程 tps 提升 4.14%,8 线程 tps 提升4.68%,16 线程 tps 提升5.38%; UOS 内核正在回合,待发布版本后使用 UOS 回归,后续将与 16k 原子写一起推给用户使用。 + +3、sealer + nydus + +docker 丢失问题还没有解决,怀疑环境有问题,建议统信开放测试环境一起定位,需要加速推进。 + +4、virtiofs + +统信同学在 bugzilla 上提交了一个问题,使用社区的 virtiofsd 提示内核 fuse 版本不匹配,其原因是 fuse 的版本有特性集的含义,由于 7.27 到 7.31 中其他特性并没有在 anck 4.19 提供支持,所以版本号并没有修改。目前想到的两个解决方案:1)使用龙蜥社区后续开源的 virtiofsd;2)提需求将中间版本的特性回合到 anck 4.19。 需要统信相关同学确认。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.05.25.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.05.25.md new file mode 100644 index 0000000000000000000000000000000000000000..bd986386e54fe62f60cb0c37ccde2be2b68c324b --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.05.25.md @@ -0,0 +1,23 @@ +# 会议时间 +2022.05.25 11:00 ~ 12:00 + +# 与会人 +josephqi,gaoxiang,hongnan_Li, wangleic,mahmut_, HanGuangyu + +# 会议纪要 + +1、16k 原子写 + 代码段大页优化 + +在阿里云 ECS 中,对16k原子写和代码段大页进行了性能对比联合测试,效果较好。在原子写基础上,又开启代码大页优化后,整体来看优化效果可叠加,不同测试项数据存在差异,效果好的测试项,可再提升10%左右,符合预期。 文件系统回归测试及mariadb回归测试运行完成。发现16k原子写特性与 compressed table 特性不兼容,当前采取在 mariadb 中对此二特性添加互斥逻辑的解决方案,16k原子写特性无法与 compressed table 特性同时开启。 + +2、sealer + nydus + +环境问题解决,测试完成。效果与预期的60%-70%+的提升基本相符。统信目前有使用sealer,后续统信内部讨论是否能把此方案作为新特性引入,有实际计划及时同步进度。 + +3、virtiofs + +此前提出两个解决方案:1)使用龙蜥社区后续开源的 virtiofsd;2)提需求将中间版本的特性回合到 anck 4.19。 目前决定采取方案2。相关同学需要明确后在社区提出需求,后续根据需求进行规划。 + +4、fscache + +初始是阿里同学进行 nydus 加速项目时,实现的一个内部方案。后续结合Linux内核主线的fscache模块,进行了场景扩大,作为内核原生的缓存方案。已经合入Linux内核上游社区主线。后续计划基于主线的方案,扩展场景,在Anolis实现开箱即用的镜像加速缓存方案。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.06.08.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.06.08.md new file mode 100644 index 0000000000000000000000000000000000000000..14606f30ffc6968cfc0b1f69cfa6aa6e11908c8e --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.06.08.md @@ -0,0 +1,28 @@ +# 会议时间 +2022.06.08 11:00 ~ 12:00 + +# 与会人 +wangleic,HanGuangyu,liujiang,taipu,josephqi,gaoxiang,hongnan_Li + +# 会议纪要 +1、16k 原子写 + +本周内核,xfs用户态工具和mariadb 10.3(基于mysql 5.7)的PR均已发出Review。 + +mariadb 10.5(基于mysql 8.0)待适配,后续会在5.10内核上再进行一次摸底。 + +2、sealer + nydus + +将在轻量级os提供本特性,以加速k8s部署,计划落在接下来的版本或者u1版本。 + +具体性能衡量指标需要进一步对齐(POC ~70%是到 master0拉起)。 + +3、virtiofs + +目前还没有正式需求提过来,后续可能需要跟云原生SIG一起跟进。 + +4、erofs over fscache + +backport到4.19内核正在进行中,后续可用于非dax rund容器场景。 + +rund开源会结合kata 3.0的发布节奏,dax rund容器场景到时也会集成在龙蜥云原生解决方案中。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.06.24.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.06.24.md new file mode 100644 index 0000000000000000000000000000000000000000..6f20d75987dc42f242ee030284ae6c20067417cb --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.06.24.md @@ -0,0 +1,24 @@ +# 会议时间 +2022.06.24 11:00 ~ 12:00 + +# 与会人 +josephqi,gaoxiang,hongnan_Li,GouHao,HanGuangyu,wamgleic + +# 会议纪要 +1、16k 原子写 + +内核、mariadb 10.3(基于mysql 5.7)、mariadb 10.5(基于mysql 8.0)、xfs用户态工具的PR均已合并。Mariadb RPM 包还未构建发布。 + +阿里同学确认 Mariadb RPM 包构建发布时间,统信同学相应判断是跟随龙蜥上游,还是自己合入 PR 内容,规划内部合入的时间安排。 + +2、sealer + nydus + +统信确认性能优化衡量指标与社区保持一致,采用“Start to create a new cluster 到 start to init master0 的时间段”。统信后续反馈集成、落地计划。 + +3、virtiofs + +暂时关闭。 + +4、erofs over fscache + +正在回合到龙蜥 4.19 内核,计划7月份Ready。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.07.06.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.07.06.md new file mode 100644 index 0000000000000000000000000000000000000000..39ebd04a552b0128180af2bf8a71e5da9da58785 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.07.06.md @@ -0,0 +1,23 @@ +# 会议时间 +2022.07.06 11:00 ~ 12:00 + +# 与会人 +wamgleic,HanGuangyu,josephqi,gaoxiang + +# 会议纪要 + +1、16k 原子写 + +用户态 rpm 包(mariadb,xfsprogs)均已发布,内核 rpm 包预计 830 版本发布(Release 12); UOS 预计 8 月初开始 cherry-pick 内核补丁,测试后同步数据,合入 9 月份的 UOS 版本。 + +2、erofs over fscache + +龙蜥 4.19 内核回合完成,review 后合入;5.10 内核回合中; erofs 去重和字典开发中,后续 nydus 也将兼容 estargz 镜像格式。 + +3、sealer + +计划落地 9 月份 UOS 轻量级 OS 版本,需要升级至 0.7.1 以上版本才能支持 nydus(反馈目前使用的是 0.5 版本)。 + +4、用户态存储 + +需要与统信 ceph 团队同学沟通下合作的可行性,如有必要可以安排一次技术交流。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.07.20.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.07.20.md new file mode 100644 index 0000000000000000000000000000000000000000..8f6fa8b474b311aceb51d81c34e9ae09526101e7 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.07.20.md @@ -0,0 +1,27 @@ +# 会议时间 +2022.07.20 11:00 ~ 12:00 + +# 与会人 +josephqi,gaoxiang,xiaoguangwang,taipu,YangXiaoliang,HanGuangyu + +# 会议纪要 + +1、16k 原子写 + +UOS 按原定计划进行中:预计 8 月初开始 cherry-pick 内核补丁,测试后同步数据,合入 9 月份的 UOS 版本。希望UOS可以先出一个临时补丁版,提前测试安排,以免出现意外修复时间不足。统信沟通后反馈。 + +2、erofs over fscache + +龙蜥 4.19、5.10 内核均已合入。 + +介绍材料: https://openanolis.cn/video/593123727115010051 https://openanolis.cn/blog/detail/576260913196929348 + +3、sealer + +计划落地 9 月份 UOS 轻量级 OS 版本。已明确会使用0.7.1及以上版本,具体版本确定后沟通。 + +4、redis io_uring + +SIG 此前工作中,曾经尝试利用 io uring 的异步下发和 FAST POLL 机制对 Redis 进行优化。并尝试将该优化推向 Redis 社区。 此前该工作进度停滞,未在 SIG 内继续同步。 + +通过与 Redis 社区的沟通,例会中 SIG 内部的交流,SIG 决定继续推动此项工作。因需要 Redis 领域的技术积累,经阿里同学沟通协调,阿里云 Redis 团队的同学会对此进行整理。初步整理完成后,继续沟通情况。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.08.03.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.08.03.md new file mode 100644 index 0000000000000000000000000000000000000000..9659545357172e2e872b64f2c35c48e43b826b6f --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.08.03.md @@ -0,0 +1,23 @@ +# 会议时间 +2022.08.03 11:00 ~ 12:00 + +# 与会人 +wamgleic,HanGuangyu,josephqi,gaoxiang + +# 会议纪要 + +1、16k原子写 + +UOS Update2 合入,统信计划 8 月底 cherry-pick 相关内核补丁,如果有问题反馈,时间节奏上与龙蜥 anck 5.10 830 版本不是很匹配。统信会再向内核组确认一下合入补丁的节奏。 + +2、sealer + +统信 sealer 版本目前还没有确定,比较大倾向于最新版或者 0.7.1;确认后沟通,如果选择大于 0.7.1 的版本,需要重点关注下测试情况。 + +3、redis iouring + +与阿里云 redis 团队沟通了社区的情况,已经安排同学开始搭建环境确认,另外也会整理并确认补丁的工作量,以提供一些输入和帮助。目前统信没有单独维护 redis 组件,需要探索一下后续有没有更深入的合作机会。 + +4、其他 + +与相关团队探讨下在 memcached 和 mq 这块有没有在龙蜥社区合作的可行性。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.08.17.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.08.17.md new file mode 100644 index 0000000000000000000000000000000000000000..206ce3daefab0b4a9b715b85cb32ddd0cc1fc973 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.08.17.md @@ -0,0 +1,27 @@ +# 会议时间 +2022.08.17 11:00 ~ 12:00 + +# 与会人 +josephqi,gaoxiang,xiaoguangwang,taipu,taijuan,wamgleic,HanGuangyu + +# 会议纪要 + +1、16k原子写 + +UOS 内核还未合入补丁,将持续跟进、推动进度。 + +2、sealer + +统信目前确定使用0.8.6版本,将在测试后在社区反馈情况。 + +3、redis iouring + +阿里云 redis 团队和 SIG 内阿里同学一起进行了查看评估,目前阿里云 ECS 场景评估此优化,未见明显优势。下阶段先调查 ECS 上效果为何不明显。 + +4、内存数据库及消息队列 + +统信有 memcached 和 rabbitmq 使用需求,希望探讨是否有在龙蜥社区合作的可行性。 阿里同学内部调研后,当前缺乏对 memcached 和 rabbitmq 的应用,主要使用 redis和 rocketmq。 统信如果内部调研,有性能提升及替换中间件的可行性,再继续沟通。 + +5、用户态存储 + +邀请到Intel的同学,进行技术及应用交流。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.08.31.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.08.31.md new file mode 100644 index 0000000000000000000000000000000000000000..8dfd2dfa3f3325e33b59924c18f7183d3a43b167 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.08.31.md @@ -0,0 +1,31 @@ +# 会议时间 +2022.08.31 11:00 ~ 12:00 + +# 与会人 +HanGuangyu,gao,taijuan,xiaoguangwang,gaoxiang,josephqi + +# 会议纪要 + +1、16k原子写 + +龙蜥社区版本验收的结果符合预期,与之前开发测试基本一致,各项 case 有不同程度的 tps 性能优化,最大达 ~50%,同时明显减少写入数据量。使用手册: + +https://openanolis.cn/sig/high-perf-storage/doc/594617348901388298 + +UOS 内核补丁合入存在滞后,需要确认下最新的计划,以及内核团队的负责同学,方便交流跟进。 + +2、sealer + +统信目前确定使用 0.8.6 版本,初步测试符合预期。后续轻量级 OS 和常规 50a 系统都会使用,目前最直接的场景为 k8s 部署。 + +3、redis iouring + +在 ECS 场景评估未见明显优势,不同于之前在物理机上的评估效果,需要进一步调查下效果差异的原因。 可以先在社区回复下还在学习重构后的 redis 相关流程代码,并试探性问下 aws 的意愿;如果 aws 愿意 take 这个工作,我们作为 reviewer 参与进去也不失为一种解决方案。 + +4、内存数据库及消息队列 + +openstack mq 替代方案将作为一项长线任务,后续不单独跟踪。 统信同学反馈 openstack ovs 在多端口使用场景下性能不行,想了解下龙蜥社区有没有相关 SIG 在做 ovs 相关的工作,需要找网络同学确认下。 + +5、用户态存储 + +对比测试了 vduse(容器和 vm 场景下的用户态存储方案,由字节贡献,已经 upstream),目前发现 ublk 在性能上还是有比较明显的优势。 与 vduse 作者做了一次交流,后续会针对当前存在的性能瓶颈进一步优化。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.09.14.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.09.14.md new file mode 100644 index 0000000000000000000000000000000000000000..5b030281409ee0cfc1068ad290bd08998d9d1eb7 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.09.14.md @@ -0,0 +1,23 @@ +# 会议时间 +2022.09.14 11:00 ~ 12:00 + +# 与会人 +josephqi,gaoxiang,HanGuangyu + +# 会议纪要 + +1、16k原子写 + +无新合入进展。统信原本希望实际应用的场景中包含 vm 并发创建场景,而实际压测发现该场景中目前瓶颈不在数据库。 + +2、redis iouring + +阿里云redis团队主要聚焦于阿里云ECS场景。因阿里云最新ECS中进行了硬件优化,缩小了io_uring带来的上下文切换开销优化,此特性在ECS中优势不明显,阿里云redis团队目前不投入此特性开发。 sig暂时不采取之前试探aws是否有在redis社区承接此工作的想法,目前统信同学正在内部询问,看统信内部是否有具备相关技术栈同学可以承接。 + +3、ovs + +龙蜥社区没有 SIG 在做 ovs 相关的工作。议题源于统信优化OpenStack需求,当前无直接合作点,后续SIG也会探索有无相关方向合作可能,此议题在SIG暂时告终。 + +4、用户态存储 + +阿里云团队正在投入方案的开发及推动。相较已知同类方案,具备明显优势。目前主要聚焦于故障恢复,同时也在积极往上游推动。目前redhat同学表示,希望用作qemu后端。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.09.28.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.09.28.md new file mode 100644 index 0000000000000000000000000000000000000000..5b02461fed9c501ac5321e68e84039095e011e6d --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.09.28.md @@ -0,0 +1,25 @@ +# 会议时间 +2022.09.28 11:00 ~ 12:00 + +# 与会人 +wangleic,HanGuangyu,gaoxiang,josephqi,xiaoguangwang + +# 会议纪要 + +1、16k 原子写 + +因研发流程调整,已对齐暂不合入 UOS,目前该特性已随 anck 5.10 release 12 发布。 + +后续 UOS 根据实际有诉求的客户场景再提交正式需求流程合入。 + +2、redis io_uring + +统信同学已排进工作计划,后续由统信同学负责社区主线推进,SIG 提供协助。 + +3、用户态存储 + +需要评估下当前内核 rbd 模块是否已经满足特性要求,用户态的优势在于可以实现更多的高级特性。 + +后续 SIG 将尝试推进 ceph 社区主线的适配。 + +统信同学下次例会分享当前在 openstack 使用 ceph 的经验。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.10.12.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.10.12.md new file mode 100644 index 0000000000000000000000000000000000000000..04d34dc6b1d516bfc3e6dc1d86767770c9b34499 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.10.12.md @@ -0,0 +1,19 @@ +# 会议时间 +2022.10.12 11:00 ~ 12:00 + +# 与会人 +josephqi,xiaoguangwang,taijuan,wangleic,HanGuangyu + +# 会议纪要 + +1、用户态存储 + +ublk 故障恢复特性已顺利合并到 Linux v6.1: + +https://lore.kernel.org/linux-block/166516202669.22254.13418351510170463181.pr-tracker-bot@kernel.org/T/#t + +ublk 已经申报今年的 CLK session,将由 redhat 的工程师和高性能存储 SIG 联合演讲。 + +2、OpenStack对接ceph交流 + +交流统信OpenStack对接ceph的使用场景,探索优化点。OpenStack对接ceph,主要用于存储系统镜像以及vm磁盘的临时存储或持久化存储。ceph端瓶颈点大体在高并发时或vm密度过高。目前SIG无直接可进行优化点。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.10.26.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.10.26.md new file mode 100644 index 0000000000000000000000000000000000000000..17e9c52a172186802fa770844d276c22fd1a0dbe --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.10.26.md @@ -0,0 +1,24 @@ +# 会议时间 +2022.10.26 11:00 ~ 12:00 + +# 与会人 +wangleic,HanGuangyu,josephqi,gaoxiang + +# 会议纪要 +1、redis io_uring + +针对先前的 PR [https://github.com/redis/redis/pull/9440] 作了回复,统信计划下周会安排新同学开始跟进基于 redis 最新版本重构的工作,到时 SIG 提供支持。 + +近期很多业务和应用都对 io_uring 表示了极大的兴趣,io_uring 作为新的异步 IO 框架,已经逐步被业界广泛接受。 + +2、sealer + nydus + +目前 sealer 社区正在重构,初期并没有考虑对 nydus 的支持;另外,sealer 社区核心成员变动也比较大。 + +建议目前先基于当前的稳定版本继续项目开发,并通过容器 os 的例会和 sealer 社区 issue 反馈下重构对企业用户的影响,明确 sealer 新版本支持 nydus 的计划。 + +3、erofs + +统信桌面同学近期有 erofs 社区提交,需要了解桌面团队对 erofs 的整体态度。希望联系下相关团队,针对桌面的需求做个交流。 + +erofs 相比其他文件系统,在反馈周期等方面会有明显优势。erofs 目前在端和云场景已经有规模的应用,希望在桌面场景也能有所突破,会是一个很好的合作契机。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.11.09.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.11.09.md new file mode 100644 index 0000000000000000000000000000000000000000..e43f64743773a7865d8e845ec2f88c770a8011e9 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.11.09.md @@ -0,0 +1,29 @@ +# 会议时间 +2022.11.09 11:00 ~ 12:00 + +# 与会人 +josephqi,gaoxiang,xiaoguangwang,taipu,taijuan,wangleic,HanGuangyu + +# 会议纪要 + +1、redis io_uring + +统信内部初步调研后,因对redis和io_uring相关基础均需补足,需要投入时间过多,调整此前计划。 + +SIG后续计划先在Anolis社区内部沟通,确认是否有同学愿意继续进行此项工作。如果Anolis社区内部无人承接,则在redis社区进行沟通。 + +2、OpenStack消息队列替换 + +统信进行了将OpenStack的消息队列从Rabbitmq替换为Rocketmq的调研工作。目前正在与OpenStack社区进行新增Rocketmq驱动的沟通。 + +目前对于Rocketmq有一些问题。当前rocketmq-client-python中异步发送方法被移除(https://github.com/apache/rocketmq-client-python/pull/68)。希望了解对于这里Rocketmq的设计;以及如果python客户端想发送异步消息,怎样做是社区鼓励的。阿里同学将进行初步了解,后续沟通。 + +3、C++协程优化 + +阿里编译器团队同学开发了一套高性能 C++20 库,并且已在GitHub alibaba仓库内(https://github.com/alibaba/yalantinglibs)开源。其中rpc异步调用涉及io_uring,io_uring在网络方向的优化也是SIG希望推进的方向,目前SIG正在与编译器团队团队合作进行C++协程相关优化工作。 + +后续统信将在产线内部邮件沟通是否有同事对此感兴趣。 + +4、用户态块设备 + +Intel和阿里同学进行相关讨论,计划把SPDK作为ublk的后端存储 。背景:用户想用SPDK的高性能,但不想在用户态适配SPDK,想走内核接口(POSIX API)之前考虑过用NVME Over TCP/RDMA Loopback,TCMU方案,现在想用ublk,看看性能是否可继续提升。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.11.23.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.11.23.md new file mode 100644 index 0000000000000000000000000000000000000000..3ccb1a762eba4771f5f8b0f8d995ae3cdb035e88 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.11.23.md @@ -0,0 +1,33 @@ +# 会议时间 +2022.11.23 11:00 ~ 12:00 + +# 与会人 +wangleic,HanGuangyu,wangkuntian,yxpeng,josephqi,gaoxiang,xiaoguangwang, ZiyangZhang + +# 会议纪要 + +1、redis io_uring + +目前尚未找到合适的同学继续推送社区的工作,建议统信在原 PR 上发表 comments,让 redis 社区感兴趣的同学接手。 + +2、openstack 消息队列替换 + +与 rocksmq 的同学交流,目前 rocksmq 的普通消息发送接口都是同步,后续将基于新的 grpc 一些开发。 + +统信同学可以将相关需求在 rocksmq 提交 issue 进行讨论。 + +3、C++ 协程优化 + +目前进行了第一轮的简单测试,ping-pong 场景相比 epoll 有 70%+ 的性能优化,但 pipeline 有 ~20% 的退化,需要进一步分析。 + +接下来会设计典型的测试 case 并进行针对性分析调优,后续会统一整理成报告发出来。 + +4、ublk + +阿里云将开始在分布式存储场景 POC。 + +社区上游开始投入到非特权容器支持,零拷贝等方向。 + +5、dsms + +凝思软件的同学 yxpeng 介绍了 dsms 项目背景,整体架构和工作计划,相关仓库已经创建,预计 2023.6 发布第一个版本。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.12.07.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.12.07.md new file mode 100644 index 0000000000000000000000000000000000000000..090a0100ba36744a0ae99699901333748d28a925 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.12.07.md @@ -0,0 +1,35 @@ +# 会议时间 +2022.12.07 11:00 ~ 12:00 + +# 与会人 +josephqi,xiaoguangwang,yxpeng,taijuan,muqi,tangguifeng,wangleic,HanGuangyu + +# 会议纪要 + +1、redis io_uring + +初步与Redis社区沟通,SIG目前的人力及安排无法继续在Redis社区推动此项工作,Redis社区maintainer表示了社区对此项工作有兴趣。后续将继续保持沟通及跟进。 + +POC PR:https://github.com/redis/redis/pull/9440 + +2、openstack 消息队列替换 + +与OpenStack社区oslo项目沟通,项目对于增加rocketmq驱动并不排斥。后续将保持RocketMQ社区的沟通,待RocketMQ的官方python客户端异步接口更新完成,继续推动。 + +https://github.com/apache/rocketmq/issues/5658 + +3、C++ 协程优化 + +本周期暂无投入,待投入后继续更新。 + +4、ublk + +进行新方案构建,设计已经完成,正在进行编码。 + +同时也在和阿里云内部的分布式存储进行POC,计划十二月底或一月初输出原型。 + +5、dsms + +凝思同学目前初步启动开发工作,暂时在debian环境开发,后续转移到Anolis环境。 + +目前Anolis发行版中未包含ceph,后续dsms引入Anolis后端也需要ceph。SIG考虑引入ceph,凝思目前使用ceph 15.2.15版本,引入将优先考虑版本一致性。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.12.21.md b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.12.21.md new file mode 100644 index 0000000000000000000000000000000000000000..a16f726b10e93244b1c786c77039fc02f4bc7173 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/2022/2022.12.21.md @@ -0,0 +1,27 @@ +# 会议时间 +2022.12.21 11:00 ~ 12:00 + +# 与会人 +yxpeng,wangleic,HanGuangyu,wangkuntian,josephqi,xiaoguangwang + +# 会议纪要 + +1、redis io_uring + +SIG 同学 zhangyin 对该项目比较感兴趣,目前测试下来 sqthread offload 模式性能提升符合预期,但单纯走系统调用的方式没有明显提升,怀疑跟环境有关(如 cpu 漏洞缓解配置等)。 后续该项目不例行跟进,社区有反馈再按需更新。 + +2、openstack 消息队列替换 + +与 rocketmq 同学沟通后,已经在社区 github issue 上回复,后续建议基于github issue 持续跟进。 + +3、C++ 协程优化 + +目前没有人力投入优化,计划在 1 月份跟进。 + +4、ublk + +已经开始往 anck 5.10 的回合工作。 另外,在准备 ebpf + io_uring 的方式实现零拷贝,预计月底会发一版 RFC 到社区上游。 + +5、dsms + +已经开始龙蜥适配的工作,过程中发现缺失一些包,怀疑是某些 repo 没有开启,需要进一步确认。 diff --git a/sig/HighPerfStorageSIG/content/meetingminutes/BiWeeklyMeeting-Rules.md b/sig/HighPerfStorageSIG/content/meetingminutes/BiWeeklyMeeting-Rules.md new file mode 100644 index 0000000000000000000000000000000000000000..35b9271bbd9506cf453529049232a1a3e26c1c49 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/meetingminutes/BiWeeklyMeeting-Rules.md @@ -0,0 +1,7 @@ +- 采用双周例会的形式,时间为每月双周周三上午 11:00 ~ 12:00 + +- 通过邮件列表申报交流议题 + +- 采用云会议的方式,会议开始前一天会将会议 ID 以及议题汇总发送到邮件列表 + +- 会议结束后纪要通过邮件列表发出,并在 SIG 中归档 diff --git a/sig/HighPerfStorageSIG/content/projects/database-optimization/16k-atomic-write-POC.md b/sig/HighPerfStorageSIG/content/projects/database-optimization/16k-atomic-write-POC.md new file mode 100644 index 0000000000000000000000000000000000000000..eec2b3053598d6dc28b215f0c03f5b4b85945c66 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/projects/database-optimization/16k-atomic-write-POC.md @@ -0,0 +1,200 @@ +# 背景 + +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](../../../assets/double-write.png) + +Double Write 介绍: + +https://dev.mysql.com/doc/refman/8.0/en/innodb-doublewrite-buffer.html + +16k 原子写方案旨在通过文件系统 COW 异地更新的机制,确保 MySQL 16k 页面原子写入,同时对 MySQL 应用无侵入,优化 MySQL 的性能和数据写入量,解决 Double Write 带来的额外带宽占用以及降低 SSD 寿命等问题。 + +# 16k 原子写 POC + +1、下载 OpenAnolis 社区 SIG 的特性分支代码,并编译安装。 + +```bash +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 和客户端: +```bash +sudo yum install -y mariadb mariadb-server mariadb-devel +``` + +3、创建 xfs 数据盘并挂载,用于保存 MySQL 数据库。 +(注意需确保 xfsprogs 版本支持 reflink 特性) +```bash +sudo mkfs.xfs -m reflink=1 +sudo mount +sudo chown -R mysql:mysql +``` + +例如: +```bash +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 +``` + +5、设置 mysql db 目录为原子写目录,如: +``` +sudo chattr +c /var/lib/mysql +``` + +dmesg 将显示原子写已针对目录开启信息: +``` +[ 330.918099] XFS (vdb): atomic write set on dir ino 128 +``` + +6、启动 mysqld 服务。 +```bash +sudo systemctl start mariadb +``` + +7、下载并编译 sysbench。 +```bash +git clone https://github.com/akopytov/sysbench.git +cd sysbench +./autogen.sh +./configure +make -j64 -s +sudo make install +``` + +8、运行测试。 +```bash +sudo ./test-mysql.sh +``` + +9、本地测试结果。 + +实例规格:ecs.c7.2xlarge 8C16G + +磁盘规格:ESSD PL1 500G,26800 IOPS + +操作系统:Alibaba Cloud Linux 2.1903 LTS,4.19 内核 + +MySQL 版本:mariadb-5.5.68 + +- oltp_update_non_index + +a)固定测试时间 180s + +| 线程数 | 测试结果项 | 开双写 | 关双写(不安全)| 原子写 | 原子写相比开双写优化 | +| -------- | -------- | -------- | -------- | -------- | -------- | +| 1 | TPS | 7854.94 | 14596.36 | 13360.93 | +70.10% | +| 1 | 数据写入量(KB) | 39532127 | 38799168 | 36009945 | -8.91% | +| 8 | TPS | 9593.61 | 21691.55 | 17918.06 | +86.77% | +| 8 | 数据写入量(KB) | 47578658 | 57184273 | 48047220 | +0.98% | +| 16 | TPS | 9329.04 | 20439.90 | 17820.32 | +91.02% | +| 16 | 数据写入量(KB) | 46345009 | 53731816 | 47346406 | +2.16% | +| 32 | TPS | 9426.33 | 21104.29 | 18396.13 | +95.16% | +| 32 | 数据写入量(KB) | 47250060 | 55832244 | 48678200 | +3.02% | + + b)固定 events 为 2M + +| 线程数 | 测试结果项 | 开双写 | 关双写(不安全)| 原子写 | 原子写相比开双写优化 | +| -------- | -------- | -------- | -------- | -------- | -------- | +| 1 | TPS | 7873.43 | 14291.27 | 13299.73 | +68.92% | +| 1 | 数据写入量(KB) | 55995777 | 29938803 | 30039073 | -46.35% | +| 8 | TPS | 9728.39 | 21028.13 | 17696.14 | +81.90% | +| 8 | 数据写入量(KB) | 55168329 | 29333677 | 29557693 | -46.42% | +| 16 | TPS | 9482.96 | 20197.76 | 17782.89 | +87.52% | +| 16 | 数据写入量(KB) | 55001560 | 29304379 | 29446255 | -46.46% | +| 32 | TPS | 9501.99 | 20291.47 | 17673.52 | +86.00% | +| 32 | 数据写入量(KB) | 55314409 | 29566061 | 29508285 | -46.65% | + +- oltp_insert + +a)固定测试时间 180s + +| 线程数 | 测试结果项 | 开双写 | 关双写(不安全)| 原子写 | 原子写相比开双写优化 | +| -------- | -------- | -------- | -------- | -------- | -------- | +| 1 | TPS | 19264.37 | 23482.19 | 22853.65 | +18.63% | +| 1 | 数据写入量(KB) | 37086672 | 25727280 | 24882876 | -32.91% | +| 8 | TPS | 24562.32 | 34490.62 | 30755.06 | +25.21% | +| 8 | 数据写入量(KB) | 53648479 | 47016444 | 42991537 | -19.86% | +| 16 | TPS | 20008.25 | 19332.95 | 20017.31 | +0.05% | +| 16 | 数据写入量(KB) | 45954919 | 30103151 | 30934187 | -32.69% | +| 32 | TPS | 19387.77 | 20131.95 | 24018.83 | +23.89% | +| 32 | 数据写入量(KB) | 44602586 | 31222080 | 36118410 | -19.02% | + + b)固定 events 为 2M + +| 线程数 | 测试结果项 | 开双写 | 关双写(不安全)| 原子写 | 原子写相比开双写优化 | +| -------- | -------- | -------- | -------- | -------- | -------- | +| 1 | TPS | 21186.13 | 25013.26 | 24566.2 | +15.953% | +| 1 | 数据写入量(KB) | 18861530 | 10499722 | 10188859 | -45.98% | +| 8 | TPS | 33614.36 | 33347.3 | 34043.86 | +1.28% | +| 8 | 数据写入量(KB) | 18858175 | 13656267 | 12629499 | -33.03% | +| 16 | TPS | 24116.70 | 18919.15 | 20415.75 | -15.35% | +| 16 | 数据写入量(KB) | 21408459 | 16185805 | 15722141 | -26.56% | +| 32 | TPS | 21650.58 | 25207.91 | 27342.33 | +26.29% | +| 32 | 数据写入量(KB) | 22208344 | 14087655 | 13408888 | -39.62% | + +- oltp_write_only + +a)固定测试时间 180s + +| 线程数 | 测试结果项 | 开双写 | 关双写(不安全)| 原子写 | 原子写相比开双写优化 | +| -------- | -------- | -------- | -------- | -------- | -------- | +| 1 | TPS | 1805.92 | 2735.14 | 2549.91 | +41.20% | +| 1 | 数据写入量(KB) | 45554816 | 37358352 | 35549446 | -21.96% | +| 8 | TPS | 2461.62 | 3752.81 | 3357.71 | +36.401% | +| 8 | 数据写入量(KB) | 49868393 | 49167253 | 43082960 | -13.61% | +| 16 | TPS | 2483.92 | 5191.67 | 4187.86 | +68.60% | +| 16 | 数据写入量(KB) | 47359563 | 51782025 | 43903632 | -7.30% | +| 32 | TPS | 2597.93 | 5806.17 | 5135.83 | +97.69% | +| 32 | 数据写入量(KB) | 48515272 | 57220863 | 50859090 | +4.83% | + + b)固定 events 为 2M + +| 线程数 | 测试结果项 | 开双写 | 关双写(不安全)| 原子写 | 原子写相比开双写优化 | +| -------- | -------- | -------- | -------- | -------- | -------- | +| 1 | TPS | 2000.18 | 3118.37 | 2824.07 | +41.19% | +| 1 | 数据写入量(KB) | 241033839 | 131181928 | 135543992 | -43.77% | +| 8 | TPS | 2494.74 | 3988.17 | 3705.43 | +48.53% | +| 8 | 数据写入量(KB) | 224525930 | 137667189 | 130066354 | -42.07% | +| 16 | TPS | 2578.07 | 4543.88 | 4490.10 | +74.17% | +| 16 | 数据写入量(KB) | 210570704 | 116910123 | 114145371 | -45.79% | +| 32 | TPS | 2534.39 | 5440.69 | 4976.54 | +96.36% | +| 32 | 数据写入量(KB) | 213153313 | 112451471 | 114696502 | -46.19% | + +# 测试脚本 + +测试脚本(test-mysql.sh)位于: + +https://gitee.com/anolis/storage-test-scripts diff --git a/sig/HighPerfStorageSIG/content/projects/database-optimization/mariadb-16-atomic-write-manual.md b/sig/HighPerfStorageSIG/content/projects/database-optimization/mariadb-16-atomic-write-manual.md new file mode 100644 index 0000000000000000000000000000000000000000..f0fb5a86d489bc856e2833343ff08670487465db --- /dev/null +++ b/sig/HighPerfStorageSIG/content/projects/database-optimization/mariadb-16-atomic-write-manual.md @@ -0,0 +1,114 @@ +# 概述 + +为了消除 double write 带来的额外开销,典型的解决方案是 16k 原子写。业界支持 16k 原子写的几种解决方案有: + +- 硬件方案 + +该方案要求 SSD 盘自身支持 16k 原子写入,并配合对应的 SDK,如 Fusion IO,Shannon SSD 等。 + +- 标准文件系统 + SSD 盘结合的方案 + +该方案实际是硬件方案的一种扩展,其同样要求 SSD 盘支持 16k 原子写入,只需要文件系统支持 16k 对齐的分配,再加上标准的 IO 栈的特定配置即可。如 Google GCP 曾选用的 Ext4 bigalloc + 云盘。 + +- 文件系统 COW 方案 + +即我们当前的方案,基于 XFS 文件系统 COW 机制实现,通过 DIO 采用异地更新机制,写入到 XFS COW fork 的 staging extent 中,待 endio 时再从 COW fork 原子切回到 data fork。方案特点: +1)基于文件系统 COW 机制;2)无硬件依赖;3)无 IO 链路配置依赖。 + +# 使用步骤 + +1、安装支持 xfs 16k 原子写的内核,要求 `kernel-5.10.134-12.an8` 及以上版本。 + +``` +sudo yum install -y kernel kernel-core kernel-modules kernel-devel kernel-headers +``` + +重启进入新内核: +``` +sudo reboot +``` + +2、安装 mariadb,要求 `mariadb-10.3.32-2.0.1` 或 `mariadb-10.5.13-1.0.1` 及以上版本。 +``` +sudo yum install -y mariadb mariadb-server mariadb-devel +``` + +3、创建 xfs 数据盘并挂载,用于存放 mariadb 数据。 + +安装最新版的 xfsprogs,要求 `xfsprogs-5.0.0-10.0.3.an8` 及以上版本。 +``` +sudo yum install -y xfsprogs xfsprogs-devel +``` + +格式化 xfs 数据盘(如 /dev/vdb),打开 reflink: +``` +sudo mkfs.xfs -m reflink=1 /dev/vdb +sudo mount /dev/vdb /var/lib/mysql +sudo chown -R mysql:mysql /var/lib/mysql +``` + +确认安装的内核已支持 xfs 16k 原子写: +``` +cat /sys/fs/xfs/extra/atomic_write +``` + +返回 `1` 表示内核文件系统已支持。 + +4、修改 mariadb 配置文件 `/etc/my.cnf.d/mariadb-server.cnf`,增加原子写相关配置。其中只针对用户表打开原子写,系统表仍然使用双写,防止系统表碎片化。例如: + +``` +... + +[mysqld] +datadir=/var/lib/mysql +socket=/var/lib/mysql/mysql.sock +log-error=/var/log/mariadb/mariadb.log +pid-file=/run/mariadb/mariadb.pid + +# The following configuaratons are newly added +innodb_use_atomic_writes = 1 +innodb_file_per_table = 1 +innodb_page_size = 16384 +innodb_buffer_pool_size = 12288M +innodb_flush_method = O_DIRECT +innodb_doublewrite = 1 + +... +``` + +5、启动 mariadb 服务。 + +``` +sudo systemctl start mariadb +``` + +dmesg 将打印相关用户表已开启原子写的日志,如: +``` +[53683.116215] XFS (vdb): set atomic write for inode 246162 +[53683.118629] XFS (vdb): set atomic write for inode 246164 +[53683.120632] XFS (vdb): set atomic write for inode 246166 +[53683.126173] XFS (vdb): set atomic write for inode 246180 +``` + +6、下载并编译测试工具 sysbench。 +``` +git clone https://github.com/akopytov/sysbench.git +cd sysbench +./autogen.sh +./configure +make -j64 -s +sudo make install +``` + +7、运行测试脚本。 +``` +git clone https://gitee.com/anolis/storage-test-scripts.git +cd storage-test-scripts +sudo ./test-mysql.sh +``` + +从我们的测试结果来看(测试机器配置为 ecs.g7.2xlarge,8 CPU 32 GiB,ESSD 云盘 PL1 500 GiB 26800 IOPS),各项 case 有不同程度的 tps 性能优化,最大达 ~50%,同时明显减少写入数据量。 + +此外,16k 原子写特性优化效果可以与 `代码段大页`[1] 优化效果叠加,即使用代码段大页,性能有进一步的提升(~5%)。 + +[1] https://openanolis.cn/sig/cloud-kernel/doc/475049355931222178 diff --git a/sig/HighPerfStorageSIG/content/projects/doing.md b/sig/HighPerfStorageSIG/content/projects/doing.md new file mode 100644 index 0000000000000000000000000000000000000000..9e09bff415c7120f496d2b38862114e5518409c8 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/projects/doing.md @@ -0,0 +1,8 @@ +# io_uring +## c++ corotine + +# EROFS + +# ublk + +# DSMS diff --git a/sig/HighPerfStorageSIG/content/projects/done.md b/sig/HighPerfStorageSIG/content/projects/done.md new file mode 100644 index 0000000000000000000000000000000000000000..a953cc723eac8702fc2cd7b3a37360a988f7872e --- /dev/null +++ b/sig/HighPerfStorageSIG/content/projects/done.md @@ -0,0 +1,53 @@ +# io_uring + +## 基础技术 + +https://openanolis.cn/sig/high-perf-storage/doc/218455073889779745 + +https://openanolis.cn/sig/high-perf-storage/doc/218947367998324809 + +https://openanolis.cn/sig/high-perf-storage/doc/218947430845775947 + +## 性能回归框架 + +https://openanolis.cn/sig/high-perf-storage/doc/218455592355495979 + +## 应用 POC + +### Echo Server + +https://openanolis.cn/sig/high-perf-storage/doc/218455838343036973 + +### Nginx + +https://openanolis.cn/sig/high-perf-storage/doc/218937516350570546 + +### Redis + +https://openanolis.cn/sig/high-perf-storage/doc/218937424285597744 + +# virtio-fs + +## virtio-fs perfile dax + +https://openanolis.cn/sig/high-perf-storage/doc/485810385468129605 + +# 容器镜像加速 + +## sealer + nydus 集群部署加速 + +https://openanolis.cn/sig/high-perf-storage/doc/461915394308588490 + +## erofs over fscache + +https://openanolis.cn/sig/high-perf-storage/doc/594615318749200391 + +# 数据库优化 + +## 16k 原子写 POC + +https://openanolis.cn/sig/high-perf-storage/doc/415544543086428789 + +## MariaDB 16k 原子写使用手册 + +https://openanolis.cn/sig/high-perf-storage/doc/594617348901388298 diff --git a/sig/HighPerfStorageSIG/content/projects/dsms/dsms-introduction.md b/sig/HighPerfStorageSIG/content/projects/dsms/dsms-introduction.md new file mode 100644 index 0000000000000000000000000000000000000000..8527da4fd4935627df0581648a1559921bcea3a3 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/projects/dsms/dsms-introduction.md @@ -0,0 +1,33 @@ +# 介绍 + +分布式存储管理系统 DSMS (Distributed Storage Management System)是由龙蜥社区高性能存储SIG开发并维护的分布式存储系统管理平台。该软件实现可视化的存储集群管理,提升分布式存储软件的易用性。 + +# 软件架构 + +DSMS (Distributed Storage Management System) 分布式存储管理系统由3个模块组成: + +dsms-ui :UI组件,提供基于web的图形界面,便于用户管理、使用DSMS系统。 + +dsms-engine :管理引擎组件,实现对分布式存储的管理。 + +dsms-storage :分布式存储组件,基于开源分布式存储定制化。 + +# 工作计划 + +1、完成分布式存储选型,完成anolis系统选型,完成分布式存储在anolis上的移植开发与测试。(2022.11.14 ~ 2022.12.31) + +2、进行可视化管理平台开发,发布初步版本。(2023.1.1 ~ 2023.6.1) + +3、进行Linux、Windows多版本系统的客户端适配测试、提供多种存储接口。(2023.6.2 ~ 2023.9.1) + +4、运营社区,持续开发完善系统。(长期) + +# 技术路线 + +1、第一期主要是针对开源的分布式文件系统(如ceph等)进行选型移植及管理平台第一版的适配开发。 + +2、第一期会完成windows、linux客户端的适配集成(如iscsi、fs、multipath等)。 + +3、第二期往后计划持续开发、完善管理平台。 + +4、第二期往后计划针对分布式文件系统、客户端等相关组件进行一些扩展开发,支持新特性、提升安全性等等。 diff --git a/sig/HighPerfStorageSIG/content/projects/image-acceleration/erofs-over-fscache.md b/sig/HighPerfStorageSIG/content/projects/image-acceleration/erofs-over-fscache.md new file mode 100644 index 0000000000000000000000000000000000000000..7753348daa3341f6f5ec616033ea9990938e94f4 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/projects/image-acceleration/erofs-over-fscache.md @@ -0,0 +1,7 @@ +# 技术博客 +开箱即用!Linux 内核首个原生支持,让你的容器体验飞起来!| 龙蜥技术
+https://openanolis.cn/blog/detail/576260913196929348 + +# 分享视频 +Nydus 容器镜像加速之内核演进之路 | 龙蜥大讲堂 22 期
+https://openanolis.cn/video/593123727115010051 diff --git a/sig/HighPerfStorageSIG/content/projects/image-acceleration/sealer-nydus-acceleration.md b/sig/HighPerfStorageSIG/content/projects/image-acceleration/sealer-nydus-acceleration.md new file mode 100644 index 0000000000000000000000000000000000000000..feb30bbe75f70847f94e88b1081cb273a4f21388 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/projects/image-acceleration/sealer-nydus-acceleration.md @@ -0,0 +1,110 @@ +# 背景 + +Sealer 在部署集群的时候,需要先将 [rootfs](https://sealer.oss-cn-beijing.aliyuncs.com/docs/advanced/define-cloudrootfs.html#how-can-i-get-cloudrootfs) 目录(集群镜像)传输到所有的节点上,然后再执行 init.sh 初始化节点,接着拉起集群。在镜像文件很大(例如 30G 大小)或者节点数很多的情况下,传输文件的过程会消耗大量的时间,成为 sealer 集群部署性能的瓶颈。 + +# Nydus加速 + +[Nydus](https://nydus.dev) 的按需加载和预取功能能够极大地提高 sealer 分发 rootfs 的性能,在 sealer 0.7.1 正式支持了 nydus 特性,只需要使用开启该特性的集群镜像就可以应用 nydus 来提高镜像分发性能。 + +当 sealer run 开启 nydus 特性的集群镜像时,会先将 rootfs 目录转换成 nydus 格式的 blob,并在本地启动一个 nydusdserver 来为 nydusd 提供静态文件服务。然后将 nydusd 和相应的脚本文件传输到远程节点上,并在节点上启动 nydusd 挂载 rootfs 目录即可。Nydus 会从 nydusdserver 按需拉取数据并缓存到本地,当所有数据都拉取完后,即使断开 nydusdserver 也不影响 rootfs 的使用,大大降低了集群镜像分发的时间。 + +## 适用场景 + +Sealer 针对文件传输环节做了优化,在初始化阶段,对于不需要 registry 目录的节点,只传输 rootfs 中非 registry 目录的文件,这大大减小了需要传输的文件数量(以 kubernetes:v1.19.8 镜像为例,只有 master0 需要传输所有文件,其他节点需传输的文件数量从 241 个降到 33 个)。启用 nydus 加速,除了镜像转换和服务启动的时间外,还需要传输一些 nydus 相关文件(7 个文件),有一定的开销,需要传输的镜像文件很少时,收益并不是很大。因此 nydus 加速适合于大镜像、多节点的集群部署。 + +## 使用方法 + +直接使用支持 nydus 加速的集群镜像即可,如 +```bash +sealer run kubernetes-nydus:v1.19.8 --masters 172.16.141.22 --passwd xxxxxx +``` + +## 制作 nydus 加速集群镜像 +方法一:基于使用 nydus 加速的基础镜像(如kubernetes-nydus:v1.19.8)制作自己的镜像; + +方法二:使用 sealer merge 将 nydus 组件 merge 到自己的集群镜像中,如: +``` +sealer merge kubernetes:v1.19.8 nydus:v1.0.0 -t kubernetes-nydus:1.0.0 +``` + +# 性能对比测试 + +## 测试环境 + +7 台阿里云ECS,内网 IP 为 172.16.141.21 ~ 172.16.141.27 + +> ECS规格:ecs.g7.xlarge
+CPU & 内存:4核16GiB
+云盘:ESSD云盘 PL1 40GiB (3800 IOPS)
+OS:Anolis OS 8.4 ANCK 64 位
+网络带宽:100M + + +## 下载安装 +在其中一台 ECS(172.16.141.21)中安装 sealer 0.7.1 作为sealer的执行机。 +```bash +wget -c https://sealer.oss-cn-beijing.aliyuncs.com/sealers/sealer-v0.7.1-linux-amd64.tar.gz && tar -xvf sealer-v0.7.1-linux-amd64.tar.gz -C /usr/bin +# 查看 sealer 版本 +sealer version +``` + +## 基础 kubernetes:v1.19.8 镜像测试 +### 集群镜像概况 +大小:787.81MB + +文件数:241 个 + +在未指定时,默认只有 master0 需要传输所有的 rootfs 文件,其他节点不需要传输 registry 目录。 + +### 单节点测试 +```bash +sealer run kubernetes:v1.19.8 --masters 172.16.141.22 --passwd xxxxxx +``` +创建成功后删除集群 +```bash +sealer delete –all +``` + +### 6 节点测试 +3 master,3 node +```bash +sealer run kubernetes:v1.19.8 \ +--masters 172.16.141.22,172.16.141.23,172.16.141.24 --nodes \ +172.16.141.25,172.16.141.26,172.16.141.27 \ +--passwd xxxxxxx +``` +创建成功后删除集群 + +## 应用 nydus 特性的 kubernetes:v1.19.8 镜像测试 +### 单节点测试 +``` +sealer run kubernetes-nydus:v1.19.8 --masters 172.16.141.22 --passwd xxxxxx +``` +创建成功后删除集群 + +### 6 节点测试 +3 master,3 node +``` +sealer run kubernetes-nydus:v1.19.8 \ +--masters 172.16.141.22,172.16.141.23,172.16.141.24 --nodes \ +172.16.141.25,172.16.141.26,172.16.141.27 \ +--passwd xxxxxxx +```` +创建成功后删除集群 + +## 大镜像模拟测试 +拉取镜像后,用 1000 个 30M 大小的随机文件填充 kubernetes:v1.19.8 镜像中的 registry 目录,模拟测试 30G 大镜像的部署性能。由于是放在 registry 目录下,对于非 master0 节点,不会传输这些目录,在实际场景下,可能不只 master0 需要传输使用 registry 目录。
+随机文件生成脚本如下 +``` +dir=/var/lib/sealer/data/overlay2/ecc826865973a8cf2cbb337e939f647840cc80834cf148b92eebcf1b213df9a9 /registry +for i in {1..1000}; do + dd if=/dev/urandom of=$dir/$i bs=2M count=15 +done +``` +然后再执行上文中的基础镜像测试步骤和应用 nydus 特性的镜像测试步骤。 + +## 测试数据对比 +![sealer-nydus-test](../../../assets/sealer-nydus-test.png) + +## 测试说明 +传输时间为 `Start to create a new cluster` 到 `start to init master0` 的时间。nydus 的镜像转换时间受限于 IO 性能。由于使用 nydus 加速时只需要镜像转换和传输固定的文件(与镜像文件无关),因此收益取决于需要传输的镜像文件总数量和大小。 diff --git a/sig/HighPerfStorageSIG/content/projects/io_uring/echo-server.md b/sig/HighPerfStorageSIG/content/projects/io_uring/echo-server.md new file mode 100644 index 0000000000000000000000000000000000000000..13328c6811e1c119ceb6939c9b547d2794b71c9c --- /dev/null +++ b/sig/HighPerfStorageSIG/content/projects/io_uring/echo-server.md @@ -0,0 +1,25 @@ +# 项目介绍 + +echo server 是一个经典的用于评估网络性能的测试套件,多个客户端并发地向服务端发送固定长度消息,服务端收到消息后直接将消息原样返回给客户端。echo server 本身也是一种经典的网络编程模型,redis,nginx 等基本都是采用此编程模型。 + +# 项目文档 + +传统上 echo server 通常利用 select,epoll,kequeue 等机制实现。以 epoll 为例,利用 epoll_ctl 监听用于网络通信的fd,利用 epoll_wait 可以获得可读写的文件句柄,然后再对每个返回的文件句柄调用 recv(),send() 等进行消息收发。 + +io_uring 提供的网络编程模型不同于 epoll,以recv()为例,它不需要通过 epoll_ctl 进行文件句柄的注册,io_uring 首先在用户态用 sqe 结构描述一个 io 请求,然后用户程序通过调用 io_uring_submit_and_wait() 来提交和等待该请求,类似于 epoll_wait(),最后 io_uring_submit_and_wait() 返回时的cqe结构用于描述之前提交的 recv() 请求的完成状态。 + +io_uring 相比于 epoll 可以极大降低系统的用户态到内核态上下文切换开销,从而提高 echo server 的 qps。 + +我们在物理机环境进行 echo server 编程模型下 io_uring 和 epoll 的性能对比,server 端 cpu Intel(R) Xeon(R) CPU E5-2682 v4 @ 2.50GHz, client 端 cpu Intel(R) Xeon(R) CPU E5-2630 0 @ 2.30GHz,OS 使用 Alibaba Cloud Linux 2.1903 LTS 64 位。 + +![io_uring-vs-epoll-qps](../../../assets/echo-server-qps.png) + +上图是 io_uring 和 epoll 在 echo_server 场景下 qps 数据对比,可以看出在测试环境中,连接数 1000 及以上时,io_uring 的性能优势开始体现,io_uring 的极限性能单 core 在 24 万 qps 左右,而 epoll 单 core 只能达到 20 万 qps 左右,收益在 20% 左右。 + +![io_uring-vs-epoll-syscalls](../../../assets/echo-server-syscalls.png) + +上图统计的是 io_uring 和 epoll 在 echo server 场景下系统调用上下文切换数量的对比,可以看出 io_uring 可以极大的减少用户态到内核态的切换次数,在连接数超过 300 时,io_uring 用户态到内核态的切换次数基本可以忽略不计。 + +# 项目仓库 + +https://gitee.com/anolis/io_uring-echo-server diff --git a/sig/HighPerfStorageSIG/content/projects/io_uring/fio.md b/sig/HighPerfStorageSIG/content/projects/io_uring/fio.md new file mode 100644 index 0000000000000000000000000000000000000000..815919a31d8df0c9a4962b59bc44ebf2bd21ad0d --- /dev/null +++ b/sig/HighPerfStorageSIG/content/projects/io_uring/fio.md @@ -0,0 +1,60 @@ +# 项目介绍 + +fio 的全称是 flexible I/O tester,是常用的磁盘性能测试工具。fio 通过产生一系列的线程或进程来执行用户指定的特定类型 IO 操作。典型的用法是用户将需要模拟的 IO 负载写入到 job file 中。fio 支持多种 IO 引擎,通过 ioengine=io_uring,我们可以在 fio 中使用 io_uring 接口来测试磁盘性能。 + +# 项目文档 + +用户需要安装 fio-3.17 以使用 io_uring 引擎。 + +``` +sudo yum install -y alinux-release-experimentals +sudo yum install -y fio-3.17 +``` + +使用 io_uring 的示例如下: + +``` +fio -name=iouring_test -filename=/mnt/vdd/testfile -iodepth=128 -thread -rw=randread -ioengine=io_uring -sqthread_poll=1 -direct=1 -bs=4k -size=10G -numjobs=1 -runtime=120 -group_reporting +``` + +- 普通 ECS + +测试环境:ecs.i2.2xlarge,8 vCPU 64 GiB,I2 本地存储 1788 GiB。 + +1、默认模式下,略微提升。
+2、开启 sqthread_poll 后,顺序读写提升很明显,达到 160% ~ 170%;随机读写提升 30% ~ 150%。 + +**4k 顺序读** + +![4k-seqread](../../../assets/4k-seq-read.png) + +**4k 顺序写** + +![4k-seqwrite](../../../assets/4k-seq-write.png) + +**4k 随机读** + +![4k-randread](../../../assets/4k-rand-read.png) + +**4k 随机写** + +![4k-randwrite](../../../assets/4k-rand-write.png) + +- 神龙裸金属 + +测试环境:神龙裸金属实例,96 CPU 503 G,本地盘为三星 PM963。 +1、开启 iopoll 后,基本与 SPDK 接近。 + +**4k 随机读** + +![4k-moc-randread](../../../assets/4k-rand-read-moc.png) + +- 相关文档 + +[Fio README](https://github.com/axboe/fio/blob/master/README) + +[io_uring 新异步 IO 机制,性能提升超 150%,堪比 SPDK](https://mp.weixin.qq.com/s?__biz=MzUxNjE3MTcwMg==&mid=2247484448&idx=1&sn=29e791cf602b8614c9d288c1859407f7) + +# 项目仓库 + +https://gitee.com/anolis/fio diff --git a/sig/HighPerfStorageSIG/content/projects/io_uring/io_uring-features.md b/sig/HighPerfStorageSIG/content/projects/io_uring/io_uring-features.md new file mode 100644 index 0000000000000000000000000000000000000000..198a19c3be01e432c27a4f3fa453725c0e037e03 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/projects/io_uring/io_uring-features.md @@ -0,0 +1,217 @@ +# Linux 6.1 + +- 支持网络零拷贝 SENDMSG(IORING_OP_SENDMSG_ZC) +- 支持 sendto(非零拷贝) +- 支持延迟异步 work 选项,允许工作负载自己决定异步 work 调度的时机,以获得更细粒度的调度控制 + +# Linux 6.0 + +- 支持 async buffered writes(当前仅支持使用 xfs 的场景),buffer 写场景性能提升 2 倍以上 +- 支持 io_uring passthrough based userspace block driver(ublk) +- io_uring_register() 增加同步取消 API +- 支持网络零拷贝 SEND(IORING_OP_SEND_ZC) +- 支持 IORING_RECV_MULTISHOT,在从相同 socket 大量接收场景显著提升应用性能 +- taskwork 锁竞争优化 +- 弃用 epoll_ctl 操作,后续版本将从 io_uring 支持的操作中彻底移除 + +## 延伸阅读 + +https://lwn.net/Articles/879724/ + + +# Linux 5.19 + +- 支持 fast poll multishot 模式 +- 支持大于 16 字节以上的大 CQE +- 支持 xattr +- IPI 优化,支持 co-operative task_work signaling +- 支持 sparse buffer 和 file maps +- 支持多种类型的取消 +- send/sendmsg 允许 MSG_WAITALL +- 支持 IORING_RECVSEND_POLL_FIRST +- 支持 nvme io_uring passthrough +- 支持 ring mapped provided buffers +- 支持 socket(2) +
在使用 io_uring direct/registered fd 时非常方便 + +# Linux 5.18 + +- 支持 ring message(IORING_OP_MSG_RING),允许 sqe 通知另外一个 ring +- 支持 ring fd 注册,优化频繁操作的原子操作开销(~15%) +- 支持 napi busy poll +- statx 加固 + +# Linux 5.17 + +- 允许忽略递交 CQE(IOSQE_CQE_SKIP_SUCCESS),使用场景如处理 linked request 等 +- 重构 io_uring internal poll,以修复当前 poll 存在的问题如 POLLFREE +- 支持按优先级的工作完成 + +# Linux 5.16 + +- pollable 请求支持 async hybrid 模式(e.g. read/write a socketfd) +- fdinfo 增加更多的 debug 信息,如 sqring/cqring head/tail 信息,sqe/cqe 详细信息等 +- 其他小的优化,如 iopoll,drain 操作等 + +# Linux 5.15 + +- 支持 mkdir 和 [sym]linkat +- 支持 descriptorless files 特性 +
在此之前,用户需要先在进程的 file table 中打开文件,然后再注册到 io_uring。该特性在 IORING_OP_OPENAT 和 OPRING_OP_OPENAT2 中支持跳过前面一步,直接注册到 io_uring 的 file table。
+LWN 文章:[Descriptorless files for io_uring](https://lwn.net/Articles/863071/) +- 支持非 4k 页 +- 支持 CLOCK_BOOTTIME/REALTIME 超时 +- 支持限制最大 worker 数量(IORING_REGISTER_IOWQ_MAX_WORKERS) +- 允许 O_NONBLOCK 文件重试 + +# Linux 5.14 + +- 对多队列设备进行 iopoll 的优化 +
之前的 iopoll 逻辑是如果 iopoll list 中的 requests 都是针对同一设备,则以 spin 的方式进行 iopoll。该逻辑对单队列设备是 ok 的,因为所有请求都会发到同一个队列,所以只对该队列 iopoll 即可。多队列设备显然不如此,因此将 spin 的条件严格限制为:iopoll list 中的 requests 都针对同一硬件队列。 +- 允许用户配置 io-wq 线程的 cpumask +
用户在实际使用 io-wq 线程时,有时希望对消耗的 cpu 资源数量和位置进行限制,因此增加该功能。 +- renameat/linkat 修改 +- fast poll 优化 +
fast poll 在第一次 vfs_poll 成功后还是会将 request 放入 io-wq 去重新下发。 但这种情况下更好的方式是在当前上下文直接重新下发,这样效率更高。该优化实现了这种改变。 +- Enable file backed buffers for shmem/memfd + +# Linux 5.13 + +- poll 请求支持 multi-shot 模式 +
通常情况下,poll 请求与其他 io_uring 操作一样,在产生一个完成事件以后会从 ring buffer 中移除。支持 multi-shot poll 以后,单个提交请求可以产生多个完成事件。 +- 更高效的引用计数 +- 移除 manager thread 的依赖 +- SQPOLL 不再依赖 CAP_SYS_ADMIN 和 CAP_SYS_NICE + +# Linux 5.12 + +- 请求回收及 task work 优化 +- 支持 memcg 记账 +
包括请求,SQ/CQ arrays 等。 +- 开启 LOOKUP_CACHED +
用于文件名 lookup 时的路径解析,在已经 cache 的场景显著提升 lookup 性能(2.9x)。 +- 支持 IORING_REGISTER_FILES_UPDATE 过滤 fd +- io-wq workers 修改为业务线程创建 +
之前为内核线程,这是一个很大的重构,不仅简化了代码代码,之前很多因为状态切换等导致的各种问题迎刃而解。Jens 甚至想将该重构合入到 v5.10 stable 分支,可见这个重构的重要程度。 + +# Linux 5.11 + +- SQPOLL 模式支持 non-fixed files +- SQPOLL 模式支持 CAP_SYS_NICE 权限 +- 支持 IORING_OP_RENAMEAT 和 IORING_OP_UNLINKAT +- 支持超时更新 +
IORING_OP_TIMEOUT_REMOVE 请求类型,带上 IORING_TIMEOUT_UPDATE 标记。 +- io_uring_enter() 支持超时 +
在此之前需要再单独下发 timeout 请求,无锁时分开在两个线程中处理 SQ 和 CQ 不安全,显示在两个处理线程中同步又会影响性能。该特性对诸如 MySQL 等应用场景有较大性能收益。 +- 支持 shutdown(2) +
在 socket 处理时比较有用。 + +# Linux 5.10 + +- 支持对特定操作的限制(sqe opcode and flags, register opcode) +
主要用于非授信常见使用 io_uring 的 ring buffer,如非信任的应用,虚拟化 guest 等。 +- 支持 sqpoll offload 模式下 blkcg 的记账 +- sqpoll 模式下支持应用等待内核消费 SQ ring +
优化 busy polling 的 CPU 开销 + +# Linux 5.9 + +- async buffered read 优化,不再依赖额外内核线程来处理 +- 支持 EPOLLEXCLUSIVE +
避免 accept 惊群效应。 + +# Linux 5.8 + +- 支持 tee(2) +- 支持启动/禁用已注册的 eventfd 通知 +- 允许IORING_OP_POLL 处理多个等待队列 +
存在 fd 的 f_ops->poll 使用不同的等待队列,通常情况下诸如读写分离(tty 设备,/dev/random 等)。 +- 导出 cq overflow 状态到用户态 +
通过 IORING_SQ_CQ_OVERFLOW 标记。 +- 支持直接调用 statx + +# Linux 5.7 + +- 重构 pollable 异步 IO 的处理机制,不再需要额外线程来处理(IORING_FEAT_FAST_POLL) +- 允许自动 buffer selection +
poll + recv 不再需要单独操作。 +- 支持 支持 splice(2) + +## 延伸阅读 + +https://lwn.net/Articles/815491/ + +# Linux 5.6 + +- 支持 fallocate(2),openat(2),and close(2) +- 支持普通版本的 read(2)/write(2) +- 支持 statx(2) +- 支持 epoll 操作(epoll_ctl(2)) +- 支持 openat2(2) +- 支持 madvise(2) 和 fadvise(2) +- 支持 send(2) and recv(2) +- 支持查询当前内核版本是否支持给定的 opcode +
通过 IORING_REGISTER_PROBE 直接查询相应 opcode 是否支持,而之前需要先尝试下发并返回 -EINVAL。 +- 支持最大 ring size clamping +
针对那些初始 ring size 比较小,并在使用过程需要增大的应用。通过 IORING_SETUP_CLAMP,不再直接返回 -EINVAL,而是增大直至支持的最大 ring size。 +- 支持 IORING_REGISTER_EVENTFD_ASYNC +
类似 IORING_REGISTER_EVENTFD,但仅在异步完成时(IRQ,io-wq worker等)触发事件通知。 +- 优化 poll 完成性能 + +# Linux 5.5 + +- 支持 connect(2) +- 支持 accept(4)(IORING_OP_ACCEPT) +- 支持 sparse file sets +
应用可扩展 file set,同时通过 IORING_REGISTER_FILES_UPDATE 修改现有 file set。 +- 支持 overflowed CQ ring +
将溢出的请求在链表中暂存,随后由内核自动 flush。 +- 支持 IORING_OP_ASYNC_CANCEL +
尝试取消 in-flight 请求,适用于文件/ Socket IO 未开始的请求,以及 Socket IO 已经在运行的请求。 +- 支持取消超时的请求(IORING_OP_TIMEOUT_REMOVE) +- 支持 linked timeouts(IORING_OP_LINK_TIMEOUT) +- 支持绝对超时 +- 支持应用配置 CQ ring(IORING_SETUP_CQSIZE) +
相比直接设置为 SQ ring 的 2 倍大小,这种方式更灵活,如网络应用场景。 +- 引入 io_uring 的专有 workqueue io-wq +- 支持 NOMMU 架构 mapping + +## 延伸阅读 + +https://lwn.net/Articles/803070/ + +# Linux 5.4 + +- 支持 IORING_OP_TIMEOUT +
类似 io_getevents() 和 epoll_wait(),用户可在等待事件时设定一个超时。 +- 优化 CQ ring 批量唤醒 +- 支持同时分配 SQ/CQ 以减少 mmap 系统调用 +- 支持在单个 io_uring_enter() 系统调用中 SQ poll 唤醒 + 事件获取 +- 支持 linked drain + +# Linux 5.3 +- 支持 recvmsg() +- 支持 sendmsg() +- 增加对 short read 的处理 +
避免应用针对剩余部分需要额外下发请求,节省系统调用上下文切换开销。 +- 支持 SQE (Submission Queue Entry) 链接 + +# Linux 5.2 + +- 支持 eventfd 通知机制 +- 支持 sync_file_range(2) +- 支持 drain (IOSQE_IO_DRAIN) +
标记为 IOSQE_IO_DRAIN 的请求在下发前将等待之前的请求完成。 + +# Linux 5.1 + +- 首次加入内核主线 +- 不仅支持 direct IO,同时也支持 buffered IO +- 支持 polling +- 高级特性支持,如 register buffers,register files 等 +- 配套用户态库 liburing + +## 延伸阅读 + +https://kernel.dk/io_uring.pdf
+https://lwn.net/Articles/776703/ diff --git a/sig/HighPerfStorageSIG/content/projects/io_uring/io_uring-kernel.md b/sig/HighPerfStorageSIG/content/projects/io_uring/io_uring-kernel.md new file mode 100644 index 0000000000000000000000000000000000000000..43d9c143f205518a543df58774a0192c02ee70df --- /dev/null +++ b/sig/HighPerfStorageSIG/content/projects/io_uring/io_uring-kernel.md @@ -0,0 +1,145 @@ +# 项目介绍 + +io_uring 是由 block 维护者 Jens Axboe 开发的新异步 IO 框架。io_uring 在 2019 年 1 月初提出,到 2019 年 3 月初合并到 Linux 内核主线,仅用短短的 2 个月时间就合入了 Linux v5.1,充分表明了社区对该框架的积极态度。当前社区发展非常火热,很多主流应用都开始提供对 io_uring 的支持。 + +# 项目文档 + +## io_uring 原理介绍 + +为了从根本上解决当前 Linux aio 存在的问题和约束,io_uring 从零开始全新设计的了异步 IO 框架。其设计的主要目标如下: + +1、简单易用,方便应用集成。
+2、可扩展,不仅仅为 block IO 使用,同样可以用于网络 IO。
+3、特性丰富,满足所有应用,如 buffered io。
+4、高效,尤其是针对大部分场景的 512 字节或 4K IO。
+5、可伸缩,满足峰值场景的性能需要。 + +io_uring 为了避免在提交和完成事件中的内存拷贝,设计了一对共享的 ring buffer 用于应用和内核之间的通信。其中,针对提交队列(SQ),应用是 IO 提交的生产者(producer),内核是消费者(consumer);反过来,针对完成队列(CQ),内核是完成事件的生产者,应用是消费者。 + +![io_uring-architecture](../../../assets/io_uring-arch.png) + +共享环的设计主要带来以下 3 个好处: + +1、提交、完成请求时节省应用和内核之间的内存拷贝;
+2、使用 SQPOLL 高级特性时,应用程序无需调用系统调用;
+3、无锁操作,用 memory ordering 实现同步。 + +## io_uring 系统调用 + +``` +/** + * io_uring_setup - setup a context for performing asynchronous I/O + * + * The io_uring_setup() system call sets up a submission queue (SQ) and completion queue (CQ) with at least + * entries entries, and returns a file descriptor which can be used to perform subsequent operations on the + * io_uring instance. The submission and completion queues are shared between userspace and the kernel, + * which eliminates the need to copy data when initiating and completing I/O. + */ +int io_uring_setup(u32 entries, struct io_uring_params *p); + +/** + * io_uring_enter - initiate and/or complete asynchronous I/O + * + * io_uring_enter() is used to initiate and complete I/O using the shared submission and completion queues + * setup by a call to io_uring_setup(2). A single call can both submit new I/O and wait for completions of I/O + * initiated by this call or previous calls to io_uring_enter(). + */ +int io_uring_enter(int fd, unsigned int to_submit, unsigned int min_complete, + unsigned int flags, sigset_t *sig); + +/** + * io_uring_register - register files or user buffers for asynchronous I/O + * + * The io_uring_register() system call registers user buffers or files for use in an io_uring(7) instance referenced + * by fd. Registering files or user buffers allows the kernel to take long term references to internal data + * structures or create long term mappings of application memory, greatly reducing per-I/O overhead. + */ + int io_uring_register(int fd, unsigned int opcode, void *arg, + unsigned int nr_args); +``` + +## 支持的异步操作 + +**IORING_OP_NOP**
+仅产生一个完成事件,除此之外没有任何操作。 + +**IORING_OP_READV / IORING_OP_WRITEV**
+异步方式提交 readv() / writev() 请求,大多数场景最核心的操作,类似 preadv2 / pwritev2。 + +**IORING_OP_FSYNC**
+异步下发 fsync() 调用,注意这里并不能保证下发 fsync() 之前的写请求一定先完成,需要额外通过标记 IOSQE_IO_DRAIN 来实现。 + +**IORING_OP_READ_FIXED / IORING_OP_WRITE_FIXED**
+使用已注册的 buffer 来提交 IO 操作,由于这些 buffer 已经完成映射,可以降低系统调用的开销。 + +**IORING_OP_POLL_ADD / IORING_OP_POLL_REMOVE**
+使用 IORING_OP_POLL_ADD 可对一组文件描述符执行 poll() 操作,可以使用 IORING_OP_POLL_REMOVE 显式地取消 poll()。注意,其工作方式为 one shot,即一旦 poll 操作完成,需要重新提交。 + +**IORING_OP_SYNC_FILE_RANGE**
+执行 sync_file_range() 调用,是对 fsync() 的一个增强。 + +**IORING_OP_SENDMSG / IORING_OP_RECVMSG**
+基于 sendmsg() 和 recvmsg() 提供异步收发网络包功能。 + +**IORING_OP_TIMEOUT / IORING_OP_TIMEOUT_REMOVE**
+用户态程序等待 IO 完成事件时,可以通过 IORING_OP_TIMEOUT 设置一个超时时间,类似 io_getevents(2) 的 timeout 机制。 + +**IORING_OP_ACCEPT**
+异步 accept4()。 + +**IORING_OP_ASYNC_CANCEL**
+尝试取消 in-flight 的异步上下文中的请求。通常可中断的请求如 socket IO 无论是否已经开始运行都将被取消,而 block IO 请求只能取消尚未开始的请求。 + +**IORING_OP_LINK_TIMEOUT**
+类似 IORING_OP_TIMEOUT,IORING_OP_LINK_TIMEOUT 仅针对特定的 linked SQE(IOSQE_IO_LINK)。 + +**IORING_OP_CONNECT**
+异步 connect(),调用者可通过 IORING_OP_POLL_ADD 来实现 connect 请求的异步等待。 + +**IORING_OP_FALLOCATE**
+异步 fallocate()。 + +**IORING_OP_OPENAT / IORING_OP_CLOSE / IORING_OP_OPENAT2**
+异步openat(),close(),openat2()。 + +**IORING_OP_FILES_UPDATE**
+IORING_REGISTER_FILES_UPDATE 的异步替代方案。 + +**IORING_OP_STATX**
+异步 statx()。 + +**IORING_OP_READ / IORING_OP_WRITE**
+异步方式提交 read / write 请求,是 IORING_OP_READV / IORING_OP_WRITEV 的 non-vectored 版本。 + +**IORING_OP_FADVISE / IORING_OP_MADVISE**
+异步 posix_fadvise() / madvise。 + +**IORING_OP_SEND / IORING_OP_RECV**
+异步 send() / recv()。 + +**IORING_OP_EPOLL_CTL**
+增加,删除或修改 epoll 的事件列表。 + +**IORING_OP_SPLICE**
+异步 splice()。 + +**IORING_OP_TEE**
+异步 tee()。 + +同时社区仍然在不断加入对新操作的支持。 + +- 相关文档 + +[Efficient IO with io_uring](http://kernel.dk/io_uring.pdf) + +[Linux异步IO新时代:io_uring](https://kernel.taobao.org/2019/06/io_uring-a-new-linux-asynchronous-io-API) + +[io_uring 新异步 IO 机制,性能提升超 150%,堪比 SPDK](https://mp.weixin.qq.com/s?__biz=MzUxNjE3MTcwMg==&mid=2247484448&idx=1&sn=29e791cf602b8614c9d288c1859407f7) + +[下一代异步 IO io_uring 技术解密](https://mp.weixin.qq.com/s?__biz=MzUxNjE3MTcwMg==&mid=2247484537&idx=1&sn=21d3104fd80fa2474a3770bf4b4b814f) + +[io_uring 社区开发报告](https://mp.weixin.qq.com/s/KWzsZy8TMhQz42hVliqtEQ) + +# 项目仓库 + +https://gitee.com/anolis/cloud-kernel diff --git a/sig/HighPerfStorageSIG/content/projects/io_uring/liburing.md b/sig/HighPerfStorageSIG/content/projects/io_uring/liburing.md new file mode 100644 index 0000000000000000000000000000000000000000..0fee875973a1fbbef6ea26424b2b8eb683041c9f --- /dev/null +++ b/sig/HighPerfStorageSIG/content/projects/io_uring/liburing.md @@ -0,0 +1,98 @@ +# 项目介绍 + +liburing 提供 io_uring 的用户态库,方便用户操作 io_uring 实例。通过 liburing 库,应用无需了解诸多 io_uring 的细节就可以简单地使用起来。例如,无需担心 memory barrier,或者是 ring buffer 管理之类等。 + +# 项目文档 + +用户需安装 liburing 和 liburing-devel 包以使用 io_uring,相关接口在头文件 /usr/include/liburing.h 中定义。 + +``` +sudo yum install liburing liburing-devel +``` + +基于 liburing 的一个 helloworld 示例如下: + +``` +#include +#include +#include +#include +#include + +#define ENTRIES 4 + +int main(int argc, char *argv[]) +{ + struct io_uring ring; + struct io_uring_sqe *sqe; + struct io_uring_cqe *cqe; + struct iovec iov = { + .iov_base = "Hello World", + .iov_len = strlen("Hello World"), + }; + int fd, ret; + + if (argc != 2) { + printf("%s: \n", argv[0]); + return 1; + } + + /* setup io_uring and do mmap */ + ret = io_uring_queue_init(ENTRIES, &ring, 0); + if (ret < 0) { + printf("io_uring_queue_init: %s\n", strerror(-ret)); + return 1; + } + + fd = open("testfile", O_WRONLY | O_CREAT); + if (fd < 0) { + printf("open failed\n"); + ret = 1; + goto exit; + } + + /* get an sqe and fill in a WRITEV operation */ + sqe = io_uring_get_sqe(&ring); + if (!sqe) { + printf("io_uring_get_sqe failed\n"); + ret = 1; + goto out; + } + + io_uring_prep_writev(sqe, fd, &iov, 1, 0); + + /* tell the kernel we have an sqe ready for consumption */ + ret = io_uring_submit(&ring); + if (ret < 0) { + printf("io_uring_submit: %s\n", strerror(-ret)); + goto out; + } + + /* wait for the sqe to complete */ + ret = io_uring_wait_cqe(&ring, &cqe); + if (ret < 0) { + printf("io_uring_wait_cqe: %s\n", strerror(-ret)); + goto out; + } + + /* read and process cqe event */ + io_uring_cqe_seen(&ring, cqe); + +out: + close(fd); +exit: + /* tear down */ + io_uring_queue_exit(&ring); + return ret; +} +``` + +- 相关文档 + +[Liburing README](https://github.com/axboe/liburing/blob/master/README) + +[Efficient IO with io_uring](http://kernel.dk/io_uring.pdf) + +# 项目仓库 + +https://gitee.com/anolis/liburing diff --git a/sig/HighPerfStorageSIG/content/projects/io_uring/nginx.md b/sig/HighPerfStorageSIG/content/projects/io_uring/nginx.md new file mode 100644 index 0000000000000000000000000000000000000000..2d93a6b8edb22933661cd35c3c801c089faf84d7 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/projects/io_uring/nginx.md @@ -0,0 +1,81 @@ +# 项目介绍 + +nginx 是一款轻量级的 web 服务器、反向代理服务器,由于它的内存占用少,启动极快,高并发能力强,在互联网项目中广泛应用。 + +![nginx-architecture](../../../assets/nginx-arch.png) + +nginx 由一个 master 和多个 worker 进程组成,master 和 worker 进程都是单线程架构,并且多个 worker 之间不需要加锁,独立处理与 client 的连接和网络请求。 + +# 项目文档 + +nginx 在 Linux 下默认使用 epoll 异步事件驱动模型来高效处理客户端请求。当系统支持 io_uring 时,我们可以配置用 io_uring 替代 epoll 作为默认的异步事件驱动模型。 + +用户需要安装 liburing 以及 liburing-devel。 + +``` +sudo yum install liburing liburing-devel +``` + +为了让 nginx 使用 io_uring,编译前需要显式加上 --with-io-uring。 + +``` +./auto/configure --with-io-uring +make +make install +``` + +**测试环境** + +CPU: Intel(R) Xeon(R) CPU E5-2682 v4 @ 2.50GHz,打开CPU漏洞缓解(mitigation=on)
+OS: Alibaba Cloud Linux 2.1903 LTS 64 位 + +nginx 配置 + +``` +user root; +http { + access_log off; + server { + access_log off; // 关闭access log,否则会写日志,影响测试 + location / { + return 200; // 不读本地文件,直接返回200 + } + } +} +``` + +**测试命令** + +使用轻量级 HTTP 性能测试工具 wrk 进行压测。 + +长连接: +``` +wrk -c $connection -t $thread -d 120 $url +``` + +短连接: +``` +wrk -c $connection -t $thread -H "Connection: Close" -d 120 $url +``` + +**测试结果** + +1、单 worker 场景,当连接数超过 500 时,QPS提升 20% 以上。
+2、connection 固定 1000,worker 数目在 8 以下时,QPS 有 20% 左右的提升。随着 worker 数目增大,收益逐渐降低。
+3、短连接场景,io uring 相对于 event poll 非但没有提升,甚至在某些场景下有 5%~10% 的性能下降。究其原因,除了 io uring 框架本身带来的开销以外,还可能跟 io uring 编程模式下请求批量下发带来的延迟有关。 + +**单worker,连接数变化,长连接QPS对比** + +![nginx-single-worker-qps](../../../assets/nginx-single-worker-qps.png) + +**连接数固定,nginx worker变化,长连接QPS对比** + +![nginx-multi-worker-qps](../../../assets/nginx-multi-worker-qps.png) + +**短连接QPS对比** + +![nginx-qps](../../../assets/nginx-qps.png) + +# 项目仓库 + +https://gitee.com/anolis/nginx/tree/feat%2Fio_uring/ diff --git a/sig/HighPerfStorageSIG/content/projects/io_uring/perf-test-for-io_uring.md b/sig/HighPerfStorageSIG/content/projects/io_uring/perf-test-for-io_uring.md new file mode 100644 index 0000000000000000000000000000000000000000..879d4850d46fc8972c5f40f0f3919d3d391dd519 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/projects/io_uring/perf-test-for-io_uring.md @@ -0,0 +1,50 @@ +# 项目介绍 + +io_uring 性能测试框架,用于 io_uring 迭代开发期的性能回归。 + +# 项目文档 + +io_uring 官方社区主要在 liburing 中进行功能测试,但性能回归测试缺乏,该项目旨在建立一套性能回归框架,其依赖 liburing,CMake,pthread 等组件。 + +**编译** + +``` +cmake -S . -B cmake-build-debug/ +make -C cmake-build-debug/ all +``` + +**快速使用** + +``` +bash ./test.sh +``` + +该命令将构建并运行 test.sh 中配置的性能测试单元。 + +**使用样例: round_writev** + +``` +$./round_write -? +Usage: round_write [OPTION...] + + Test Arguments + -d io_depth set io_depth + -f file_name set file path for test + -i io_size set io_size + -s file_size set test file size + + Loader Arguments + -r round_count set round count + -w warm_up set warm up round + + -?, --help Give this help list + --usage Give a short usage message +``` + +- 相关文档 + +https://gitee.com/anolis/perf-test-for-io_uring/blob/master/README.md + +# 项目仓库 + +https://gitee.com/anolis/perf-test-for-io_uring diff --git a/sig/HighPerfStorageSIG/content/projects/io_uring/redis.md b/sig/HighPerfStorageSIG/content/projects/io_uring/redis.md new file mode 100644 index 0000000000000000000000000000000000000000..acb41f872ab5515a8dcc3df18792bd11ba85766f --- /dev/null +++ b/sig/HighPerfStorageSIG/content/projects/io_uring/redis.md @@ -0,0 +1,68 @@ +# 项目介绍 + +redis 是一个高性能的 key-value 数据结构存储,可以用来作为数据库,缓存和消息队列。 +redis 将所有数据集存储在内存中,性能非常高,并且支持 Pipelining 命令,可一次发送多条命令来提高吞吐率,减少通信延迟。另外相比较其他 key-value 缓存产品,它还有以下几个特点: +1)redis 支持数据的持久化。
+2)redis 不仅支持简单的 key-value 类型的数据,同时还提供 list,set,zset,hash 等数据结构的存储。
+3)redis 支持主从复制。
+ +# 项目文档 + +redis 6.0 之前为单线程模型,客户端请求的处理都在主线程内完成,通过 ae 事件模型以及 IO 多路复用技术来高速的处理客户端请求。具体流程如下。 + +![redis-epoll-flow](../../../assets/redis-epoll-flow.png) + +> 注意:redis 4.0 版本之后就不是传统意义的单线程模型,server 端会起一些后台线程来处理缓慢的操作。但在 redis 6.0 之前,处理客户端的请求(包括 socket 读、包解析和处理,socket 写)都是由顺序串行的主线程处理,也就是我们这里所谓的“单线程”。 + +redis 6.0 之后,可以配置用一组单独的 IO 线程进行 read/write socket 读写调用(默认不开启)。ae 事件依然在主线程中处理,当有数据需要读写时,主线程把任务平均分发给 IO 线程(主线程也处理一部分任务),并等待所有线程完成,其余流程保持不变。为了简化模型,我们这里的描述和测试都以单线程为例。 + +利用 io uring 的异步下发和 FAST POLL 机制优化之后,redis 的主线程大致流程图如下: + +![redis-iouring-flow](../../../assets/redis-iouring-flow.png) + +注意:这里的 readQueryFromClient 和 writeToClient 都从原来的同步读写变为异步接口,只是准备读写请求,在io_uring_submit_and_wait() 中统一下发。请求真实完成之后,调用新增的回调函数 readDoneFromClient 和writeDoneToClient 进行后续处理。 + +**测试环境** +CPU: Intel(R) Xeon(R) CPU E5-2682 v4 @ 2.50GHz
+OS: Alibaba Cloud Linux 2.1903 LTS 64 位
+server 和 client 在同一台机器上。 + +![redis-ping_inline-qps](../../../assets/redis-ping_inline-qps.png) + +![redis-ping_bulk-qps](../../../assets/redis-ping_bulk-qps.png) + +![redis-get-qps](../../../assets/redis-get-qps.png) + +![redis-set-qps](../../../assets/redis-set-qps.png) + +以上是 redis 在 event poll 和 io_uring 下的 qps 对比,可以看到: + +1. 高负载情况下,io_uring 相比 event poll,吞吐提升 8%~11%。
+2. 开启 sqpoll 时,吞吐提升 24%~32%。 + +这里读者可能会有个疑问,开启 sqpoll 额外使用了一个 CPU,性能为什么才提升 30% 左右?那是因为 redis 运行时同步读写就消耗了 70% 以上的 CPU,而 sq_thread 只能使用一个 CPU 的能力,把读写工作交给 sq_thread 之后,理论上 QPS 最多能提升 40% 左右(1/0.7 - 1 = 0.42),再加上 sq_thread 还需要处理中断以及本身的开销,因此只能有 30% 左右的提升。 + +# 使用Anolis OS 环境进行测试的步骤和注意事项 +1. 安装 liburing
+2. 安装 redis - wtih io_uring
+地址:https://gitee.com/anolis/redis/tree/feat%2Fio_uring/ + +``` + git clone git@gitee.com:anolis/redis.git + cd redis + git checkout feat/io_uring + su + mkdir -p /usr/local/redis/conf + cp sentinel.conf redis.conf /usr/local/redis/conf/ + make + make install PREFIX=/usr/local/redis + cd /usr/local/redis/bin && ls +``` +3. 运行 redis-server 以及 redis-benchmark 进行测试。
+4. 注意事项:
+观察测试机器的 NUMA 架构信息,redis-server 以及产生的子线程(如 sqthread)和 redis-benchmark 都要绑定在同一个 NUMA 节点的 cpu 集合上,防止远端内存访问造成干扰。 +``` + taskset -c cpu_x-cpu_y /usr/local/redis/bin/redis-server + taskset -c cpu_z /usr/local/redis/bin/redis-benchmark +``` +cpu_x\-cpu_y and cpu_z 都是同一 NUMA 节点上的 cpu。 diff --git a/sig/HighPerfStorageSIG/content/projects/userspace-block-device/setup-ublk-env.md b/sig/HighPerfStorageSIG/content/projects/userspace-block-device/setup-ublk-env.md new file mode 100644 index 0000000000000000000000000000000000000000..3cb57e928d6f3d9696deab9866166f83dd7fc2f1 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/projects/userspace-block-device/setup-ublk-env.md @@ -0,0 +1,156 @@ +`环境要求:内核,liburing,ubdsrv(用户态程序)` + +# 内核版本: 主线6.0及以上 +- 直接从主线下载安装即可,注意内核编译选项设置**CONFIG_BLK_DEV_UBLK=m**,选择ublk_drv.ko为模块; +- 或者从aliyun ecs下载fedora 35,执行 yum update kernel --enablerepo Plus 更新内核到6.0,这个内核是自带ublk_drv.ko模块 +- **请注意从比较老的OS(例如Anolis7.9)用rpm安装的方式升级内核可能会失败,因为rpm等工具链可能是旧的。请考虑比较新的OS,例如Alibaba Cloud Linux 3(使用5.10内核)** + +检查内核支持ublk的方法: +``` +# modinfo ublk-drv +filename: /lib/modules/6.0.0+/extra/ublk_drv.ko +license: GPL +author: Ming Lei +srcversion: B8E732FD6A43D49DBA539AB +depends: +retpoline: Y +name: ublk_drv +vermagic: 6.0.0+ SMP preempt mod_unload modversions +# modprobe ublk-drv +# ls /dev | grep ublk +ublk-control + +``` +**能看到/dev/ublk-control说明内核支持ublk**,这个control设备是用来管理ublk块设备的。 + +# liburing + +- **ublk需要io_uring的一些新特性**。不要直接使用yum安装,那样版本太低。 +- 请在 https://github.com/axboe/liburing 下载liburing-2.2,解压后执行 make && make install + +# 用户态程序ubdsrv(ublksrv) + +**ubdsrv默认需要gcc 10以上,因为ubdsrv的几个target是CPP协程写的。注意单独编译ubdsrv的库(lib目录下的C文件)不需要CPP协程支持。如果以后自己适配ublk,是不用协程的,对gcc版本没要求**。 + +``` +git clone https://github.com/ming1/ubdsrv + +cd ubdsrv +``` + +运行这个脚本(就是在ubdsrv目录下的build_with_liburing_src): +``` +#!/bin/bash + +set -eo pipefail + +script_dir="$(dirname ${BASH_SOURCE[0]})" + +autoreconf -i "${script_dir}" + +OPTS="-g -O0" +: "${LIBURING_DIR:=/root/git/liburing}" #replace with your own liburing path +PKG_CONFIG_PATH=${LIBURING_DIR} \ +${script_dir}/configure \ + --enable-gcc-warnings \ + CFLAGS="-I${LIBURING_DIR}/src/include $OPTS" \ + CXXFLAGS="-I${LIBURING_DIR}/src/include $OPTS" \ + LDFLAGS="-L${LIBURING_DIR}/src" + +make -j$(nproc) +``` + +如果仍然提示找不到liburing,请: +- export PKG_CONFIG_PATH=/usr/lib/pkgconfig +- 检查liburing.so.2.2是否安装到了/usr/lib 而不是/usr/lib64。 + +## make时,ld发现找不到pthread的库 + +手工指定下lpthread,例如 +``` +./configure LDFLAGS="-lpthread" +``` +或者用前面的脚本安装的话,LDFLAGS="-L${LIBURING_DIR}/src -lpthread" + +## 简单看看搭建是否成功 + +编译成功后,请执行./ublk list试试: +``` +# ./ublk help +ublk add -t {null|loop|qcow2} -n DEV_ID -q NR_HW_QUEUES -d QUEUE_DEPTH -u URING_COMP -g NEED_GET_DATA -r USER_RECOVERY -i USER_RECOVERY_REISSUE + loop: -f backing_file [--buffered_io] + default is direct IO to backing file + qcow2: -f backing_file +ublk del -n DEV_ID [-a | --all] +ublk list [-n DEV_ID] +``` + +# ublk使用方法 + +## 使用null设备 + +先添加一个null的设备,执行: +``` +# ./ublk add -t null -q 4 -d 64 +dev id 0: nr_hw_queues 4 queue_depth 64 block size 512 dev_capacity 524288000 + max rq size 524288 daemon pid 169528 flags 0x2 state LIVE + queue 0: tid 169530 affinity(0 4 5 12 13 ) + queue 1: tid 169531 affinity(1 6 7 14 15 ) + queue 2: tid 169532 affinity(2 8 9 ) + queue 3: tid 169533 affinity(3 10 11 ) + target {"dev_size":268435456000,"name":"null","type":0} +# ls /dev | grep ublk +ublkb0 +ublkc0 +ublk-control +``` +我们添加了一个/dev/ublkb0块设备(4个队列,64深度),业务直接读写/dev/ublkb0就行,当然后端存储是null,什么都不做。 + +然后列出当前的ublk设备: +``` +# ./ublk list +dev id 0: nr_hw_queues 4 queue_depth 64 block size 512 dev_capacity 524288000 + max rq size 524288 daemon pid 169528 flags 0x2 state LIVE + queue 0: tid 169530 affinity(0 4 5 12 13 ) + queue 1: tid 169531 affinity(1 6 7 14 15 ) + queue 2: tid 169532 affinity(2 8 9 ) + queue 3: tid 169533 affinity(3 10 11 ) + target {"dev_size":268435456000,"name":"null","type":0} +``` + +删掉ublk设备,需要指定ID(这里是0) +``` +# ./ublk del -n 0 +# ./ublk list +``` + +详细的说明请看ubdsrv的README + +## 使用demo_event(太复杂,可先不看代码) + +直接执行 ./demo_event +若 ./demo_event -f /root/loop.img,则指定loop.img为后端存储; +若 ./demo_event,则为null后端 + +demo_event运行nr_queue个ublksrv线程,不断地进行io_uring_enter()循环,把req分发给worker执行;还运行1个worker线程,不断地遍历每个queue->submit_list中的req,执行pread/pwrite,然后把req及其结果放到queue->cmpl_list。 + +每到来一个ublk_io,io_uring就返回一个cqe;然后执行demo_handle_io_async(cqe->req),该函数把req放到submit_list中,然后efd_write()。 + +同时worker线程不断循环submit_list,执行pread/pwrite,然后把req及其结果放到queue->cmpl_list;执行efd_read();最后执行send_event()通知ublksrv线程。 如果没有请求到来,就没人efd_write(),worker就卡在efd_read()这里,**所以这里有一个小优化:用epoll来等待efd的可读事件** + +worker每执行一次send_event(),在ublksrv的io_uring中就返回一个cqe;然后执行demo_handle_event(),该函数把queue->cmpl_list的req都完成,通知内核(发送sqe)。 + +## ubdsrv项目中的示例 + +ubdsrv包括 +- lib目录下的library本身(C语言编写),如ublksrv.c +- ublksrv_tgt.cpp,ublksrv为了方便用户开发提供的target支持,用户可以自己编写target(如tgt_loop.cpp,tgt_null.cpp,demo_null.c,demo_event.c) +- tgt_loop.cpp,tgt_null.cpp,demo_null.c,demo_event.c四个例子 +- test目录里面的测试 +- qcow2支持,我们不用管 + +可以在ubdsrv中注意到tgt_loop.cpp,tgt_null.cpp,demo_null.c,demo_event.c四个例子。前两个例子就是ublk add -t null/loop添加的target,**它们限制了后端存储必须为io_uring,我们没法用这些target来接入pov,因为pov有自己的RPC库来处理IO,不支持io_uring**, + +demo_event.c和demo_null.c展示**后端存储不走io_uring。我们以后要接入分布式存储的话,就是模仿这两个例子**。demo_null是后端没存储,直接返回给前端;demo_event类似loop target,后端接入一个文件。 +- handle_io_async()方法需要我们自己实现,每来一个ublk io,io_uring主线程调用一次这个函数。一般就是把IO派发给worker +- handle_event()也要我们自己实现,当我们完成一些IO后,worker线程需要通知io_uring主线程(worker调用ublksrv_queue_send_event),随后ublksrv会调用一次handle_event()方法,一般这个方法就是通知内核请求完成了 **为什么不让worker直接通知内核IO完成了呢?因为io_uring编程模型是最好只要一个主线程调用io_uring_enter(),所以我们让worker先通知主线程,主线程再把这些IO回给内核** diff --git a/sig/HighPerfStorageSIG/content/projects/userspace-block-device/ublk-fault-recovery.md b/sig/HighPerfStorageSIG/content/projects/userspace-block-device/ublk-fault-recovery.md new file mode 100644 index 0000000000000000000000000000000000000000..77cf822c4d987552612a9d244a720687d1efecfe --- /dev/null +++ b/sig/HighPerfStorageSIG/content/projects/userspace-block-device/ublk-fault-recovery.md @@ -0,0 +1,71 @@ +# 简介 + +在ublk简介一文中我们介绍了**Linux社区新提出的ublk:基于io_uring的全新高性能用户态块设备**。ublk已经合入Linux 6.0主线,并且操作系统团队已经在ublk上开展了一系列实践,并在2022年中国LInux内核开发者大会上分享了阿里云在ublk上的实践。 + +为了适配阿里云的分布式云存储产品,我们对ublk添加了**NEED_GET_DATA特性和故障恢复特性**。前者对数据拷贝进行优化,属于小特性,不多介绍;后者则是ublk产品化必备的特性,非常重要。本文对ublk故障恢复方案进行介绍,我们前后一共设计了3版方案,在不断的优化与迭代过程中收获颇丰,最终顺利合入6.1主线,并被LWN发文,在此分享给大家。 + +# ublk背景知识 + +ublk提供了用户态块设备的能力。简单地说,就是提供一个/dev/ublkb*这样的块设备,所有这个设备上的IO请求的读写逻辑都是您在用户态编写的代码,比如pread/pwrite到一个具体地文件(这样就是loop设备了)。使用用户态块设备,你可以方便地向上层业务提供您的存储系统(如ceph),业务只需要对/dev/ublkb*执行标准的读写操作即可。如果您有一个用户态的存储系统(可以是跨多个机器的网络分布式存储),想要向业务暴露/dev/ublkb* 来提供IO读写功能的,就可以考虑ublk。比如您的业务用了容器或者虚拟机,就可以暴露/dev/ublkb*作为他们的磁盘,读写/dev/ublkb*会导致实际IO passthrough(透传)给您的用户态存储系统(如ceph)。如果您没有存储系统,也可以使用ublk,因为ublksrv可以自己在本地运行daemon处理实际IO,如作为qcow target运行向容器或虚拟机提供qcow磁盘。ublk的系统架构如图所示: + +``` + target(backend)------------> null/loop/qcow/socket/ceph/rpc... + ^ + | + | + libublksrv + fio ^ + | | user +--------|-----------------------------|--------------- + | | kernel + v | + /dev/ubdbX | + | | + | | + v io_uring + blk-mq ^ + | | + -----------> ublk_drv--------- +``` + +如同FUSE要运行fuse daemon来把IO转发给用户态文件系统,ublk需要在用户态运行daemon,称为ublksrvd,进行数据转发。**在现有的ublk实现中,daemon一旦退出,会导致内核驱动自动删掉所有资源**,包括/dev/ublkb*块设备,避免资源泄露。这种方法使得内核驱动实现简单,但不可用于生产环境,因为daemon进程很容易退出:如内存oom被内核干掉;daemon代码写错了导致段错误;各种用户态的攻击手段或管理员退出等等。**为了让ublk产品化,我们需要设计故障恢复机制**。 + +# 故障恢复设计 + +先确定一下设计目标:为了让前端业务顺利运行,在daemon退出(称为故障)后,我们不能让/dev/ublkb*消失;且要允许用户通过某些手段,启动新的daemon并关联到该/dev/ublkb*设备,接管所有IO,整个系统继续运行。 + +## 让前端业务顺利运行 + +为了满足第一个目标,我们需要一个检测daemon是否退出的机制,现有的ublk会周期性地运行一个monitor_work,检查daemon是否为PF_EXITING,该标记会在进程挂掉时被内核设置。现有的ublk的逻辑是直接abort掉所有的blk-mq请求(blk_mq_end_request),然后del_gendisk()删掉/dev/ublkb*块设备。现在我们需要在开启故障恢复特性时,保留该块设备。因此,我们设计了UBLK_F_USER_RECOVERY标记,用户在创建ublk块设备时指定feature标记,内核在monitor_work检查标记判断是否开启故障恢复特性,否则走原来的删除逻辑,是则保留该块设备(代码上就是什么都不做)。 + +那么,该如何处理故障后发来的用户请求呢?因为ublk位于通用块设备层,它需要实现->queue_rq()接口,每来一个blk-mq请求,->queue_rq()都会被调用一次。现有的ublk实现的ublk_queue_rq()函数会通过io_uring passthrough机制的io_uring command通知用户态daemon有新的请求需要处理(详情看ublk简介)。在发生故障后,我们不能这么做,因为没有用户态daemon了,这里我们想了好几种方案: + +- V1:在ublk_queue_rq()中,请求被放到一个链表pending_list中,然后等到新的daemon起来后,把pending list中的请求都下发下去。这种思想是很直接的,但在代码实现时,遇到了很大的困难:由于ublk使用io_uring passthrough机制,每个blk-mq请求都对应一个io_uring command,而这个cmd必须是用户态daemon事先发给内核(io_uring sqe),然后在ublk_queue_rq(),发送io_uring cqe。这使得我们“刷”pending list的时机很难控制:我们要在新的daemon把所有的(队列深度个)io_uring command都发给内核ready后,才能“刷”pending list。然而,倘若只有一部分cmd ready新daemon又crash了该怎么办呢?我们还要考虑旧的cmd的释放问题(因为旧的daemon已经退出了,但是它发给内核的cmd还没被内核返回cqe,导致io_uring ctx在内核没被释放)避免内存泄漏……总之,这种pendling list的方案看上去直接,但很难写出代码,我们卡了一个月有余……在某次浏览其他块设备驱动代码时,笔者突然发现了新曙光。 + +- V2:blk-mq提供了**blk_mq_freeze_queue()和blk_mq_quiesce_queue()函数**,顾名思义两者都能让请求下发“暂停”,其功能的差异本文不予赘述。总之,在旧daemon退出后,monitor_work可以调用blk_mq_quiesce_queue(),阻止->queue_rq()的调用,这样新请求就进不来了。这里可能有人要问:**那前端业务会不会不能提交IO,导致业务卡住啊?**经过代码分析,笔者认为不会卡住IO下发,因为blk-mq在接受到上层提交IO(如submit_bio)后,会先让它们排队,队列深度是用户自己设置的(比如128)。当队列quiesced后,请求都留在blk-mq的队列里,在调用blk_mq_quiesce_unqueue()后,再对每个请求都->queue_rq()一下。其实blk_mq_quiesce_queue()已经帮我们完美地做了一个pending list了,所以以后还是要先积累知识,多看代码,不可贸然下手啊……你能想到的问题,别人早就踩过坑了…… + +解决了上述“故障后到来的请求该如何处理”问题后,我们又突然想到一类请求没有处理:**“故障到来前已经发给旧daemon,但daemon挂了所以我也不知道他做完了没”**,为此,我们设计了UBLK_F_USER_RECOVERY_REISSUE标记,用户可选地设置该feature。新daemon关联到/dev/ublkb*后,这类请求会被重新下发一次,因此要求后端的分布式存储有处理重复写入的能力。在代码上,若开启该标记,monitor_work会blk_mq_requeue_request请求(此时是quiesced状态,不会发生->queue_rq),否则直接blk_mq_end_request。可以说,UBLK_F_USER_RECOVERY_REISSUE是从实际业务出发而设计的。 + +## 启动新的daemon + +这部分的设计简单了许多,我们考虑把恢复分为2阶段:**START_RECOVERY**和**END_RECOVERY**。在START_RECOVERY我们必须重置一些状态:比如ublk会记忆旧daemon的mm struct,task struct,都要清理掉;ublk自己的IO结构体有一些状态位,也置位初始。在END_RECOVERY阶段我们要等待新的daemon把所有的io_uring command都下发完成后,unquiesce队列,然后就可以愉快地ublk_queue_rq()并把IO透传给后端分布式存储了!之所以设计成两阶段,一是为了用户方便用(用户自己发START_RECOVERY,启动新的daemon,再发END_RECOVERY,几个阶段很清晰);二是简化了开发(因为ublk记录很多用户态daemon的信息,START_RECOVERY释放并重置信息,END_RECOVERY确认新信息)。 + +# 总结 + +ublk故障恢复是笔者在ublk上开发的第一个大型特性,也是第一次接触block层的代码。由于不熟悉block的实现,我们走了很多弯路,幸好在社区的指导和自我努力下,我们完成了设计与编码,历时3月有余。我们积累了很多Linux知识(如linux work的原理,io_uring ctx的管理,gendisk的管理,block层的API),并为ublk在分布式存储的应用扫清了道路。 + +# 参考文献 + +【1】 https://lwn.net/Articles/906097/ + +【2】https://developer.aliyun.com/article/989552 + +【3】https://lore.kernel.org/all/20220523131039.17697-1-ankit.kumar@samsung.com/ + +【4】https://lore.kernel.org/all/8a52ed85-3ffa-44a4-3e28-e13cdc793732@linux.alibaba.com/ + +【5】https://github.com/ming1/ubdsrv + +【6】https://lore.kernel.org/all/20220713140711.97356-1-ming.lei@redhat.com/ + +【7】https://lore.kernel.org/all/20220923153919.44078-1-ZiyangZhang@linux.alibaba.com/ diff --git a/sig/HighPerfStorageSIG/content/projects/userspace-block-device/ublk-introduction.md b/sig/HighPerfStorageSIG/content/projects/userspace-block-device/ublk-introduction.md new file mode 100644 index 0000000000000000000000000000000000000000..9ecf0e4ec0ff992d4e6e40dde522a57304e64b00 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/projects/userspace-block-device/ublk-introduction.md @@ -0,0 +1,134 @@ +`如果您想快速了解ublk的意义、作用及性能,请直接看第二节Q&A部分。` + +# 一、简介 + +用户态块设备,就是提供/dev/ublkbX这样的标准块设备给业务,业务读写这个块的实际IO处理由您编写的用户态的代码决定。这就好比您使用FUSE,所有对挂载于FUSE的目录的读写都是您编写的IO handler来处理一样。使用用户态块设备,您可以方便地为上层业务**暴露块设备(/dev/ublkbX),来提供您的自定义存储系统(如ceph)的服务**,上层业务只需要对块设备执行标准的读写操作即可。 + +[ublk](https://lore.kernel.org/all/8a52ed85-3ffa-44a4-3e28-e13cdc793732@linux.alibaba.com/)是社区提出的基于最新的、流行的[io_uring passthrough机制](https://lore.kernel.org/all/20220523131039.17697-1-ankit.kumar@samsung.com/)实现的用户态块设备,目前已经在block社区引起广泛讨论,并合并进了6.0内核主线。社区提供的代码包括内核态的[ublk_drv.ko内核模块](https://lore.kernel.org/all/20220713140711.97356-1-ming.lei@redhat.com/)和用户态的[ublksrv](https://github.com/ming1/ubdsrv)。 + + +``` + fio target(backend): null/loop/qcow/socket/ceph/rpc... + libublksrv user +---------------------------------------------------- + ublk_drv.ko io_uring kernel +``` + +ublk_drv.ko是一个非常轻量级的内核模块:通过实现queue_rq()接口,获取来自blk-mq的IO请求;然后通过io_uring_passthrough机制把新的IO请求到来的通知回传给用户。真实的IO描述信息(如长度、opcode和flag等)由内核写入一块被用户态只读mmap()后的共享内存区域中,供用户态的ublksrv随后获取IO信息。 + +ublksrv是ublk的用户态部分,负责处理由内核发来的IO请求。ublksrv把IO请求交给: +- 注册的target(null、loop和qcow等)完成,每个target都按照各自的需求实现处理IO的接口,而ublksrv将自己作为daemon运行; +- 使用ublksrv的library API的自定义存储,ublksrv的逻辑嵌入到存储的IO处理框架(如ceph等大规模分布式系统)中,IO收发与处理运行在IO处理框架的上下文中。 + +目前,主流的用户态的块设备框架有nbd(nbdkit)和tcmu([tcmu-runner](https://github.com/open-iscsi/tcmu-runner)),nbd的性能与tcmu相近。我们特别调研了tcmu,它表现出了一些问题: +- tcmu使用SCSI协议,使得**软件栈开销较大**,我们使用fio iodepth=1, numjobs=1测试验证了这一事实。事实上,SCSI协议对于仅仅想要提供通用块设备的业务场景来说并不是必须的。 +- tcmu不支持**多队列**,没有利用blk-mq的特点;由于tcmu设计基于早年的uio框架,tcmu只能提供一个IO命令队列与唯一的fd供线程轮询(poll),使得多个io worker在分发IO请求时必须加全局锁;在io worker数量很大时,锁竞争的现象会很严重。 +- tcmu内部分配了data buffer,增加了额外的**拷贝开销**。以写请求为例,数据先复制到tcmu内部buffer,再复制到业务的后端IO框架的buffer(如RPC库的buffer);针对tcmu拷贝开销问题,龙蜥社区给出了**bypass和零拷贝**等解决方案并开源(https://gitee.com/anolis/cloud-kernel/pulls/410)。然而,我们的努力只是缓解了tcmu的拷贝问题,并没有解决tcmu的根本缺陷。 + +相比现有的tcmu、nbd等用户态块设备方案,ublk不受到任何协议的限制(如unix domain socket或SCSI协议),代码简洁**软件栈开销很小**;此外,ublk直接一一映射了blk-mq的**多队列**,每个ublk队列都包括一个io_uring实例互不干扰,**不需要加锁**同步任何信息,使得ublk的可扩展性优秀;最新的ublksrv还提供了library API,使得ublksrv嵌入到现有的IO处理框架中,使得这些框架提供/dev/ublkbX块设备直接使用;ublksrv支持**data bypass**机制,即允许直接把bio vectors的数据拷贝到业务后端的data buffer中,也将在未来支持异步dma、零拷贝或splice机制(目前上游社区暂无完美的零拷贝方案)。总之,ublk的潜力不容小觑。 + +我们在ublk开发初期便参与了社区讨论与代码设计,并及时测试新版本的性能。目前我们在block社区邮件列表对ublk进行特性贡献。ublk的性能也被我们完整地测试过。对比tcmu-runner,ublk在单IO的全链路时延、多线程场景IOPS和CPU开销上均有优势。测试数据详见后文Q&A部分。 + +# 二、Q & A + +**Q1:什么是用户态块设备,意义是什么?什么业务能用ublk?** + +用户态块设备就是提供一个/dev/ubdbX这样的块设备,所有这个设备上的IO请求的读写逻辑都是您在用户态编写的代码,比如pread/pwrite到一个具体地文件(这样就是loop设备了)。可以类比FUSE,ublk内核模块就是fuse.ko,libfuse就是ublksrv,IO后端(比如passthrough_ll.c)就是您的业务逻辑(ublk target)。 + +所以你可以方便地向上层业务提供您的存储系统(如ceph),业务只需要对块设备执行标准的读写操作即可。如果您有一个用户态的存储系统(可以是跨多个机器的网络分布式存储),想要向业务暴露/dev/ublkbX块设备 ,提供IO读写功能的,就可以考虑ublk。比如您的业务用了容器或者虚拟机,就可以暴露/dev/ublkbX作为他们的磁盘,读写这些磁盘会导致实际IO passthrough(透传)给您的用户态存储系统(如ceph)。如果您没有网络分布式存储系统,也可以使用ublk,因为ublksrv可以自己在本机(host)运行daemon处理实际IO,如作为qcow target运行向容器或虚拟机提供qcow磁盘。 + +**Q2:现在ublk在linux社区是一个什么状态?你们现在ublk的支持怎样了,能否在现在的4.19或者5.10上跑起来?** + +ublk利用了io_uring_passthrough新机制,是io_uring新特性的最佳实践之一,受到block与io_uring社区广泛关注。自ublk的idea提出以来,社区大佬们也赞誉有加。目前 io_uring_passthrough和ublk已经合并6.1主线。 + +我们预计在Anolis23上适配ublk(对应的内核版本待定为5.10)。**如果您有适配ublk来POC的需求也欢迎找到我们讨论**。 + +**Q3:感觉ublk和FUSE、SPDK、VDUSE或者NVMe over Fabrics很像?有没有什么对比?** +ublk可以和FUSE类比,但FUSE是根据挂载点来区分不同的IO后端的,而ublk提供的一个个块设备的IO后端也不同,可以说是不同的东西。 + +SPDK实际上bypass了整个内核,所以提供出支持POSIX API的块设备是困难的,您需要让业务使用SPDK的API才行,这样也许不太方便。此外SPDK也有CPU占用高、迁移成本大的问题。 + +VDUSE是基于virtio的用户态块设备方案,它同时支持容器(qemu_storage_daemon)和虚拟机(qemu vhost-user)。我们通过在本地启动qemu_storage_daemon+VDUSE对比了VDUSE和ublk在null_blk后端的性能,**发现VDUSE的单IO延时是ublk的2倍,ublk的多任务IOPS是VDUSE的3倍**。 + +NVMf确实是一种用户态块设备的替代方案,但它要走网络协议栈,开销比ublk大。类似nbd。 + +**Q4:ublk的一个IO的全链路是怎样的?** + +业务(如fio)向/dev/ublkbX发起IO请求,内核blk-mq模块通过queue_rq()向用户态ublksrv passthrough该IO请求,并填写映射的IO描述符信息;随后用户态ublksrv获取该IO信息并转交给特定的target(或者在library中)执行具体的IO处理(如loop设备的pread/pwrite);在IO完成后,ublksrv应通知给内核的blk-mq模块该IO已经完成。整个系统的框架如下: + +``` + target(backend)------------> null/loop/qcow/socket/ceph/rpc... + ^ + | + | + libublksrv + fio ^ + | | user +--------|-----------------------------|--------------- + | | kernel + v | + /dev/ubdbX | + | | + | | + v io_uring + blk-mq ^ + | | + -----------> ublk_drv--------- +``` + +**Q5:ublk的性能如何?** + +对比了tcmu-runner和ublk的全链路时延和多线程IOPS,为了消除实际IO的开销,我们用null_blk作为后端IO设备。所有对null_blk的读写都被简单地返回。 + +- 测试环境 + +NVMe SSD: Intel DC P3600 Series 800GB, + +Intel(R) Xeon(R) CPU E5-2682 v4 @ 2.50GHz, + +Linux 6.0主线内核 + +- 测试选项 + +测试使用fio,direct=1,bs=4k + +ublksrv使用( https://github.com/ming1/ubdsrv )的代码,内核直接使用主线6.0 release。 + +tcmu-runner( https://github.com/open-iscsi/tcmu-runner )的后端存储为user: fbo,一个对文件进行pread/pwrite的handler。 + +IO后端都是loop到一个null_blk,创建方法为: +```modprobe null_blk submit_queues=16 hw_queue_depth=128``` + +- 测试参数 + +tcmu-runner的**nr_rthreads**是一个handler上的io worker的个数,您可以理解为有nr_rthreads个io worker不停地在一个SCSI队列上竞争拿取IO请求,每个串行地处理各自的IO请求(pread/pwrite)。 + +ublk的**nr_queues**是blk-mq的hardware queue的个数,hardware queue一一对应ublk的queue与其io_uring实例。ublk的queue互不干扰地拿取自己队列上的IO并串行地处理(pread/pwrite)。 + +- 测试数据 + +单任务时延(usec) fio参数:iodepth=1, numjobs=1,tcmu-runner设置nr_rthreads=1,ublksrv设置nr_queues=1 + +| lat(us) | tcmu | ublk | +| -------- | -------- | -------- | +| seq-read | 20.33 | 10.47 | +| rand-read | 19.10 | 10.49 | + +**ublksrv的单任务时延为tcmu-runner的一半**,展示出ublk软件栈开销小的优势。 + +多任务IOPS(k) fio参数:iodepth=64, numjobs=4,tcmu-runner设置nr_rthreads=4,ublksrv设置nr_queues=4 + +| IOPS(k) | tcmu | ublk | +| -------- | -------- | -------- | +| seq-read | 123 | 1886 | +| rand-read | 191 | 1849 | + +**ublksrv的多任务IOPS均大于tcmu-runner**。 + +**Q6:后面ublk还有什么支持?** + +我们已经贡献了NEED_GET_DATA(即data_bypass,减少一次数据拷贝)和故障恢复特性;社区正在推进非特权ublk(不使用root权限也能创建并读写ublk设备)和splice零拷贝方案;我们还计划做dma offloading。在保持跟随社区进展的同时,我们也会及时在ATA同步ublk的开发进展,希望大家多多关注ublk。 + +**Q7:ublk适配产品了吗?** + +正在阿里云存储产品进行POC。 diff --git a/sig/HighPerfStorageSIG/content/projects/virtio-fs/virtiofs-per-file-dax.md b/sig/HighPerfStorageSIG/content/projects/virtio-fs/virtiofs-per-file-dax.md new file mode 100644 index 0000000000000000000000000000000000000000..ba3bd024d7a69374d7629bb75755ee6efb989fbd --- /dev/null +++ b/sig/HighPerfStorageSIG/content/projects/virtio-fs/virtiofs-per-file-dax.md @@ -0,0 +1,50 @@ +本文介绍了现有的 virtiofs DAX 实现存在的限制,并进而引出了对应的 per-inode DAX 解决方案。 + +per-inode DAX 方案非常的简单、直观,但是这需要用户在一定先验知识的基础上实现相应的策略,因而我们相信这一定还不是终态的方案。目前该方案已经合入到 Linux 内核上游 5.17 版本和 anolis cloud kernel 4.19 版本。 + +接下来我们将继续探索更进一步的解决方案,让 virtiofs DAX 更加的高效、易用。 + +# DAX window 资源存在争抢 + +在具体阐述之前,有必要先简单介绍 virtiofs 是怎样实现 DAX 的。 + +![virtiofs-dax](../../../assets/virtiofs-dax.png) + +dax 模式下,VMM (e.g., qemu) 需要给 virtiofs 设备分配一段 GPA (Guest Physical Address) 地址空间,有了这一段 GPA 地址空间,VMM 才能让 guest 共享 host page cache,这一段 GPA 地址空间在 virtio 协议中称为 shared memory region,qemu 中可以通过 "-device vhost-user-fs-pci,...,cache-size=2G" 中的 "cache-size" 参数指定这段地址空间的大小。 + +virtiofs 会将这段 GPA 地址空间划分为一个个小的切片,称为 dax window,guest 在访问 virtiofs 中的文件的时候,就需要为当前访问的文件区间分配对应的 dax window,dax window 就用于 GPA->HPA 之间的地址翻译,从而使得guest 内部访问这个文件区间的时候,实际访问的是对应的 host page cache。 + +dax window 的大小对于性能具有重要影响。减小 dax window 的粒度,那么 shared memory region 大小一定的情况下,那么可用的 dax window 的数量更多,资源更加宽裕,但是由于单个 dax window 覆盖的范围变小了,guest 会更加频繁地触发 FUSE_SETUPMAPPING fuse 请求,从而带来性能开销;而如果增大 dax window 的粒度,那么 shared memory region 大小一定的情况下,可用的 dax window 的数量就变少了,更容易引发对 dax window 资源的竞争。 + +目前 dax window 的粒度是默认的 2M,在编译时确定,运行时无法动态修改。 + +由于 dax window 的数量是有限的,当 dax window 资源耗尽时,virtiofs 会触发 recalim 流程,即同步/异步地回收一些之前分配的、但当前已经不再使用的 dax window。 + +同步触发的 recalim 流程会严重影响性能,此时进程在访问文件时就需要同步等待可用的 dax window 资源,从而影响性能。例如需要访问大量小文件的场景,会快速耗尽 dax window 资源,从而进入 dax window 的 relcaim 流程,从而严重影响性能。 + +以下通过编译内核来模拟上述场景,将 kernel tree 通过 virtiofs 挂载到 guest 中,在 guest 中测试执行 `make vmlinux -j128` 的时间 + +| type | cache | cache-size | time | +| ---- | ----- | ---------- | ---- | +| non-dax | always | - | real 2m48.119s | +| dax | always | 64M | real 4m49.563s | +| dax | always | 1G | real 3m14.200s | +| dax | always | 4G | real 2m41.141s | + +从上述数据可以看出,在访问大量小文件的场景下,dax window 的 reclaim 操作会带来性能损耗,且 dax window 资源越紧张,损耗越大,相较于 non-dax,dax window 为 64M 大小时性能损耗为 -70%,dax window 为 1G 大小时性能损耗为 -15%。 + +# 有时候并不真的节省内存 + +上一节描述了 recalim 流程会严重影响性能,那么理论上只要扩大 shared memory region,从而增大 dax window 的数量,就能避免 reclaim 流程的触发。从上面的测试也可以看到,"cache-size=4G" 时,dax 与 non-dax 的性能已经持平。 + +但是需要指出的是,增大 cache-size 并非毫无代价,虽然 cache-size 消耗的是 host 上的 VMM (例如 qemu) 的虚拟地址空间,而非真正消耗物理内存,但是在 guest 中同样需要为 cache-size 分配对应的 struct page 描述符。那么 struct page 描述符就会存在 1.5% (64/4096 = ~1.5%,struct page 的大小为 64 字节,假设 page 是 4k 的) 的内存开销,所以 1G cache-size 就存在 16M 的内存开销。也就是说 cache-size 过大,虽然消除了潜在的性能损耗,但是 page 描述符带来的额外内存开销,反而可能对冲掉 dax 特性节省的内存。 + +# per-inode DAX 方案 + +针对上述问题,我们提出了 per-inode DAX 的方案。在此之前,DAX 模式的开启或关闭是 mount 级别的,即每个 virtiofs 文件系统,要么全部开启 DAX 模式,要么全部关闭 DAX 模式。而有了 per-inode DAX 之后,每个文件可以控制开启或关闭 DAX 模式,相当于是为 DAX 模式的开启或关闭提供更细粒度的控制。用户可以根据场景和需求,自行控制每个文件是否开启 DAX 模式。 + +例如在上述介绍的场景中,文件大小小于 32KB 的文件就关闭 DAX 模式,这是考虑到在DAX 模式下,这个文件会占用一个 2M 大小的 dax window,这个 dax window 对应的 page 描述符会占用 32 KB 内存;而在关闭 DAX 的模式下,这个文件的 guest page cache 占用的内存不会超过 32KB。显然这种情况下,关闭 DAX 的模式更加节省内存。 + +![virtiofs-perfile-dax](../../../assets/virtiofs-perfile-dax.png) + +我们实现的方案非常简单,virtiofs 是基于 FUSE 协议实现的,在 lookup 阶段 guest 会向 host daemon 发送 FUSE_LOOKUP message,在返回的 reply 中包含了对应 inode 的元数据。而 per-inode DAX 方案下,FUSE_LOOKUP message 返回的 reply 中包含的 FUSE_ATTR_DAX 标记就描述了该文件是否开启 DAX 模式。也就是说由 host daemon 控制某个文件是否开启 DAX 模式,即由用户来实现各样的策略。 diff --git a/sig/HighPerfStorageSIG/content/report/2021/2021.08.md b/sig/HighPerfStorageSIG/content/report/2021/2021.08.md new file mode 100644 index 0000000000000000000000000000000000000000..8d2863f5b9f7f04b83e3299da4d8a795d0ece924 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/report/2021/2021.08.md @@ -0,0 +1,31 @@ +# 统信软件合作 +统信软件作为 SIG 的 Maintainer 之一,深度参与到高性能存储技术 SIG 当中。一期计划先基于 Anolis OS 搭载的 io_uring 进行了评测,并将相关技术移植到统信 OS 中。评测对象包括:使用 fio 基于 NVMe 盘对比测试 libaio 和 io_uring 的 IO 性能,使用 SIG 中 nginx 和 redis 支持 io_uring 的 POC 分支版本对比测试 io_uring 和 epoll 的网络性能等。初步测试结果表明,大部分场景 io_uring 的确能带来性能优化,与 SIG POC 数据基本一致,具体测试报告细节整理完成后会发布到 SIG 中;感谢统信同学 @wangleic,@HanGuangyu 的参与。 + +评测过程中也发现了一些问题:
+1、redis io_uring fast poll 支持问题
+修复补丁:783f39482587 fix wrong poll mask in fast poll(@maomao123) + +2、redis-benchmark 工具 register files 支持
+修复补丁:02b8c5eaa2ab add missing register files in redis-benchmark(@maomao123) + +3、redis sqpoll 支持
+修复补丁:1b631b5a6350 add a sqpoll argument for server and benchmark(@maomao123) + +4、redis 在打开 NUMA 场景性能不及预期
+测试中通过绑核解决。(@maomao123,@HanGuangyu) + +5、nginx 短连接性能下降 20%
+比 SIG POC 数据下降 5% ~ 10% 要差,初步分析原因与频繁 accept 连接有关,后续需要重点分析和优化。(@maomao123) + +# 软件包更新 +1、支持 CPU 资源优化特性的 liburing 适配
+优化补丁:a6cf7cd33634 support sqthread cpu resource optimization(@maomao123) + +# SIG 社区项目动态 +结合异步 IO 业务场景,围绕 io_uring 我们将继续探索对 RocksDB 以及 Netty 的优化。其中 RocksDB 是广泛应用的 KV 存储引擎,Netty 作为 Java 网络应用的基础框架同样有着非常广泛的应用。(@wangxiaoguang) + +virtiofs 目前已经在容器化存储场景(kata)默认使用,我们针对高性能场景提出 per-file DAX 优化,已经发到 v4 版本,正在上游社区推进中。(@Jingbo Xu) + +我们也在积极探索数据库场景的垂直优化,目前针对 MySQL double write 带来的性能和带宽开销做了一些研究,期望通过文件系统层的优化来消除 double write。(@gaoxiang,@josephqi) + +由于上述工作都会涉及到 Anolis Kernel,而当前 Kernel SIG 相关流程规范还在讨论中。待 Kernel SIG 的流程规范公布后,我们会第一时间将我们的研究成果开放在高性能存储技术 SIG 中,并期望有更多的同学参与进来一起完善。 diff --git a/sig/HighPerfStorageSIG/content/report/2021/2021.09.md b/sig/HighPerfStorageSIG/content/report/2021/2021.09.md new file mode 100644 index 0000000000000000000000000000000000000000..6b09ff9ed9cb3a6cb1e02160f4543d47d103f885 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/report/2021/2021.09.md @@ -0,0 +1,81 @@ +# Cloud Kernel +合入 Anolis Cloud Kernel 主线 Merge Request 8 个,包含 fuse 优化,virtiofs per-file DAX 特性,以及 overlayfs,dm-thin,block 以及 ext4 等稳定性 bugfix: + +1)fuse: enable caching of symlinks
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/26728 + +2)fuse: mischelaneous cleanup and backport
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/26733 + +3)ovl: allow upperdir inside lowerdir
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/26742 + +4)fuse:virtiofs: support per-file dax
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/26769 + +5)anolis: block: fix race in blk_mq_check_rq_hang()
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/26830 + +6)dm thin metadata: Fix use-after-free in dm_bm_set_read_only
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/26854 + +7)ext4: limit the length of per-inode prealloc list
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/26898 + +8)ext4: fix reserved space counter leakage
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/26935 + +# VirtioFS per-file DAX +通过性能摸底,发现当前 DAX 的两种约束场景:
+1)DAX window 的大小是有限的,当 DAX window 资源不够用(例如大量小文件的场景)时,会拖累性能;
+2)盲目增大 DAX window 并不可取,因为 DAX window 本身(占用的 struct page 描述符)会消耗内存资源,与 VirtioFS DAX 节省内存的初衷背道而驰。 + +目前上游社区已经推送到 v5 版本,就 per-file DAX 的语义达成了一致:
+https://lore.kernel.org/all/20210923092526.72341-1-jefflexu@linux.alibaba.com/ + +# 容器镜像加速 +完成与内核主线 erofs 兼容的 rafs v6 格式设计,5.15 内核中 erofs 已经完成第一阶段 chunk 去重的 upstream 工作[1],5.16 内核预期新增多层容器镜像多设备 / blob 的支持[2],nydus[3] 的对接支持当前正在联合开发中,力争 10 月份完成开发与联调。
+[1] https://lore.kernel.org/r/20210820100019.208490-2-hsiangkao@linux.alibaba.com
+[2] https://lore.kernel.org/r/20211007070224.12833-1-hsiangkao@linux.alibaba.com
+[3] https://github.com/dragonflyoss/image-service + +# 16k 原子写 +完成原型代码的讨论和两轮 review:
+https://codeup.openanolis.cn/codeup/storage/cloud-kernel/merge_request/26798
+https://codeup.openanolis.cn/codeup/storage/cloud-kernel/merge_request/26823 + +第三版代码已经发出 Merge Request,预计 10 月中旬可以完成特性合并,并提供 POC 测试文档:
+https://codeup.openanolis.cn/codeup/storage/cloud-kernel/merge_request/26925 + +# io_uring 优化 +1)Netty 优化
+修复 poll request 代码逻辑问题:
+https://github.com/torvalds/linux/commit/5b7aa38d86f348847a48f71e9ac7715406de900e
+https://github.com/torvalds/linux/commit/a62682f92eedb41c1cd8290fa875a4b85624fb9a + +poll request cqe batch generation,尝试通过将 poll request 的 cqe generation 阶段批量化(利用 completion cache)来提高性能,但目前测试来看没有明显效果。
+https://lore.kernel.org/io-uring/20210917193820.224671-1-haoxu@linux.alibaba.com/
+https://lore.kernel.org/io-uring/20210922123417.2844-4-xiaoguang.wang@linux.alibaba.com/ + +poll request 在事件发生时会将对应的 wait entry 从等待列表中删除,这个操作是耗时的,通过用一个 flag 代替来降低这部分的开销:
+https://lore.kernel.org/io-uring/20210924042224.8061-1-xiaoguang.wang@linux.alibaba.com/ + +当前设置 IOSQE_ASYNC 标志的 sqe 请求会直接由 io-worker 线程进行提交,这对普通 IO 请求是 make sense 的,然而对于网络请求而言由于其完成时间的不确定性可能导致处理它的 io-worker 阻塞很长时间,进而导致其他任务得不到及时处理,特别是当前 io-worker 数量已经达到最大值的情况下问题会比较严重。初步解决方案是引入新的标志 IOSQE_ASYNC_HYBRID, 将 io-worker 机制和 fast poll 结合起来,io-worker 只负责 poll 相关基础设施的安装,防止被阻塞。目前调试中,计划 10 月发布第一个 RFC。
+ +2)task work 优化
+目前包括网络(pure poll, fast poll)请求在内的很多场景利用了 task work 机制,特别是读写请求的完成也是通过 task work 机制完成的,当 task work 列表中等待了大量任务时读写请求的时延就会变大,具体优化方法见 RFC:
+https://lore.kernel.org/io-uring/20210927105123.169301-1-haoxu@linux.alibaba.com/ + +3)accept 支持 multishot 模式
+用户只需提交一个 accept sqe 请求,后续所有客户端的连接都由该请求进行处理,减少了反复提交 accept 请求带来的开销(主要是减少了调用 vfs_poll 的开销)。目前发布了第一版 RFC 到社区:
+https://lore.kernel.org/io-uring/20210903110049.132958-1-haoxu@linux.alibaba.com/ + +4)其他优化和 bugfix
+io_uring fdinfo 运维信息优化
+https://lore.kernel.org/io-uring/20210913130854.38542-1-haoxu@linux.alibaba.com/ + +sqthread 绑核逻辑优化
+https://lore.kernel.org/io-uring/20210901124322.164238-1-haoxu@linux.alibaba.com/ + +io-worker 线程创建和计数问题修复
+https://github.com/torvalds/linux/commit/767a65e9f31789d80e41edd03a802314905e8fbf diff --git a/sig/HighPerfStorageSIG/content/report/2021/2021.10.md b/sig/HighPerfStorageSIG/content/report/2021/2021.10.md new file mode 100644 index 0000000000000000000000000000000000000000..6cc812c23b1903971c0abfbeb1b1b46aa61ae512 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/report/2021/2021.10.md @@ -0,0 +1,59 @@ +# Cloud Kernel +合入 Anolis Cloud Kernel 主线 Merge Request 3 个。 + +1)ext4: fix reserved space counter leakage
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/26935
+该问题为 @Jingbo Xu 在 AnolisOS 的下游 Alibaba Cloud Linux 2 的 生产环境中发现,并提交修复补丁到上游社区,社区接收至 Linux 主线后再回合。 + +2)several bug fixes
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/27026
+包含 virtio,ext4,dm-snapshot 以及 nfsv4 等稳定性补丁。 + +3)CVE fixes
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/27102
+包含 ext4 和 overlayfs 的 CVE 修复。 + +# VirtioFS per-file DAX +根据与社区的讨论,更新了该特性的默认行为,以获取更好的向前兼容性。当前最新一版的补丁 v7 已经发出,预计合入 5.17 主线。
+https://lore.kernel.org/all/20211102052604.59462-1-jefflexu@linux.alibaba.com/ + +# 容器镜像加速 +多设备多 blob 文件支持已经合入 5.16 主线,至此 v6 格式 on disk 部分已经完成;blob cache fscache 方案开发中;nydus 支持 v6 格式镜像已经开发完成,正在 E2E 联调中。
+anolis cloud kernel 预计 11 月份完成适配支持。 + +# 16k 原子写 +背景介绍,方案思路,以及 POC 测试步骤及数据已经开放在 SIG 中:
+https://openanolis.cn/sig/high-perf-storage/doc/415544543086428789 + +当前基于 mariadb-5.5.68 分别测试了 oltp_update_non_index,oltp_insert,以及 oltp_write_only 等 benchmark 模型,从 POC 测试数据来看,无论在 tps 还是数据量的节省都有比较明显的优化。 + +统信同学计划 11 月份中旬基于 UOS 龙蜥版完成评测,并基于测试结果评估提需求正式在龙蜥 OS 落地。 + +# io_uring 优化 +1)增强 io_uring file registration 特性的用户态易用性
+目前 io_uring file registration 特性需要用户态维护空闲的 slot 信息,会对用户引入额外的编程负担,尤其是在高并发的多线程应用, 可能需要同步多个线程间的 io_uring file table 的 slot 信息,不易于用户使用。文件句柄本身其实是一种天然互斥的资源,内核文件 系统本身保证同一个进程里的每个打开的文件拥有不同的句柄,从而如果我们直接用文件句柄作为 io_uring file registation 的 file table 的 slot 信息,可以极大简化用户态使用 file registration。我们的 patch 主要实现了 io_uring file registration file table 的自动扩容功能。
+https://lore.kernel.org/io-uring/9f27045b-7b1f-28a6-ed28-6b5e11723714@gmail.com/T/#t + +2)增加 fixed poll 支持
+io_uring 的 fast poll 特性在请求第一次 nowait 尝试没有成功时,会主动注册一个 poll 事件,等到事件满足时,继续发起第二次请求执行,但该 poll 事件是一次性的,对于后续发生同样的文件上的请求,仍然可能需要同样的 poll 事件注册,从而引 入overhead。对 io_uring 添加 fixed poll 支持,可以减少 fast poll 模式下频繁的 poll 事件注册。
+https://lore.kernel.org/io-uring/20211028122850.13025-1-xiaoguang.wang@linux.alibaba.com/T/#t + +poll request 在事件发生时会将对应的 wait entry 从等待列表中删除,这个操作是耗时的,通过用一个 flag 代替来降低这部分的开销:
+https://lore.kernel.org/io-uring/f571790c-ba98-5b58-3836-d0482ec0d49e@linux.alibaba.com/ + +3)io_uring vs epoll
+关于 io_uring 和 epoll 的对比,社区有过很多争论,比如:
+https://github.com/axboe/liburing/issues/189
+我们通过对 echo server 网络编程模型性能分析和量化,期望将该问题阐述清楚,后续我们会发出相关分析文章。 + +4)task work 优化
+对 task work 的处理方式进行优化,有效降低 sqpoll 模式下的 request 的延迟:
+https://lore.kernel.org/io-uring/20211029122237.164312-1-haoxu@linux.alibaba.com/T/#t + +5)async hybrid feature
+io-wq 线程池在处理网络请求时效率极低,可用性比较差。我们期望通过引入 async hybrid 特性进行优化。具体来说在线程处理请求时不再阻塞等待,而是设置好 poll 回调相关数据结构后返回处理其他请求,把剩余工作交给中断和 task work。
+https://lore.kernel.org/io-uring/20211018133445.103438-1-haoxu@linux.alibaba.com/ + +6)decouple work list from wqe->lock
+wqe->lock 目前保护了太多对象,这使得 work_list 和 free_list 之间存在较大访问冲突,通过增加 work_list 自有的锁解决该问题,具体见:
+https://lore.kernel.org/io-uring/153b3bed-7aea-d4bb-1e5b-ffe11e8aabc1@linux.alibaba.com/T/#t diff --git a/sig/HighPerfStorageSIG/content/report/2021/2021.11.md b/sig/HighPerfStorageSIG/content/report/2021/2021.11.md new file mode 100644 index 0000000000000000000000000000000000000000..8c9df83088949c42576e7506152966e890f03910 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/report/2021/2021.11.md @@ -0,0 +1,101 @@ +# 代码仓库迁移 +应社区要求代码仓库从 12 月起将从 codeup 切换至 gitee:
+https://gitee.com/anolis/ + +# Cloud Kernel +合入 Anolis Cloud Kernel 主线 Merge Request 12 个。 + +1)ext4: improve delalloc buffer write performance
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/27153
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/27175 + +回合自社区上游,已同步合入 anolis 4.19 和 5.10 内核。该 patchset 对 ext4 delalloc + buffer 写场景有比较明显的性能提升,如 unixbench file copy benchmark (fstime/fsbuffer/fsdisk),测试数据参见 merge request。 + +2)io_uring sqpoll 模式下 cpu 开销优化
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/27142
+针对容器化部署场景的资源优化,相比社区版本开启 sqthread poll 需要独占一个核,消耗更少的 cpu 资源同样获得比较好的业务时延优化。该特性已经在阿里云内部业务得到应用,相比传统的 aio,不增加 cpu 资源开销,业务时延优化 20%。 + +3)erofs 支持新容器镜像加速格式
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/27190
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/27239
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/27388 + +在 anolis 4.19 中,基于 erofs 实现新容器镜像加速格式支持。该项工作是容器镜像加速项目的基础部分。 + +4)ext4 优化
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/27204 + +在文件碎片化很严重(extents 数量很多)的情况下,fiemap dump 可能触发 soft lockup。该补丁修复这个问题。 + +5)fuse 支持 FUSE_MAX_PAGES
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/27307 + +目前 anolis cloud kernel 单个 fuse 请求最多只能包含 32 个 page,引入 max_pages 特性后,双方可以通过 fuse 协议协商单个 fuse 请求可以包含的 page 的最大数量,最大不超过 256。 + +6)性能优化
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/27354
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/27355 + +回合自社区上游,优化 64k page size 下 clear_buffer_new() 带来的原子操作。 + +7)支持 SMR zone 设备
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/27361 + +需求来源与阿里云内部,特性已经开始灰度验证。
+关于 SMR zone 设备,参见 https://zonedstorage.io/docs/getting-started/smr-disk + +8)fuse bugfix
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/27395 + +回合主线 fuse 的修复补丁。 + +# VirtioFS per-file DAX +为 virtio-fs 提供文件粒度的 DAX enable/disable 支持,以适应多样化的应用场景。11 月向社区推出新一版补丁(v8),计划合入版本上游内核主线 5.17。
+https://lore.kernel.org/all/20211125070530.79602-1-jefflexu@linux.alibaba.com/ + +# 容器镜像加速 +Nydus 支持新镜像格式已经 E2E 联调完成,xattr 生成也已开发完毕。erofs 已合入 anolis cloud kernel 内核主线。
+https://codeup.openanolis.cn/codeup/kernel/cloud-kernel/merge_request/27190 + +erofs-utils 1.4 已发布,原生支持多设备/blob,支持 dump 和 fsck 功能。
+https://lore.kernel.org/r/20211121172455.GA8626@hsiangkao-HP-ZHAN-66-Pro-G1 + +erofs fscache 支持已完成一版原型开发,待进一步整理代码并发到社区讨论。
+Nydus + sealer POC 进行中。 + +# 16k 原子写 +统信同学基于物理机 NVMe 盘完成 POC 测试。从测试结果来看,写入数据量优化 30% ~ 60%,符合预期;但 tps 存在 5% ~ 30% 的下降。
+初步分析是物理机盘的顺序与随机性能存在差异导致,而原 POC 是 基于 ECS 云盘,顺序与随机性能基本相当。
+接下来需要结合物理机测试环境进一步分析确认;并根据实际业务应用场景调整策略,如使用随机 IO 转顺序等方案优化等。 + +# io_uring 优化 +1)task work 优化
+task work 优化根据社区 review 意见更新,最新发出 v6 版本,已接近接收状态。
+该优化一定程度上降低了读写请求的时延,主要是 task work 密集场景下,实现了 “用于请求完成的 task work“ 的聚合,使得请求的完成更快速。最近一个更新是关于对聚合的 task work 应用何种优化手段加快处理,社区对此存在不同看法,最后我打算先用保守的方案,即尽可能使用已有的 inline completion cache。该 patchset 的具体实现和相关数据参见:
+https://lore.kernel.org/io-uring/20211126100740.196550-1-haoxu@linux.alibaba.com/T/#t + +2)fixed worker +fixed worker 机制发出 RFC 版本,目的是想解决 iowq 的锁冲突,原型版本在 nop 操作 POC 测试中吞吐提升 300%,社区反应不错。
+io_uring 实现异步化最重要的基础设施是 iowq,即 io_uring 自己实现的一套内核线程机制。但是这套机制目前存在较大瓶颈,因为所有 worker 使用公用的 work list,导致锁竞争很大,在高 IO 压力下可以达到 ~40%。
+基于此背景,诞生了 fixed worker 这样一个新的 worker 机制。该机制通过让每个 worker 拥有私有的 work list 基本达到了zero lock contension。同时 fixed worker 在创建之后生命周期与 io_uring 实例自身一致,用户态可以方便地对其进行定制化操作。相关 patchset 参见:
+https://lore.kernel.org/io-uring/1c900f05-5f3f-9649-5240-813b16daf8eb@linux.alibaba.com/T/#t + +其中,10 月份 sig 月报中提到的 decouple work list from wqe->lock 将作为该 patchset 的一部分先被接收。目前 fixed worker 还有用户态接口等部分需要编码实现。 + +3) async hybrid
+特性已经合入内核主线 5.16,目前已经开始引起用户态应用的讨论,如 Netty:
+https://github.com/netty/netty-incubator-transport-io_uring/issues/127 + +4)fixed poll
+支持特性由于代码改动比较大,且性能提升有限,社区暂时没有给予太多关注,优先级放低。
+https://lore.kernel.org/io-uring/20211028122850.13025-1-xiaoguang.wang@linux.alibaba.com/T/#t + +5)io_uring file registration
+针对该特性的易用性增强,由于社区担心在进程打开很多文件,且仅仅注册少量句柄的场景下存在 file table 内存浪费,暂未接收该补丁,需要进一步优化。
+https://lore.kernel.org/io-uring/9f27045b-7b1f-28a6-ed28-6b5e11723714@gmail.com/T/#t + +6)graph link 特性
+目前 io_uring 的 link 类型请求是线性的,即只处理一维的依赖。但是实际业务可能存在更复杂的应用场景,如有向无环图(DAG)。该特性旨在针对这种场景提供支持,特性编码实现中,预计 12 月份推向社区。 + +7)io_uring vs epoll
+通过对 echo server 网络编程模型性能量化分析文章将在近期发出,敬请关注龙蜥社区公众号。 diff --git a/sig/HighPerfStorageSIG/content/report/2021/2021.12.md b/sig/HighPerfStorageSIG/content/report/2021/2021.12.md new file mode 100644 index 0000000000000000000000000000000000000000..96096c9bc2de6ac2278327913447f8efb9b46828 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/report/2021/2021.12.md @@ -0,0 +1,79 @@ +12 月份是龙蜥社区代码仓库整体迁移到 gitee 后的第一个月。高性能存储 SIG 也积极配合将相关 repo 迁移到 gitee,除 kernel repo 因 gitee 目前暂不支持 fork 到同一目录,其余都统一放在 anolis 目录,后续将根据该功能支持情况进行相应调整。repo 具体链接请参照 SIG 主页。 + +另外,我们也根据项目的应用时间诉求,对当前 SIG 项目优先级进行了适当调整,加大了容器存储方向的投入。各项目具体进展如下: + +# cloud kernel +共合入 cloud kernel 的 pull request 9 个。 + +1)io_uring fixes
+修复 io_uring locked_vm 数值异常问题,该问题可能导致 io_uring 实例创建失败; 此外,该 PR 的还修复 async buffer read 特性可能因唤醒失效导致 task work 无法被正常处理,从而可能导致 hang。
+https://gitee.com/anolis/cloud-kernel/pulls/51 + +修复 io_uring async buffer read 在 short read 场景处理不完善的问题。
+https://gitee.com/anolis/cloud-kernel/pulls/72 + +2)task work 代码清理
+社区上游补丁 91989c707884 ("task_work: cleanup notification modes") 已经切换到 TWA_* 枚举通知模式,但 Cloud Kernel 中仍然存在代码使用老的 0/1/false/true 来通知,因此清理并统一。
+https://gitee.com/anolis/cloud-kernel/pulls/52
+https://gitee.com/anolis/cloud-kernel/pulls/53 + +3)erofs fixes
+支持 blob_path_dir 挂载参数,方便查找 blob。
+https://gitee.com/anolis/cloud-kernel/pulls/43 + +修复读流程中异常处理,以及 __ClearPageWaiters() 的竞争问题,并通过优化打印以降低启动时间。
+https://gitee.com/anolis/cloud-kernel/pulls/57 + +修复 erofs 在 virtiofs 场景发现的问题。
+https://gitee.com/anolis/cloud-kernel/pulls/73 + +4)stable kernel fixes
+跟踪 stable kernel 并 cherry-pick 相关修复补丁,包含 vfs,fuse,proc 等。
+https://gitee.com/anolis/cloud-kernel/pulls/63 + +5)overlayfs fixes
+回合上游补丁,修复 "ovl: implement async IO routines" 特性发现的 WARNING 以及可能的 UAF 问题。
+https://gitee.com/anolis/cloud-kernel/pulls/67 + +# vrtiofs per-file dax +该特性已合入 maintainer 的 tree,预计合入 5.17 主线:
+https://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse.git/log/?h=for-next + +另外,作者 Jeffle Xu 也于 2021.12.14 在 CLSF 会议上分享了该特性,如果对特性材料感兴趣,可以加入 SIG 群获取。 + +# 容器镜像加速 +1)erofs over fscache
+用于实现内核原生按需加载,已向社区发出了 RFC 和 v1 版本,由于当前处于假期,当前处于等待反馈的阶段:
+https://lore.kernel.org/r/20211227125444.21187-1-jefflexu@linux.alibaba.com/ + +同时在 nydus 项目组简单介绍了该特性的实现,nydus 端到端适配待开发;
+ +2)sealer集群镜像分发加速
+POC 阶段将 nydusd 挂载过程集成进 sealer 代码中,测试结果显示整体时间降低了约 33%,详细测试报告参见:
+https://openanolis.cn/sig/high-perf-storage/doc/461915394308588490 + +目前已经进入正式方案的开发,基于 Rocket 框架实现 nydusd 的 http server,编码实现中;
+ +3)nydusd fuse daemon 支持 RAFS v6格式
+元数据和数据侧均已调通,下一步会将 PR 发出来 review; + +4)erofs + virtiofs bugfix
+与 virtiofs 的 dax window slot 配合的 dmap pin 方案已合入 anolis cloud kernel,PR 参见:
+https://gitee.com/anolis/cloud-kernel/pulls/73 + +# 16k 原子写 +因人力重点投入容器镜像加速项目,16k 原子写投入较少。目前分析到物理盘 insert tps 性能回退的原因基本锁定在元数据更新开销上,1 月份会重点分析并确定优化方向。
+统信目前主要关注物理盘的场景,不过后续也有基于 cinder 即 ceph rbd 分布式存储的场景。1 月份有条件可以协调 openstack + ceph 的环境做测试。 + +# io_uring +1)zerocopy send
+io_uring 社区最近推出了网络零拷贝 send 的方案,引起社区讨论,我们也在积极跟进。包括对社 区提出的 send 方案进行测试以及对 zero receive 方案进行调研。 相关进展会在 1 月份陆续更新。
+https://lore.kernel.org/io-uring/cover.1638282789.git.asml.silence@gmail.com/#t + +2)graph link
+由于目前投入重点在 1)上,graph link 目前进展不大,主要是与社区继续讨论,Christian 近期抛出了一个对 graph dependency sqes 进行测试的框架,后续我们会利用这个工具测试不同解决方案的 优劣,以便进一步确定该特性的走向。
+https://lore.kernel.org/io-uring/20211214055734.61702-1-haoxu@linux.alibaba.com/ + +3)fixed worker
+目前没有进一步的更新,待后续跟进。
+https://lore.kernel.org/io-uring/20211124044648.142416-1-haoxu@linux.alibaba.com/ diff --git a/sig/HighPerfStorageSIG/content/report/2022/2022.01.md b/sig/HighPerfStorageSIG/content/report/2022/2022.01.md new file mode 100644 index 0000000000000000000000000000000000000000..618dccd5169517d34ff11c68c1b26309cbafa613 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/report/2022/2022.01.md @@ -0,0 +1,88 @@ +# cloud kernel +共提交 11 个 PR,涉及 cve 修复,io_uring,ext4,erofs,fuse 等。 + +1)cve 修复
+修复 fget,f2fs,xfs,btrfs,fs_context 等 cve 问题。
+https://gitee.com/anolis/cloud-kernel/pulls/80
+https://gitee.com/anolis/cloud-kernel/pulls/118
+https://gitee.com/anolis/cloud-kernel/pulls/121
+https://gitee.com/anolis/cloud-kernel/pulls/129
+https://gitee.com/anolis/cloud-kernel/pulls/130 + +同时,由于 fget 修复 cve 补丁引入了性能 regression,对此又进行了优化。
+https://gitee.com/anolis/cloud-kernel/pulls/81 + +2)io_uring
+相关修复包括:使用 WRITE_ONCE() 修改 sq_flags,split bio 场景关闭 iopoll,sqpoll 场景允许 non-fixed files 等。
+https://gitee.com/anolis/cloud-kernel/pulls/102 + +3)ext4
+revert 掉 dioread_nolock 挂载选项下的 jbd2 handle 在提交 io 时可能被 hang 住的 workaround。
+2019 年我们曾尝试将该补丁推向 ext4 社区,社区认同该补丁的作用,但提议进行更大规模的重构优化,后来我们没有参与,只将该补丁合入内部版本。由于社区最新代码在 dioread_nolock 这块有过其他优化,可以先 revert 掉。
+https://gitee.com/anolis/cloud-kernel/pulls/106 + +4)erofs
+修复 erofs metadata 在 virtiofs dax 场景的问题,该修复系列为 pull request 73 的延续。
+https://gitee.com/anolis/cloud-kernel/pulls/107
+https://gitee.com/anolis/cloud-kernel/pulls/117 + +5)fuse
+支持通过挂载参数设置后端 fuse 文件系统的类型。fuse 文件系统实现有很多种,但实际差异很大,例如 myfs 适合 oltp 场景,而 lfs 则适合 olap 场景。后续我们将对 fuse 进行一系列的优化。
+https://gitee.com/anolis/cloud-kernel/pulls/119 + +# virtiofs per-file dax +该特性已合入 5.17 主线:
+https://lore.kernel.org/lkml/164203136723.22460.16198679667354025783.pr-tracker-bot@kernel.org/T/ + +另外,我们在 sig 中撰写了一篇文章详细介绍该项目的背景和方案:
+https://openanolis.cn/sig/high-perf-storage/doc/485810385468129605 + +# 容器镜像加速 +1)erofs over fscache
+代码已经发出 v1 和 v2,fscache maintainer 回复了一些修改意见,接下来将根据意见发出 v3:
+https://lore.kernel.org/linux-fsdevel/20211227125444.21187-1-jefflexu@linux.alibaba.com/
+https://lore.kernel.org/linux-fsdevel/20220118131216.85338-1-jefflexu@linux.alibaba.com/ + +2)sealer 对接
+单节点、多节点开发基本完成,相关测试效果如下:
+770M 的 kubernetes:v1.19.8 镜像,单节点的 init 时间从 93s 降低至 23s(6s 的 nydus-images 镜像转换时间 + 17s 的 init 时间),6 节点测试 init 时间从 95s 降低 28s。
+30G 的大镜像模拟测试中,单节点的 init 时间从 16m40s 降低至 6m20s(6min 的 images 转换时间 + 20s 的 init 时间),6 节点测试 init 时间从 17m56s 降低至 6m23s(包含 6min 的 image 转换时间)。 + +基本功能已测试通过,本周完成一轮 code review,根据意见继续完善中,后续与 sealer 同学确认适配细节,准备发起正式 PR。 + +# 16k 原子写 +经过多机型的对比和不同存储盘(云盘、SATA SSD 和 NVMe 物理盘)的测试,目前物理盘的 tps 性能问题锁定在元数据更新增加的延迟上,因此在云盘和 SATA SSD 上由于 IO 延迟相对较高,元数据更新的延迟就变得不这么敏感。
+因此接下来的优化方向主要是尽可能减少元数据的操作,目前根据火焰图的表现正在优化 end_cow 的 btree 更新相关逻辑,原方式为 unmap 后 remap,预期优化为有条件直接 remap。
+ +# io_uring +1)zerocopy receive
+结合 io_uring 实现网络链路的 zerocopy,发送端已经发出 v2 版本:
+https://lore.kernel.org/io-uring/cover.1640029579.git.asml.silence@gmail.com/ + +我们也在考虑将其应用到接收端,已经发出 RFC:
+https://lore.kernel.org/io-uring/20220124094320.900713-1-haoxu@linux.alibaba.com/ + +接下来需要结合社区意见修改推进。 + +2)fixed worker
+继续尝试优化,第一步先将 wqe->lock 的竞争优化拆分出来:
+https://lore.kernel.org/io-uring/20220206095241.121485-1-haoxu@linux.alibaba.com/ + +3)用户态中断
+intel 在社区推进用户态中断特性,参见:
+https://lore.kernel.org/lkml/20210913200132.3396598-1-sohil.mehta@intel.com/ + +我们正在调研用户态中断特性与 io_uring 结合的可能,目前初步判断用户态中断可以给传统基于事件的编程框架带来革新,内核事件直接发送到用户态进行处理,不需要用户态通过系统调用进入内核获得事件然后再进行处理,可以提高事件响应的及时性。 + +# tcmu 优化 +分布式文件系统 client 端可以使用 tcm_loop + tcmu 的方式对外提供 block 语义的设备,但目前我们在测试过程中发现,该方案存在因多次内存拷贝和大粒度 mutex 锁导致的 io 吞吐较低,资源开销高。我们对 lio 及 tcmu 相关组件进行性能分析,并进行相关优化。 + +1)zerocopy
+tcmu 目前的实现中对于读写都需要进行一次额外的拷贝,在大 io size 场景下引起显著的 cpu 开销,导致 io 吞吐受限。目前我们针对 tcmu backstore 分配私有数据内存的情形进行优化,为 uio 框架添加一个 ioctl 接口,将 tcmu backstore 私有数据直接通过 ioctl 接口拷贝进 tcmu 内部的 sg pages,从而可以减少一次往 tcmu data area 拷贝的操作。fio 显示在大 io size job 下,显著的提高性能。
+相关代码近期将推送到 gitee storage-cloud-kernel 中。 + +2)io completion 优化
+tcmu 的 io completion 是在 workqueue 中触发 block 软中断进行的,因为 tcmu 没有实际的硬件中断,通过软中断反而会引起上下文切换等开销,使其继续在 workqueue 对应的进程上下文中完成 io,可以提高性能。
+https://lore.kernel.org/linux-block/YfJr76LOsSWLUqk2@infradead.org/T/#m96eb0e750d4ff18a428a998afb91568fd9ddcb28 + +同时我们目前还在进行 tcmu 多队列,uio 框架等性能优化,相关工作正在进行中。 diff --git a/sig/HighPerfStorageSIG/content/report/2022/2022.02.md b/sig/HighPerfStorageSIG/content/report/2022/2022.02.md new file mode 100644 index 0000000000000000000000000000000000000000..fe1112fdef520b488487b1f25e5c59b7cf47b87c --- /dev/null +++ b/sig/HighPerfStorageSIG/content/report/2022/2022.02.md @@ -0,0 +1,83 @@ +# cloud kernel +合并 PR 10 个,涉及 cve 修复,nvme,fuse,block,erofs,io_uring,fs 等。 + +1)cve 修复
+修复 nfs_atomic_open() 可能存在的未初始化使用问题。
+https://gitee.com/anolis/cloud-kernel/pulls/190
+https://gitee.com/anolis/cloud-kernel/pulls/191 + +2)nvme
+修复插入新 nvme 盘后,原 nvme 盘符可能发生变化的问题,例如,一般情况下系统盘为 nvme0n1,在插入一块新 nvme 盘并重启后,系统盘变成了 nvme1n1。
+https://gitee.com/anolis/cloud-kernel/pulls/145
+https://gitee.com/anolis/cloud-kernel/pulls/148 + +3)fuse
+支持通过挂载参数设置后端 fuse 文件系统的类型。
+https://gitee.com/anolis/cloud-kernel/pulls/119 + +4)block
+修复联通同学 wangyoua 反馈的使用 fio 测试 HDD mq-deadline 存在一定程度 regression。经分析是之前优化 blk-mq 批量处理请求过程中,回合的 “blk-mq: support batching dispatch from scheduler” 系列补丁存在一个 bug。
+https://gitee.com/anolis/cloud-kernel/pulls/157 + +5)erofs
+修复 Jeffle Xu 反馈 ANCK 4.19 erofs over block device 存在偶发 segment fault 问题。
+https://gitee.com/anolis/cloud-kernel/pulls/171 + +6)io_uring
+修复 abaci fuzzy 测试反馈的 inconsistent lock state 和 possible deadlock 问题。
+https://gitee.com/anolis/cloud-kernel/pulls/169
+https://gitee.com/anolis/cloud-kernel/pulls/170 + +7)fs
+回合社区上游 stable 补丁,修复 ext4,jffs2,fsdlm 等模块在异常场景下 BUG_ON,deadlock 等问题。
+https://gitee.com/anolis/cloud-kernel/pulls/153 + +# 16k 原子写 +结合 oltp_insert 的 on-cpu 的火焰图,在 XFS 文件系统 COW 流程中做了两个优化:
+在 xfs end cow 路径上增加 fast path,避免 unmap 后再 map COW fork,优化已同步提交到 xfs 社区:
+https://lore.kernel.org/linux-xfs/20220216030854.30180-1-hsiangkao@linux.alibaba.com/ + +避免由于 DIRECT I/O 模式 COW 带来的一次额外 UNWRITTEN 转换,也提交到 xfs 社区:
+https://lore.kernel.org/linux-xfs/20220217095542.68085-1-hsiangkao@linux.alibaba.com/ + +# 容器镜像加速 +1)Kata 安全容器已支持 nydus 镜像加速方案:
+https://github.com/kata-containers/kata-containers/pull/2977 + +2)Nydus 镜像加速一期已集成到 Sealer 集群镜像分发方案:
+https://github.com/alibaba/sealer/pull/1134 + +3)nydusd_http_server 代码 review 中:
+https://github.com/dragonflyoss/image-service/pull/304 + +4)fscache over erofs
+目前已发出第三版,正在根据社区意见设计与 cachefiles 无关的 kAPI:
+https://lore.kernel.org/r/20220209060108.43051-1-jefflexu@linux.alibaba.com/ + +5)Nydus官方网站已上线:
+https://nydus.dev/ + +# io_uring +1)io-wq 锁优化
+io_uring io-wq wqe->lock 锁的使用粒度优化,patchset 已被接收:
+https://yhbt.net/lore/all/20220206095241.121485-3-haoxu@linux.alibaba.com/t/ + +# tcmu 优化 +1)uio 框架优化
+利用 percpu_ref_count 替换 mutex,提高并发:
+https://lore.kernel.org/lkml/YgNv9folAsgtGl5Z@infradead.org/T/#t + +需要进一步补充测试数据。 + +2)tcmu command ring 大小控制
+默认为 8MB,不够灵活,在实例数较多且 command 较少时浪费内存,增加一个接口可以控制 command ring 大小, 该特性已经被接收:
+https://lore.kernel.org/lkml/164601967777.4503.13105145657095242015.b4-ty@oracle.com/ + +3)tcmu ioctl
+目前的实现中对于读写都需要进行一次额外的拷贝,在大 io size 场景下引起显著的 cpu 开销,导致 io 吞吐受限。目前我们针对 tcmu backstore 分配私有数据内存的情形进行优化,为 uio 框架添加一个 ioctl 接口,将 tcmu backstore 私有数据直接通过 ioctl 接口拷贝进 tcmu 内部的 sg pages,从而可以减少一次往 tcmu data area 拷贝的操作。fio 显示在大 io size job 下,显著的提高性能。
+https://lore.kernel.org/lkml/Yg4gL1tL7yJELNL2@kroah.com/T/ + +目前还在社区讨论中,tcmu 维护者认同该优化方案,但 Greg KH 不同意给 uio 增加新 ioctl 接口,需要寻找其他替代方案。 + +4)tcmu 零拷贝
+将 sg pages 映射到 tcmu 用户态 backstore,彻底解决 tcmu 大 io 场景下吞吐低问题。 相关代码近期将推送到 sig 代码库 storage-cloud-kernel 中。 diff --git a/sig/HighPerfStorageSIG/content/report/2022/2022.03.md b/sig/HighPerfStorageSIG/content/report/2022/2022.03.md new file mode 100644 index 0000000000000000000000000000000000000000..e2cfe43616037eb8d871e413d319c9b03a0d4aa8 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/report/2022/2022.03.md @@ -0,0 +1,31 @@ +# 整体进展 +cloud kernel 主线,共计合并 10 个 PR,其中包含:修复 CVE-2022-0847,CVE-2021-44879,CVE-2021-45868 等;修复使用 md 场景导致的 kernel crash;修复安全容器场景发现的 cgroup writeback 特性导致 cgroup 长时间残留问题;以及文件系统的一些稳定性 bugfix。 + +sealer 0.7.1 正式支持通过 nydus 加速集群镜像分发,使用指导请参见 SIG 项目文档《Sealer + Nydus 集群部署加速特性使用指南》。 + +# SIG 项目进展 + +1)16k 原子写
+统信同学完成在 ceph 云存储场景的 POC 测试,使用 mysql 5.7 和 mariadb 10.3,大多数测试 case io 量和 tps 都有明显优化,效果符合预期。接下来计划通过正式需求,将该特性在 anolis cloud kernel 中落地。内核版本上,将先在 5.10 内核中支持,待成熟稳定后再回合到 4.19。
+感谢统信同学的效果验证和反馈。 + +2)容器镜像加速
+nydus fscache 端到端支持实现中,erofs 的 fscache 支持补丁已经发到第 7 版,修复了端到端联调过程中发现的一些问题,具体参见 lore 邮件列表:
+[PATCH v7 00/19] fscache,erofs: fscache-based on-demand read semantics
+https://lore.kernel.org/all/20220331115753.89431-1-jefflexu@linux.alibaba.com/ + +sealer + nydus 集群部署加速一期开发已完成,使用指导参见 SIG 项目文档,目前正在邀测中。 + +3)tcmu 优化
+zero copy 特性发送到社区,目前讨论的焦点集中在 mm 子系统是否能提供合适的内存映射 helper 以 映射 io 请求的 sgl pages 到用户态,sql pages 来自匿名页或者 page cache 页,暂时没有明确结论。社区维护者对于方案本身基本认同,待进一步跟踪,具体参见 lore 邮件列表:
+[RFC 0/3] Add zero copy feature for tcmu
+https://lore.kernel.org/all/20220318095531.15479-1-xiaoguang.wang@linux.alibaba.com/ + +过程中提交三个 tcmu bug fixes 到社区,主要修复在某些场景下可能存在数据损坏问题,具体参见 lore 邮件列表:
+[PATCH v2 0/3] three bug fixes about tcmu page fault handle
+https://lore.kernel.org/all/20220323134940.31463-1-xiaoguang.wang@linux.alibaba.com/ + +# 下一步计划 +1、16k 原子写方案落地正式版本,包含用户态工具配套等;
+2、fscache over erofs 方案合入上游主线,成为社区主线方案;
+3、container os 支持 nydus + erofs,达到更高效的分发,去重和强一致数据保障。 diff --git a/sig/HighPerfStorageSIG/content/report/2022/2022.04.md b/sig/HighPerfStorageSIG/content/report/2022/2022.04.md new file mode 100644 index 0000000000000000000000000000000000000000..06d47f56d5a9c02b1dd2fc543c334a3b1aa68bcd --- /dev/null +++ b/sig/HighPerfStorageSIG/content/report/2022/2022.04.md @@ -0,0 +1,33 @@ +# 整体进展 +cloud kernel 主线,共计合并 9 个 PR,其中包含: + +NFS 等 fs 相关稳定性修复(PR253);fuse async dio 支持(PR259);fd_install 可能导致 double free 问题修复(PR272);CVE 修复:CVE-2022-1011(PR241),CVE-2022-0168(PR275),CVE-2022-0617(PR278,PR279),CVE-2022-29582(PR310);cgroup writeback bugfix(PR273)等。 + +16k 原子写确定先在 anck 5.10 版本中落地,mariadb 和 anck 5.10 内核代码开发已基本完成。 + +erofs over fscache 容器镜像加速方案继续根据 review 意见修改,已基本成型;同时多个外部公司开始测试试用,并表明意向共同推进。 + +# SIG 项目进展 + +1)16k 原子写
+基于 mariadb 10.3.28 和 anck 5.10 的代码开发基本完成,并开始相关测试。后续 mysql 如果需要使用原子写特性,需要移植 mariadb 原子写相关框架支持补丁即可。 + +2)容器镜像加速
+erofs over fscache 已经发到第10版,方案相关问题已经基本收敛:
+https://lore.kernel.org/r/20220425122143.56815-1-jefflexu@linux.alibaba.com/ + +nydus fscache 方案预取实现合入nydus fscache特性分支:
+https://github.com/dragonflyoss/image-service/pull/402 + +erofs 开启 export nfs 解决 overlayfs hardlink export 问题并支持 nfs 挂载:
+https://lore.kernel.org/r/20220425040712.91685-1-hongnan.li@linux.alibaba.com/ + +3)tcmu 优化 & ubd
+tcmu 在大 io 场景下的性能优化方案目前在经过业务的多轮测试,显示大 io 吞吐提升显著,代码目前正在社区 review 中,预计 5 月底完成合入。
+tcmu 对于小 io 场景性能不佳,目前 io_uring 社区出现一种新的基于 io_uring 的用户态块设备方案,我们初步进行性能评估,其显示在小 io 场景比 tcmu 有极大性能提升,其起代码更加简洁。目前我们正在参与该新特性开发,并同步进行 POC 测试,相关的讨论参见:
+https://lore.kernel.org/all/8a52ed85-3ffa-44a4-3e28-e13cdc793732@linux.alibaba.com/ + +# 下一步计划 +1、16k 原子写方案测试,包括性能对比,xfstests 回归,mariadb 回归等;同时需要梳理 xfsprogs 工具配套;
+2、fscache over erofs 方案推进上游;
+3、ubd 社区方案跟进及 POC。 diff --git a/sig/HighPerfStorageSIG/content/report/2022/2022.05.md b/sig/HighPerfStorageSIG/content/report/2022/2022.05.md new file mode 100644 index 0000000000000000000000000000000000000000..a47fe2bdb58f76def39dcda238bb90aea83d605c --- /dev/null +++ b/sig/HighPerfStorageSIG/content/report/2022/2022.05.md @@ -0,0 +1,81 @@ +# 整体进展 +本月共合入 anolis 主线 PR 21 个,包含多个主要组件的特性支持,稳定性加固,以及 CVE 修复; + +容器镜像加速 rafs v6 社区主线方案 erofs over fscache 已正式合入 Linux 内核 5.19 版本,后续也会同步回合到 anck 内核,使得在龙蜥操作系统中真正开箱即用; + +16k 原子写已经将内核,用户态工具,以及 mariadb 的 PR 发出,review 中; + +用户态存储 tcmu 性能优化已发出 PR 并完成第一轮 review; + +io_uring task work 优化已发出 PR,review 中;该 PR 为龙蜥社区北大选修课存储栈实践内容,由两位北大同学 flyhaf 和 chenshaohua 负责,感谢两位同学的贡献。 + +# 项目具体进展 + +1)anolis cloud kernel(anck)
+相关 PR 包括: + +cve:CVE-2022-29582(PR310),CVE-2022-1011(PR390) + +xfs:fix stale disk exposure after crash(PR312),prohibit fstrim in norecovery mode(PR313),properly serialise fallocate against aio+dio(PR315/PR356),fix tail rounding in xfs_alloc_file_space(PR326),general scubber fixes and more metadata verifier tightening(PR353),show proper user quota options(PR424/PR425),io fast path optimization(PR430) + +ext4:do not zeroout extents beyond i_disksize(PR337),don't allow writes to swap files(PR340) + +fuse:fix cuse broken release(PR365),synchronize with upstream per-file dax(PR376)and support per-file dax in anck 5.10(PR379) + +overlayfs:fix WARN_ON nlink drop to zero(PR371),return required buffer size for file handles(PR373),fix corner case of non-constant st_dev/st_ino(PR380) + +misc:tcmu format warning(PR311),enable blk-iocost in anck 5.10(PR423) + +2)容器镜像加速
+经过约半年的努力,erofs over fscache 内核主线容器镜像加速方案定格在 v11,按照预期合入了 Linux 内核 5.19 主线。这也成为了 Linux 内核首个源生支持的容器镜像加速方案,接下来我们会对该方案持续迭代和完善,并回合到 anolis 4.19 和 5.19 内核,使得龙蜥操作系统真正开箱即用。
+整个过程中也得到了很多外部团队的支持和帮助,也欢迎更多感兴趣的同学加入进来一起携手共建更好的容器镜像生态。 + +社区主线合并链接:
+https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=65965d9530b0c320759cd18a9a5975fb2e098462 + +相关技术分享文章:
+https://mp.weixin.qq.com/s/w7lIZxT9Wk6-zJr23oBDzA + +3)16k 原子写
+经过 xfs 用例回归,mariadb 用例回归,已经性能对比等测试后,xfs 支持 16k 原子写 PR 已经发出 review。 + +anck 5.10 内核 PR:
+https://gitee.com/anolis/cloud-kernel/pulls/415 + +xfsprogs PR:
+https://gitee.com/src-anolis-os/xfsprogs/pulls/7 + +mariadb PR:
+https://gitee.com/src-anolis-os/mariadb/pulls/5 + +4)用户态存储(tcmu & ubd)
+tcmu 性能优化已发出 PR,并完成第一轮 review,待 review 结束后合并到 anck 主线:
+https://gitee.com/anolis/cloud-kernel/pulls/410 + +ubd 是 io_uring 社区出现一种新的基于 io_uring 提供的基于全新 opcode(IORING_OP_URING_CMD)的用户态块设备方案。
+io_uring 社区 在 ubd 内核模块部分快速迭代,目前已产生两版 patch:
+https://lore.kernel.org/all/20220509092312.254354-1-ming.lei@redhat.com/
+https://lore.kernel.org/all/20220517055358.3164431-1-ming.lei@redhat.com/ + +我们目前参与了该方案的社区讨论,并同步进行 POC,包括 ubd 用户态 library 等,以方便用户快速适配 ubd。 + +5)io_uring
+龙蜥社区北大选修课实践,将 io_uring 上游针对 task work 的优化回合到 anck 主线。 + +经过过去近两个月的努力,两位北大同学终于本地测试通过并将 PR 发出,review 中:
+https://gitee.com/anolis/cloud-kernel/pulls/418 + +网络场景应用方面,netty 已经提供 io_uring 支持,具体参见:
+https://github.com/netty/netty-incubator-transport-io_uring + +我们进行性能测试时发现 io_uring 版的 netty 性能不如 epoll 版本的 netty,通过分析性能瓶颈,利用 io_uring 的 mulit-shot 性能对 netty 进行优化改造,且利用 io_uring 的 non-ipi task work 以及 file registration 等特性,目前在小包场景且系统调用 batch 较高时,io_uring 相比于 epoll 能稳定带来 10%+ 的性能提升,某些场景甚至可以有 25% 以上的性能提升。目前我们正在进行代码完善,预计在六月底将代码开源出来。
+ +经过不断的与社区沟通,终于解决了 file registration 难以使用的问题,参见:
+https://git.kernel.dk/cgit/linux-block/commit/?h=io_uring-5.19&id=a7c41b4687f5902af70cd559806990930c8a307b
+https://git.kernel.dk/cgit/liburing/commit/?id=87b6b2112c3de7be7b6c0a32974cbd6ee61ddcb7 + +# 下一步计划 +erofs over fscache 继续完成遗留事项的开发,并回合到 anck;
+16k 原子写合入到龙蜥社区主线,默认 yum 源可直接安装;
+完成 ubd 用户态 library 开发,并提供 example 程序,并完成 POC;
+netty io_uring 优化遗留事项开发,完善 netty 代码,并将依赖的 io_uring 特性回合到龙蜥内核,使得 netty io_uring 版本在龙蜥操作系统中开箱即用。 diff --git a/sig/HighPerfStorageSIG/content/report/2022/2022.06.md b/sig/HighPerfStorageSIG/content/report/2022/2022.06.md new file mode 100644 index 0000000000000000000000000000000000000000..67f2827d85e9d27169125c574c1a86ce2bd747cb --- /dev/null +++ b/sig/HighPerfStorageSIG/content/report/2022/2022.06.md @@ -0,0 +1,77 @@ +# 整体进展 +本月共合入 anolis 主线 PR 17 个,包含多个主要组件的特性支持,稳定性加固,以及 CVE 修复。 + +16k 原子写已经同步合入主线,包含 anck 5.10,xfsprogs 以及 mariadb;目前 xfsprogs 以及 mariadb 已经发布 rpm 包,链接参见 Errata;anck 5.10 下一个 release 预计在 8 月底发布(release 12)。用户当前可通过自行构建 anck 5.10 主线内核,并更新用户态包以使用该特性。 + +用户态存储 tcmu 性能优化补丁已经合入 anck 4.19 主线,业务侧使用 zero copy 和 bypass data area 等增强特性后,tcmu 设备性能得到显著提升,大块 IO 如 512k 读最大提升 1 倍,写提升 3 倍。 + +io_uring task work 优化系列补丁已经合入 anck 5.10 主线,感谢北大两位同学 flyhaf 和 chenshaohua 通过北大选修课对龙蜥社区所做的贡献。 + +# 项目具体进展 + +1)anolis cloud kernel(anck)
+相关 PR 包括: + +cve:CVE-2022-1786(PR473) + +xfs:atomic write support(PR415/PR 488/PR489),io fast path optimization(PR431),restore shutdown check in mapped write fault path(PR448),sync lazy sb accouting on quiesce of read-only mounts(PR451),skip repetitive warnings about mount options(PR454),pouch out data fork delalloc blocks on COW writeback failure(PR455),revert "xfs: actually bump warning counts when we send warnings"(PR467),validate inode fork size against fork format(PR474) + +tcmu:tcmu zerocopy/bypass data area enhancement(PR410) + +io_uring:request alloaction and task work optimization(PR418),fix lack of protection for compl_nr(PR469), + +2)容器镜像加速
+erofs over fscache 已经完成 4.19 内核的回合,目前 PR 已经提交,待合入:
+https://gitee.com/anolis/cloud-kernel/pulls/484 + +5.10 内核 backport 正在进行中。
+erofs 压缩去重的内核实现已经基本完成,调试中;另外,同步进行压缩字典的开发。
+nydus 已经支持 [e]stargz 按需加载。 + +3)16k 原子写
+相关 PR 已经合并到主线,相比基于硬件的方案,其特点如下:
+a、基于文件系统 COW 机制
+b、无硬件依赖
+c、无 IO 链路配置依赖 + +测试数据显示(基于 ecs.g7.2xlarge + 500GiB PL1 ESSD),相比默认打开双写,有至多 ~60% 的性能的提升,同时能显著减少磁盘 IO 量。另外,叠加代码段大页优化特性后,性能可获得进一步提升。 + +内核:
+https://gitee.com/anolis/cloud-kernel/pulls/415
+https://gitee.com/anolis/cloud-kernel/pulls/488
+https://gitee.com/anolis/cloud-kernel/pulls/489 + +xfsprogs:
+https://gitee.com/src-anolis-os/xfsprogs/pulls/7
+ +mariadb 10.3 & 10.5:
+https://gitee.com/src-anolis-os/mariadb/pulls/6
+https://gitee.com/src-anolis-os/mariadb/pulls/7 + +Errata:
+https://anas.openanolis.cn/errata/detail/ANEA-2022:0532
+https://anas.openanolis.cn/errata/detail/ANEA-2022:0533
+https://anas.openanolis.cn/errata/detail/ANEA-2022:0534 + +4)用户态存储(tcmu & ubd)
+libubd 已经完成 POC 版本:
+https://gitee.com/anolis/libubd + +同时我们还发 RFC 到上游社区,收到 ubd 作者的积极反馈:
+https://lore.kernel.org/all/fd926012-6845-05e4-077b-6c8cfbf3d3cc@linux.alibaba.com/ + +目前计划与作者合作,进行 libubd 的改造工作,具体包括:重构用户态代码,将 libubd 作为 ubd 用户态部分的底座,使得业务将 ubd 接入到后端存储框架中,以及实现基于 libubd 的 target demo。 + +上游社区已经发布了 v3 版 ubd 内核部分补丁,我们参与讨论和 review,并积极推进其进入内核主线 staging:
+https://lore.kernel.org/all/20220628160807.148853-1-ming.lei@redhat.com/ + +5)io_uring
+北大两位同学在龙蜥社区北大选修课实践中回合的上游 task work 优化 PR 已合入 anck 5.10 主线:
+https://gitee.com/anolis/cloud-kernel/pulls/418 + +io_uring netty 优化,当前正在与中间件团队同学适配并验证端到端性能。 + +# 下一步计划 +16k 原子写用户文档。
+erofs over fscache anck 4.19 发布可用,以及 anck 5.10 回合。
+ubd 社区方案推进。 diff --git a/sig/HighPerfStorageSIG/content/report/2022/2022.07.md b/sig/HighPerfStorageSIG/content/report/2022/2022.07.md new file mode 100644 index 0000000000000000000000000000000000000000..e30dbd141435f70480fc3e4f8e5b6264b61123bf --- /dev/null +++ b/sig/HighPerfStorageSIG/content/report/2022/2022.07.md @@ -0,0 +1,61 @@ +# 整体进展 +本月共合入 anolis 主线 PR 14 个,包含多个主要组件的特性支持,稳定性加固,以及 CVE 修复等。 + +erofs over fscache 容器镜像加速特性已回合到 anck 4.19 和 5.10。该特性为龙蜥社区贡献到 Linux 内核上游首个内核原生支持的容器镜像加速方案,并在 Linux 内核主线 5.19 提供支持。 + +fuse 支持 fd passthrough 和 fd attach 增强特性。其中 fuse passthrough 能将常用场景的 IO 延迟降低到先前的 10%;fd attach 支持无损恢复 fuse 挂载点连接,提升生产环境的稳定性。 + +ublk 内核驱动已经合入 5.20 主线,其中包含我们主导开发的 NEED_GET_DATA 特性。该特性后续将替代 tcmu 等用户态存储场景,相比优势为更轻量级的协议栈,更好的性能。 + +# 项目具体进展 + +1)anolis cloud kernel(anck)
+相关 PR 包括: + +cve:CVE-2022-1184(PR536/PR537) + +erofs:erofs over fscache 特性支持(PR484/PR511/PR523) + +xfs:修复 ABBA 死锁,以及移除不正确的 ASSERT(PR527) + +fuse:支持 fuse fd passthrough 和 fd attach(PR500/PR586) + +io_uring:fix a soft lockup issue(PR525/PR526) + +misc:移植 open_tree and move_mount 以支持 rootless 容器(PR498),user_namespace 增强(PR461/PR462),buffer read 性能优化(PR542) + +2)容器镜像加速
+erofs over fscache ANCK 4.19 和 5.10 内核均已合入。
+erofs 压缩去重特性社区开发中。
+fscache bitmap 支持第一版 RFC 已发到 fscache 社区邮件列表:
+https://listman.redhat.com/archives/linux-cachefs/2022-August/007050.html + +3)16k 原子写
+用户态 rpm(mariadb & xfsprogs)已经发布,统信 UOS 预计 8 月份开始 cherry-pick 内核补丁。待最终效果反馈。 + +4)用户态存储(tcmu & ublk)
+ublk 介绍文章已经发布,已经支持从其他用户态存储方案迁移到 ublk,欢迎 POC:
+https://developer.aliyun.com/article/989552 + +ublk_drv 内核驱动已经合入 5.20 主线,其中包含我们主导开发的 NEED_GET_DATA 特性:
+https://kernel.source.codeaurora.cn/pub/scm/linux/kernel/git/axboe/linux-block.git/log/?h=for-5.20/block + +目前正在编码 ublk 故障恢复特性,准备发 RFC 到社区。 + +5)io_uring
+完成对社区 netty-incubator-transport-io_uring 的重新改造,增加 io_uring 的 multi-shot, task work non-ipi 等特性支持,目前内部整理代码中,预计 8 月下旬会开放到龙蜥社区。 + +redis 对 io_uring 的支持,之前主要是基于 fast poll 进行优化。
+https://github.com/redis/redis/pull/9440 + +社区之前忙于 7.0 版本,review 工作进展缓慢。最近社区反馈希望继续推进该工作,目前正在基于最新的 redis io 框架重构,并进一步完善代码后在 redis 社区推进。 + +6)fuse
+fuse 支持 fd passthrough 和 fd attach 增强特性,旨在提升 fuse IO 场景的性能和故障恢复能力。
+https://gitee.com/anolis/cloud-kernel/pulls/500
+https://gitee.com/anolis/cloud-kernel/pulls/586 + +# 下一步计划 +erofs 压缩去重和 fscache bitmap 特性合并到上游主线。
+ublk 故障恢复特性开发。
+16k 原子写发布 UOS。 diff --git a/sig/HighPerfStorageSIG/content/report/2022/2022.08.md b/sig/HighPerfStorageSIG/content/report/2022/2022.08.md new file mode 100644 index 0000000000000000000000000000000000000000..6f71c4a25e2ef62a6411e490dbca548d42f3fc8c --- /dev/null +++ b/sig/HighPerfStorageSIG/content/report/2022/2022.08.md @@ -0,0 +1,62 @@ +# 整体进展 +本月共合入 anolis 主线 PR 12 个,包含多个主要组件的特性支持,bugfix,以及 CVE 修复等。 + +e2fsprogs 基线版本升级至 1.46.0,以支持 ext4 fast commit 特性。该特性对数据库场景 fsync 有比较明显的优化,从业务测试结果来看能提升 5%+。此外,我们也将上游主线相关优化和 bugfix 进行了回合。 + +ublk 故障恢复特性以发出 RFC 版本到社区,目前基本得到社区的认可,并上了 lwn:
+https://lwn.net/SubscriberLink/906097/52def497973c3a5a/
+目前已结合社区的 review 意见更新至 v2 版本,预计可以合并到 Linux v6.1。 + +# 项目具体进展 + +1)anolis os
+相关 PR 包括: + +cve:CVE-2022-2978(PR668/PR674) + +erofs:优化 anonymous fd 释放时 flush 请求的逻辑(PR556/PR596) + +ext4:ext4 fast commit 优化和 bugfix(PR640),e2fsprogs 支持 fast commit(PR10) + +io_uring:删除冗余的参数 in_async(PR602) + +misc:因依赖补丁未合入,回退先前因 cve 修复引入的额外补丁(PR607),支持 SMR zoned device(PR619),buffer read 优化 off-by-one 问题修复(PR655),修复 mpt3sas 驱动在 intel_iommu=on 以及 iommu=pt 情况下 panic 问题(PR654),perf bench futex-wake 数据显示异常问题修复(PR630) + +2)容器镜像加速
+针对 anck 的 4.19 和 5.10 版本的 fscache 老基线预读功能增强开发中:
+https://gitee.com/anolis/cloud-kernel/pulls/692 + +感谢字节开发 fscache 相关的特性 failover 和 shared domain。
+failover:
+https://lore.kernel.org/r/20220818135204.49878-1-zhujia.zj@bytedance.com + +shared domain:
+https://lore.kernel.org/r/20220902105305.79687-1-zhujia.zj@bytedance.com + +另外,压缩去重特性开发进度 90%,预计下一个版本合入。 + +3)16k 原子写
+龙蜥社区版本验收的结果符合预期,与之前开发测试基本一致,各项 case 有不同程度的 tps 性能优化,最大达 ~50%,同时明显减少写入数据量。
+UOS 内核补丁合入存在滞后,已明确让统信同学跟进下具体原因,并与内核团队确认下最新计划。另外,需要明确内核团队的负责同学,方便交流跟进。 + +使用手册:
+https://openanolis.cn/sig/high-perf-storage/doc/594617348901388298 + +4)用户态存储
+ublk NEED_GET_DATA 特性已合入 Linux 6.0 主线,支持用户后端存储传递 buffer,避免拷贝; + +故障恢复 USER_RECOVERY 特性已经发了两版 RFC 补丁到社区,正在根据社区 review 意见开发 v3 版本。
+https://lore.kernel.org/linux-block/20220831155136.23434-1-ZiyangZhang@linux.alibaba.com/T/#t + +上述两个特性是从实际生产角度来设计的,待故障恢复特性合入主线后,我们将进一步开展产品适配 POC。 + +5)io_uring
+netty io_uring 在 selector=1 时平均 tps 提升 16%,已经超过线上 selector=6 的 nio 性能,但 selector=6 时数据对比并没有明显优势。从通用性角度,希望这个特性能进上游主线,业务能通过更新社区版本来获得。需要进一步讨论确认。 + +redis io_uring 在 ecs 场景评估未见明显优势,不同于之前在物理机上的评估效果,需要进一步调查下效果差异的原因。 redis 社区 aws 对该特性比较感兴趣,可以在社区询问下 aws 的意愿。如果 aws 愿意 take 该工作,我们也作为 reviewer 参与进去。 + +# 下一步计划 +完成 16k 原子写特性合入 UOS。
+完成 erofs 压缩去重特性并合入社区主线。
+ublk 故障恢复特性合入社区主线,并开始业务场景 POC。
+完成 netty io_uring 新内核版本性能分析。 diff --git a/sig/HighPerfStorageSIG/content/report/2022/2022.09.md b/sig/HighPerfStorageSIG/content/report/2022/2022.09.md new file mode 100644 index 0000000000000000000000000000000000000000..ec1b1f53e92ffc9ada6ef3aff49ce555bf83770b --- /dev/null +++ b/sig/HighPerfStorageSIG/content/report/2022/2022.09.md @@ -0,0 +1,55 @@ +# 整体进展 +本月共合入 anolis 主线 PR 14 个,包含多个主要组件的特性支持,CVE 修复,以及 bugfix 等。 + +由于 codebase 差异,之前贡献到社区主线(v5.19)的 fscache based readahead 实现无法直接回合到 anck。因此 anck 针对 4.19/5.10 内核进行重新适配,优化顺序读场景的性能。 + +ublk 故障恢复特性已顺利合并到 Linux v6.1。同时,ublk 已经成功申报今年的 CLK 演讲议题,将包含高性能存储 SIG 贡献的 NEED_GET_DATA 和 故障恢复特性。 + +# 项目具体进展 + +1)anolis os
+cve:CVE-2022-3202(PR730),CVE-2022-3176(PR734/PR735),CVE-2021-4037(PR740/PR741) + +overlayfs:支持 unprivileged overlay mounts(PR676),抑制异常场景的频繁打印以避免 soft lockup(PR691) + +xfs:修复 xfstests xfs/518 用例失败问题(PR704),16k 原子写两个小问题修复(PR720) + +erofs:支持 fscache based readahead 特性(PR692/PR694) + +fuse:支持 copy_file_range(PR719/PR721) + +tcmu:支持 cmd ring 大小可配(PR748) + +2)容器镜像加速
+Linux 6.1 主线合入了字节跳动开发,高性能存储 SIG 参与 review 的 shared domain 特性,优化了不同镜像间的重复数据存储冗余。 + +另外 erofs 在 Linux 6.1 也支持了 fragment 和压缩去重特性,使镜像大小进一步精简,详见
+https://www.phoronix.com/news/Linux-6.1-EROFS
+https://lore.kernel.org/lkml/YzrD50lgln3c9zEf@debian/
+https://lore.kernel.org/linux-erofs/20220926152511.94832-1-hsiangkao@linux.alibaba.com/T/#t + +ANCK 针对代码基线的差异,在 4.19 和 5.10 实现了 fscache readahead 特性支持,解决无 readahead 特性时顺序读性能问题。 + +3)16k 原子写
+内核模块,用户态工具 xfsprogs 以及适配的 mariadb 已经随 anolis 8.6 发布。
+统信内部流程调整,暂不合入 UOS,后续根据实际客户诉求再提需求合入。 + +4)用户态存储
+ublk 故障恢复特性已顺利合并到 Linux v6.1:
+https://lore.kernel.org/linux-block/166516202669.22254.13418351510170463181.pr-tracker-bot@kernel.org/T/#t + +当用户态进程退出后,/dev/ublkb* 不会消失,向该设备发出的 I/O 请求都会暂时在内核中排队,用户可以通过 UBLK_CMD_START_RECOVERY 和 UBLK_CMD_END_RECOVERY 来启动新进程并关联到该 /dev/ublkb* 设备,使得在排队的 I/O 请求被处理。
+我们针对不能忍受返回 I/O 错误的场景,提供了 RECOVERY_REISSUE 支持,把已经下发给挂掉进程的请求重新下发给新的进程,进而使得上层应用不感知到 I/O 错误。由于用户态进程容易挂掉(如内存耗尽,段错误等异常与信号),故障恢复特性是一个在生产环境中非常重要的特性。 + +另外,ublk 已经申报今年的 CLK session,将由 redhat 的工程师和高性能存储 SIG 联合演讲。 + +5)io_uring
+Intel 提供了新的用户态中断原型:
+https://github.com/intel/uintr-linux-kernel/ + +高性能存储 SIG 将基于 echo server 评估 io_uring 场景的实际收益。 + +# 下一步计划 +erofs fscache failover、daemonless 等特性合入社区主线,并在业务场景完成 POC。
+ublk 应用场景 POC。
+io_uring 用户态中断性能评估。 diff --git a/sig/HighPerfStorageSIG/content/report/2022/2022.10.md b/sig/HighPerfStorageSIG/content/report/2022/2022.10.md new file mode 100644 index 0000000000000000000000000000000000000000..5cb1bc8556f398417e67305ab46e05110c69303f --- /dev/null +++ b/sig/HighPerfStorageSIG/content/report/2022/2022.10.md @@ -0,0 +1,42 @@ +# 整体进展 +本月共合入 anolis 主线 PR 11 个,包含多个主要组件的性能优化,CVE 修复,以及 bugfix 等。 + +本月举行的第十七届 CLK 会议,高性能存储 SIG 组参与了 IO 与 ebpf 分论坛的两个主题演讲:1)EROFS over FSCACHE:内核原生的镜像加速方案,由 Jeffle Xu 与字节跳动的同学合作演讲;2)High performance generic userspace block device (ublk),由 Ziyang Zhang 与 Redhat 同学合作演讲。 + +通过结合 erofs 垂直优化 overlayfs credential 和 acl 性能,在 ab(apache benchmark)测试中带来 ~40% 的性能提升。 + +ANCK 4.19 提供 dax cow 特性支持,该特性主要基于社区 Shiyang Ruan 的 ”fsdax: introduce fs query to support reflink“ 系列补丁重构,为后续文件系统层支持 dax reflink 提供基础。 + +# 项目具体进展 + +1)anolis os
+cve:CVE-2022-2602(PR784/788),CVE-2022-0494(PR794) + +overlayfs/erofs:rafsv6 性能优化(PR775/783) + +xfs:修复 inode btree format 转换失败问题(PR766) + +fuse:修复 dax soft lockup 问题(PR771),优化 getattr 请求(PR786/PR787) + +vfs:容器启动性能性能优化(PR791) + +dax:支持 cow(PR808) + +2)容器镜像加速
+fscache 共享域特性(字节同学贡献),erofs 压缩去重和 fragment 等特性合入 Linux 6.1 主线。
+当前 erofs 代码中使用了 libnetfs 的相关接口,与 fscache 设计初衷有些违背,需要在社区就 erofs 与 netfs 接口架构层次问题讨论并达成一致,方便后续特性的推进。
+Jeffle Xu 与字节跳动同学合作在 CLK 上针对 erofs over fscache 特性做了主题演讲。 + +3)用户态存储
+ublk 故障恢复特性顺利合入 Linux 6.1,并参与社区io_uring_cmd_complete_in_task() batch submit特性的 review 和task_work_add()性能对比工作。
+Ziyang Zhang 与 Redhat 同学合作在 CLK 上针对 ublk 模块做了主题演讲,内容包括ublk在阿里云的实践、故障恢复等特性和下一步的计划,ppt分享在:
+https://github.com/ChinaLinuxKernel/CLK2022。 + +4)io_uring
+搭建 Intel Uintr + io_uring 环境,改造 echo server 测试程序后发现,uintr 在高负载场景可以带来 ~5.6% 的性能提升,与之前的理论分析不同,需要继续分析原因,并挖掘出实际可操作的 SIG 项目。
+结合 Samba 在 io_uring 适配过程中遇到的一些问题,我们计划继续推进 io_uring 在网络应用上的优化,如异步 IO 且 batch 较高的协程。 + +# 下一步计划 +推进 erofs over fscache failover、daemonless 等特性,并就 erofs 与 netfs 接口架构层达成一致。
+ublk 内存拷贝优化和业务 POC。
+io_uring 网络方向的应用优化,如协程。 diff --git a/sig/HighPerfStorageSIG/content/report/2022/2022.11.md b/sig/HighPerfStorageSIG/content/report/2022/2022.11.md new file mode 100644 index 0000000000000000000000000000000000000000..399f6034275f81b0bd145c2937f0d1570f7a97b6 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/report/2022/2022.11.md @@ -0,0 +1,54 @@ +# 整体进展 +本月共合入 anolis 主线 PR 23 个,包含多个主要组件的性能优化,CVE 修复,以及 bugfix 等。 + +erofs over fscache 回合上游新特性 shared domain 和 failover。这两个特性是由火山引擎内核与虚拟化团队的同学贡献,Jeffle Xu 和 gaoxiang 参与 review。shared domain 特性支持多镜像间共享相同内容的 blob 存储空间;failover 特性支持 daemon 崩溃后恢复。这两个特性的合入,进一步促进了 erofs over fscache 镜像加速方案的生产可用。 + +xfs 社区长期存在一个 inode extent-to-btree 转换失败,最终导致 fs shutdown 的问题。gaoxiang 通过构造相关场景,并成功抓取到问题发生时的 dump,最终将解决方案发到社区,并提前在 anck 中修复。同时,该修复合入后发现 xfstests 用例需要同步更新,正在推社区的过程中。 + +回合社区主线 fsdax-rmap 相关基础补丁,用于支持 fsdax 场景 tracking shared page。后续将基于该方案进一步支持 xfs fsdax reflink。 + +凝思软件贡献 DSMS 项目到高性能存储 SIG。当前项目仓库已经构建,并发布整体工作计划,预计 2023.6 发布第一个版本。 + +# 项目具体进展 + +1)anolis os
+cve:CVE-2022-3649(PR813),CVE-2022-2503(PR856),CVE-2022-26365(PR859),CVE-2022-3621(PR858),CVE-2022-3646(PR878) + +erofs:misc fixes for fscache mode(PR881/PR884),use kill_anon_super() to kill super in fscache mode(PR883),支持 fscache shared domain 特性(PR893),支持 fscache failover 特性(PR894/PR915), + +xfs:修复 syscalls/quotactl07 case 失败(PR877),修复 inode extent-to-btree 转换失败导致的 fs shutdown(PR891),fsck 支持恢复日志(PR14) + +fuse:修复 getattr 优化的问题(PR854) + +crypto:SM4 XTS symmetric algorithm support(PR895) + +dax:支持 dax cow(PR905) + +io_uring:sqthread park/unpark race fixes(PR857),don't convert to jiffies for waiting on timeouts(PR868/PR869),移除异步 ioctl 支持(PR923),解决 IORING_ENTER_SQ_SUBMIT_ON_IDLE 与上游特性的冲突(PR924),anolis23 liburing(PR6) + +2)容器镜像加速
+针对之前回合到龙蜥社区的容器镜像加速方案 (erofs over fscache),从主线社区回合一系列修复补丁。
+share domain 特性回合到 ANCK 5.10 内核,支持镜像之间层 (image layer) 粒度的共享,从而节省镜像在磁盘上的存储空间。该特性于 v6.1 合入主线内核。
+failover 特性回合到 ANCK 5.10 内核,支持 user daemon 异常退出并恢复之后,容器内对容器镜像的访问可以自动恢复,整体过程对容器无感透明。该特性目前仍在主线社区讨论中,但是该方案已经在字节内部生产环境上部署。
+share domain 与 failover 特性回合 ANCK 4.19 内核仍在进行中。 + +3)用户态存储
+ublk 已经开始在分布式存储场景 POC,代码适配中。
+目前我们正在为 ublk 开发零拷贝特性,方案设计已初步完成,预计12月下旬完成编码和测试工作。 + +4)io_uring
+Anolis 23 的 liburing 打包中,选型 2.3 上游版本 + 自研特性。
+io_uring + async_simple 协程优化目前正在进行初步性能分析,预计 12 月底完成评估。后续计划使能 io_uring 新的高级特性,进一步性能优化。 + +async_simple git repo:
+https://github.com/alibaba/async_simple + +5)dsms
+凝思软件的同学 yxpeng 介绍了 dsms 项目背景,整体架构和工作计划,相关仓库已经创建,预计 2023.6 发布第一个版本。
+ +# 下一步计划 +share domain 与 failover 特性回合到 ANCK 4.19 内核。
+chunk 级别 page cache 共享,以节省内存占用,实现资源超卖,计划合入上游主线 v6.3,然后再回合到 ANCK 5.10/4.19。
+完成基于 io_uring + ebpf 的 ublk 零拷贝特性开发。
+io_uring + async_simple 性能调优。
+dsms 完成分布式存储的选型以及在 anolis 上的移植与开发测试。 diff --git a/sig/HighPerfStorageSIG/content/report/2022/2022.12.md b/sig/HighPerfStorageSIG/content/report/2022/2022.12.md new file mode 100644 index 0000000000000000000000000000000000000000..b73249a6a8630c382a298ed8e991388ef365c178 --- /dev/null +++ b/sig/HighPerfStorageSIG/content/report/2022/2022.12.md @@ -0,0 +1,42 @@ +# 整体进展 +本月共合入 anolis 主线 PR 16 个,包含多个主要组件的特性增强,CVE 修复,以及 bugfix 等。
+继上个月在 ANCK 5.10 增强 erofs over fscache,支持上游新特性 shared domain 和 failover 后,本月在 ANCK 4.19 也支持这两个新特性,为 ANCK 4.19 erofs over fscache 镜像加速方案上生产环境铺平了道路。
+xfs inode extent-to-btree 转换失败问题社区主线方案仍在讨论中,xfstests 用例更新已合入主线。
+DSMS 开始适配 AolisOS 的适配工作,项目文档同步开始更新至 SIG。 + +# 项目具体进展 +1)anolis os
+cve:CVE-2022-33981 / CVE-2022-1836(PR552)
+erofs:misc bug fixes for RAFS mode(PR967),cachefiles: add missing lock protection when polling(PR1004),support shared domain feature on ANCK 4.19(PR974),support failover feature on ANCK 4.19(PR975),cachefiles: fix potential NULL in error path(PR1023)
+ext4:fix BUG at mballoc(PR993),fix BUG at jbd2 commit(PR994),fix NULL pointer dereference BUG(PR995)
+xfs:fix NULL pointer dereference BUG(PR996), fix two deadlocks for xfs_rename(PR1005)
+block:blk-iocost: don't ignore vrate_min on QD contention(PR1021)
+dax:fix wrong arg passing in dax_insert_entry(PR1013)
+io_uring:fix compile error when cgroup disabled(PR968/PR972),add support for 128-byte SQEs and uring-cmd(PR1017) + +2)容器镜像加速
+ANCK 4.19 开始支持 shared domain 和 failover 特性,接下来会在生产环境应用 erofs over fscache 加速方案。
+RAFS 模式下的相关问题修复。
+page cache 共享特性原型已基本开发完毕,待整理发到社区。 + +3)用户态存储
+已经讨论确定在 ANCK 5.10 中支持 ublk,正在合入 ublk 代码,涉及 block-mq,mm 等层适配等工作。
+ebpf + io_uring 的零拷贝方案基本原型已经跑通,待整理后发起社区 RFC。 + +4)io_uring
+ANCK 5.10 和 liburing 已经支持 128 字节 SQE 特性和 uring cmd 特性,为 ANCK 5.10 支持 ublk 作准备。
+io_uring + async_simple 协程优化因人力投入进展缓慢,计划 1 月份会加快优化进度。 + +5)dsms
+DSMS 开始适配 AnolisOS,过程中发现缺失了一些依赖包,目前已经解决。
+DSMS 后端初步计划适配 ceph,后续考虑引入 ceph 版本并在 AnolisOS 中维护起来。
+相关项目文档同步开始在 SIG 中维护更新。 + +# 下一步计划 +page cache 共享特性合入上游主线,并回合到 ANCK 4.19 和 5.10。
+erofs over fscache 加速方案支持 fs-verity 和 encrypt 特性,合入上游主线,并回合到 ANCK 4.19 和 5.10。
+ANCK 4.19 和 5.10 支持 fscache daemonless 特性。
+ANCK 5.10 支持 ublk 高性能用户态存储方案。
+io_uring + ebpf 的 ublk 零拷贝方案合入社区主线,并回合到 ANCK 5.10。
+io_uring + async_simple 性能优化。
+dsms 完成 AnolisOS 上的移植与适配。 diff --git a/sig/HighPerfStorageSIG/content/report/MonthlyReport-Rules.md b/sig/HighPerfStorageSIG/content/report/MonthlyReport-Rules.md new file mode 100644 index 0000000000000000000000000000000000000000..0e58d03db0cc9e9ed8e1df3066c66ce97fef8dac --- /dev/null +++ b/sig/HighPerfStorageSIG/content/report/MonthlyReport-Rules.md @@ -0,0 +1,6 @@ +- 每月的第一周总结发出上月的报告,并更新到 SIG 页面,如 2022.01 + +- 月报包含内容: + + 整体进展:SIG 该月的亮点特性 + + 具体进展:SIG 项目的详细进展,包含龙蜥社区的 PR,以及上游社区的邮件等 + + 下一步计划:SIG 项目下一步的工作方向 diff --git a/sig/HighPerfStorageSIG/sig-info.yaml b/sig/HighPerfStorageSIG/sig-info.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c13f29909560629649e3575b9febadca4704e578 --- /dev/null +++ b/sig/HighPerfStorageSIG/sig-info.yaml @@ -0,0 +1,52 @@ +name: 高性能存储 SIG +en_name: High Performance Storage SIG +home_page: https://openanolis.cn/sig/high-perf-storage +description: 存储领域的发展历程,本质上是存储介质与软件栈相互促进发展的过程。高性能存储技术兴趣组致力于存储栈性能挖掘,当前主要聚焦内核 io_uring 技术优化异步 IO 性能,使用持久化内存提升业务单成本性能,容器场景存储技术优化等课题。高性能存储 SIG 期望通过社区合作,打造标准的高性能存储技术软件栈,推动软硬件协同发展。高性能存储 SIG 期望通过社区合作,打造标准的高性能存储技术软件栈,推动软硬件协同发展。 +en_description: There are many applications still relying on standard storage IO interfaces, e.g. standard system calls. High Performance Storage Technologies SIG is focusing on those technologies providing high IO performance for end users. Currently we mainly focus on the next asynchronous IO standard io_uring, and persistent memory related topic, container storage technologes, etc. Through community cooperation, we expect to build a standard high performance IO stack, and promote the collaborative development of software and hardware. +mailing_list: storage@lists.openanolis.cn + +maintainers: +- openanolis_id: josephqi + gitee_id: josephhz +- openanolis_id: gaoxiang + gitee_id: hsiangkao +- openanolis_id: xiaoguangwang + gitee_id: legezywzh +- openanolis_id: wangleic + gitee_id: wanglei-uos +- openanolis_id: HanGuangyu + gitee_id: han-guangyu +- openanolis_id: yxpeng + gitee_id: pencc + +contributors: +- openanolis_id: Jingbo Xu + gitee_id: JeffleXu +- openanolis_id: ZiyangZhang + gitee_id: taijuanZZY +- openanolis_id: hongnan_Li + gitee_id: hongnanli +- openanolis_id: HaoXu + gitee_id: hao-xu2 +- openanolis_id: anuo + gitee_id: uudiin + +repositories: +- repo: + - anolis/storage-cloud-kernel + - anolis/liburing + - anolis/fio + - anolis/perf-test-for-io_uring + - anolis/io_uring-echo-server + - anolis/nginx + - anolis/redis + - anolis/storage-test-scripts + - anolis/xfsprogs-dev + - anolis/mariadb-server + - anolis/erofs-utils + - anolis/sealer + - anolis/image-service + - anolis/libubd + - anolis/ubdsrv + - anolis/e2fsprogs + - anolis/dsms diff --git a/sig/Hygon Arch/README.en.md b/sig/Hygon Arch/README.en.md new file mode 100644 index 0000000000000000000000000000000000000000..0dec6c202f2d751c2bd1fb36cbffc5edd612666a --- /dev/null +++ b/sig/Hygon Arch/README.en.md @@ -0,0 +1,12 @@ +## SIG Mission +Our group is devoted to software support based on Hygon c86 processor in Chinese cryptography, Trusted Compute, confidential compute, virtualization etc. + +## SIG Members +jiangxin00, fenghao, BugKeeper, chench00, wojiaohanliyang, panpingsheng, poetic-bone + +## Chat GROUP +Dingding: 33089820 + +Weixin: + +![weixin-sig](./assets/wx-sig.jpg) diff --git a/sig/Hygon Arch/README.md b/sig/Hygon Arch/README.md new file mode 100644 index 0000000000000000000000000000000000000000..5ac86aaf2157bfa15f9cea942c1d9532e62b1186 --- /dev/null +++ b/sig/Hygon Arch/README.md @@ -0,0 +1,44 @@ +## SIG目标 +致力于构建国产C86架构的软件生态,包括国密、可信计算、机密计算、虚拟化和基础软件库等。 + +## SIG详细介绍 +C86处理器兼容市场主流的x86指令集,具有成熟而丰富的应用生态,内置专用安全硬件,支持通用的可信计算标准,能够进行主动安全防护。本小组计划在openAnolis社区软件支持C86处理器功能(机密计算、国密、可信、基础软件库等) + +## SIG成员 +jiangxin00, fenghao, BugKeeper, chench00, wojiaohanliyang, panpingsheng, poetic-bone + +## 项目清单 +- 密码技术 + - HCT(Hygon Crypto Technology)是基于密码协处理器和密码指令集自主设计和研发的一套密码算法加速技术软件开发套件。HCT利用密码协处理器和密码指令集,以openssl标准接口为系统应用提供标准密码算法接口,极大提升传统密码算法性能。现有HCT版本(HCT 1.0)对密码协处理器处理采用同步处理方式,在密码协处理器执行密码算法运算的同时,C86侧处理器采用轮询方式查询密码协处理器状态,当C86侧查询到协处理器处理完成,继续后续数据处理。由于密码协处理器和C86独立运行,当协处理器执行密码运算时,采用异步处理模式,C86侧则可以释放计算资源,用以处理其他事务(如准备待加密数据等),以节约CPU计算资源,提升密码协处理器吞吐量(throughput)。 + - TKM(Trusted Key Management Module)是海光CPU基于安全处理器PSP和密码协处理器CCP实现的密钥管理模块,实现密钥“可用不可见”,具有安全的密钥管理和高效的密码运算功能。TKM符合国密认证要求,支持向上提供符合GM/T 0018标准的SDF标准接口,能够快速适配各种密码应用。 +- 机密计算 + - CSV是海光自主研发的机密计算技术,采用国密算法实现,CSV虚拟机在写内存数据时CPU硬件自动加密,读内存数据时硬件自动解密,每个CSV虚拟机使用不同的密钥。 + - CSV2在加密虚拟机内存的基础上,增加了虚拟机状态加密功能,进一步增强了加密虚拟机的安全性。 + - CSV3在前二代技术的基础上继续增强,在CPU内部实现了虚拟机数据的安全隔离,禁止主机操作系统对虚拟机内存的读写,保证了虚拟机数据的完整性,实现了云计算环境下的数据机密性和完整性的双重安全。 + +- 可信计算 + - TPCM(Trusted Platform Control Module)是国内新兴的可信计算技术,是中国可信计算3.0的底层芯片标准,实现可信计算的信任根,由中关村可信计算联盟制定。和TPM/TCM相比,TPCM增加了对系统主动监视和控制的功能,可以实现系统启动时的主动启动度量,及程序运行时的动态度量和监控,进一步增强系统的安全性。 + - TPM2.0(Trusted Platform Module)是国际可信计算标准,海光基于安全处理器以固件的形式实现了TPM2.0设备,命令接口符合TPM2.0规范。同时,利用内置的密码运算硬件加速引擎CCP实现所有密码运算相关操作,克服传统固件实现TPM的不足,提高了系统性能,硬件加速引擎全面支持商密标准。 + - TCM2.0(Trusted Crypto Module)是国内传统的可信计算标准,有着广泛的应用。2020年国密局升级了TCM标准,推出了TCM2.0规范《GM/T 0012-2020 可信计算 可信密码模块接口规范》。TCM2.0功能与接口的定义基于TPM2.0,与TPM2.0具有较强的兼容性,TCM2.0只支持商密标准。与TPM2.0一样,TCM2.0基于CPU安全处理器以固件的形式实现,固件以BIOS PI的形式发布给OEM厂商,因此使用TCM2.0需与OEM厂商确认BIOS已使能该功能支持。 + - TDM(Trusted Dynamic Measurement)是海光基于安全处理器实现的轻量级动态度量,是特有功能。通过TDM可以实现对设定内存目标进行持续的周期性度量,及时发现程序异常,保护程序运行时安全;同时TDM通过独有的双重授权保护方式确保非授权用户无法篡改TDM内的度量任务设定,极大的增强了模块的安全性。 + - TSB(Trusted Secure Boot)是除了上述TPCM/TPM/TCM之外另一个独立的由CPU硬件验证平台固件BIOS完整性的功能,验证基于数字签名。CPU上电或重启时,TSB首先验证颁发的OEM公钥证书,再用OEM公钥证书中的公钥验证BIOS固件的OEM签名,验证通过后才运行BIOS固件,从而保证BIOS固件的安全以及后续整个启动信任链的源头安全。 + +- 高性能数学库 + - HML(Hygon Math Library)是基于海光CPU平台构建的一套高性能数学库,基于海光CPU架构特点极致优化,能够充分发挥海光CPU计算性能。 + - BLAS库:为HML子项,基础线性代数运算数学库(Basic Linear Algebra Subprograms),提供level1、level2、level3共几十个函数优化,该库可以用于HPC和AI。 + - SPARSE库:为HML子项,稀疏基础线性代数运算库(Sparse Basic Linear Algebra Subprograms),提供稀疏的向量和向量、稀疏的向量和矩阵、稀疏的矩阵和矩阵运算。 + - SMM库:为HML子项,小矩阵乘法运算库(Small matrix multiplication),提供小规模矩阵乘矩阵运算,在小规模下性能极致优化。 + - VML库:向量数学库(Vector Mathematical),向量的数学运算,包含幂函数、三角函数、指数函数、双曲函数、对数函数等,根据海光CPU特性深度优化,在保证精度的同时,性能达到最优。 + - VSIP库:矢量、信号和图像处理库(Vector Signal Image Processing),包含向量基础运算、矩阵基础运算、快速傅里叶运算等,提供视频、图像、信号处理的础软件算法和框架。 + +## 联系我们 +使用以上功能时,遇到任何问题,请发邮件到`securitytech@hygon.cn`。 + +## 钉钉/微信群 + +欢迎搜索钉钉群号*33089820*进入*Hygon-Arch SIG* + +欢迎扫描下方微信二维码进入*Hygon-Arch SIG* + +![weixin-sig](./assets/wx-sig.jpg) + diff --git a/sig/Hygon Arch/assets/HCT/HCT_VM1.png b/sig/Hygon Arch/assets/HCT/HCT_VM1.png new file mode 100644 index 0000000000000000000000000000000000000000..98beaf910f3fce7e25810b0ea78e856f44304242 Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/HCT_VM1.png differ diff --git a/sig/Hygon Arch/assets/HCT/HCT_VM10.png b/sig/Hygon Arch/assets/HCT/HCT_VM10.png new file mode 100644 index 0000000000000000000000000000000000000000..73aaeebe9c1421a3b1036826b175c790e89b00ca Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/HCT_VM10.png differ diff --git a/sig/Hygon Arch/assets/HCT/HCT_VM11.png b/sig/Hygon Arch/assets/HCT/HCT_VM11.png new file mode 100644 index 0000000000000000000000000000000000000000..5a9737f9481feed75bb8fb25259915ad7f03c567 Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/HCT_VM11.png differ diff --git a/sig/Hygon Arch/assets/HCT/HCT_VM12.png b/sig/Hygon Arch/assets/HCT/HCT_VM12.png new file mode 100644 index 0000000000000000000000000000000000000000..0989a02fe8012c43730b1985d666f6accd603ba6 Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/HCT_VM12.png differ diff --git a/sig/Hygon Arch/assets/HCT/HCT_VM14.png b/sig/Hygon Arch/assets/HCT/HCT_VM14.png new file mode 100644 index 0000000000000000000000000000000000000000..f028d548d9e0f6c42e8816c0ef9a4957de4c7293 Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/HCT_VM14.png differ diff --git a/sig/Hygon Arch/assets/HCT/HCT_VM15.png b/sig/Hygon Arch/assets/HCT/HCT_VM15.png new file mode 100644 index 0000000000000000000000000000000000000000..fb9ed6bbb571c8968b8820c6e3632fd46a58ea18 Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/HCT_VM15.png differ diff --git a/sig/Hygon Arch/assets/HCT/HCT_VM16.png b/sig/Hygon Arch/assets/HCT/HCT_VM16.png new file mode 100644 index 0000000000000000000000000000000000000000..a4ab8a8a2c8f4e0a0c45b05f0f6a883bf58e073c Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/HCT_VM16.png differ diff --git a/sig/Hygon Arch/assets/HCT/HCT_VM17.png b/sig/Hygon Arch/assets/HCT/HCT_VM17.png new file mode 100644 index 0000000000000000000000000000000000000000..99d7cd8220664666585edd347b951b8090df2e94 Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/HCT_VM17.png differ diff --git a/sig/Hygon Arch/assets/HCT/HCT_VM18.png b/sig/Hygon Arch/assets/HCT/HCT_VM18.png new file mode 100644 index 0000000000000000000000000000000000000000..5c24a485a71c8fc16f895b4cf9915d2f35098dca Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/HCT_VM18.png differ diff --git a/sig/Hygon Arch/assets/HCT/HCT_VM19.png b/sig/Hygon Arch/assets/HCT/HCT_VM19.png new file mode 100644 index 0000000000000000000000000000000000000000..bcf5ebcfe6bec8334c02cb7fd7a179ecef16d909 Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/HCT_VM19.png differ diff --git a/sig/Hygon Arch/assets/HCT/HCT_VM2.png b/sig/Hygon Arch/assets/HCT/HCT_VM2.png new file mode 100644 index 0000000000000000000000000000000000000000..b3bfd6d5379c3bcfb7dfe300aa0409cd92a1d24e Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/HCT_VM2.png differ diff --git a/sig/Hygon Arch/assets/HCT/HCT_VM20.png b/sig/Hygon Arch/assets/HCT/HCT_VM20.png new file mode 100644 index 0000000000000000000000000000000000000000..d8cff3bd79a7012621678578bd177eb227e3a9f7 Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/HCT_VM20.png differ diff --git a/sig/Hygon Arch/assets/HCT/HCT_VM3.png b/sig/Hygon Arch/assets/HCT/HCT_VM3.png new file mode 100644 index 0000000000000000000000000000000000000000..368516fedf7ff7df6ba925e858e76e8266bc2b82 Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/HCT_VM3.png differ diff --git a/sig/Hygon Arch/assets/HCT/HCT_VM4.png b/sig/Hygon Arch/assets/HCT/HCT_VM4.png new file mode 100644 index 0000000000000000000000000000000000000000..3f6c1248a4bd3f9a551e580a903f0691aef187be Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/HCT_VM4.png differ diff --git a/sig/Hygon Arch/assets/HCT/HCT_VM5.png b/sig/Hygon Arch/assets/HCT/HCT_VM5.png new file mode 100644 index 0000000000000000000000000000000000000000..0d90580caa6c596306410a2655dc0116ebfb36dc Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/HCT_VM5.png differ diff --git a/sig/Hygon Arch/assets/HCT/HCT_VM6.png b/sig/Hygon Arch/assets/HCT/HCT_VM6.png new file mode 100644 index 0000000000000000000000000000000000000000..4f5c9ce551754e3ba0e2144206c413e908715567 Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/HCT_VM6.png differ diff --git a/sig/Hygon Arch/assets/HCT/HCT_VM7.png b/sig/Hygon Arch/assets/HCT/HCT_VM7.png new file mode 100644 index 0000000000000000000000000000000000000000..d9a53561f6e087afa3a7c5675e57af340c40dd77 Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/HCT_VM7.png differ diff --git a/sig/Hygon Arch/assets/HCT/HCT_VM8.png b/sig/Hygon Arch/assets/HCT/HCT_VM8.png new file mode 100644 index 0000000000000000000000000000000000000000..44c3f01adb1e914129b942c6d0be37a53cbd5cc2 Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/HCT_VM8.png differ diff --git a/sig/Hygon Arch/assets/HCT/HCT_VM9.png b/sig/Hygon Arch/assets/HCT/HCT_VM9.png new file mode 100644 index 0000000000000000000000000000000000000000..d8d44b5519ad252a6f9be2d0e25f0a8eb2467ef0 Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/HCT_VM9.png differ diff --git a/sig/Hygon Arch/assets/HCT/white_paper/hct_wp1.png b/sig/Hygon Arch/assets/HCT/white_paper/hct_wp1.png new file mode 100644 index 0000000000000000000000000000000000000000..525748301738edcb05cffe64db2ecc14b66ae37c Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/white_paper/hct_wp1.png differ diff --git a/sig/Hygon Arch/assets/HCT/white_paper/hct_wp2.png b/sig/Hygon Arch/assets/HCT/white_paper/hct_wp2.png new file mode 100644 index 0000000000000000000000000000000000000000..cb5ed812480e53aa56b0ac3320cdc1bda86c83c6 Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/white_paper/hct_wp2.png differ diff --git a/sig/Hygon Arch/assets/HCT/white_paper/hct_wp3.png b/sig/Hygon Arch/assets/HCT/white_paper/hct_wp3.png new file mode 100644 index 0000000000000000000000000000000000000000..79cc2304b0d61e23e797c862865e15e995d2f2f8 Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/white_paper/hct_wp3.png differ diff --git a/sig/Hygon Arch/assets/HCT/white_paper/hct_wp4.png b/sig/Hygon Arch/assets/HCT/white_paper/hct_wp4.png new file mode 100644 index 0000000000000000000000000000000000000000..0c658569d68a8bad36152d5cb55b525bef50facd Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/white_paper/hct_wp4.png differ diff --git a/sig/Hygon Arch/assets/HCT/white_paper/hct_wp5.png b/sig/Hygon Arch/assets/HCT/white_paper/hct_wp5.png new file mode 100644 index 0000000000000000000000000000000000000000..f8e055df953e0853be116559183b157201a2d1f2 Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/white_paper/hct_wp5.png differ diff --git a/sig/Hygon Arch/assets/HCT/white_paper/hct_wp6.png b/sig/Hygon Arch/assets/HCT/white_paper/hct_wp6.png new file mode 100644 index 0000000000000000000000000000000000000000..b4d9758b934a4e0cbb99f2f090985013fd2fbdfc Binary files /dev/null and b/sig/Hygon Arch/assets/HCT/white_paper/hct_wp6.png differ diff --git a/sig/Hygon Arch/assets/SDF/fw_version.png b/sig/Hygon Arch/assets/SDF/fw_version.png new file mode 100644 index 0000000000000000000000000000000000000000..5f08356844b62f603239f5e436da176d0880414c Binary files /dev/null and b/sig/Hygon Arch/assets/SDF/fw_version.png differ diff --git a/sig/Hygon Arch/assets/TKM/hgsc_tkm.png b/sig/Hygon Arch/assets/TKM/hgsc_tkm.png new file mode 100644 index 0000000000000000000000000000000000000000..522a27e98411e5246e7b832656a1dec58ecd8d0c Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/hgsc_tkm.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-1.png b/sig/Hygon Arch/assets/TKM/tkm-1.png new file mode 100644 index 0000000000000000000000000000000000000000..fa7428314463ccee3997f8a8dadf46b191e6a4f3 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-1.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-10.png b/sig/Hygon Arch/assets/TKM/tkm-10.png new file mode 100644 index 0000000000000000000000000000000000000000..e7dc40c89eec840da6ee46c693d32b56b499b4ed Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-10.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-11.png b/sig/Hygon Arch/assets/TKM/tkm-11.png new file mode 100644 index 0000000000000000000000000000000000000000..14aecdb5cfbda0340b9795144cab8251a0d31e7c Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-11.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-12.png b/sig/Hygon Arch/assets/TKM/tkm-12.png new file mode 100644 index 0000000000000000000000000000000000000000..871d1e61938f260db232600a0af2d6a042b08332 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-12.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-13.png b/sig/Hygon Arch/assets/TKM/tkm-13.png new file mode 100644 index 0000000000000000000000000000000000000000..eee82fca32ec82617fcec323fc9727ae6f2ad101 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-13.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-14.png b/sig/Hygon Arch/assets/TKM/tkm-14.png new file mode 100644 index 0000000000000000000000000000000000000000..f99eab0094fcc04254fc18a2ac960b24abbf7ee7 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-14.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-15.png b/sig/Hygon Arch/assets/TKM/tkm-15.png new file mode 100644 index 0000000000000000000000000000000000000000..4895de6bcfeb5d6c7929562135e4e88478fd3a32 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-15.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-16.png b/sig/Hygon Arch/assets/TKM/tkm-16.png new file mode 100644 index 0000000000000000000000000000000000000000..70bea265752b041caf7db5ac020079e570c32b46 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-16.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-17.png b/sig/Hygon Arch/assets/TKM/tkm-17.png new file mode 100644 index 0000000000000000000000000000000000000000..e64d9001aaf4af61699cdecc601ad0e3155e76e4 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-17.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-18.png b/sig/Hygon Arch/assets/TKM/tkm-18.png new file mode 100644 index 0000000000000000000000000000000000000000..c7a202a023f6d83d01f7a6046c0dc713b22a2d7a Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-18.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-19.png b/sig/Hygon Arch/assets/TKM/tkm-19.png new file mode 100644 index 0000000000000000000000000000000000000000..10dbb8cf455f57f519b74e27fd02b2e6ecb0a812 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-19.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-2.png b/sig/Hygon Arch/assets/TKM/tkm-2.png new file mode 100644 index 0000000000000000000000000000000000000000..b3dedf0ca441819f0f33389870316e00a2d911ea Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-2.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-20.png b/sig/Hygon Arch/assets/TKM/tkm-20.png new file mode 100644 index 0000000000000000000000000000000000000000..eee82fca32ec82617fcec323fc9727ae6f2ad101 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-20.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-21.png b/sig/Hygon Arch/assets/TKM/tkm-21.png new file mode 100644 index 0000000000000000000000000000000000000000..ec15be16f82b484f3b53f5489ea04b57223a51b4 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-21.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-22.png b/sig/Hygon Arch/assets/TKM/tkm-22.png new file mode 100644 index 0000000000000000000000000000000000000000..05a2941ec212fc727818fa3bbf3a5f371c083725 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-22.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-23.png b/sig/Hygon Arch/assets/TKM/tkm-23.png new file mode 100644 index 0000000000000000000000000000000000000000..b7e381fcfa866b0b2c0a63400051bf7a467bd02c Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-23.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-24.png b/sig/Hygon Arch/assets/TKM/tkm-24.png new file mode 100644 index 0000000000000000000000000000000000000000..dd4b4ab4a9a4aafd4e709d594f05f4789bc2ac13 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-24.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-25.png b/sig/Hygon Arch/assets/TKM/tkm-25.png new file mode 100644 index 0000000000000000000000000000000000000000..147c8cd40d1c27e44199ab33d23deac53eb9b174 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-25.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-26.png b/sig/Hygon Arch/assets/TKM/tkm-26.png new file mode 100644 index 0000000000000000000000000000000000000000..5c8d42c63fd3ed38bffcf517bc6d1d8a9ae80d6e Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-26.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-27.png b/sig/Hygon Arch/assets/TKM/tkm-27.png new file mode 100644 index 0000000000000000000000000000000000000000..380b185b15e172107a0a6e8d712f152f4a7714ca Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-27.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-28.png b/sig/Hygon Arch/assets/TKM/tkm-28.png new file mode 100644 index 0000000000000000000000000000000000000000..db974ef6178da4c12fca17eef8508a3dcb9921e0 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-28.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-29.png b/sig/Hygon Arch/assets/TKM/tkm-29.png new file mode 100644 index 0000000000000000000000000000000000000000..3f0f7ddabec314ef52a7bf6c3517a8d3bfd8f10d Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-29.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-3.png b/sig/Hygon Arch/assets/TKM/tkm-3.png new file mode 100644 index 0000000000000000000000000000000000000000..4fc0a90535e8cd9c8261b65779bdefadd14b04b9 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-3.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-30.png b/sig/Hygon Arch/assets/TKM/tkm-30.png new file mode 100644 index 0000000000000000000000000000000000000000..6c0629af88968f24e3141b6bc8831ca0757eabbb Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-30.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-31.png b/sig/Hygon Arch/assets/TKM/tkm-31.png new file mode 100644 index 0000000000000000000000000000000000000000..9a6ecd8dce8bb274e6547ceb19d3d35b74d2a0ce Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-31.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-32.png b/sig/Hygon Arch/assets/TKM/tkm-32.png new file mode 100644 index 0000000000000000000000000000000000000000..2a41cb2c233e7f3c13e1e6752e7fb722147ca93b Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-32.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-33.png b/sig/Hygon Arch/assets/TKM/tkm-33.png new file mode 100644 index 0000000000000000000000000000000000000000..b68f635f4492a7d1f8edc9b4a31c94b654181dd2 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-33.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-34.png b/sig/Hygon Arch/assets/TKM/tkm-34.png new file mode 100644 index 0000000000000000000000000000000000000000..91804a303752e7161ab5eed2fd58bd8378af5dea Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-34.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-35.png b/sig/Hygon Arch/assets/TKM/tkm-35.png new file mode 100644 index 0000000000000000000000000000000000000000..0ee3baf70c445c76f3d985d1b321825904b0c131 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-35.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-36.png b/sig/Hygon Arch/assets/TKM/tkm-36.png new file mode 100644 index 0000000000000000000000000000000000000000..e3054feb364194df066fd4a1fbf1e1e41ccb9f51 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-36.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-37.png b/sig/Hygon Arch/assets/TKM/tkm-37.png new file mode 100644 index 0000000000000000000000000000000000000000..1827e2623c948376f3546ad33bae9d62d05c78d8 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-37.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-38.png b/sig/Hygon Arch/assets/TKM/tkm-38.png new file mode 100644 index 0000000000000000000000000000000000000000..000d6b8e3d1036881d42d13b7fffc96e2458e68b Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-38.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-39.png b/sig/Hygon Arch/assets/TKM/tkm-39.png new file mode 100644 index 0000000000000000000000000000000000000000..147a074f7cd9e75cdf8cfd085b624b2bc82ab5a7 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-39.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-4.png b/sig/Hygon Arch/assets/TKM/tkm-4.png new file mode 100644 index 0000000000000000000000000000000000000000..9635cfcfbbba0c27c0f4492309953a2c4085706d Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-4.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-40.png b/sig/Hygon Arch/assets/TKM/tkm-40.png new file mode 100644 index 0000000000000000000000000000000000000000..54b444e019028d0f4d303b4664c7dfb41373cc11 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-40.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-41.png b/sig/Hygon Arch/assets/TKM/tkm-41.png new file mode 100644 index 0000000000000000000000000000000000000000..0707962817f54bfadbf68a8862aec68630bfdf34 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-41.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-42.png b/sig/Hygon Arch/assets/TKM/tkm-42.png new file mode 100644 index 0000000000000000000000000000000000000000..8c326f6e8ec0892ef343e4889dbcd06318f6d5f9 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-42.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-43.png b/sig/Hygon Arch/assets/TKM/tkm-43.png new file mode 100644 index 0000000000000000000000000000000000000000..8099e8e90d3ebf43ecde09f990453333709bcd5f Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-43.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-44.png b/sig/Hygon Arch/assets/TKM/tkm-44.png new file mode 100644 index 0000000000000000000000000000000000000000..da0d79fb712ca18d89e855eb0a9a05f3a8bc26a2 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-44.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-45.png b/sig/Hygon Arch/assets/TKM/tkm-45.png new file mode 100644 index 0000000000000000000000000000000000000000..e136632089da7a26792ae149435828693d612cdb Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-45.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-46.png b/sig/Hygon Arch/assets/TKM/tkm-46.png new file mode 100644 index 0000000000000000000000000000000000000000..313c5635d3f332293428e89ca57679c536f07923 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-46.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-47.png b/sig/Hygon Arch/assets/TKM/tkm-47.png new file mode 100644 index 0000000000000000000000000000000000000000..2712bef4f097267b05b00123da4daf7e763deeeb Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-47.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-48.png b/sig/Hygon Arch/assets/TKM/tkm-48.png new file mode 100644 index 0000000000000000000000000000000000000000..a95d814baacb70f213ad1f017f07e537bac67afb Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-48.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-49.png b/sig/Hygon Arch/assets/TKM/tkm-49.png new file mode 100644 index 0000000000000000000000000000000000000000..6708326bfbe6923c4facaa3c5531f15afa9fb0d2 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-49.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-5.png b/sig/Hygon Arch/assets/TKM/tkm-5.png new file mode 100644 index 0000000000000000000000000000000000000000..544743c786356cfed79b3a5c09f5100ce7a339e0 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-5.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-50.png b/sig/Hygon Arch/assets/TKM/tkm-50.png new file mode 100644 index 0000000000000000000000000000000000000000..b81104763f429471315433c4812ee116bfc8f67c Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-50.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-51.png b/sig/Hygon Arch/assets/TKM/tkm-51.png new file mode 100644 index 0000000000000000000000000000000000000000..e7ed6bda94f6e70e0bb600cbc69250edf69e8bb9 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-51.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-52.png b/sig/Hygon Arch/assets/TKM/tkm-52.png new file mode 100644 index 0000000000000000000000000000000000000000..08f570438d1830dd950cb372cd199ed989b2749c Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-52.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-53.png b/sig/Hygon Arch/assets/TKM/tkm-53.png new file mode 100644 index 0000000000000000000000000000000000000000..48d2cae9269bac792e629ed83ca0897d21f634e1 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-53.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-54.png b/sig/Hygon Arch/assets/TKM/tkm-54.png new file mode 100644 index 0000000000000000000000000000000000000000..050468182ecece5390342688595edf8ae1a03003 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-54.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-55.png b/sig/Hygon Arch/assets/TKM/tkm-55.png new file mode 100644 index 0000000000000000000000000000000000000000..4363de25d97f6f225bc827e3a6987877ba57d467 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-55.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-56.png b/sig/Hygon Arch/assets/TKM/tkm-56.png new file mode 100644 index 0000000000000000000000000000000000000000..ae07b5393e16644269a34bf318c44e0a44819169 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-56.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-57.png b/sig/Hygon Arch/assets/TKM/tkm-57.png new file mode 100644 index 0000000000000000000000000000000000000000..ae34cf00900b12b65cb0cb6dbad9ab25bdd67ccb Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-57.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-58.png b/sig/Hygon Arch/assets/TKM/tkm-58.png new file mode 100644 index 0000000000000000000000000000000000000000..16b2c91306756a8bfec056eaa3e232db3481cfbf Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-58.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-59.png b/sig/Hygon Arch/assets/TKM/tkm-59.png new file mode 100644 index 0000000000000000000000000000000000000000..ff87bf3d9bad7d4e09d43dca271b1b5ca39e6503 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-59.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-6.png b/sig/Hygon Arch/assets/TKM/tkm-6.png new file mode 100644 index 0000000000000000000000000000000000000000..e02f721dcce2d7e8b85708f2f7011e3f66794066 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-6.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-60.png b/sig/Hygon Arch/assets/TKM/tkm-60.png new file mode 100644 index 0000000000000000000000000000000000000000..3ef00f800f60bea3f2e3a74f9730379eb00b41e4 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-60.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-61.png b/sig/Hygon Arch/assets/TKM/tkm-61.png new file mode 100644 index 0000000000000000000000000000000000000000..8cc930278d72fafbc89f74324354e23bb0feaa6f Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-61.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-62.png b/sig/Hygon Arch/assets/TKM/tkm-62.png new file mode 100644 index 0000000000000000000000000000000000000000..df098cd05ad11485a113d933aff47731012dc47e Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-62.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-63.png b/sig/Hygon Arch/assets/TKM/tkm-63.png new file mode 100644 index 0000000000000000000000000000000000000000..703389443ab97390e1f4f0518e95477ffb1f3b61 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-63.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-64.png b/sig/Hygon Arch/assets/TKM/tkm-64.png new file mode 100644 index 0000000000000000000000000000000000000000..c31a2d36253288229201abd115d81f0fd0e0fe30 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-64.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-65.png b/sig/Hygon Arch/assets/TKM/tkm-65.png new file mode 100644 index 0000000000000000000000000000000000000000..13c6211b83028f26305cac47db32a0b69cc0dfb3 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-65.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-66.png b/sig/Hygon Arch/assets/TKM/tkm-66.png new file mode 100644 index 0000000000000000000000000000000000000000..4e12ae559926debdee405b22e4b19da729dcbe9e Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-66.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-67.png b/sig/Hygon Arch/assets/TKM/tkm-67.png new file mode 100644 index 0000000000000000000000000000000000000000..da0b8b9b59adf25a726fe03b6cb3cb56c6e3421b Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-67.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-68.png b/sig/Hygon Arch/assets/TKM/tkm-68.png new file mode 100644 index 0000000000000000000000000000000000000000..7f0b47842dd3dd731c29a08c4a11542c30c37ca4 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-68.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-69.png b/sig/Hygon Arch/assets/TKM/tkm-69.png new file mode 100644 index 0000000000000000000000000000000000000000..4a38df177a86b984d93c99a66d5ff4bf568e8547 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-69.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-7.png b/sig/Hygon Arch/assets/TKM/tkm-7.png new file mode 100644 index 0000000000000000000000000000000000000000..eee82fca32ec82617fcec323fc9727ae6f2ad101 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-7.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-8.png b/sig/Hygon Arch/assets/TKM/tkm-8.png new file mode 100644 index 0000000000000000000000000000000000000000..86e2eb54d1cf57243774ae66f482934207b77d3a Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-8.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm-9.png b/sig/Hygon Arch/assets/TKM/tkm-9.png new file mode 100644 index 0000000000000000000000000000000000000000..01c8ae2e584e1f2d067242b7f1ee42f9a2998d09 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm-9.png differ diff --git a/sig/Hygon Arch/assets/TKM/tkm_get_key_usage.png b/sig/Hygon Arch/assets/TKM/tkm_get_key_usage.png new file mode 100644 index 0000000000000000000000000000000000000000..5727027d3d1601b03f900038a48beed29d71abf2 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/tkm_get_key_usage.png differ diff --git a/sig/Hygon Arch/assets/TKM/vTKM-1.png b/sig/Hygon Arch/assets/TKM/vTKM-1.png new file mode 100644 index 0000000000000000000000000000000000000000..111c87580241684995150772768f33a10ffbf86f Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/vTKM-1.png differ diff --git a/sig/Hygon Arch/assets/TKM/vTKM-2.png b/sig/Hygon Arch/assets/TKM/vTKM-2.png new file mode 100644 index 0000000000000000000000000000000000000000..e8edeccb74385da8e787344d456e9f1abac3fb4d Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/vTKM-2.png differ diff --git a/sig/Hygon Arch/assets/TKM/vTKM_CSV_launch.png b/sig/Hygon Arch/assets/TKM/vTKM_CSV_launch.png new file mode 100644 index 0000000000000000000000000000000000000000..350fb2aac0ce00f1446a68016a99e70770bab245 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/vTKM_CSV_launch.png differ diff --git a/sig/Hygon Arch/assets/TKM/vTKM_all_key_usage.png b/sig/Hygon Arch/assets/TKM/vTKM_all_key_usage.png new file mode 100644 index 0000000000000000000000000000000000000000..b00902558411c89f328ece349a6c552d977c0321 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/vTKM_all_key_usage.png differ diff --git a/sig/Hygon Arch/assets/TKM/vTKM_dev_info.png b/sig/Hygon Arch/assets/TKM/vTKM_dev_info.png new file mode 100644 index 0000000000000000000000000000000000000000..a866c6e58cd60bce5ff0574b825624240e773822 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/vTKM_dev_info.png differ diff --git a/sig/Hygon Arch/assets/TKM/vTKM_exclusive_vid_create.png b/sig/Hygon Arch/assets/TKM/vTKM_exclusive_vid_create.png new file mode 100644 index 0000000000000000000000000000000000000000..db567ee444a4cc675d7c9c0e62bb72f456c344e9 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/vTKM_exclusive_vid_create.png differ diff --git a/sig/Hygon Arch/assets/TKM/vTKM_get_vid_key_usage.png b/sig/Hygon Arch/assets/TKM/vTKM_get_vid_key_usage.png new file mode 100644 index 0000000000000000000000000000000000000000..0a01e8c78b8f5097ef8bc7b4c78f67a4d86fb6af Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/vTKM_get_vid_key_usage.png differ diff --git a/sig/Hygon Arch/assets/TKM/vTKM_mem2.png b/sig/Hygon Arch/assets/TKM/vTKM_mem2.png new file mode 100644 index 0000000000000000000000000000000000000000..881ddc04636409f0a57e624533a4bd7f29402aa0 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/vTKM_mem2.png differ diff --git a/sig/Hygon Arch/assets/TKM/vTKM_mem2_cmdline.png b/sig/Hygon Arch/assets/TKM/vTKM_mem2_cmdline.png new file mode 100644 index 0000000000000000000000000000000000000000..0a931031266d6301a8e1a66134ab8437e722d4d5 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/vTKM_mem2_cmdline.png differ diff --git a/sig/Hygon Arch/assets/TKM/vTKM_vid_destroy.png b/sig/Hygon Arch/assets/TKM/vTKM_vid_destroy.png new file mode 100644 index 0000000000000000000000000000000000000000..1dd000cc31114a3d25d16e513fe9c7f887966980 Binary files /dev/null and b/sig/Hygon Arch/assets/TKM/vTKM_vid_destroy.png differ diff --git a/sig/Hygon Arch/assets/VPP-IPSec/dual_machine_topology.png b/sig/Hygon Arch/assets/VPP-IPSec/dual_machine_topology.png new file mode 100644 index 0000000000000000000000000000000000000000..36af6fd7eda94deaa039e7a45d77c3ef32719082 Binary files /dev/null and b/sig/Hygon Arch/assets/VPP-IPSec/dual_machine_topology.png differ diff --git a/sig/Hygon Arch/assets/VPP-IPSec/single_machine_topology.png b/sig/Hygon Arch/assets/VPP-IPSec/single_machine_topology.png new file mode 100644 index 0000000000000000000000000000000000000000..75a554c64933607d62b48a5ac5cb99b53c4f2562 Binary files /dev/null and b/sig/Hygon Arch/assets/VPP-IPSec/single_machine_topology.png differ diff --git a/sig/Hygon Arch/assets/VPP-IPSec/worker_bound_to_nic.png b/sig/Hygon Arch/assets/VPP-IPSec/worker_bound_to_nic.png new file mode 100644 index 0000000000000000000000000000000000000000..811208fe709f360025e259c54c041cbb68105e52 Binary files /dev/null and b/sig/Hygon Arch/assets/VPP-IPSec/worker_bound_to_nic.png differ diff --git a/sig/Hygon Arch/assets/attestation_1.png b/sig/Hygon Arch/assets/attestation_1.png new file mode 100644 index 0000000000000000000000000000000000000000..dd3adebcfdd2dee4b295b8188a8cdf133210d975 Binary files /dev/null and b/sig/Hygon Arch/assets/attestation_1.png differ diff --git a/sig/Hygon Arch/assets/attestation_2.png b/sig/Hygon Arch/assets/attestation_2.png new file mode 100644 index 0000000000000000000000000000000000000000..a2e4261d0075bbc094a932c1c3f7efb48945f4af Binary files /dev/null and b/sig/Hygon Arch/assets/attestation_2.png differ diff --git a/sig/Hygon Arch/assets/bootloader_info1.jpg b/sig/Hygon Arch/assets/bootloader_info1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..69d9e9f4cd9119f5a704f831436b6015ef29daf6 Binary files /dev/null and b/sig/Hygon Arch/assets/bootloader_info1.jpg differ diff --git a/sig/Hygon Arch/assets/bootloader_info2.jpg b/sig/Hygon Arch/assets/bootloader_info2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7f33129d89b32cfaa904d5788eb998e8a148d85e Binary files /dev/null and b/sig/Hygon Arch/assets/bootloader_info2.jpg differ diff --git a/sig/Hygon Arch/assets/bootloader_info_4.jpg b/sig/Hygon Arch/assets/bootloader_info_4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..daadf169448e5200ae4b21d4c7ed77bfdffd6afa Binary files /dev/null and b/sig/Hygon Arch/assets/bootloader_info_4.jpg differ diff --git a/sig/Hygon Arch/assets/cpu_arch-1.png b/sig/Hygon Arch/assets/cpu_arch-1.png new file mode 100644 index 0000000000000000000000000000000000000000..8e98c4ec47e7e22bfdaf3356b0934d95cce2932b Binary files /dev/null and b/sig/Hygon Arch/assets/cpu_arch-1.png differ diff --git a/sig/Hygon Arch/assets/csv10-1.png b/sig/Hygon Arch/assets/csv10-1.png new file mode 100644 index 0000000000000000000000000000000000000000..20c5a20c67439f132c7fedba8b9ea1105094d312 Binary files /dev/null and b/sig/Hygon Arch/assets/csv10-1.png differ diff --git a/sig/Hygon Arch/assets/csv10-2.png b/sig/Hygon Arch/assets/csv10-2.png new file mode 100644 index 0000000000000000000000000000000000000000..ddfe857ff49d520122a3301ed69a3333fc723d47 Binary files /dev/null and b/sig/Hygon Arch/assets/csv10-2.png differ diff --git a/sig/Hygon Arch/assets/csv10-3.png b/sig/Hygon Arch/assets/csv10-3.png new file mode 100644 index 0000000000000000000000000000000000000000..20c5a20c67439f132c7fedba8b9ea1105094d312 Binary files /dev/null and b/sig/Hygon Arch/assets/csv10-3.png differ diff --git a/sig/Hygon Arch/assets/csv10-4.png b/sig/Hygon Arch/assets/csv10-4.png new file mode 100644 index 0000000000000000000000000000000000000000..8ee5fd7f9c33d6a0c77ad2c1c301be5ae3be9f13 Binary files /dev/null and b/sig/Hygon Arch/assets/csv10-4.png differ diff --git a/sig/Hygon Arch/assets/csv2-1.png b/sig/Hygon Arch/assets/csv2-1.png new file mode 100644 index 0000000000000000000000000000000000000000..8bea91954721abe61b766b7904c8c87d49fd81d2 Binary files /dev/null and b/sig/Hygon Arch/assets/csv2-1.png differ diff --git a/sig/Hygon Arch/assets/csv3-1.png b/sig/Hygon Arch/assets/csv3-1.png new file mode 100644 index 0000000000000000000000000000000000000000..c37dcc687a039f7de618674e9969ec986a2f807a Binary files /dev/null and b/sig/Hygon Arch/assets/csv3-1.png differ diff --git a/sig/Hygon Arch/assets/csv3-2.png b/sig/Hygon Arch/assets/csv3-2.png new file mode 100644 index 0000000000000000000000000000000000000000..5297e223d18e08dc26fe740e1112d14035d134b6 Binary files /dev/null and b/sig/Hygon Arch/assets/csv3-2.png differ diff --git a/sig/Hygon Arch/assets/csv3-6-1.png b/sig/Hygon Arch/assets/csv3-6-1.png new file mode 100644 index 0000000000000000000000000000000000000000..98b078f590bb3cbde795f549c842ac1a16cefe82 Binary files /dev/null and b/sig/Hygon Arch/assets/csv3-6-1.png differ diff --git a/sig/Hygon Arch/assets/csv3-6-2.png b/sig/Hygon Arch/assets/csv3-6-2.png new file mode 100644 index 0000000000000000000000000000000000000000..fd02909bc26834df14eda3346f4ce555e5cb1e74 Binary files /dev/null and b/sig/Hygon Arch/assets/csv3-6-2.png differ diff --git a/sig/Hygon Arch/assets/csv3-6-3.png b/sig/Hygon Arch/assets/csv3-6-3.png new file mode 100644 index 0000000000000000000000000000000000000000..9f9f66a1c95b2fc6098f78d9f736607463a7e9ce Binary files /dev/null and b/sig/Hygon Arch/assets/csv3-6-3.png differ diff --git a/sig/Hygon Arch/assets/csv3-arch2.png b/sig/Hygon Arch/assets/csv3-arch2.png new file mode 100644 index 0000000000000000000000000000000000000000..33f942d6088849af8c69a8c769b304a48a8a8dd5 Binary files /dev/null and b/sig/Hygon Arch/assets/csv3-arch2.png differ diff --git a/sig/Hygon Arch/assets/csv3-test-memory-1.png b/sig/Hygon Arch/assets/csv3-test-memory-1.png new file mode 100644 index 0000000000000000000000000000000000000000..3480a2e4337626544022e3664cd2010a9e5d1ed3 Binary files /dev/null and b/sig/Hygon Arch/assets/csv3-test-memory-1.png differ diff --git a/sig/Hygon Arch/assets/csv3-test-memory-2.png b/sig/Hygon Arch/assets/csv3-test-memory-2.png new file mode 100644 index 0000000000000000000000000000000000000000..d6aafab3168c2b87ffc89b4a9a0c9059772e189a Binary files /dev/null and b/sig/Hygon Arch/assets/csv3-test-memory-2.png differ diff --git a/sig/Hygon Arch/assets/csv3-test-memory-3.png b/sig/Hygon Arch/assets/csv3-test-memory-3.png new file mode 100644 index 0000000000000000000000000000000000000000..8a8dacf3c2c3d472c52ed4406fcc9a0f86b4528c Binary files /dev/null and b/sig/Hygon Arch/assets/csv3-test-memory-3.png differ diff --git a/sig/Hygon Arch/assets/csv3-test-memory-4.png b/sig/Hygon Arch/assets/csv3-test-memory-4.png new file mode 100644 index 0000000000000000000000000000000000000000..02cb48fdd26c04c0a0840c2da936ba802c14365f Binary files /dev/null and b/sig/Hygon Arch/assets/csv3-test-memory-4.png differ diff --git a/sig/Hygon Arch/assets/csv6-1.png b/sig/Hygon Arch/assets/csv6-1.png new file mode 100644 index 0000000000000000000000000000000000000000..f38a3bcc1f2e002f62c06f44e7a66353f3ee752a Binary files /dev/null and b/sig/Hygon Arch/assets/csv6-1.png differ diff --git a/sig/Hygon Arch/assets/csv8-1.png b/sig/Hygon Arch/assets/csv8-1.png new file mode 100644 index 0000000000000000000000000000000000000000..3677f4a52784a4e7d2b4cdaca6167910c89375b0 Binary files /dev/null and b/sig/Hygon Arch/assets/csv8-1.png differ diff --git a/sig/Hygon Arch/assets/dcu_attestation_arch.png b/sig/Hygon Arch/assets/dcu_attestation_arch.png new file mode 100644 index 0000000000000000000000000000000000000000..b6d057982433adaa2745e5fe184416435d3db6ac Binary files /dev/null and b/sig/Hygon Arch/assets/dcu_attestation_arch.png differ diff --git a/sig/Hygon Arch/assets/dcu_attestation_chip.png b/sig/Hygon Arch/assets/dcu_attestation_chip.png new file mode 100644 index 0000000000000000000000000000000000000000..efe5d1debe0d0c6bd9676e8dc3d72959c49a4e0e Binary files /dev/null and b/sig/Hygon Arch/assets/dcu_attestation_chip.png differ diff --git a/sig/Hygon Arch/assets/disk_encryption1.png b/sig/Hygon Arch/assets/disk_encryption1.png new file mode 100644 index 0000000000000000000000000000000000000000..73479358eaf6c992b76c56598be27738440a3d47 Binary files /dev/null and b/sig/Hygon Arch/assets/disk_encryption1.png differ diff --git a/sig/Hygon Arch/assets/disk_encryption2.png b/sig/Hygon Arch/assets/disk_encryption2.png new file mode 100644 index 0000000000000000000000000000000000000000..52e868ebeb3cb770b5163e8e34124cfb44af3fcd Binary files /dev/null and b/sig/Hygon Arch/assets/disk_encryption2.png differ diff --git a/sig/Hygon Arch/assets/disk_encryption3.png b/sig/Hygon Arch/assets/disk_encryption3.png new file mode 100644 index 0000000000000000000000000000000000000000..524912dc4fa14f8562c72c6a69da1b5df1b5f84e Binary files /dev/null and b/sig/Hygon Arch/assets/disk_encryption3.png differ diff --git a/sig/Hygon Arch/assets/enable-iommu.png b/sig/Hygon Arch/assets/enable-iommu.png new file mode 100644 index 0000000000000000000000000000000000000000..8d20e82731d26f4285dcf5ca8619bcac0e7bbdeb Binary files /dev/null and b/sig/Hygon Arch/assets/enable-iommu.png differ diff --git a/sig/Hygon Arch/assets/enable-iommu_4.png b/sig/Hygon Arch/assets/enable-iommu_4.png new file mode 100644 index 0000000000000000000000000000000000000000..8b04481892c6a230445bc26d304eaed90f4f0f66 Binary files /dev/null and b/sig/Hygon Arch/assets/enable-iommu_4.png differ diff --git a/sig/Hygon Arch/assets/enable-smee.png b/sig/Hygon Arch/assets/enable-smee.png new file mode 100644 index 0000000000000000000000000000000000000000..75e1830be9e0a63be5d4c22a4351aac8a61b9081 Binary files /dev/null and b/sig/Hygon Arch/assets/enable-smee.png differ diff --git a/sig/Hygon Arch/assets/enable-smee_4.png b/sig/Hygon Arch/assets/enable-smee_4.png new file mode 100644 index 0000000000000000000000000000000000000000..3d813ba788fa0fd68c6850745576bc7a09b418aa Binary files /dev/null and b/sig/Hygon Arch/assets/enable-smee_4.png differ diff --git a/sig/Hygon Arch/assets/firmware_download.png b/sig/Hygon Arch/assets/firmware_download.png new file mode 100644 index 0000000000000000000000000000000000000000..57939e2e496f61bfae43060304fc463d1417a63e Binary files /dev/null and b/sig/Hygon Arch/assets/firmware_download.png differ diff --git a/sig/Hygon Arch/assets/general_check_fw_version.png b/sig/Hygon Arch/assets/general_check_fw_version.png new file mode 100644 index 0000000000000000000000000000000000000000..7953419433e4936c6d55c3e5c8526fe5976d0df3 Binary files /dev/null and b/sig/Hygon Arch/assets/general_check_fw_version.png differ diff --git a/sig/Hygon Arch/assets/hgsc_download1.png b/sig/Hygon Arch/assets/hgsc_download1.png new file mode 100644 index 0000000000000000000000000000000000000000..634837a9ddefa88f6bda4c27ceee08644871720c Binary files /dev/null and b/sig/Hygon Arch/assets/hgsc_download1.png differ diff --git a/sig/Hygon Arch/assets/hgsc_download2.png b/sig/Hygon Arch/assets/hgsc_download2.png new file mode 100644 index 0000000000000000000000000000000000000000..12de5234f9d4706d310743e1378dc7f07c522154 Binary files /dev/null and b/sig/Hygon Arch/assets/hgsc_download2.png differ diff --git a/sig/Hygon Arch/assets/hgsc_import.png b/sig/Hygon Arch/assets/hgsc_import.png new file mode 100644 index 0000000000000000000000000000000000000000..d5e9b1bfe9863927884290fc0c0eb927a35b879e Binary files /dev/null and b/sig/Hygon Arch/assets/hgsc_import.png differ diff --git a/sig/Hygon Arch/assets/hgsc_version2.png b/sig/Hygon Arch/assets/hgsc_version2.png new file mode 100644 index 0000000000000000000000000000000000000000..4541ff830cd2317829bb231c813ede91736e0e90 Binary files /dev/null and b/sig/Hygon Arch/assets/hgsc_version2.png differ diff --git a/sig/Hygon Arch/assets/img2-1.png b/sig/Hygon Arch/assets/img2-1.png new file mode 100644 index 0000000000000000000000000000000000000000..438644db9da67e2b6b19df957ead3ee3011056c7 Binary files /dev/null and b/sig/Hygon Arch/assets/img2-1.png differ diff --git a/sig/Hygon Arch/assets/img2-2.png b/sig/Hygon Arch/assets/img2-2.png new file mode 100644 index 0000000000000000000000000000000000000000..cee35bf1d91ee5c121fe3a24d48a2d13f2624304 Binary files /dev/null and b/sig/Hygon Arch/assets/img2-2.png differ diff --git a/sig/Hygon Arch/assets/img2-3.png b/sig/Hygon Arch/assets/img2-3.png new file mode 100644 index 0000000000000000000000000000000000000000..d5329634335157fc28080ef689d1168d6b4918f6 Binary files /dev/null and b/sig/Hygon Arch/assets/img2-3.png differ diff --git a/sig/Hygon Arch/assets/img2-4.png b/sig/Hygon Arch/assets/img2-4.png new file mode 100644 index 0000000000000000000000000000000000000000..7c22e5d52866633aaa7bad1c1515e9aebbd04d43 Binary files /dev/null and b/sig/Hygon Arch/assets/img2-4.png differ diff --git a/sig/Hygon Arch/assets/img2-5.png b/sig/Hygon Arch/assets/img2-5.png new file mode 100644 index 0000000000000000000000000000000000000000..59009035fc58676e19cc11d8e2eed081adb8bf6e Binary files /dev/null and b/sig/Hygon Arch/assets/img2-5.png differ diff --git a/sig/Hygon Arch/assets/img2-6.png b/sig/Hygon Arch/assets/img2-6.png new file mode 100644 index 0000000000000000000000000000000000000000..80a48ad2c2405572b860c6ca10828f716b9737ed Binary files /dev/null and b/sig/Hygon Arch/assets/img2-6.png differ diff --git a/sig/Hygon Arch/assets/sealing-key.png b/sig/Hygon Arch/assets/sealing-key.png new file mode 100644 index 0000000000000000000000000000000000000000..8d8df726655c4c27a451f0871546f9d5d11b673e Binary files /dev/null and b/sig/Hygon Arch/assets/sealing-key.png differ diff --git a/sig/Hygon Arch/assets/tc_whitebook-1.png b/sig/Hygon Arch/assets/tc_whitebook-1.png new file mode 100644 index 0000000000000000000000000000000000000000..8e98c4ec47e7e22bfdaf3356b0934d95cce2932b Binary files /dev/null and b/sig/Hygon Arch/assets/tc_whitebook-1.png differ diff --git a/sig/Hygon Arch/assets/tc_whitebook-10.png b/sig/Hygon Arch/assets/tc_whitebook-10.png new file mode 100644 index 0000000000000000000000000000000000000000..edb88d3e74f2fac776be42fcef2d3aef3afc2202 Binary files /dev/null and b/sig/Hygon Arch/assets/tc_whitebook-10.png differ diff --git a/sig/Hygon Arch/assets/tc_whitebook-2.png b/sig/Hygon Arch/assets/tc_whitebook-2.png new file mode 100644 index 0000000000000000000000000000000000000000..1cb2313c204dbfa21801f5529a5082e393ba7855 Binary files /dev/null and b/sig/Hygon Arch/assets/tc_whitebook-2.png differ diff --git a/sig/Hygon Arch/assets/tc_whitebook-3.png b/sig/Hygon Arch/assets/tc_whitebook-3.png new file mode 100644 index 0000000000000000000000000000000000000000..82adadc6fa1dc67022db67300fa04e927a34203a Binary files /dev/null and b/sig/Hygon Arch/assets/tc_whitebook-3.png differ diff --git a/sig/Hygon Arch/assets/tc_whitebook-4.png b/sig/Hygon Arch/assets/tc_whitebook-4.png new file mode 100644 index 0000000000000000000000000000000000000000..79872133f3854f12fbd700ccea69935250372f9d Binary files /dev/null and b/sig/Hygon Arch/assets/tc_whitebook-4.png differ diff --git a/sig/Hygon Arch/assets/tc_whitebook-5.png b/sig/Hygon Arch/assets/tc_whitebook-5.png new file mode 100644 index 0000000000000000000000000000000000000000..93f6439cb3d7fcc8e6d2cd2a2cb7f0e6ed9e1e43 Binary files /dev/null and b/sig/Hygon Arch/assets/tc_whitebook-5.png differ diff --git a/sig/Hygon Arch/assets/tc_whitebook-6.png b/sig/Hygon Arch/assets/tc_whitebook-6.png new file mode 100644 index 0000000000000000000000000000000000000000..051220e1c36db658786577af176d24215fac19b3 Binary files /dev/null and b/sig/Hygon Arch/assets/tc_whitebook-6.png differ diff --git a/sig/Hygon Arch/assets/tc_whitebook-7.png b/sig/Hygon Arch/assets/tc_whitebook-7.png new file mode 100644 index 0000000000000000000000000000000000000000..ccf3ae58b65258d58ed44e7a1eb9affb0397509c Binary files /dev/null and b/sig/Hygon Arch/assets/tc_whitebook-7.png differ diff --git a/sig/Hygon Arch/assets/tc_whitebook-8.png b/sig/Hygon Arch/assets/tc_whitebook-8.png new file mode 100644 index 0000000000000000000000000000000000000000..20bf2d888ac86ddeb4ecaef0521e74d352fc6dfa Binary files /dev/null and b/sig/Hygon Arch/assets/tc_whitebook-8.png differ diff --git a/sig/Hygon Arch/assets/tc_whitebook-9.png b/sig/Hygon Arch/assets/tc_whitebook-9.png new file mode 100644 index 0000000000000000000000000000000000000000..d0249afebb686c6feafcf38e12e22693d3a8c55a Binary files /dev/null and b/sig/Hygon Arch/assets/tc_whitebook-9.png differ diff --git a/sig/Hygon Arch/assets/tdm-1.png b/sig/Hygon Arch/assets/tdm-1.png new file mode 100644 index 0000000000000000000000000000000000000000..0ec834b20cbe699138247d53de8de836ce93c938 Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-1.png differ diff --git a/sig/Hygon Arch/assets/tdm-10.png b/sig/Hygon Arch/assets/tdm-10.png new file mode 100644 index 0000000000000000000000000000000000000000..50c97a648785e069858d27d541051256109b682d Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-10.png differ diff --git a/sig/Hygon Arch/assets/tdm-11.png b/sig/Hygon Arch/assets/tdm-11.png new file mode 100644 index 0000000000000000000000000000000000000000..80111a59a36c8cd7456f244468008ae972ac72e9 Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-11.png differ diff --git a/sig/Hygon Arch/assets/tdm-12.png b/sig/Hygon Arch/assets/tdm-12.png new file mode 100644 index 0000000000000000000000000000000000000000..ae7538e1056197acd177a7a6e1e2399365405a6c Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-12.png differ diff --git a/sig/Hygon Arch/assets/tdm-13-1.png b/sig/Hygon Arch/assets/tdm-13-1.png new file mode 100644 index 0000000000000000000000000000000000000000..92306fead1607504862637a9746a7fe1075c6c3c Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-13-1.png differ diff --git a/sig/Hygon Arch/assets/tdm-13.png b/sig/Hygon Arch/assets/tdm-13.png new file mode 100644 index 0000000000000000000000000000000000000000..ed2700eab2500886ee26825e36ce220d498d6869 Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-13.png differ diff --git a/sig/Hygon Arch/assets/tdm-14.png b/sig/Hygon Arch/assets/tdm-14.png new file mode 100644 index 0000000000000000000000000000000000000000..8c81008f544583a52874aa785d76ae7982786683 Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-14.png differ diff --git a/sig/Hygon Arch/assets/tdm-15.png b/sig/Hygon Arch/assets/tdm-15.png new file mode 100644 index 0000000000000000000000000000000000000000..508ed0a34309d261e186004051d40c4b31220b36 Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-15.png differ diff --git a/sig/Hygon Arch/assets/tdm-16.png b/sig/Hygon Arch/assets/tdm-16.png new file mode 100644 index 0000000000000000000000000000000000000000..128809187d295d49c0987e3521319cf219950315 Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-16.png differ diff --git a/sig/Hygon Arch/assets/tdm-17.png b/sig/Hygon Arch/assets/tdm-17.png new file mode 100644 index 0000000000000000000000000000000000000000..75a2514e56a4b2dce7a4b2395be381187383c8c1 Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-17.png differ diff --git a/sig/Hygon Arch/assets/tdm-18.png b/sig/Hygon Arch/assets/tdm-18.png new file mode 100644 index 0000000000000000000000000000000000000000..b26a79e07d34f7348a914cb998abacf9a752f484 Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-18.png differ diff --git a/sig/Hygon Arch/assets/tdm-19.png b/sig/Hygon Arch/assets/tdm-19.png new file mode 100644 index 0000000000000000000000000000000000000000..8b9134df0407c97299f78afc2f78941f8a4c0cc8 Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-19.png differ diff --git a/sig/Hygon Arch/assets/tdm-2.png b/sig/Hygon Arch/assets/tdm-2.png new file mode 100644 index 0000000000000000000000000000000000000000..93ab725592d5e027ffc6b2d4d8cffdd8e3c51ff5 Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-2.png differ diff --git a/sig/Hygon Arch/assets/tdm-20.png b/sig/Hygon Arch/assets/tdm-20.png new file mode 100644 index 0000000000000000000000000000000000000000..e69f7825879fbdd6fb62ae27811be26db60c8afd Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-20.png differ diff --git a/sig/Hygon Arch/assets/tdm-21.png b/sig/Hygon Arch/assets/tdm-21.png new file mode 100644 index 0000000000000000000000000000000000000000..2ac70d08be49d7977ecf93aa5462688c7def60c8 Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-21.png differ diff --git a/sig/Hygon Arch/assets/tdm-22.png b/sig/Hygon Arch/assets/tdm-22.png new file mode 100644 index 0000000000000000000000000000000000000000..f0683632dce4cc8b473e79efb87a6341eb332013 Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-22.png differ diff --git a/sig/Hygon Arch/assets/tdm-23.png b/sig/Hygon Arch/assets/tdm-23.png new file mode 100644 index 0000000000000000000000000000000000000000..d297aaf0e36c5a709b4d2daa318d90fedacdce99 Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-23.png differ diff --git a/sig/Hygon Arch/assets/tdm-24.png b/sig/Hygon Arch/assets/tdm-24.png new file mode 100644 index 0000000000000000000000000000000000000000..f6664dbbe2fb810cf1a09947bf7efca9cfe5e14f Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-24.png differ diff --git a/sig/Hygon Arch/assets/tdm-25.png b/sig/Hygon Arch/assets/tdm-25.png new file mode 100644 index 0000000000000000000000000000000000000000..ad3f2222a72fd8f6d5cf66bdd68cbe2db3c4dbca Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-25.png differ diff --git a/sig/Hygon Arch/assets/tdm-26.png b/sig/Hygon Arch/assets/tdm-26.png new file mode 100644 index 0000000000000000000000000000000000000000..347927b28090ac4b7efe33971f28952fe820e64d Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-26.png differ diff --git a/sig/Hygon Arch/assets/tdm-27.png b/sig/Hygon Arch/assets/tdm-27.png new file mode 100644 index 0000000000000000000000000000000000000000..31927189848a4731c4033b4f37db7a1b3e467c76 Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-27.png differ diff --git a/sig/Hygon Arch/assets/tdm-28.png b/sig/Hygon Arch/assets/tdm-28.png new file mode 100644 index 0000000000000000000000000000000000000000..135cf11d7c7bb3daa117fcc677f0e3179d071662 Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-28.png differ diff --git a/sig/Hygon Arch/assets/tdm-29.png b/sig/Hygon Arch/assets/tdm-29.png new file mode 100644 index 0000000000000000000000000000000000000000..4039c8ce2884ee7465fbe19cfed75338529116bf Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-29.png differ diff --git a/sig/Hygon Arch/assets/tdm-3.png b/sig/Hygon Arch/assets/tdm-3.png new file mode 100644 index 0000000000000000000000000000000000000000..19fd1beab6802df7238e13c7edc616589f318e17 Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-3.png differ diff --git a/sig/Hygon Arch/assets/tdm-4.png b/sig/Hygon Arch/assets/tdm-4.png new file mode 100644 index 0000000000000000000000000000000000000000..02d9f2ddb248b31b9ba07d9dffb783a5b62aa13c Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-4.png differ diff --git a/sig/Hygon Arch/assets/tdm-5.png b/sig/Hygon Arch/assets/tdm-5.png new file mode 100644 index 0000000000000000000000000000000000000000..fff7d627c23e2d46cb1d6fcbf46e5e874efab838 Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-5.png differ diff --git a/sig/Hygon Arch/assets/tdm-6.png b/sig/Hygon Arch/assets/tdm-6.png new file mode 100644 index 0000000000000000000000000000000000000000..a9c237cabbeace571dbe971c74602a45e95e60a8 Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-6.png differ diff --git a/sig/Hygon Arch/assets/tdm-7.png b/sig/Hygon Arch/assets/tdm-7.png new file mode 100644 index 0000000000000000000000000000000000000000..9ceb07cba30a5c23e4ffbfc1ffe9ae271ff45468 Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-7.png differ diff --git a/sig/Hygon Arch/assets/tdm-8.png b/sig/Hygon Arch/assets/tdm-8.png new file mode 100644 index 0000000000000000000000000000000000000000..67bc3699260c2983e208dff647c290d767437721 Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-8.png differ diff --git a/sig/Hygon Arch/assets/tdm-9.png b/sig/Hygon Arch/assets/tdm-9.png new file mode 100644 index 0000000000000000000000000000000000000000..ac258367800e53ef9269cac04381be8840c808ab Binary files /dev/null and b/sig/Hygon Arch/assets/tdm-9.png differ diff --git a/sig/Hygon Arch/assets/tkm_arch-1.png b/sig/Hygon Arch/assets/tkm_arch-1.png new file mode 100644 index 0000000000000000000000000000000000000000..1fad60f0b75fb769515cd3f4eeabb542ad67f664 Binary files /dev/null and b/sig/Hygon Arch/assets/tkm_arch-1.png differ diff --git a/sig/Hygon Arch/assets/tkm_scene-1.png b/sig/Hygon Arch/assets/tkm_scene-1.png new file mode 100644 index 0000000000000000000000000000000000000000..b4d9758b934a4e0cbb99f2f090985013fd2fbdfc Binary files /dev/null and b/sig/Hygon Arch/assets/tkm_scene-1.png differ diff --git a/sig/Hygon Arch/assets/tpcm-1.png b/sig/Hygon Arch/assets/tpcm-1.png new file mode 100644 index 0000000000000000000000000000000000000000..782f830c43082b1891e4aec621efe1f4331662df Binary files /dev/null and b/sig/Hygon Arch/assets/tpcm-1.png differ diff --git a/sig/Hygon Arch/assets/tpm2-1.png b/sig/Hygon Arch/assets/tpm2-1.png new file mode 100644 index 0000000000000000000000000000000000000000..d17bbbb093b317a37b1b67152aa8db487fc9dad5 Binary files /dev/null and b/sig/Hygon Arch/assets/tpm2-1.png differ diff --git a/sig/Hygon Arch/assets/tpm2-2.png b/sig/Hygon Arch/assets/tpm2-2.png new file mode 100644 index 0000000000000000000000000000000000000000..8789c18ef409ad7afc0d908a2e39e68fca465ca6 Binary files /dev/null and b/sig/Hygon Arch/assets/tpm2-2.png differ diff --git a/sig/Hygon Arch/assets/tpm2-3.png b/sig/Hygon Arch/assets/tpm2-3.png new file mode 100644 index 0000000000000000000000000000000000000000..e99a1f890742dc4915066c433d77a8d3fea97fc6 Binary files /dev/null and b/sig/Hygon Arch/assets/tpm2-3.png differ diff --git a/sig/Hygon Arch/assets/tpmtcm_image1.jpeg b/sig/Hygon Arch/assets/tpmtcm_image1.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..1f2381e1234c57577365b8b2992f26a85fbaa12e Binary files /dev/null and b/sig/Hygon Arch/assets/tpmtcm_image1.jpeg differ diff --git a/sig/Hygon Arch/assets/tpmtcm_image10.png b/sig/Hygon Arch/assets/tpmtcm_image10.png new file mode 100644 index 0000000000000000000000000000000000000000..7a2618e2b16d8c85a938996768532a4932fbe17d Binary files /dev/null and b/sig/Hygon Arch/assets/tpmtcm_image10.png differ diff --git a/sig/Hygon Arch/assets/tpmtcm_image11.png b/sig/Hygon Arch/assets/tpmtcm_image11.png new file mode 100644 index 0000000000000000000000000000000000000000..33cab70d465a1ee261c7fb4a5db9e01101e3d24b Binary files /dev/null and b/sig/Hygon Arch/assets/tpmtcm_image11.png differ diff --git a/sig/Hygon Arch/assets/tpmtcm_image12.png b/sig/Hygon Arch/assets/tpmtcm_image12.png new file mode 100644 index 0000000000000000000000000000000000000000..ddaf726d3184f9c186ac8eb3b9e60de01d7a0e46 Binary files /dev/null and b/sig/Hygon Arch/assets/tpmtcm_image12.png differ diff --git a/sig/Hygon Arch/assets/tpmtcm_image13.jpeg b/sig/Hygon Arch/assets/tpmtcm_image13.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..23e1d4c39c74e8a01627e39657af13cb2d26271b Binary files /dev/null and b/sig/Hygon Arch/assets/tpmtcm_image13.jpeg differ diff --git a/sig/Hygon Arch/assets/tpmtcm_image14.png b/sig/Hygon Arch/assets/tpmtcm_image14.png new file mode 100644 index 0000000000000000000000000000000000000000..1b83db3b3fe69357f9e57d77be264fdf91d7c1e0 Binary files /dev/null and b/sig/Hygon Arch/assets/tpmtcm_image14.png differ diff --git a/sig/Hygon Arch/assets/tpmtcm_image15.png b/sig/Hygon Arch/assets/tpmtcm_image15.png new file mode 100644 index 0000000000000000000000000000000000000000..4ecb010e8cba70b1ea63d1c36eb18ddd93c16adc Binary files /dev/null and b/sig/Hygon Arch/assets/tpmtcm_image15.png differ diff --git a/sig/Hygon Arch/assets/tpmtcm_image16.png b/sig/Hygon Arch/assets/tpmtcm_image16.png new file mode 100644 index 0000000000000000000000000000000000000000..597f07dd4b8374b4a9abb9e63b105f5f93585b58 Binary files /dev/null and b/sig/Hygon Arch/assets/tpmtcm_image16.png differ diff --git a/sig/Hygon Arch/assets/tpmtcm_image17.png b/sig/Hygon Arch/assets/tpmtcm_image17.png new file mode 100644 index 0000000000000000000000000000000000000000..40f08be9354f9183e5b11a64b5c3395eeecd58e3 Binary files /dev/null and b/sig/Hygon Arch/assets/tpmtcm_image17.png differ diff --git a/sig/Hygon Arch/assets/tpmtcm_image18.png b/sig/Hygon Arch/assets/tpmtcm_image18.png new file mode 100644 index 0000000000000000000000000000000000000000..9ef678e4be88910220c1cab43724ca4ebc9bc729 Binary files /dev/null and b/sig/Hygon Arch/assets/tpmtcm_image18.png differ diff --git a/sig/Hygon Arch/assets/tpmtcm_image19.jpeg b/sig/Hygon Arch/assets/tpmtcm_image19.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..961cb75d3c944df02daafe073946204791aa5d1f Binary files /dev/null and b/sig/Hygon Arch/assets/tpmtcm_image19.jpeg differ diff --git a/sig/Hygon Arch/assets/tpmtcm_image2.png b/sig/Hygon Arch/assets/tpmtcm_image2.png new file mode 100644 index 0000000000000000000000000000000000000000..a492bf6e4be37270810023c4ca9ec8e03a91da9a Binary files /dev/null and b/sig/Hygon Arch/assets/tpmtcm_image2.png differ diff --git a/sig/Hygon Arch/assets/tpmtcm_image20.png b/sig/Hygon Arch/assets/tpmtcm_image20.png new file mode 100644 index 0000000000000000000000000000000000000000..57acd6be8d8a7704ab181d238be12d6957f6be58 Binary files /dev/null and b/sig/Hygon Arch/assets/tpmtcm_image20.png differ diff --git a/sig/Hygon Arch/assets/tpmtcm_image21.png b/sig/Hygon Arch/assets/tpmtcm_image21.png new file mode 100644 index 0000000000000000000000000000000000000000..fb34a43c5c2f4c77d8068a7b44033fef9c4a3559 Binary files /dev/null and b/sig/Hygon Arch/assets/tpmtcm_image21.png differ diff --git a/sig/Hygon Arch/assets/tpmtcm_image3.png b/sig/Hygon Arch/assets/tpmtcm_image3.png new file mode 100644 index 0000000000000000000000000000000000000000..460f26cc8dccce596691c01a9535d0e72b2d79b3 Binary files /dev/null and b/sig/Hygon Arch/assets/tpmtcm_image3.png differ diff --git a/sig/Hygon Arch/assets/tpmtcm_image4.png b/sig/Hygon Arch/assets/tpmtcm_image4.png new file mode 100644 index 0000000000000000000000000000000000000000..0d9a5765d32505b46c4829663b15167cf9f3a1bf Binary files /dev/null and b/sig/Hygon Arch/assets/tpmtcm_image4.png differ diff --git a/sig/Hygon Arch/assets/tpmtcm_image5.png b/sig/Hygon Arch/assets/tpmtcm_image5.png new file mode 100644 index 0000000000000000000000000000000000000000..4e29ad9b3a5ebca6cba0ba12e66060ae3d1ce4f7 Binary files /dev/null and b/sig/Hygon Arch/assets/tpmtcm_image5.png differ diff --git a/sig/Hygon Arch/assets/tpmtcm_image6.png b/sig/Hygon Arch/assets/tpmtcm_image6.png new file mode 100644 index 0000000000000000000000000000000000000000..f6ceec2830283976c36a9f6ac037e32aa83343fd Binary files /dev/null and b/sig/Hygon Arch/assets/tpmtcm_image6.png differ diff --git a/sig/Hygon Arch/assets/tpmtcm_image7.png b/sig/Hygon Arch/assets/tpmtcm_image7.png new file mode 100644 index 0000000000000000000000000000000000000000..9f34bd7a203d91a00bcee77330dfcafd3658ce4f Binary files /dev/null and b/sig/Hygon Arch/assets/tpmtcm_image7.png differ diff --git a/sig/Hygon Arch/assets/tpmtcm_image8.png b/sig/Hygon Arch/assets/tpmtcm_image8.png new file mode 100644 index 0000000000000000000000000000000000000000..b9521c887a9e3edbb4e46f6cddbfb0ff1e16c407 Binary files /dev/null and b/sig/Hygon Arch/assets/tpmtcm_image8.png differ diff --git a/sig/Hygon Arch/assets/tpmtcm_image9.jpeg b/sig/Hygon Arch/assets/tpmtcm_image9.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..8f0f77892063f1e1ce534114009de6dba391698d Binary files /dev/null and b/sig/Hygon Arch/assets/tpmtcm_image9.jpeg differ diff --git a/sig/Hygon Arch/assets/vncviewer.png b/sig/Hygon Arch/assets/vncviewer.png new file mode 100644 index 0000000000000000000000000000000000000000..a6a6f71ce20d6ffd363a7fcb067e7180acee31f3 Binary files /dev/null and b/sig/Hygon Arch/assets/vncviewer.png differ diff --git a/sig/Hygon Arch/assets/wx-sig.jpg b/sig/Hygon Arch/assets/wx-sig.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7432cf4afc200575798cdcf2602e7358cb1b514f Binary files /dev/null and b/sig/Hygon Arch/assets/wx-sig.jpg differ diff --git "a/sig/Hygon Arch/content/0-\346\265\267\345\205\211\350\265\204\350\256\257/1-\346\265\267\345\205\211\345\256\211\345\205\250\350\265\204\350\256\257.md" "b/sig/Hygon Arch/content/0-\346\265\267\345\205\211\350\265\204\350\256\257/1-\346\265\267\345\205\211\345\256\211\345\205\250\350\265\204\350\256\257.md" new file mode 100644 index 0000000000000000000000000000000000000000..d7acbb51873ebdabffa66fda2ec4c12f3a2d65f8 --- /dev/null +++ "b/sig/Hygon Arch/content/0-\346\265\267\345\205\211\350\265\204\350\256\257/1-\346\265\267\345\205\211\345\256\211\345\205\250\350\265\204\350\256\257.md" @@ -0,0 +1,66 @@ +## 综合资讯 + +- [海光亮相龙蜥安全会议,打破芯片加密“不可能三角”](https://www.toutiao.com/article/7412563357133193728/) +- [海光信息亮相外滩大会,构筑云计算数据安全底座](https://www.toutiao.com/article/7413933810120753673/) +- [每日一芯 | 海光CPU处理器](https://mp.weixin.qq.com/s/EQ-Cf4WXWdB44C_IkW9xmw) +- [海光信息:把好国产处理器安全大关](http://www.semiinsights.com/s/microprocessor/26/48437.shtml) +- [开放合作“芯”生态:海光信息国产C86芯片亮相2024世界计算大会](http://hn.people.com.cn/n2/2024/0926/c356884-40990136.html) +- [海光信息:为国产处理器筑牢信息安全底线](https://www.eet-china.com/news/202409297546.html) +- [从指令集和微架构底层创新开始,构建国产CPU的国密级别硬件安全](https://www.toutiao.com/article/7423288947109610038/) +- [【深度观察】融合多项创新技术 海光处理器将安全进行到底](https://mp.weixin.qq.com/s/aOL3X5YWPGVyr9eGonLYwA) +- [海光:构筑国产处理器安全新高地](https://www.eefocus.com/article/1759461.html) +- [“第39次全国计算机安全学术交流会—网络综合治理分论坛”在西安顺利召开](https://mp.weixin.qq.com/s/4kHnm8C4cMQ_ZMDVG5-FxA) +- [发布两款产品!安恒信息亮相“第二届海光安全技术高峰论坛”](https://mp.weixin.qq.com/s/N4S6m8MLRJ2jdIbVJzSnTQ) +- [成本可控、产业可落地 数据流通迎来密态时代](https://baijiahao.baidu.com/s?id=1813758838188748430&wfr=spider&for=pc) +- [芯片安全,信创选型第一道难关!](https://mp.weixin.qq.com/s/VdQUPikcWZ-qO34_LY10jA) +- [国产计算安全再突破,海光C86颠覆式创新](https://mp.weixin.qq.com/s/nW62HqEn1GAQFfBGBWQ_yA) +- [海光信息推动芯片安全技术进阶 联手构筑全场景安全生态](https://finance.sina.com.cn/jjxw/2024-11-16/doc-incwfyah5329729.shtml) +- [芯片安全事件频发,这家国产芯片向漏洞Say No](https://mp.weixin.qq.com/s/NtgBfvQbI3BqZobwT7qT9g) +- [国产≠安全!CPU安全标准如何定义?](https://mp.weixin.qq.com/s/9QZiOtgfYUpJZKu5AKOxIA) +- [信创芯片选型难?安全性能全都要!](https://mp.weixin.qq.com/s/obFPYo5yX9KU2UoAE620jg) +- [从底层创新探索国产CPU的国密级别安全之路](https://mp.weixin.qq.com/s/fXWBnVQjDTQC2juOIaov_g) +- [2024信创:一文看懂国产芯片格局](https://mp.weixin.qq.com/s/Kfudv0qIaGP7-uD0B-W95Q) +- [医疗信创四大关,国产CPU怎么过?](https://mp.weixin.qq.com/s/-nuXVcxBMMGzGn6oGfa2HA) + +## 隐私计算 + +- [携手中科海光,龙蜥社区正式上线首个 CSV 机密容器解决方案](https://mp.weixin.qq.com/s/m_jrA0nWNszJ5u--0_SCrw) +- [海光公司与安恒信息联合发布安全岛隐私计算一体机](https://mp.weixin.qq.com/s/vnaooR8y1E-caRTOZVrbUA) +- [集智达携手海光,推出多款网安产品,为信息安全保驾护航](https://mp.weixin.qq.com/s/UVD2dDT9VX1rixQ5tKVKng) +- [绿盟科技与海光公司联合发布新产品:“数安湖”隐私计算平台](https://mp.weixin.qq.com/s/fu1lNdK2_jIqa1B4-v6WLw) +- [星河案例ㅣ中国电信 X 冲量在线:基于智算中心的隐私计算应用实践](https://mp.weixin.qq.com/s/WAvMKlrzn1GpB_0qdQVtFg) +- [冲量在线亮相警博会,携手海光打造最前沿警务数据安全共享流通平台,护航新时代!](https://mp.weixin.qq.com/s/ZAb7fh3NQiiHCMhyEzgKkw) +- [富数科技Avatar可信隐私计算一体机亮相第二届海光安全技术高峰论坛](https://mp.weixin.qq.com/s/3X5FH4KCO__5a0T4sXkdRA) +- [带你读《云原生机密计算最佳实践白皮书》——海光CSV:海光安全虚拟化技术](https://developer.aliyun.com/article/1231608) +- [海光CSV:海光安全虚拟化技术](https://mp.weixin.qq.com/s/OvbDwbo1gzLyOx6Lm0qnYg) +- [获奖方案|冲量在线打通隐私计算“最后一公里”](https://mp.weixin.qq.com/s/7Y-RsBQybQQ2Gh5Yajc-Dg) +- [技术解读:CSV 机密计算技术栈和解决方案 | 龙蜥技术](https://mp.weixin.qq.com/s/2zNtcBAVtUnovl_DJxwsWQ) +- [数据由裸奔到穿衣,再到钢铁护甲过程中,安全加密架构到底哪个是钢铁护甲?](https://mp.weixin.qq.com/s/V4csTZY06xV4CP84vlHiOw) +- [官宣丨基于海光TEE的数据安全解决方案正式发布(附详细方案)](https://mp.weixin.qq.com/s/2QIBCTuA9N-wy0pfGp7eXg) +- [前沿 | 机密计算在金融数据安全存储中的应用探索](https://mp.weixin.qq.com/s/50SduP7-DyAK03mByuayFA) +- [墙裂推荐!云上机密计算,阿里云上体验了一下海光内存加密和远程认证](https://blog.csdn.net/s445320/article/details/141403121) +- [墙裂推荐!云上机密计算,试试海光CSV虚拟机](https://www.toutiao.com/article/7405521921015595574) +- [综述 | (冯登国院士团队)基于动态完整性度量的机密计算运行时监控方案](https://mp.weixin.qq.com/s/swZYCUzRWsaC9A2GSo5AFQ) +- [【携手向前】冲量在线受邀参与由海光信息主导围绕计算安全的国产C86技术成果与应用闭门研讨会](https://mp.weixin.qq.com/s/YfSDm7svHtldLijwuE6AfQ) + +## 可信计算 + +- [通俗理解什么是:“可信计算”及其实现原理](https://mp.weixin.qq.com/s/Ni02_l2qvJld80EltlZsBw) +- [行业动态 | 从“安全可靠”迈向“安全可信”](https://mp.weixin.qq.com/s/uXCUfrKNposWAJzfPxgiyw) +- [信息安全的基石,要靠国产处理器解决](https://www.toutiao.com/article/7413652455877018139) + +## 密码技术 + +- [【商密动态】新一代商用密码产品和密码服务](https://mp.weixin.qq.com/s/JJAYa2M5RRiAgZzPXWVTmw) +- [超融合国产加密技术适配验证与用户实践](https://mp.weixin.qq.com/s/wCer-OkvMWoBLBOa3y-O7A) +- [全栈超融合,开始卷其他赛道了](https://mp.weixin.qq.com/s/Vvj0d2YDSZ57qMUgoqTTGQ) +- [海光CPU,为国产硬件筑起安全屏障](https://mp.weixin.qq.com/s/5XoRKOfM-GI06o-kHWdvQw) +- [高速密码处理器,为什么海光的CPU更有优势?](https://www.eeworld.com.cn/qrs/eic679812.html) +- [海光在通用CPU上内置安全功能模块,可更好替代外置加密卡](https://www.cena.com.cn/semi/20240924/124799.html) +- [海光CPU:五大密码技术优势傍身 安芯守护信息安全](https://mp.weixin.qq.com/s/MXWUKDIXxnBMgegElGlZQQ) +- [用“芯”筑安全,协“密”更高效 | 格尔软件积极探索国产计算安全实践路径](https://mp.weixin.qq.com/s/fge53daKmyICHRw_1LShDw) +- [信创趋势下的商密变革,国产CPU内生安全最关键!](https://mp.weixin.qq.com/s/Vo162PQvB87IGnpI1gfS3w) + +## 漏洞防御 + +- [国外芯片漏洞频发 国产CPU替代加速](https://finance.sina.com.cn/roll/2024-11-17/doc-incwincs1407818.shtml) diff --git "a/sig/Hygon Arch/content/1-\345\256\211\345\205\250\345\212\237\350\203\275\347\216\257\345\242\203\351\205\215\347\275\256/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/Hygon Arch/content/1-\345\256\211\345\205\250\345\212\237\350\203\275\347\216\257\345\242\203\351\205\215\347\275\256/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..647bf4f420405ab3dc9928e6b2077689c08f9739 --- /dev/null +++ "b/sig/Hygon Arch/content/1-\345\256\211\345\205\250\345\212\237\350\203\275\347\216\257\345\242\203\351\205\215\347\275\256/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,145 @@ +# 安全功能配置要求 + +## 硬件配置要求 + +安全功能包括CSV、TPM2.0、TCM2.0、TPCM、TDM、TKM、HCT等,这些功能依赖CPU硬件、BIOS。 +- 表1是各种CPU型号所属的CPU代际信息。 +- 表2是各代际CPU使用安全功能的硬件配置版本要求。 +- 表3是各代际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.6`,以`PI4.2.x`为前缀的PI版本要求>=`PI4.2.0.10`。 | + +表 3 机密计算硬件能力细分说明 + +| CPU | CSV支持情况 | +| --- | --- | +|

海光2号

| CSV1,支持15个不同虚拟机加密密钥1 | +|

海光C86-3G

| CSV1,支持15个不同虚拟机加密密钥1,2
CSV2,支持15个不同虚拟机加密密钥1,2 | +|

海光C86-4G

| CSV1,支持500个不同虚拟机加密密钥3
CSV2,支持500个不同虚拟机加密密钥3
CSV3,支持500个不同虚拟机加密密钥3,4 | +- 1. 海光支持ASID复用扩展启动的CSV1/2虚拟机个数 +- 2. CSV1/2共用15个密钥 +- 3. CSV1/2/3共用500个密钥 +- 4. 海光C86-4G的54xx、74xx支持CSV3,34xx不支持CSV1/2/3 + +## Bootloader 版本查看 +海光2号配置 +``` +Setup Utility -> Advanced -> PSP Firmware Versions +``` +如下图: + +![bootloader_info1](../../assets/bootloader_info1.jpg) + +![bootloader_info2](../../assets/bootloader_info2.jpg) + +海光C86-4G配置 +``` +Chipset -> PSP Firmware Versions +``` +如下图: + +![bootloader_info1](../../assets/bootloader_info_4.jpg) +## 国产OS安全功能支持情况 + +> 您可根据表格中OS的版本,支持的CPU型号,及支持的安全功能;选择您需要的OS。推荐使用版本更高的OS,其支持的安全功能更为完善。 +> +> 备注: 表格中,如果TPM2-TOOLS版本低于5.5(不包含5.5),则TCM有两个命令不支持:ecc encrypt/decrypt + +表 4 国产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 +``` +效果如下图: + +![enable-smee](../../assets/enable-smee.png) + +海光C86-4G配置 +``` +Advanced -> HYGON CBS -> Core Common Options +``` +效果如下图: + +![enable-smee](../../assets/enable-smee_4.png) +### 2. DCU直通功能 + +要使用DCU直通功能,必须进入BIOS设置,通过以下路径打开IOMMU功能。 + +#### CPU BIOS配置参考 +海光2号配置 +``` +HYGON CBS -> NBIO Common Options -> NB Configuration -> IOMMU +``` +``` +Setup Utility -> Advanced -> HYGON CBS -> NBIO Common Options +``` + +效果如下图: + +![enable-iommu](../../assets/enable-iommu.png) + +海光C86-4G配置 +``` +Advanced -> HYGON CBS -> NBIO Common Options +``` +效果如下图: + +![enable-iommu](../../assets/enable-iommu_4.png) + +sssaa diff --git "a/sig/Hygon Arch/content/1-\345\256\211\345\205\250\345\212\237\350\203\275\347\216\257\345\242\203\351\205\215\347\275\256/1-\345\256\211\350\243\205\346\223\215\344\275\234\347\263\273\347\273\237\345\222\214\345\206\205\346\240\270.md" "b/sig/Hygon Arch/content/1-\345\256\211\345\205\250\345\212\237\350\203\275\347\216\257\345\242\203\351\205\215\347\275\256/1-\345\256\211\350\243\205\346\223\215\344\275\234\347\263\273\347\273\237\345\222\214\345\206\205\346\240\270.md" new file mode 100644 index 0000000000000000000000000000000000000000..b43b034ffcb00dc2e60837be8509eba3b4f7cea1 --- /dev/null +++ "b/sig/Hygon Arch/content/1-\345\256\211\345\205\250\345\212\237\350\203\275\347\216\257\345\242\203\351\205\215\347\275\256/1-\345\256\211\350\243\205\346\223\215\344\275\234\347\263\273\347\273\237\345\222\214\345\206\205\346\240\270.md" @@ -0,0 +1,34 @@ +测试过程中需要下载源代码和软件,请确保网络连接稳定。 + +## 安装开源操作系统 +从下面的镜像中任选一个,下载并完成安装。 + +1. http://mirrors.openanolis.org/anolis/8.4/isos/GA/x86_64/AnolisOS-8.4-x86_64-dvd.iso (**该系统安装时内核可以选择,在Kernel Selection 选项中选择4.19版本的内核安装**) + +2. https://releases.ubuntu.com/20.04/ubuntu-20.04.6-live-server-amd64.iso + +3. 麒麟server V10 SP3 2403,向麒麟确认获取 + +**注:不同版本可能存在差异,可以根据实际情况调整。** +## 下载测试代码仓库 + +如果仓库较大clone困难,可以加参数 --depth 1 进行精简clone 。 +**如果客户将仓库作为zip压缩包下载下来,要将zip包传输到目标机器上再解压,不要解压后再传到目标机器,容易出现文件丢失。** + +``` +$ sudo chmod a+w /opt +$ cd /opt/ +$ git clone https://gitee.com/anolis/hygon-devkit.git +$ mv hygon-devkit hygon +$ sudo cp /opt/hygon/bin/hag /usr/bin +``` + +## 更新内核 + +``` +$ git clone https://gitee.com/anolis/hygon-cloud-kernel.git +$ cd hygon-cloud-kernel/ +$ sudo /opt/hygon/build_kernel.sh +``` + +更新完成后重启,选择新安装的内核进入系统,**麒麟系统不会安装主机内核,使用系统自带内核,但仍然需要重启使配置生效**。 diff --git "a/sig/Hygon Arch/content/1-\345\256\211\345\205\250\345\212\237\350\203\275\347\216\257\345\242\203\351\205\215\347\275\256/2-\345\257\274\345\205\245\351\200\232\347\224\250\345\256\211\345\205\250\350\257\201\344\271\246.md" "b/sig/Hygon Arch/content/1-\345\256\211\345\205\250\345\212\237\350\203\275\347\216\257\345\242\203\351\205\215\347\275\256/2-\345\257\274\345\205\245\351\200\232\347\224\250\345\256\211\345\205\250\350\257\201\344\271\246.md" new file mode 100644 index 0000000000000000000000000000000000000000..2e0e63e5832226bcbba70aae2076f0d3b63dd9b3 --- /dev/null +++ "b/sig/Hygon Arch/content/1-\345\256\211\345\205\250\345\212\237\350\203\275\347\216\257\345\242\203\351\205\215\347\275\256/2-\345\257\274\345\205\245\351\200\232\347\224\250\345\256\211\345\205\250\350\257\201\344\271\246.md" @@ -0,0 +1,152 @@ + +通用安全证书导入后,会写入安全flash,不重新烧录bios的情况下,无需重新导入。以下操作都无需重新导入证书:重启机器、升级安全固件。 + +## 安装依赖 +说明: 从https网站下载文件,需要依赖ssl证书,可以使用以下方法安装: + +Ubuntu: +``` +$ sudo apt-get install -y ca-certificates +``` +Centos: +``` +$ sudo yum install -y ca-certificates +``` + +### 下载hag + +``` +# 如果已经根据 1-安装操作系统和内核部分安装了hygon-devkit,可以在以下目录找到hag +$ ls -l /opt/hygon/bin/hag +# 如果没有安装hygon-devkit,可以使用以下命令下载 +$ mkdir -p /opt/hygon/bin/ +$ cd /opt/hygon/bin/ +$ wget https://gitee.com/anolis/hygon-devkit/raw/master/bin/hag +$ chmod +x hag +``` + +## 导入通用安全证书 + +> 说明:通用安全证书支持在线导入和离线导入两种方式。 +> +> 注意:要在C86-4G上使用`TKM`功能的客户,请参见`导入升级版通用安全证书` + +### 在线导入 + +``` +$ cd /opt/hygon/bin/ +$ sudo ./hag general hgsc_import +``` +图 1 在线导入通用安全证书 + +![](../../assets/img2-1.png) + +### 离线导入 + +(1) 获取芯片的chip ID和证书版本号 +``` +$ cd /opt/hygon/bin +$ sudo ./hag general get_id +$ sudo ./hag general hgsc_version +``` +图 2 获取芯片chip ID + +![](../../assets/img2-2.png) + +图 3 获取证书版本号 + +![](../../assets/img2-3.png) + +(2) 网站下载证书 +说明:在可以连接互联网的机器上,访问 https://cert.hygon.cn/hgsc, 如下图所示,输入您的服务器的Chip ID、证书版本号,以及您的公司信息。 + +注意:授权码请不要填写 + +图 4 网站下载证书 + +![](../../assets/hgsc_download1.png) + +(3) 导入证书 + +``` +$ cd /opt/hygon/bin +$ sudo ./hag general hgsc_import -offline -in /realpath/to/hgsc_certchain +``` + +说明:将下载的证书拷贝到对应的服务器,证书名称类似为hygon-hgsc-certchain-v1.0-NZA9T02082605.bin。如下图,使用hag离线导入该证书。 + +图 5 离线导入证书 + +![](../../assets/img2-5.png) + +## 导入升级版通用安全证书 + +### 获取`授权码` + +在C86-4G上使用TKM功能,需要导入升级版通用安全证书,该证书需要使用授权码下载和导入,请联系securitytech@hygon.cn获取授权码,邮件中需提供以下信息。 + +``` +1.您的公司名称 +2.您的公司邮箱地址 +3.您购买的CPU型号 +4.您购买的CPU数量 +``` + +获取授权码后,即可使用`在线导入`或`离线导入`方式导入证书。 + +### 在线导入 + +``` +$ cd /opt/hygon/bin/ +# -authcode后面跟获取到的授权码 +$ sudo ./hag general hgsc_import -authcode xxxxx-xxxxx-xxxxx +``` + +图 6 在线导入升级版通用安全证书 + +![](../../assets/hgsc_import.png) + +### 离线导入 + +(1) 获取芯片的chip ID和证书版本号 + +``` +$ cd /opt/hygon/bin +$ sudo ./hag general get_id +$ sudo ./hag general hgsc_version +``` + +图 7 获取芯片chip ID和证书版本号 + +![](../../assets/hgsc_version2.png) + +(2) 网站下载证书 +说明:在可以连接互联网的机器上,访问 https://cert.hygon.cn/hgsc, 如下图所示,输入您的服务器的Chip ID、证书版本号,您的公司信息,以及获取的授权码。 + +图 4 网站下载证书 + +![](../../assets/hgsc_download2.png) + +(3) 导入证书 + +``` +$ cd /opt/hygon/bin +$ sudo ./hag general hgsc_import -offline -in /realpath/to/hgsc_certchain +``` + +说明:将下载的证书拷贝到对应的服务器,证书名称类似为hygon-hgsc-certchain-v2.0-KPA64911201107.bin。如下图,使用hag离线导入该证书。 + +图 5 离线导入证书 + +![](../../assets/img2-5.png) + +## 确认证书导入成功 + +``` +$ cd /opt/hygon/bin +$ sudo ./hag csv platform_status +``` + +图 6 确认证书导入成功 + +![](../../assets/img2-6.png) \ No newline at end of file diff --git "a/sig/Hygon Arch/content/1-\345\256\211\345\205\250\345\212\237\350\203\275\347\216\257\345\242\203\351\205\215\347\275\256/3-\346\243\200\346\237\245\350\275\257\347\241\254\344\273\266\347\211\210\346\234\254.md" "b/sig/Hygon Arch/content/1-\345\256\211\345\205\250\345\212\237\350\203\275\347\216\257\345\242\203\351\205\215\347\275\256/3-\346\243\200\346\237\245\350\275\257\347\241\254\344\273\266\347\211\210\346\234\254.md" new file mode 100644 index 0000000000000000000000000000000000000000..9412e3a28f916187de7e0c093546f3727bcc59c8 --- /dev/null +++ "b/sig/Hygon Arch/content/1-\345\256\211\345\205\250\345\212\237\350\203\275\347\216\257\345\242\203\351\205\215\347\275\256/3-\346\243\200\346\237\245\350\275\257\347\241\254\344\273\266\347\211\210\346\234\254.md" @@ -0,0 +1,35 @@ +## 查看CPU型号 + +``` +$ lscpu |grep "Model name" +Model name: Hygon C86 7280 32-core Processor +``` +第2位数字代表CPU型号,7280表示是2号CPU,类似地7180代表1号CPU,7380代表3号CPU。 + +## 查看hag版本 + +``` +$ cd /opt/hygon/bin +$ ./hag general version +Version: 1820 (release) +``` + +## 查看固件版本 + +``` +$ cd /opt/hygon/bin +$ sudo ./hag csv platform_status +api_major: 1 +api_minor: 3 +platform_state: CSV_STATE_INIT +owner: PLATFORM_STATE_SELF_OWN +chip_secure: SECURE +fw_enc: ENCRYPTED +fw_sign: SIGNED +CSV: CSV CSV2 CSV3 +build id: 1805 +guest_count: 0 +is HGSC imported: YES +supported csv guest:11 +platform_status command successful +``` \ No newline at end of file diff --git "a/sig/Hygon Arch/content/1-\345\256\211\345\205\250\345\212\237\350\203\275\347\216\257\345\242\203\351\205\215\347\275\256/9-FAQ/1-BIOS.md" "b/sig/Hygon Arch/content/1-\345\256\211\345\205\250\345\212\237\350\203\275\347\216\257\345\242\203\351\205\215\347\275\256/9-FAQ/1-BIOS.md" new file mode 100644 index 0000000000000000000000000000000000000000..aba460267b2d34ff2b063927f16803653194ce90 --- /dev/null +++ "b/sig/Hygon Arch/content/1-\345\256\211\345\205\250\345\212\237\350\203\275\347\216\257\345\242\203\351\205\215\347\275\256/9-FAQ/1-BIOS.md" @@ -0,0 +1,6 @@ +# BIOS FAQ + +#### Q: 文档中提到bios必须支持CSV、fTPM2.0、fTCM2.0、TPCM,如何查看我的机器的BIOS是否已支持 + +A: 使用`sudo ./hag general check`检查是否已支持;如果不支持把这个要求发送给`OEM`厂商 + diff --git "a/sig/Hygon Arch/content/1-\345\256\211\345\205\250\345\212\237\350\203\275\347\216\257\345\242\203\351\205\215\347\275\256/9-FAQ/2-Linux_Kernel.md" "b/sig/Hygon Arch/content/1-\345\256\211\345\205\250\345\212\237\350\203\275\347\216\257\345\242\203\351\205\215\347\275\256/9-FAQ/2-Linux_Kernel.md" new file mode 100644 index 0000000000000000000000000000000000000000..70de3ea8fcaa3d6bf96b2867a96fafac13f10171 --- /dev/null +++ "b/sig/Hygon Arch/content/1-\345\256\211\345\205\250\345\212\237\350\203\275\347\216\257\345\242\203\351\205\215\347\275\256/9-FAQ/2-Linux_Kernel.md" @@ -0,0 +1,8 @@ +# Linux Kernel FAQ + +#### Q: C86-4G上,ccp模块卸载时提示:`rmmod: ERROR: Module ccp is in use` + +A: C86-4G平台上,需要把ccp设置为DMA_PRIVATE,才能让ccp的引用计数变得正常,有以下两种方式: + +1. `echo 'options ccp dma_chan_attr=1' | tee -a /etc/modprobe.d/ccp.conf` , 然后重启设备,之后ccp模块都可以被正常卸载 +2. 手动insmod时,也需要添加参数:`insmod ccp.ko dma_chan_attr=1` \ No newline at end of file diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/1-\345\256\211\350\243\205CSV\350\275\257\344\273\266.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/1-\345\256\211\350\243\205CSV\350\275\257\344\273\266.md" new file mode 100644 index 0000000000000000000000000000000000000000..935b902d35afe031da91c1a77032ad6ff7f6c543 --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/1-\345\256\211\350\243\205CSV\350\275\257\344\273\266.md" @@ -0,0 +1,68 @@ + +安装CSV软件之前,请先准备系统环境并导入通用安全证书。 + +请参考[1-1-安装操作系统和内核](https://openanolis.cn/sig/Hygon-Arch/doc/865622272844371792)准备系统环境。 + +请参考[1-2-导入通用安全证书](https://openanolis.cn/sig/Hygon-Arch/doc/865622274698254162)导入通用安全证书。 + +## 安装依赖软件 + +``` +$ sudo /opt/hygon/csv/install_csv_sw.sh +``` + +## 安装qemu +**麒麟系统不需要该步骤,使用系统自带即可,kata 测试不需要该步骤*** +``` +$ git clone https://gitee.com/anolis/hygon-qemu.git +$ cd hygon-qemu/ +$ sudo /opt/hygon/csv/build_qemu.sh +``` + + +## 安装grub +**麒麟系统不需要该步骤,使用系统自带即可,kata 测试不需要该步骤*** +``` +$ wget https://ftp.gnu.org/gnu/grub/grub-2.06.tar.gz +$ tar -xvf grub-2.06.tar.gz +$ cd grub-2.06/ +$ sudo /opt/hygon/csv/build_grub.sh +``` + +## 安装edk2 +**麒麟系统不需要该步骤,使用系统自带即可,kata 测试不需要该步骤** + +**编译依赖安装grub章节** +``` +$ git clone https://gitee.com/anolis/hygon-edk2.git +$ cd hygon-edk2/ +$ git submodule update --init +$ sudo /opt/hygon/csv/build_edk2.sh +``` + +## 安装devkit + +``` +$ cd /opt/hygon/csv/ +$ sudo ./make_vm_img.sh +$ git clone -b master https://github.com/guanzhi/GmSSL.git +$ sudo ./build_devkit.sh +``` +## 安装虚拟机内核 + +**kata 测试不需要该步骤** + +### 运行虚拟机 +``` +$ sudo qemu-system-x86_64 -name csv-vm --enable-kvm -cpu host -m 6114 -hda /opt/hygon/csv/vm.qcow2 -drive if=pflash,format=raw,unit=0,file=/opt/hygon/csv/OVMF_CODE.fd,readonly=on -qmp tcp:127.0.0.1:2222,server,nowait -vnc 0.0.0.0:0 -object sev-guest,id=sev0,policy=0x1,cbitpos=47,reduced-phys-bits=5 -machine memory-encryption=sev0 -netdev bridge,br=virbr0,id=net0 -device virtio-net-pci,netdev=net0,romfile= -nographic +``` +### 安装虚拟机内核 +虚拟机内核使用主机编译好的内核,登录虚拟机,虚拟机账号为root,密码为root。 +``` +# dhclient +# scp host@hostip:/opt/hygon/kernel.tgz ./ +# scp host@hostip:/opt/hygon/csv/vm_kernel_install.sh ./ +# chmod +x vm_kernel_install.sh +# ./vm_kernel_install.sh +# poweroff +``` diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/10-\346\212\200\346\234\257\344\273\213\347\273\215/1-CSV3\345\212\240\345\257\206\350\231\232\346\213\237\346\234\272\346\236\266\346\236\204\346\246\202\350\246\201\344\273\213\347\273\215.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/10-\346\212\200\346\234\257\344\273\213\347\273\215/1-CSV3\345\212\240\345\257\206\350\231\232\346\213\237\346\234\272\346\236\266\346\236\204\346\246\202\350\246\201\344\273\213\347\273\215.md" new file mode 100644 index 0000000000000000000000000000000000000000..465207fb0b3b5636726ee5e0305a3c5dbb0636f2 --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/10-\346\212\200\346\234\257\344\273\213\347\273\215/1-CSV3\345\212\240\345\257\206\350\231\232\346\213\237\346\234\272\346\236\266\346\236\204\346\246\202\350\246\201\344\273\213\347\273\215.md" @@ -0,0 +1,48 @@ +测试之前,请参考[2-1-安装CSV软件](https://openanolis.cn/sig/Hygon-Arch/doc/865622260278236994?lang=zh)准备软件环境。 + +## CSV3加密虚拟机架构概要介绍 +海光第三代安全虚拟化技术(CSV3)在前二代技术的基础上继续增强,在CPU内部实现了虚拟机数据的安全隔离,禁止主机操作系统读写CSV3虚拟机内存,
+禁止主机操作系统读写虚拟机嵌套页表,保证了虚拟机数据的完整性,实现了CSV3虚拟机数据机密性和完整性的双重安全。 + + ![](../../../assets/csv3-arch2.png) + + +#### 安全内存隔离单元 +安全内存隔离单元是海光第三代安全虚拟化技术的专用硬件,是实现虚拟机数据完整性的硬件基础。
+该硬件集成于CPU内部,放置于CPU核心访问内存控制器的系统总线路径上。
+该硬件可获取CSV3虚拟机安全内存的信息,包括内存物理地址,虚拟机VMID,及相关的权限等。
+CPU在访问内存时,访问请求先经过安全内存隔离单元做合法性检查,若访问允许,继续访问内存,否则访问请求被拒绝。
+ +以CSV3架构图为例,在CSV3虚拟机运行过程中读取或写入内存时,先经过页表翻译单元完成虚拟机物理地址(GPA, Guest Physical Address)
+到主机物理地址(HPA, Host Physical Address)的转换,再向地址总线发出内存访问请求。
+访问请求中除了包含读写命令、内存地址(HPA),还必须同时发出访问者的VM ID。
+ +当CPU读取内存数据时,若安全内存隔离单元判断内存读取请求者的VMID错误,返回固定模式的数据。
+当CPU写入内存数据时,若安全内存隔离单元判断内存写入请求者的VMID错误,丢弃写入请求。 + +#### 安全处理器 +安全内存隔离单元是海光第三代安全虚拟化保护虚拟机内存完整性的核心硬件,
+对此硬件单元的配置必须保证绝对安全,无法被主机操作系统修改。
+ +海光安全处理器是SoC内独立于主CPU之外的处理器,是CPU的信任根。
+安全处理器在CPU上电后,通过内置验签密钥验证固件的完整性,并加载执行。
+安全处理器具有独立硬件资源和封闭的运行环境,是CPU内最高安全等级硬件,管理整CPU的安全。
+安全内存隔离单元的内容仅安全处理器有权限配置和管理,主机操作系统无权读写。
+ +在虚拟机启动时,主机操作系统向安全处理器发送请求,安全处理器对安全内存隔离单元做初始配置。
+虚拟机运行期间,安全处理器固件更新安全内存隔离单元。
+虚拟机退出后,安全处理器清除安全内存隔离单元的配置。
+安全处理器会检查主机发来的配置请求是否合法,主机向安全处理器发起的任何非法配置请求,都会被拒绝。
+ +虚拟机整生命周期内,安全内存隔离单元都在安全处理器的管理控制之下,保证了其配置的安全性。
+ +#### Virtual Machine Control Block(VMCB)保护 +Virtual Machine Control Block(VMCB)是虚拟机的控制信息块,保存了虚拟机ID(VMID),虚拟机页表基地址,虚拟机寄存器页面基地址等控制信息,
+主机操作系统通过修改虚拟机控制信息能够影响并更改虚拟机内存数据。 + +CSV3增加了对虚拟机控制信息的保护,安全处理器负责创建VMCB,并配置于安全内存隔离单元的硬件保护之下。
+主机操作系统无法更改CSV3虚拟机VMCB的内容。 + +为更好的与主机操作系统的软件配合,CSV3创建了真实VMCB与影子VMCB页面。主机操作系统创建影子VMCB,填入控制信息,传递给安全处理器。
+安全处理器创建真实VMCB页面,复制影子VMCB中除虚拟机ID,虚拟机页表基地址,虚拟机寄存器页面基地址等关键信息之外的控制信息,并自行添加关键控制信息。
+虚拟机使用真实VMCB页面启动和运行,阻止了主机操作系统对虚拟机VMCB的攻击。
diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/10-\346\212\200\346\234\257\344\273\213\347\273\215/2-CSV\350\277\234\347\250\213\350\256\244\350\257\201\346\212\200\346\234\257\344\273\213\347\273\215.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/10-\346\212\200\346\234\257\344\273\213\347\273\215/2-CSV\350\277\234\347\250\213\350\256\244\350\257\201\346\212\200\346\234\257\344\273\213\347\273\215.md" new file mode 100644 index 0000000000000000000000000000000000000000..2a238823568288556188f12569936d1d83f2f939 --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/10-\346\212\200\346\234\257\344\273\213\347\273\215/2-CSV\350\277\234\347\250\213\350\256\244\350\257\201\346\212\200\346\234\257\344\273\213\347\273\215.md" @@ -0,0 +1,105 @@ +测试之前,请参考[2-1-安装CSV软件](https://openanolis.cn/sig/Hygon-Arch/doc/865622260278236994?lang=zh)准备软件环境。 + +## 概要 +CSV 虚拟机具有远程认证功能,从CSV 虚拟机中获取报告,将报告发送到认证方进行认证,从而确保机密信息是运行在客户可信的平台上。 + +## 证书链 +为保证认证报告的真实性、完整性和不可否认性,认证报告中包含对报告中部分字段项的签名值。签名密钥为PEK私钥,PEK(Platform Endorsement Key) 是一组 SM2公私钥对,由CSV 固件使用硬件真随机数发生器产生。PEK证书可以被芯片密钥CEK 和硬件所有者密钥 OCA同时签名,以建立起可信证书链。 + +### 秘钥介绍 + +#### Platform Diffie-Hellman Key +Platform Diffie-Hellman key (PDH)是国密SM2公私钥对,用于CSV固件和虚拟机使用者之间进行密钥协商。CSV固件使用硬件真随机数发生器产生PDH,PDH私钥保存于CSV固件中,PDH公钥可从CSV固件中导出,供虚拟机使用者使用。 +虚拟机使用者随机生成主密钥(master secret),并使用PDH公钥对主密钥加密后传递给CSV固件,CSV固件使用PDH私钥解密得到主密钥,后续CSV固件可使用主密钥派生出其他密钥。 +PDH被PEK签名,如果PEK改变,必须生成新的PDH。PDH在平台的生命周期内不变。 +#### Platform Endorsement Key +Platform Endorsement Key(PEK)是国密SM2公私钥对,作为平台的身份标识签名PDH证书,同时PEK证书被CEK和OCA签名,这样建立起可信证书链保证PDH证书是合法的。 +CSV固件使用硬件真随机数发生器产生PEK。PEK在平台的生命周期内不变。 +#### Chip Endorsement Key +Chip Endorsement Key(CEK)是国密SM2公私钥对,作为芯片标识签名PEK证书。CEK由保存在芯片安全fuse中的数据派生,每颗芯片的CEK都不相同,在芯片的生命周期内不变。 +#### Hygon CSV Signing Key +Hygon CSV Signing Key(HSK) 是国密SM2公私钥对,签名CEK证书。HSK私钥保存在海光专用的HSK签名服务器上。 +#### Hygon Root Key +Hygon Root Key(HRK) 是国密SM2公私钥对,签名HSK证书。HRK私钥保存在海光专用的HRK签名服务器上。 +#### Owner Certificate Authority +Owner Certificate Authority(OCA) 是国密SM2公私钥对,是平台所有者的身份标识,签名PEK证书。平台所有者可以是CSV固件或者硬件所有者,如果CSV固件是平台所有者,OCA由CSV固件使用硬件真随机数发生器产生;否则平台所有者将OCA证书导入到CSV固件。 + +### 证书链构建流程 +CSV 固件初始化时,CSV固件是平台所有者,OCA由CSV固件使用硬件真随机数发生器产生,平台初始化时CEK 和OCA 私钥对PEK 进行签名,构建一套默认和客户无关的海光证书链,由海光确保证书链可信。 + +如果虚拟机使用者想使用自己的私钥对相关的证书链签名,可使用以下流程:
+![](../../../assets/attestation_2.png) + +1、生成OCA公私钥对,使用公私钥对构造OCA自签名证书。
+2、生成PEK证书的签名请求,签名请求中包含PEK 公钥以及其他平台相关信息。
+3、使用OCA私钥将签名请求签名生成PEK证书。
+4、将签名后的PEK和OCA 证书文件导入到固件平台。
+CSV 固件利用芯片密钥CEK对PEK证书进行再次签名。此时PEK证书中包含PEK公钥和2个签名(CEK私钥签名和OCA私钥签名),实现包含用户私钥签名的可信证书链建立。PEK证书在生成认证报告时被传入报告中。 + + + +## 远程认证报告生成校验 + + ![](../../../assets/attestation_1.png) +### 远程认证报告生成 +#### 虚拟机摘要值生成 +为了保证系统程序及其运行环境的完整性,虚拟机启动过程中,安全处理器需要对OVMF.fd、虚拟机内核文件和虚拟机内存文件(initrd)进行度量。
+1、将服务程序放入initrd文件中。
+2、对initrd文件、OVMF.fd和虚拟机内核镜像文件,利用SM3算法计算虚拟机文件摘要值。
+3、在虚拟机启动时提供虚拟机文件和摘要值,CPU中的安全处理器利用 SM3 算法计算虚拟机文件的摘要并进行完整性检验。
+4、完整性信息校验通过,虚拟机成功启动,在生成认证报告时将此摘要值作为虚拟机摘要值写入认证报告中。
+#### 生成认证报告 +认证报告生成包含如下步骤:
+1、固件将 CSV 虚拟机启动时传入的虚拟机的 ID、版本号信息填入认证报告。
+2、将DH公钥的摘要值以及 MNONCE 填入认证报告,公钥摘要值用来确定启动虚拟机的用户身份, MNONCE用来确保认证报告的唯一性。
+3、将虚拟机摘要值、虚拟机规则、签名密钥、签名算法、PEK证书等信息填入认证报告中。
+4、固件会生成随机数并填写到认证报告的ANONCE 字段,由 ANONCE 对认证报告的00h-BBh和150h-9B3h范围分别进行异或。
+5、利用PEK私钥对认证报告中异或后的部分字段签名并填写到SIG1字段。
+6、利用MNONCE对认证报告中异或后的部分字段计算HMAC并写入到 MAC字段。
+### 远程认证报告校验 +用户端在获取到认证报告后,随即对PEK证书链进行验证,验证通过后进行验签,并校验报告中的其他字段项。 +#### 证书链校验 +PEK证书中包含CEK签名和客户私钥签名两个签名值,CEK证书被HSK(Hygon CSV Signing Key)密钥签名,HSK证书被HRK(Hygon Root Key)密钥签名。用户端需分别对两个签名值的证书链进行校验。
+CEK签名证书链校验流程:
+1、根据认证报告中芯片ID的值,从海光证书服务器下载对应的CEK证书、HSK证书和HRK证书。
+2、使用 HRK 公钥验证 HSK 证书,使用 HSK公钥验证 CEK 证书,使用 CEK 公钥验证 PEK 证书。
+3、验签通过说明PEK证书是由合法的海光芯片中的密钥颁发的。
+同样地,用户端可以使用客户OCA证书中公钥对PEK验签,验证OCA证书链,从而证明该 PEK 证书是由客户可信证书链保证的。 +#### 报告内容校验 +用户在完成PEK证书证书链校验后,对获取到的认证报告内容进行校验,校验过程如下:
+1、获取认证报告中的ANONCE字段值,利用ANONCE字段值对报告的00h-BBh范围进行异或。
+2、利用PEK证书中的公钥完成对认证报告中SIG1值的验签。
+3、根据提前获取到的虚拟机信息、虚拟机摘要值、USERDATA、MNONCE等信息对报告中的相应字段完成校验。校验通过说明是在可信的CSV虚拟机中。 + + +### 报告格式 + +报告输入数据的格式,客户可以定制下面字段的内容 + +| 偏移 | 比特位 | 输入/输出 | 名称 | 描述 | +|----- |-------| ---------|---------|------| +|00h | 511:0| In | USERDATA| 用户自定义数据 | +|40h | 127:0| In | MNONCE | 一次性随机数 | +|50h | 255:0| In | HASH |SM3(USERDATA \|\| MNONCE)| + +报告输出数据的格式 + +| 偏移 | 比特位 | 输入/输出 | 名称 | 描述 | +|-----|--------|----------|---------------|--------------| +|00h |255:0 | Out | PUBKEY_DIGEST | DH公钥的SM3摘要值,用于确认启动虚拟机的用户身份。DH密钥由虚
拟机用户生成,用于对虚拟机启动参数进行签名。| +|20h |127:0 | Out | ID |虚拟机ID,虚拟机用户自定义。| +|30h |127:0 | Out |Version |虚拟机版本号,虚拟机用户自定义。| +|40h |511:0 | Out |USERDATA |用户自定义数据| +|80h |127:0 | Out |MNONCE |一次性随机数,用于区别报告内容防重放攻击,由虚拟机用户生成。| +|90h |255:0 | Out |DIGEST |虚拟机的启动摘要,虚拟机initrd文件、OVMF.fd和虚拟机内核
镜像文件的SM3摘要值。| +|B0h |31:0 | Out |POLICY |虚拟机规则| +|B4h |31:0 | Out |SIG_USAGE |签名密钥用途 PEK| +|B8h |31:0 | Out |SIG_ALGO |签名算法 SM2| +|BCh |31:0 | Out |ANONCE |固件产生的随机数,用于对报告进行混淆处理,防止主机攻击。| +|C0h |1151:0 | Out |SIG1 |PEK签名| +|150h |16671:0 | Out |PEK_CERT |平台的PEK证书| +|974h |511:0 | Out |CHIP_ID |芯片ID,字符串| +|9B4h |255:0 | Out |Reserved2 |保留字段| +|9D4h |255:0 | Out |MAC |MNONCE完整性保护PEK_CERT \|\| CHIP_ID \|\| Reserved2生成的HMAC| + + diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/10-\346\212\200\346\234\257\344\273\213\347\273\215/3-CSV\347\247\230\351\222\245\345\260\201\345\215\260\346\212\200\346\234\257\344\273\213\347\273\215.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/10-\346\212\200\346\234\257\344\273\213\347\273\215/3-CSV\347\247\230\351\222\245\345\260\201\345\215\260\346\212\200\346\234\257\344\273\213\347\273\215.md" new file mode 100644 index 0000000000000000000000000000000000000000..dcc2cff590dcc11fc911d8dab3f77e1652dd1ca6 --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/10-\346\212\200\346\234\257\344\273\213\347\273\215/3-CSV\347\247\230\351\222\245\345\260\201\345\215\260\346\212\200\346\234\257\344\273\213\347\273\215.md" @@ -0,0 +1,65 @@ +测试之前,请参考[2-1-安装CSV软件](https://openanolis.cn/sig/Hygon-Arch/doc/865622260278236994?lang=zh)准备软件环境。 + +## 概要 +CSV虚拟机可以从海光安全固件中获取由机器根密钥和虚拟机相关信息派生出的密钥。该key不需要存储,只能通过账号密码登录或访问虚拟机中服务等方式从虚拟机内部获取,没有泄漏风险,key绑定了虚拟机和主机的相关信息,可信唯一,该密钥可以被客户用于任何目的,例如加密磁盘中的敏感数据,通过派生出的密钥对磁盘中存储的数据进行加密,确保即使攻击者访问存储介质,也无法读取数据,虚拟机启动后从虚拟机中获取该key并用其对磁盘中的敏感数据进行解密。 + +## 原理介绍 +![](../../../assets/sealing-key.png) + +1、海光安全固件通过硬件派生出的root-key 、固件中csv-sealing-key 字符串、虚拟机| policy | user_pubkey_digest | user_vm_digest | vm_id | vm_version | 内容派生出sealing key,该key 只能从虚拟机内部获取,确保了key的可信,在相同的主机上使用相同的虚拟机参数和虚拟机相关文件启动虚拟机,虚拟机中的key保持不变,key绑定了虚拟机和主机的相关信息,确保了key的唯一性。 + +2、虚拟机通过相应的接口获取海光安全固件中产生的sealing key。 + +3、虚拟机中用户应用程序使用获取的sealing key 进行一定场景的业务应用。 + +### 派生sealing key组件描述 + +| 组件 | 描述 | +|----- |-------| +|root-key|海光安全固件通过硬件派生出的root-key,每台机器唯一且固定不变。| +|csv-sealing-key|海光安全固件提供的字符串,固定不变,作为派生秘钥的参数之一。| +|policy|csv虚拟机的启动策略,用户通过 hag csv generate_policy --nodebug 生成默认的配置,csv generate_policy --help 可以查看详细配置说明,qemu 启动虚拟机的policy 参数配置需要和hag 设置的一致。| +|user_pubkey_digest|DH公钥的SM3摘要值,用于确认启动虚拟机的用户身份。DH证书在使用hag csv generate_launch_blob -build $build_id -bios OVMF.fd -kernel vmlinuz -initrd initramfs.img 计算虚拟机组件摘要时候自动生成,证书中包含DH公钥,DH证书文件为guest_owner_dh.cert,作为qemu的参数传入。| +|user_vm_digest|虚拟机组件启动摘要,通常由ovmf,内核image,文件系统initrd组成,通过hag csv generate_launch_blob -build $build_id -bios OVMF.fd -kernel vmlinuz -initrd initramfs.img 命令生成launch_blob.bin文件,该文件中包含虚拟机启动摘要,文件作为qemu 启动参数传入。| +|vm_id|虚拟机id,用户自己定义,hag csv generate_launch_blob --help 中 通过-id 参数传入,字段默认都为0。| +|vm_version|虚拟机版本号,用户自己定义,hag csv generate_launch_blob --help 中 通过-version 参数传入,字段默认都为0。| + +### sealing key qemu启动参数介绍 + +1、获取安全固件build_id +``` +build_id=`sudo hag csv platform_status |grep "build id"` +``` +2、导出证书链 +``` +hag csv export_cert_chain +``` +3、生成 policy 文件 +``` +hag csv generate_policy --nodebug +``` +4、生成launch_blob.bin、guest_owner_dh.cert +``` +hag csv generate_launch_blob -build $build_id -bios OVMF.fd -kernel vmlinuz -initrd initramfs.img +``` +guest_owner_dh.cert 为用户dh证书,对应的私钥对launch_blob.bin中的字段进行签名,dh证书和私钥都由hag中 generate_launch_blob 命令自动生成,guest_owner_dh.cert 作为qemu的参数传入,海光安全固件获取证书中的公钥,对launch_blob.bin 中的内容进行验签。 +launch_blob.bin作为qemu启动参数传入,launch_blob.bin内容对应为SESSION的数据结构,内容如下: + + +| 偏移 | 比特位 | 输入/输出 | 名称 | 描述 | +|----- |-------| ---------|---------|------| +|00h | 127:0| In | NONCE| 一次性随机数,用户随机生成 | +|10h | 255:0| In | WRAP_TK | KEK对 TEKTIK 加密形成WRAP_TK,TEKTIK 用户随机生成 ,KEK 由主密钥派生出来| +|30h | 127:0| In | WRAP_IV |加密TEKTIK使用的IV,加密参数之一| +|40h | 255:0| In | WRAP_MAC |使用KIK作为key 对WRAP_TK,WRAP_IV 进行hmac计算生成WRAP_MAC进行完整性保护,KIK 由主密钥派生出来| +|60h | 255:0| In | SESSION_MAC |使用TIK对policy\|\|session data(0x124 - 0x2C3)进行hmac计算生成SESSION_MAC对数据进行完整性保护| +|80h | 1311:0| In | - |保留字段,0| +|124h | 2047:0| In | Menc |主密钥,用户随机生成,被PDH公钥加密后为Menc,KEKKIK 由主密钥派生,海光安全固件中使用PDH私钥对Menc进行解密得到主密钥,使用主密钥派生出KEKKIK,使用KIK对WRAP_TK、WRAP_IV 进行完整性验证,KEK解密WRAP_TK 得到TEKTIK,使用KIK对policy\|\|session data(0x124 - 0x2C3)重新进行hmac计算和SESSION_MAC进行对比,实现数据完整性保护| +|224h | 255:0| In | DIGEST |虚拟机摘要,使用虚拟机组件计算生成,虚拟机组件如 OVMF.fd、 vmlinuz 、initramfs.img,安全固件中会对其进行重新计算和用户计算出的DIGEST进行对比,从而实现可信度量启动| +|244h | 255:0| In | - |保留字段,0| +|264h | 127:0| In | VM_ID |虚拟机id,用户自己定义,hag csv generate_launch_blob --help 中 通过-id 参数传入| +|274h | 127:0| In | VM_VERSION |虚拟机版本号,用户自己定义,hag csv generate_launch_blob --help 中 通过-version 参数传入| +|284h | 511:0| In | USERDATA |用户自定义数据| +|2C4h | 511:0| In | SIG |用户DH私钥对SESSION数据的签名| + +### 测试用例参考 [2-3-2-测试密钥封印](https://openanolis.cn/sig/Hygon-Arch/doc/865622217613776670?lang=zh) diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/10-\346\212\200\346\234\257\344\273\213\347\273\215/4-CSV\347\243\201\347\233\230\345\212\240\345\257\206\346\212\200\346\234\257\344\273\213\347\273\215.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/10-\346\212\200\346\234\257\344\273\213\347\273\215/4-CSV\347\243\201\347\233\230\345\212\240\345\257\206\346\212\200\346\234\257\344\273\213\347\273\215.md" new file mode 100644 index 0000000000000000000000000000000000000000..39334b0b491c7a04119a07148e3ddb4017c2950f --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/10-\346\212\200\346\234\257\344\273\213\347\273\215/4-CSV\347\243\201\347\233\230\345\212\240\345\257\206\346\212\200\346\234\257\344\273\213\347\273\215.md" @@ -0,0 +1,75 @@ +测试之前,请参考[2-1-安装CSV软件](https://openanolis.cn/sig/Hygon-Arch/doc/865622260278236994?lang=zh)准备软件环境。 + +## 概要 +普通虚拟机磁盘加密技术只能对虚拟机数据分区进行加密,且秘钥管理是一个问题,秘钥放在boot分区存在泄漏的风险,CSV虚拟机提供了全磁盘加密技术,可以同时对boot分区和数据分区进行加密,boot分区的秘钥加密后通过 +虚拟机qemu启动参数动态注入到虚拟机内存中,秘钥只能虚拟机启动后从虚拟机内存获取,实现磁盘的解密启动,虚拟机boot分区中不保存boot分区的加密秘钥,秘钥具有很强的安全性,虚拟机磁盘中的数据在主机上为密文形式存储,确保数据安全不被泄漏。 + +## 原理介绍 + +### 磁盘加密 + +![](../../../assets/disk_encryption1.png) + +1、使用iso镜像安装虚拟机,安装时选择对磁盘的数据分区进行加密,虚拟机安装完毕,关机。 + +2、使用安装好的磁盘镜像启动虚拟机,输入安装时的加密数据分区的秘钥,虚拟机启动成功。 + +3、对虚拟机的boot分区加密,设置加密秘钥,该秘钥后续会作为qemu 的参数传入注入到虚拟机内存中。 + +4、安装支持磁盘加密的grub,使能grub 的磁盘加密配置。 + +5、生成秘钥,秘钥放到initrd文件系统中,生成的密钥文件添加到数据分区的一个新的 LUKS 密钥槽中,LUKS 支持多个密钥槽,每个密钥槽可存储一个解锁加密磁盘的密钥,每个密钥槽中的密钥都可以独立解锁加密分区,更新/etc/crypttab配置,使得系统可以在启动时通过密钥文件自动解锁数据分区,该秘钥和iso安装虚拟机时加密磁盘的秘钥是相互独立的,都可以对磁盘进行解密,它们分别属于不同的秘钥槽。 + +6、设置完成,虚拟机关机。 + + +### 打包秘钥 + +![](../../../assets/disk_encryption2.png) + +1、将加密boot 分区的秘钥进行加密打包,使用TEK 和IV 对数据进行加密,后续会将该秘钥注入到虚拟机内存中,用于解密boot分区,TEK由hag 命令generate_launch_blob 随机产生并写入到文件中,后续由hag 加密打包命令package_secret使用,IV 由hag 打包命令随机生成。 + +2、将加密后的数据写入文件,该文件为秘钥文件。 + +3、将文件内容进行base64 编码处理,使内容为base64 编码的格式存储在秘钥文件中,该文件会作为qemu参数传入。 + +4、将秘钥头的结构数据写入到秘钥头文件中。 + + 秘钥头参数 + + | 参数 | 描述 | + |----- |-------| + |FLAGS|FLAGS.REUSE=0时,MEASURE 是LAUNCH_MEASURE命令返回的MEASURE值。FLAGS.REUSE=1时,MEASURE=0。| + |IV|加密秘钥数据的参数之一,随机产生| + |HMAC|对(0x01 \|\| FLAGS \|\| IV \|\| GUEST_LENGTH \|\| TRANS_LENGTH \|\| DATA \|\|MEASURE\|\| TIK)进行hmac 计算,用于保护数据的完整性,GUEST_LENGTH为虚拟机密钥的长度,16的整数倍,不超过16K,TRANS_LENGTH为源数据的长度,DATA 为加密后的秘钥,MEASURE 为虚拟机的MEASURE,TIK为完整性保护用的KEY,由hag 命令generate_launch_blob 随机产生并写入到文件中,后续由hag 加密打包命令package_secret使用| + +5、将秘钥头文件内容进行base64编码转换,该文件会作为qemu参数传入。 + +### 注入秘钥,解密磁盘加密分区 + +![](../../../assets/disk_encryption3.png) + +1、将上面步骤打包好的秘钥头文件和秘钥数据文件作为qemu参数传入启动虚拟机。 + +2、qemu 找到虚拟机中可以注入秘钥的内存地址。 + +3、将需要注入的数据还原成原有格式,即将base64 的数据格式恢复成原始的格式。 + +4、调用秘钥注入接口函数将秘钥注入。 + +5、海光安全固件中重新将(0x01 || FLAGS || IV || GUEST_LENGTH || TRANS_LENGTH || DATA ||MEASURE||TIK)进行计算和传下来的秘钥头结构中的mac 进行对比,实现完整性保护。 + +6、使用TEK对加密数据进行解密。 + +7、使用虚拟机ASID 对应的VEK 对秘钥数据加密。 + +8、将加密后的数据放到qemu寻找到的内存地址中,完成秘钥注入,秘钥数据是被虚拟机VEK 加密的,主机上是看不到明文,只有在虚拟机中才能获取明文秘钥。 + +9、启动虚拟机,虚拟机grub 从秘钥注入的内存读取秘钥,解密boot分区。 + +10、grub 引导boot 分区中的内核和initrd 内存文件系统启动。 + +11、使用initrd 中的key 自动解密数据分区,完成整个加密磁盘的解密启动。 + + +### 测试用例参考 [2-3-3-测试全盘加密](https://openanolis.cn/sig/Hygon-Arch/doc/865622219333441312?lang=zh) diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/2-\346\265\213\350\257\225\344\270\273\346\234\272\345\206\205\345\255\230\345\212\240\345\257\206.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/2-\346\265\213\350\257\225\344\270\273\346\234\272\345\206\205\345\255\230\345\212\240\345\257\206.md" new file mode 100644 index 0000000000000000000000000000000000000000..73a4aee8507b1f1811ec9cd1acfefc4e79a3ac12 --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/2-\346\265\213\350\257\225\344\270\273\346\234\272\345\206\205\345\255\230\345\212\240\345\257\206.md" @@ -0,0 +1,28 @@ +测试之前,请参考[2-1-安装CSV软件](https://openanolis.cn/sig/Hygon-Arch/doc/865622260278236994?lang=zh)准备软件环境。 + +## 功能描述 +主机内存加密技术用来加密主机内存,主机写内存数据时,如果页表项的加密位C bit为1,CPU会自动对数据加密后再写入内存;如果页表项的C bit为0,CPU不会进行加密。主机操作系统通过将重要数据的页表项C bit设置为1,可以实现数据加密后保存在内存中,保护数据的安全性。 + +## 测试主机内存加密功能 + +### 运行测试程序 +测试程序的执行过程分为 3 步: +1. 分配内存并将内存中的数据初始化为 0xab,通过 clflush 指令将数据从缓存写入内存,默认情况下页表中的 C bit=1,因此内存中的数据是被加密后的数据。 +2. 调用系统函数set_memory_decrypted将内存的 C bit 设置为0然后读出,发现不是0xab而是加密的数据。 +3. 调用系统函数set_memory_encrypted将内存的C bit设置为1然后读出,发现数据被恢复成 0xab。 + +``` +$ cd /opt/hygon/csv/sme_test +$ sudo insmod sme_test.ko +$ dmesg +``` + + 图 1 主机内存加密测试结果 + + ![](../../assets/csv2-1.png) + +### 卸载测试程序 + +``` +$ sudo rmmod sme_test +``` diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/1-\346\265\213\350\257\225\345\206\205\345\255\230\345\212\240\345\257\206.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/1-\346\265\213\350\257\225\345\206\205\345\255\230\345\212\240\345\257\206.md" new file mode 100644 index 0000000000000000000000000000000000000000..85a63391d70ee25a8d8f8705f07d63f1425bb14b --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/1-\346\265\213\350\257\225\345\206\205\345\255\230\345\212\240\345\257\206.md" @@ -0,0 +1,114 @@ +测试之前,请参考[2-1-安装CSV软件](https://openanolis.cn/sig/Hygon-Arch/doc/865622260278236994?lang=zh)准备软件环境。 + +## 功能描述 +CSV技术通过加密虚拟机的内存来保护虚拟机数据的安全性,每个CSV虚拟机使用不同的密钥,主机和其他虚拟机都不能访问当前CSV虚拟机的内存数据,本文描述了测试CSV虚拟机功能的方法。 + +## 测试内存加密功能 + +### 查看普通虚拟机的内存数据 +运行普通虚拟机。 + +``` +$ sudo qemu-system-x86_64 -name normal-vm --enable-kvm -cpu host -m 2048 -hda /opt/hygon/csv/vm.qcow2 -drive if=pflash,format=raw,unit=0,file=/opt/hygon/csv/OVMF_CODE.fd,readonly=on -qmp tcp:127.0.0.1:1111,server,nowait -vnc 0.0.0.0:0 -nographic +``` + +虚拟机启动后,登陆虚拟机,用户名为root,密码为root。 + +打开新终端,保存虚拟机的内存数据到文件。 + +``` +$ telnet 127.0.0.1 1111 +$ { "execute" : "qmp_capabilities" } +$ { "execute": "pmemsave", "arguments": {"val": 0, "size": 256, "filename": "normal.txt"} } +``` + +按下Ctrl+]退回到终端,查看文件中的内存数据。 + +``` +$ quit +$ hexdump -v normal.txt +``` +**normal.txt 文件在运行虚拟机命令的目录下** + +普通虚拟机的内存数据如下图,数据是明文。 + +图 1 普通虚拟机的内存数据 + + ![](../../../assets/csv3-1.png) + +关闭普通虚拟机。 + +### 查看CSV虚拟机的内存数据 +运行CSV虚拟机。 + +``` +$ sudo qemu-system-x86_64 -name csv-vm --enable-kvm -cpu host -m 2048 -hda /opt/hygon/csv/vm.qcow2 -drive if=pflash,format=raw,unit=0,file=/opt/hygon/csv/OVMF_CODE.fd,readonly=on -qmp tcp:127.0.0.1:2222,server,nowait -vnc 0.0.0.0:1 -object sev-guest,id=sev0,policy=0x1,cbitpos=47,reduced-phys-bits=5 -machine memory-encryption=sev0 -nographic +``` + +虚拟机启动后,登陆虚拟机,用户名为root,密码为root。 + +保打开新终端,保存虚拟机的内存数据到文件。 + +``` +$ telnet 127.0.0.1 2222 +$ { "execute" : "qmp_capabilities" } +$ { "execute": "pmemsave", "arguments": {"val": 0, "size": 256, "filename": "csv.txt"} } +``` + +按下Ctrl+]退回到终端,查看文件中的内存数据。 + +``` +$ quit +$ hexdump -v csv.txt +``` +**csv.txt 文件在运行虚拟机命令的目录下** + +CSV虚拟机的内存数据如下图,数据是密文。 + +图 2 CSV虚拟机的内存数据 + + ![](../../../assets/csv3-2.png) + +关闭CSV虚拟机。 + +## 测试远程认证功能 + +### 生成认证报告 +运行CSV虚拟机。 + +``` +$ sudo qemu-system-x86_64 -name csv-vm --enable-kvm -cpu host -m 2048 -hda /opt/hygon/csv/vm.qcow2 -drive if=pflash,format=raw,unit=0,file=/opt/hygon/csv/OVMF_CODE.fd,readonly=on -qmp tcp:127.0.0.1:2222,server,nowait -vnc 0.0.0.0:1 -object sev-guest,id=sev0,policy=0x1,cbitpos=47,reduced-phys-bits=5 -machine memory-encryption=sev0 -netdev bridge,br=virbr0,id=net0 -device virtio-net-pci,netdev=net0,romfile= -nographic +``` + +虚拟机启动后,登陆虚拟机,用户名为root,密码为root。 + +在虚拟机中使用scp命令从主机拷贝远程认证测试程序,假设主机的用户名是user,host_ip 为主机ip,在虚拟机中运行测试程序get-attestation生成认证报告。 + +``` +# dhclient +# scp user@${host_ip}:/opt/hygon/csv/attestation/get-attestation ./ +# ./get-attestation +``` + +测试程序get-attestation产生mnonce和userdata作为认证报告的输入,生成的认证报告使用PEK私钥签名,并且包含mnonce和userdata,认证方需要检查认证报告的签名、mnonce、userdata。 + +### 验证认证报告 +可以在任意机器上验证认证报告,这里使用主机作为示例,验证程序需要联网从芯片证书服务器下载芯片证书验证认证报告的证书链。 + +在虚拟机中使用scp命令将认证报告拷贝到主机。 + +``` +# scp report.cert test@192.168.122.1:/opt/hygon/csv/attestation/ +``` + +在主机中运行验证程序verify-attestation。 + +``` +$ cd /opt/hygon/csv/attestation +$ sudo chmod 666 report.cert +$ ./verify-attestation true +``` + +验证程序verify-attestation从芯片证书服务器下载HRK、HSK、CEK芯片证书,使用PEK公钥验证认证报告的签名,并且验证HRK->HSK->CEK->PEK证书链的签名。 + +关闭CSV虚拟机。 diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/2-\346\265\213\350\257\225\345\257\206\351\222\245\345\260\201\345\215\260.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/2-\346\265\213\350\257\225\345\257\206\351\222\245\345\260\201\345\215\260.md" new file mode 100644 index 0000000000000000000000000000000000000000..103a4f23e57ab3a64c4d183d750681e8433cb755 --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/2-\346\265\213\350\257\225\345\257\206\351\222\245\345\260\201\345\215\260.md" @@ -0,0 +1,53 @@ +测试之前,请参考[2-1-安装CSV软件](https://openanolis.cn/sig/Hygon-Arch/doc/865622260278236994?lang=zh)准备软件环境。 + +**注:麒麟系统不支持** + +## 功能描述 +CSV虚拟机支持密钥封印功能,CSV虚拟机可以请求安全处理器固件生成一个与虚拟机绑定的密钥,虚拟机重启后该密钥保持不变,本文描述了测试CSV虚拟机密钥封印功能的方法。 + +## 测试密钥封印功能 + +### 准备测试文件 + +``` +$ cd /opt/hygon/csv +$ sudo ./sealing_key.sh +``` +注:**如果机器不能联网**,需要将sealing_key.sh 中hag csv export_cert_chain 步骤注释掉,然后使用[2-3-5-测试CSV虚拟机迁移](https://openanolis.cn/sig/Hygon-Arch/doc/944532750000611833) 中 **离线导出证书** 章节步骤进行制作证书,制作完执行cp -f /opt/hygon/bin/*cert /opt/hygon/csv/ 命令将证书拷贝到对应目录,再重新运行sudo ./sealing_key.sh 脚本 + +### 启动CSV虚拟机 +**该功能支持需要使用hygon-edk2 编译出的OVMF.fd 文件而不是OVMF_CODE.fd 文件** +``` +$ sudo qemu-system-x86_64 --enable-kvm -cpu host -smp 4 -m 4G -kernel /opt/hygon/csv/vmlinuz -initrd /opt/hygon/csv/initramfs.img -drive if=pflash,format=raw,unit=0,file=/opt/hygon/csv/OVMF.fd,readonly=on -object sev-guest,id=sev0,policy=1,cbitpos=47,reduced-phys-bits=5,kernel-hashes=on,session-file=launch_blob.bin,dh-cert-file=guest_owner_dh.cert -machine memory-encryption=sev0 -vnc 0.0.0.0:1 -netdev bridge,br=virbr0,id=net0 -device virtio-net-pci,netdev=net0 +``` +### 连接CSV虚拟机 +**linux 端登录** + +*0.0.0.0*替换为虚拟机所在物理机的ip,本机登录不需要替换 + +``` +$ vncviewer 0.0.0.0:1 +``` +**windows端登录** + +*192.168.1.66* 替换为虚拟机所在物理机的ip + +![](../../../assets/vncviewer.png) + +**dhclient 可以获取虚拟机ip** +### 在CSV虚拟机中获取封印密钥 + +``` +# cd / +# ./get_key +sealing key: +1460ca87d513047c01729272fe0247d29f53e28895113f962c6a8ffbc7218ff5 +# reboot +虚拟机重启完毕,重新登录虚拟机 +# cd / +# ./get_key +sealing key: +1460ca87d513047c01729272fe0247d29f53e28895113f962c6a8ffbc7218ff5 + +可以看出,虚拟机重启后,封印秘钥不变 +``` diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/3-\346\265\213\350\257\225\345\205\250\347\233\230\345\212\240\345\257\206.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/3-\346\265\213\350\257\225\345\205\250\347\233\230\345\212\240\345\257\206.md" new file mode 100644 index 0000000000000000000000000000000000000000..ceac62f91e6a75bea41eee8ecdfd16fc73941d4a --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/3-\346\265\213\350\257\225\345\205\250\347\233\230\345\212\240\345\257\206.md" @@ -0,0 +1,36 @@ +测试之前,请参考[2-1-安装CSV软件](https://openanolis.cn/sig/Hygon-Arch/doc/865622260278236994?lang=zh)准备软件环境。 + +**注:麒麟系统不支持** + +## 功能描述 +操作系统使用的磁盘包含启动分区和数据分区,全盘加密是指将启动分区和数据分区全部加密,保证系统的所有文件都不会被窃取或者篡改,本文描述了CSV虚拟机使用全盘加密的方法。 + +## 测试全盘加密功能 + +### 制作全盘加密的虚拟机镜像 + +使用ISO镜像安装虚拟机,安装过程选择选择磁盘加密加密/dev/sda3,使用abc作为示例密码。 + +``` +$ cd /opt/hygon/csv/ +$ wget http://mirrors.163.com/ubuntu-releases/18.04/ubuntu-18.04.6-desktop-amd64.iso +$ qemu-img create -f qcow2 ubuntu.qcow2 10g +$ sudo qemu-system-x86_64 -enable-kvm -cpu host -smp 4 -m 4096 -drive if=pflash,format=raw,unit=0,file=/opt/hygon/csv/OVMF_CODE.fd,readonly=on -hda ./ubuntu.qcow2 -boot d -cdrom ./ubuntu-18.04.6-desktop-amd64.iso -vnc 0.0.0.0:1 +``` +安装完成后重启虚拟机,安装过程中加密了虚拟机的数据分区/dev/sda3,接下来加密启动分区/dev/sda2并替换虚拟机中的grub。 +由于虚拟机的分区/dev/sda3已经被加密,启动过程中需要输入密码abc进行解密,启动后在虚拟机中使用scp命令将主机中的文件拷贝到虚拟机,这里假设主机的用户名为test,IP地址为192.168.122.1。 + +``` +$ scp test@192.168.122.1:/opt/hygon/csv/setup-encrypt.sh ./ +$ scp test@192.168.122.1:/opt/hygon/csv/grub.tar.gz ./ +$ sudo ./setup-encrypt.sh +``` +脚本setup-encrypt.sh执行过程中,请按提示输入YES(大写)和密码abc,执行完成后关闭虚拟机,此时虚拟机的启动分区和数据分区都已经被密码abc加密 + +### 使用加密的镜像启动CSV虚拟机 +disk_encryption.sh默认使用abc,如果密码正确,虚拟机会正常启动,否则会提示输入密码。 +``` +$ cd /opt/hygon/csv +$ sudo ./disk_encryption.sh +``` +vncviewer 0.0.0.0:1 登录虚拟机看虚拟机能否正常启动 diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/4-\346\265\213\350\257\225CSV\350\231\232\346\213\237\346\234\272\347\233\264\351\200\232DCU.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/4-\346\265\213\350\257\225CSV\350\231\232\346\213\237\346\234\272\347\233\264\351\200\232DCU.md" new file mode 100644 index 0000000000000000000000000000000000000000..03447182a92289920fe13e4faa65e1cf7df8e460 --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/4-\346\265\213\350\257\225CSV\350\231\232\346\213\237\346\234\272\347\233\264\351\200\232DCU.md" @@ -0,0 +1,118 @@ +测试之前,请参考[2-1-安装CSV软件](https://openanolis.cn/sig/Hygon-Arch/doc/865622260278236994?lang=zh)准备软件环境。 + +## 功能描述 +某些应用场景需要在CSV虚拟机中运行图像识别、机器学习等算法,这些场景下使用DCU加速卡可以极大地提高计算性能,CSV虚拟机支持设备直通,可以将DCU卡直通给CSV虚拟机使用。 + +## 测试CSV虚拟机使用DCU卡 + +### 运行CSV虚拟机 +``` +$ sudo qemu-system-x86_64 -name csv-vm --enable-kvm -cpu host -m 6114 -hda /opt/hygon/csv/vm.qcow2 -drive if=pflash,format=raw,unit=0,file=/opt/hygon/csv/OVMF_CODE.fd,readonly=on -qmp tcp:127.0.0.1:2222,server,nowait -vnc 0.0.0.0:1 -object sev-guest,id=sev0,policy=0x1,cbitpos=47,reduced-phys-bits=5 -machine memory-encryption=sev0 -netdev bridge,br=virbr0,id=net0 -device virtio-net-pci,netdev=net0,romfile= -nographic +``` + +### 在虚拟机中安装DCU软件栈 +``` +# dhclient +# scp host@hostip:/opt/hygon/csv/dcu/vm_dcu_sw_deploy.sh ./ +# ./vm_dcu_sw_deploy.sh +# poweroff +``` + +### 将DCU卡分配给VFIO +找到DCU设备的设备标识、Device Id和Vendor Id + +``` +$ lspci -nn | grep Display +``` +命令的执行效果如下图,该设备的VendorID为1d94, Device Id为53b7。 + + ![](../../../assets/csv8-1.png) + +将DCU设备与VFIO模块关联 +``` +$ sudo modprobe vfio +$ sudo modprobe vfio-pci +$ sudo echo 0000:03:00.0 > /sys/bus/pci/devices/0000:03:00.0/driver/unbind +$ sudo -s +# echo 1d94 53b7 > /sys/bus/pci/drivers/vfio-pci/new_id +``` +命令说明:示例中用到的设备标识、VendorID、DeviceID,请替换成上一步自己获取到的信息。对于第三条命令(unbind),如果PCI设备已经与宿主机绑定,则需要执行;如未绑定,将不存在unbind文件,则无需执行。 + +### 运行直通DCU卡的CSV虚拟机 + +``` +$ sudo qemu-system-x86_64 -name csv-vm --enable-kvm -cpu host -m 10240 -hda /opt/hygon/csv/vm.qcow2 -drive if=pflash,format=raw,unit=0,file=/opt/hygon/csv/OVMF_CODE.fd,readonly=on -qmp tcp:127.0.0.1:2222,server,nowait -vnc 0.0.0.0:1 -object sev-guest,id=sev0,policy=0x1,cbitpos=47,reduced-phys-bits=5 -machine memory-encryption=sev0 -device vfio-pci,host=03:00.0 -fw_cfg name=opt/ovmf/X-PciMmio64Mb,string=65536 -netdev bridge,br=virbr0,id=net0 -device virtio-net-pci,netdev=net0,romfile= -nographic +``` + +### 在CSV虚拟机中运行DCU测试程序 + +``` +# git clone https://github.com/ROCm-Developer-Tools/HIP-Examples.git +# source /opt/dtk/env.sh +# cd HIP-Examples/vectorAdd +# make clean;make +# ./vectoradd_hip.exe +``` +## 测试 DCU Attestation 功能 (DCU远程身份认证功能) +### 背景 +从深算二号(K100-AI)开始,海光DCU开始支持Attestation(身份认证)功能。
+(DCU驱动版本 rock-kernel-refactory-rock-5.7.1-6.2.26-V1.5.aio.run +https://cancon.hpccube.com:65024/6/main/latest%E9%A9%B1%E5%8A%A8),
+DCU Attestation的目的是向DCU加速器的使用者证明,正在使用中的DCU设备具有真实身份,
+其芯片ID、固件版本、硬件环境等相关数据皆为真实可信,用户可将机密数据下发到DCU中计算,无需担心数据被恶意的加速器窃取。 +### 机制 + + ![](../../../assets/dcu_attestation_arch.png) + + 每一颗DCU芯片拥有唯一的芯片ID(ChipID),在芯片生产时烧入,以后无法更改。
+芯片内置一SM2密钥对(DCEK, DCU Chip Endorsement Key),私钥作为DCU芯片的身份象征,只保存在DCU芯片,永不外泄。
+公钥被HDSK(海光DCU签名密钥)/HRK(海光根密钥)签名后,存放于海光证书系统中,可公开下载。
+ +步骤一:当CSV虚拟机启动完毕后,用户加载DCU驱动识别DCU卡。用户运行Attestation App通过DCU驱动向DCU卡请求远程认证报告。
+DCU卡生成远程认证报告,内容包含DCU芯片ID,固件版本等信息,并使用DCEK私钥签名,返回给用户。
+步骤二:用户从远程认证报告中取出DCU芯片ID,向海光证书系统请求该芯片的DCEK/HDSK/HRK公钥证书。
+步骤三:用户依次验证HRK->HDSK->DCEK证书链的签名,并使用DCEK证书中的公钥验证远程认证报告的签名。
+全部验证过程正确可认为该DCU芯片为真实的海光芯片,报告中的数据真实可信。
+验证过程中任一步失败,则验证过程失败。 + +海光提供了Attestation App demo,演示了CSV虚拟机用户向DCU请求认证报告、获取认证报告、下载证书链、
+验证远程报告、验证证书链的全过程。该demo程序仅做展示,用户可根据需要修改或重新编写。
+ +### 测试过程 +假设CSV中直通DCU的环境已经搭建完毕,CSV虚拟机能够访问DCU。
+(请依据[4-测试CSV虚拟机直通DCU](https://openanolis.cn/sig/Hygon-Arch/doc/865622222638552866?lang=zh) 搭建环境 ) + +拷贝主机中的测试程序(/opt/hygon/csv/attestation/)到CSV虚拟机中
+目录中的dcu_attestation_demo文件为演示DCU远程证明的示例程序。 + +1)如果您的CSV虚拟机能够直接连接海光证书服务器(https://cert.hygon.cn/)
请直接运行 +``` +$./dcu_attestation_demo +``` +示例程序将自动完成DCU认证过程。 + +2)如果您的CSV虚拟机无法连接海光证书服务器,则需要手动下载证书后,放置于dcu_attestation_demo程序的所在的目录下,步骤如下:
+2.1)运行demo程序,获取DCU ChipID +``` +$./dcu_attestation_demo +``` +该程序会打印出DCU ChipID,并打印证书下载失败的日志后退出。 +
![](../../../assets/dcu_attestation_chip.png)
+该DCU的ChipID为”T6N6980002080601” + +2.2)在相同目录下,手动下载该芯片的HSK_CEK证书 +``` +$ curl -s -f -o hsk_cek.cert https://cert.hygon.cn/hsk_cek?snumber=T6N6980002080601 +``` +完成后,在运行程序的目录下,生成hsk_cek.cert文件,文件包含HSK证书和CEK证书
+ +2.3)在相同目录下,手动下载HRK证书 +``` +curl -s -f -o ./hrk.cert https://cert.hygon.cn/hrk +``` +完成后,在运行程序的目录下,生成hrk.cert
+ +2.4)再次运行attestation demo程序,完成DCU身份验证过程 +``` +$./dcu_attestation_demo +``` \ No newline at end of file diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/5-\346\265\213\350\257\225CSV\350\231\232\346\213\237\346\234\272\350\277\201\347\247\273.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/5-\346\265\213\350\257\225CSV\350\231\232\346\213\237\346\234\272\350\277\201\347\247\273.md" new file mode 100644 index 0000000000000000000000000000000000000000..c70393e8bec4b455ba9aad5e295fe10a5b71d278 --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/5-\346\265\213\350\257\225CSV\350\231\232\346\213\237\346\234\272\350\277\201\347\247\273.md" @@ -0,0 +1,137 @@ +测试之前,请参考[2-1-安装CSV软件](https://openanolis.cn/sig/Hygon-Arch/doc/865622260278236994?lang=zh)准备软件环境。 + +## 功能描述 +CSV 虚拟机支持在线迁移,本文档描述CSV虚拟机迁移测试步骤 +## 测试CSV虚拟机迁移 +### 迁移源端启动虚拟机 +``` +sudo qemu-system-x86_64 \ + -name csv_send \ + --enable-kvm \ + -cpu host \ + -m 4096 \ + -smp 2 \ + -drive if=pflash,format=raw,unit=0,file=/opt/hygon/csv/OVMF_CODE.fd,readonly=on \ + -object sev-guest,id=sev0,policy=0x1,cbitpos=47,reduced-phys-bits=5 \ + -machine q35,memory-encryption=sev0 \ + -vnc 0.0.0.0:0 \ + -device virtio-blk-pci,scsi=off,drive=drive0,disable-legacy=on,iommu_platform=on \ + -drive file=/opt/hygon/csv/vm.qcow2,if=none,id=drive0 \ + -qmp tcp:localhost:4444,server,nowait \ + -nographic + +``` +### 迁移目标端启动虚拟机 +``` +sudo qemu-system-x86_64 \ + -name csv_receive \ + --enable-kvm \ + -cpu host \ + -m 4096 \ + -smp 2 \ + -drive if=pflash,format=raw,unit=0,file=/opt/hygon/csv/OVMF_CODE.fd,readonly=on \ + -object sev-guest,id=sev0,policy=0x1,cbitpos=47,reduced-phys-bits=5 \ + -machine q35,memory-encryption=sev0 \ + -vnc 0.0.0.0:1 \ + -device virtio-blk-pci,scsi=off,drive=drive0,disable-legacy=on,iommu_platform=on \ + -drive file=/opt/hygon/csv/vm.qcow2,if=none,id=drive0 \ + -qmp tcp:localhost:4445,server,nowait \ + -incoming tcp:127.0.0.1:6666 \ + -nographic + +``` +注:这里测试是本机迁移,设置ip为**127.0.0.1**,跨机迁移ip需要设置对应机器的ip地址 + +此时,迁移源端可以正常登录操作,迁移目标端处于等待接收迁移数据的状态。 + +send端: + + ![](../../../assets/csv3-6-1.png) + +receive端: + + ![](../../../assets/csv3-6-2.png) + +图 VNCViewer连接迁移源端和迁移目标端 +### 迁移目标端设置迁移参数 +``` +$ cd /opt/hygon/bin +$ sudo ./hag csv export_cert_chain +$ cat hsk.cert hrk.cert > vendor_cert.bin && \ + cat pek.cert oca.cert cek.cert > plat_cert.bin && \ + cat pdh.cert > pdh.bin && \ + base64 -w 0 vendor_cert.bin > vendor_cert.base64 && \ + base64 -w 0 plat_cert.bin > plat_cert.base64 && \ + base64 -w 0 pdh.bin > pdh.base64 +$ sudo chmod 666 *.base64 +$ sudo cp -a *.base64 /tmp +$ sudo socat - tcp:localhost:4445 +{"QMP": {"version": {"qemu": {"micro": 1, "minor": 2, "major": 4}, "package": "v4.2.1-42-g6e701de2d0-dirty"}, "capabilities": ["oob"]}} +{"execute":"qmp_capabilities"} +{"return": {}} +{"execute":"migrate-set-parameters","arguments":{"sev-pdh":"/tmp/pdh.base64","sev-plat-cert":"/tmp/plat_cert.base64","sev-amd-cert":"/tmp/vendor_cert.base64"}} +{"return": {}} +``` +#### 离线导出证书 +如果机器不能连接外网,提供离线方式,如下方式是对上面步骤 +*sudo ./hag csv export_cert_chain*的替换 + +获取芯片chip ID + +![](../../../assets/img2-2.png) + +网站下载HSK,CEK证书 + +![](../../../assets/csv3-6-3.png) + +将证书文件hygon-hsk-cek-cert-NZA9T02082605.bin +拷贝到机器上的 /opt/hygon/bin/目录,生成hsk.cert,cek.cert +``` +$ dd if=hygon-hsk-cek-cert-NZA9T22092805.bin bs=1 count=832 of=hsk.cert +$ dd if=hygon-hsk-cek-cert-NZA9T22092805.bin bs=1 skip=832 count=2084 of=cek.cert +``` +下载HRK证书,拷贝hrk.cert 到/opt/hygon/bin 目录 +``` +$ wget -O hrk.cert https://cert.hygon.cn/hrk +$ scp hrk.cert user@your_machine_ip:/opt/hygon/bin/ +``` +生成pdh.cert,pek.cert,oca.cert +``` +$ cd /opt/hygon/bin +$ sudo ./hag csv pdh_cert_export +$ dd if=cert_chain.cert bs=1 count=2084 of=pek.cert +$ dd if=cert_chain.cert bs=1 skip=2084 count=2084 of=oca.cert +``` + +### 迁移源端发起迁移 +``` +$ sudo socat - tcp:localhost:4444 +{"QMP": {"version": {"qemu": {"micro": 1, "minor": 2, "major": 4}, "package": "v4.2.1-42-g6e701de2d0-dirty"}, "capabilities": ["oob"]}} +{"execute":"qmp_capabilities"} +{"return": {}} +{"execute":"migrate","arguments":{"uri":"tcp:127.0.0.1:6666"}} +{"return": {}} + +``` + +### 等待迁移结束 +在迁移完成时,迁移源端提示STOP;迁移目标端提示RESUME + +|迁移源端|迁移目标端| +|--------|----------| +|$ sudo socat - tcp:localhost:4444 |$ sudo socat - tcp:localhost:4445
| +|{"QMP": {"version": ……: ["oob"]}}
|{"QMP": {"version": ……: ["oob"]}}
| +|{"execute":"qmp_capabilities"}
|{"execute":"qmp_capabilities"}
| +|{"return": {}}
|{"return": {}}
| +|{"execute":"migrate","……tcp:127.0.0.1:6666"}}
|{"execute":"migrate-set-param……vendor_cert.base64"}}
| +|{"return": {}}
|{"return": {}}
| +|__{"timestamp": {"seconds": 1686879657, "microseconds": 25486}, "event": "STOP"}__|__{"timestamp": {"seconds": 1686879658, "microseconds": 783299}, "event": "RESUME"}__
| + + +此时VNCViewer看到迁移源端的虚拟机已经停止响应;而迁移目的端的虚拟机沿着迁移源端停止的状态继续运行,并响应用户操作。 + +receive端: + + ![](../../../assets/csv3-6-1.png) + +图 迁移目标端继续运行迁移过来的虚拟机 diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/6-\346\265\213\350\257\225CSV2\350\231\232\346\213\237\346\234\272\347\233\264\351\200\232DCU.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/6-\346\265\213\350\257\225CSV2\350\231\232\346\213\237\346\234\272\347\233\264\351\200\232DCU.md" new file mode 100644 index 0000000000000000000000000000000000000000..0d8a99653d828dee5e1b00e39a768e978f4266c9 --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/6-\346\265\213\350\257\225CSV2\350\231\232\346\213\237\346\234\272\347\233\264\351\200\232DCU.md" @@ -0,0 +1,55 @@ +测试之前,请参考[2-1-安装CSV软件](https://openanolis.cn/sig/Hygon-Arch/doc/865622260278236994?lang=zh)准备软件环境。 + +## 功能描述 +某些应用场景需要在CSV2虚拟机中运行图像识别、机器学习等算法,这些场景下使用DCU加速卡可以极大地提高计算性能,CSV2虚拟机支持设备直通,可以将DCU卡直通给CSV2虚拟机使用。 + +## 测试CSV2虚拟机使用DCU卡 + +### 运行CSV2虚拟机 +``` +$ sudo qemu-system-x86_64 -name csv-vm --enable-kvm -cpu host -m 6114 -hda /opt/hygon/csv/vm.qcow2 -drive if=pflash,format=raw,unit=0,file=/opt/hygon/csv/OVMF_CODE.fd,readonly=on -qmp tcp:127.0.0.1:2222,server,nowait -vnc 0.0.0.0:1 -object sev-guest,id=sev0,policy=0x5,cbitpos=47,reduced-phys-bits=5 -machine memory-encryption=sev0 -netdev bridge,br=virbr0,id=net0 -device virtio-net-pci,netdev=net0,romfile= -nopraghic +``` + +### 在虚拟机中安装DCU软件栈 +``` +# dhclient +# scp host@hostip:/opt/hygon/csv/dcu/vm_dcu_sw_deploy.sh ./ +# ./vm_dcu_sw_deploy.sh +# poweroff +``` + +### 将DCU卡分配给VFIO +找到DCU设备的设备标识、Device Id和Vendor Id + +``` +$ lspci -nn | grep Display +``` +命令的执行效果如下图,该设备的VendorID为1d94, Device Id为53b7。 + + ![](../../../assets/csv8-1.png) + +将DCU设备与VFIO模块关联 +``` +$ sudo modprobe vfio +$ sudo modprobe vfio-pci +$ sudo echo 0000:03:00.0 > /sys/bus/pci/devices/0000:03:00.0/driver/unbind +$ sudo -s +# echo 1d94 53b7 > /sys/bus/pci/drivers/vfio-pci/new_id +``` +命令说明:示例中用到的设备标识、VendorID、DeviceID,请替换成上一步自己获取到的信息。对于第三条命令(unbind),如果PCI设备已经与宿主机绑定,则需要执行;如未绑定,将不存在unbind文件,则无需执行。 + +### 运行直通DCU卡的CSV2虚拟机 + +``` +$ sudo qemu-system-x86_64 -name csv-vm --enable-kvm -cpu host -m 10240 -hda /opt/hygon/csv/vm.qcow2 -drive if=pflash,format=raw,unit=0,file=/opt/hygon/csv/OVMF_CODE.fd,readonly=on -qmp tcp:127.0.0.1:2222,server,nowait -vnc 0.0.0.0:1 -object sev-guest,id=sev0,policy=0x5,cbitpos=47,reduced-phys-bits=5 -machine memory-encryption=sev0 -device vfio-pci,host=03:00.0 -fw_cfg name=opt/ovmf/X-PciMmio64Mb,string=65536 -netdev bridge,br=virbr0,id=net0 -device virtio-net-pci,netdev=net0,romfile= -nopraghic +``` + +### 在CSV2虚拟机中运行DCU测试程序 + +``` +# git clone https://github.com/ROCm-Developer-Tools/HIP-Examples.git +# source /opt/dtk/env.sh +# cd HIP-Examples/vectorAdd +# make clean;make +# ./vectoradd_hip.exe +``` diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/7-\345\220\257\345\212\250CSV3\345\212\240\345\257\206\350\231\232\346\213\237\346\234\272.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/7-\345\220\257\345\212\250CSV3\345\212\240\345\257\206\350\231\232\346\213\237\346\234\272.md" new file mode 100644 index 0000000000000000000000000000000000000000..51bab9e1c87045a0486062ca6d2edfdf86d1f752 --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/7-\345\220\257\345\212\250CSV3\345\212\240\345\257\206\350\231\232\346\213\237\346\234\272.md" @@ -0,0 +1,36 @@ +测试之前,请参考[2-1-安装CSV软件](https://openanolis.cn/sig/Hygon-Arch/doc/865622260278236994?lang=zh)准备软件环境。 + + +## 启动CSV3加密虚拟机 + +从4号CPU开始,支持CSV3安全虚拟化功能。 + +##### 配置主机系统kernel启动参数 +``` +$ sudo /opt/hygon/setup_csv3_memory.sh +``` +> setup_csv3_memory.sh脚本会在kernel启动参数cmdline中配置“csv_mem_percentage=50“,表示系统内存的50%可用于CSV3安全内存,CSV3虚拟机内存总量不能超过主机预留的CMA内存量。 +> 当需要启动的所有CSV3虚拟机内存总量较大时,可以调整kernel启动参数cmdline中csv_mem_percentage值大小,csv_mem_percentage最大为80,表示最多配置主机80%的内存作为CMA内存。 + +重新重启主机系统。 + + +#### 运行CSV3加密虚拟机。 +``` +$ sudo qemu-system-x86_64 -name csv3-vm --enable-kvm -cpu host -m 6114 -hda /opt/hygon/csv/vm.qcow2 -drive if=pflash,format=raw,unit=0,file=/opt/hygon/csv/OVMF_CODE.fd,readonly=on -qmp tcp:127.0.0.1:2222,server,nowait -vnc 0.0.0.0:0 -object sev-guest,id=sev0,policy=0x45,cbitpos=47,reduced-phys-bits=5 -machine memory-encryption=sev0 -nographic +``` +虚拟机启动后,登陆虚拟机,用户名为root,密码为root。 + +在虚拟机终端运行 +``` +# dmesg | grep "HYGON CSV" +``` +会看到 +``` +# dmesg | grep "HYGON CSV" + HYGON CSV + HYGON CSV2 + HYGON CSV3 +``` +表示虚拟机为CSV3加密虚拟机。 +关闭虚拟机。 diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/8-\346\265\213\350\257\225CSV2\345\257\204\345\255\230\345\231\250\345\212\240\345\257\206.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/8-\346\265\213\350\257\225CSV2\345\257\204\345\255\230\345\231\250\345\212\240\345\257\206.md" new file mode 100644 index 0000000000000000000000000000000000000000..6bc11c5b855c3894e93d0964eee965b120a521e7 --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/8-\346\265\213\350\257\225CSV2\345\257\204\345\255\230\345\231\250\345\212\240\345\257\206.md" @@ -0,0 +1,94 @@ +测试之前,请参考[2-1-安装CSV软件](https://openanolis.cn/sig/Hygon-Arch/doc/865622260278236994?lang=zh)准备软件环境。 + +## 功能描述 +3号CPU开始支持CSV2安全虚拟化功能,在CSV技术加密虚拟机内存的基础上,CSV2技术增加了虚拟机寄存器加密的功能,主机不能访问或者篡改CSV2虚拟机的寄存器。 + +## 测试CSV2虚拟机的寄存器加密功能 + +### 升级主机内核 +``` +$ wget https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.17.tar.gz  +$ tar -xvf linux-5.17.tar.gz +$ cd linux-5.17/ +$ sudo /opt/hygon/csv/build_csv2_kernel.sh  +``` +修改/etc/selinux/config ,设置SELINUX=disabled,完成后重启,内核选择5.17.0-csv2 + +### 运行普通虚拟机 + +运行普通虚拟机。 +``` +$ sudo qemu-system-x86_64 -name normal-vm --enable-kvm -cpu host -m 2048 -hda /opt/hygon/csv/vm.qcow2 -drive if=pflash,format=raw,unit=0,file=/opt/hygon/csv/OVMF_CODE.fd,readonly=on -qmp tcp:127.0.0.1:1111,server,nowait -vnc 0.0.0.0:0 -netdev bridge,br=virbr0,id=net0 -device virtio-net-pci,netdev=net0,romfile= -nopraghic +``` +虚拟机启动后,登陆虚拟机,用户名为root,密码为root。 + +### 升级虚拟机内核 +假设主机的用户名为user +``` +# dhclient +# scp user@${host_ip}:/opt/hygon/csv/kernel.tgz ./ +# scp user@${host_ip}:/opt/hygon/csv/vm_kernel_install.sh ./ +# ./vm_kernel_install.sh  +``` +安装完成后,选择安装的内核重启虚拟机 + +### 普通虚拟机运行寄存器测试程序 +假设主机的用户名为user + +``` +# dhclient +# scp user@${host_ip}:/opt/hygon/csv/csv2-reg-test/csv2_reg_test ./ +# chmod 777 csv2_reg_rest +# ./csv2_reg_rest +``` +测试程序循环执行设置虚拟机rbx 值为100并打印rbx。 + +图1 普通虚拟机修改寄存器打印 + + ![](../../../assets/csv10-1.png) + +打开主机攻击程序,主机修改虚拟机rbx寄存器为200,虚拟机中打印rbx变为200。 +``` +$ sudo -s +# echo 1 >/sys/module/kvm/parameters/vm_reg_test +``` + +图2 主机修改普通虚拟机寄存器打印 + + ![](../../../assets/csv10-2.png) + +关闭主机攻击程序,虚拟机中打印rbx恢复为100。 +``` +$ sudo -s +# echo 0 >/sys/module/kvm/parameters/vm_reg_test +``` + +### 运行CSV2虚拟机 + +``` +$ sudo qemu-system-x86_64 -name csv2-vm --enable-kvm -cpu host -m 2048 -hda /opt/hygon/csv/vm.qcow2 -drive if=pflash,format=raw,unit=0,file=/opt/hygon/csv/OVMF_CODE.fd,readonly=on -qmp tcp:127.0.0.1:2222,server,nowait -vnc 0.0.0.0:1 -object sev-guest,id=sev0,policy=0x5,cbitpos=47,reduced-phys-bits=5 -machine memory-encryption=sev0 -nopraghic +``` +虚拟机启动后,登陆虚拟机。 + + +### 运行CSV2虚拟机寄存器测试程序 + +``` +$ ./csv2_reg_rest +``` + +图3 CSV2虚拟机修改寄存器打印 + + ![](../../../assets/csv10-3.png) + +打开主机攻击程序,主机修改虚拟机rbx寄存器为200,CSV2虚拟机无法继续执行,CSV2虚拟机可以阻止主机篡改虚拟机的寄存器。 +``` +$ sudo -s +# echo 1 >/sys/module/kvm/parameters/vm_reg_test +``` + +图4 主机修改CSV2虚拟机寄存器打印 + + ![](../../../assets/csv10-4.png) + + diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/9-\346\265\213\350\257\225CSV3\345\206\205\345\255\230\351\232\224\347\246\273.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/9-\346\265\213\350\257\225CSV3\345\206\205\345\255\230\351\232\224\347\246\273.md" new file mode 100644 index 0000000000000000000000000000000000000000..9a15fec0d9cfd66f0b30dd74315dc47e90f84387 --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/3-\350\231\232\346\213\237\346\234\272/9-\346\265\213\350\257\225CSV3\345\206\205\345\255\230\351\232\224\347\246\273.md" @@ -0,0 +1,116 @@ +测试之前,请参考[2-1-安装CSV软件](https://openanolis.cn/sig/Hygon-Arch/doc/865622260278236994?lang=zh)准备软件环境。 + +## 功能描述 +海光4号CPU支持CSV3安全虚拟化功能,在CSV/CSV2技术加密虚拟机内存和加密虚拟机寄存器的基础上,CSV3技术增加了虚拟机安全内存隔离、关键控制信息保护、嵌套页表完整性保护等功能。 + +本文演示读写CSV3虚拟机安全内存,展示内存访问隔离效果。 + +## 测试方案说明 + +### CSV3虚拟机内存物理地址 +CSV3虚拟机所使用的安全内存由主机操作系统从系统内存中分配,并不映射到用户态地址空间,无法直接从用户进程中获取。 +因此需要从主机操作系统内核中获取并打印出分配给CSV3虚拟机使用的内存地址,用于CSV3虚拟机内存读写测试。 + +### 测试用例说明 +首先启动CSV3安全虚拟机,获取主机操作系统为CSV3虚拟机分配的内存物理地址;然后执行测试用例,对CSV3虚拟机内存执行读写测试。 + +测试用例主要包括用户层测试用例程序和内核层驱动程序两部分。如图1所示,csv3_test为用户层测试用例程序,用于接收用户输入的CSV3虚拟机内存物理地址,并将该地址传递给内核层驱动,打印测试结果;csv3_dev.ko为内核层驱动程序,用于对用户层传递的内存物理地址建立页表映射,进行内存读写,并将读取的内存数据返回给用户层。 + +![](../../../assets/csv3-test-memory-1.png) + +
图1 测试用例框图
+ +## 测试过程 +### 获取CSV3虚拟机内存地址 +可以通过以下两种方式获取CSV3虚拟机内存地址,两种方式选择一种即可。 + +推荐使用方式一。 + +#### 方式一、通过bpftrace工具获取 +该方式获取的优点为不需要修改和替换主机操作系统内核。 + +1: 安装bpftrace + +在操作系统linux发行版中安装bpftrace工具: +``` +$ sudo yum install bpftrace +``` +或 +``` +$ sudo apt install bpftrace +``` + +2: 使用bpftrace工具探测CSV3虚拟机的内存物理地址 + +在启动CSV3虚拟机前执行以下命令,开始探测: +``` +$ sudo bpftrace -e 'kretprobe:csv_alloc_from_contiguous { printf("address 0x%llx \n", retval); }' +``` + +3: 启动CSV3虚拟机 + +参考 [7-启动CSV3加密虚拟机](https://openanolis.cn/sig/Hygon-Arch/doc/984441308636882971) + +4: CSV3虚拟机启动完成后,bpftrace打印出探测到的内存地址。 + +bpftrace工具打印出CSV3虚拟机内存地址区间如下所示: +![](../../../assets/csv3-test-memory-2.png) + +#### 方式二、通过修改操作系统内核源码打印获取 +1: 在Linux内核源码arch/x86/kvm/svm/csv.c中添加打印,CSV3虚拟机启动过程中,打印出CSV3虚拟机使用的全部内存地址。 + +参考[csv3-memory-address-kernel-patch](https://gitee.com/anolis/hygon-cloud-kernel/commit/40d1732d942bebf4fc2281c06ea2f1ea46cb9341)提交修改内核源码; + +或者 + +直接使用 [anolis/hygon-cloud-kernel](https://gitee.com/anolis/hygon-cloud-kernel)仓库中的内核源码编译内核。 + +2: 重新编译并更新操作系统内核 + +参考[1-安装操作系统和内核](https://openanolis.cn/sig/Hygon-Arch/doc/865622272844371792) + +3: 开启csv.c文件debug级别log的动态打印 +``` +$ su root +# echo 'file csv.c +p' > /sys/kernel/debug/dynamic_debug/control +``` + +4: 启动CSV3虚拟机 + +参考 [7-启动CSV3加密虚拟机](https://openanolis.cn/sig/Hygon-Arch/doc/984441308636882971) + +5: 通过打印获取CSV3虚拟机安全内存地址 + +CSV3虚拟机启动完成后,在主机操作系统中执行dmesg ,并搜索“csv3 guest memory region”关键字,获取CSV3虚拟机安全内存区地址列表。 +``` +$ dmesg | grep -A 10 "csv3 guest memory region" +``` +具体需要显示地址区域的个数取决于CSV3虚拟机启动参数中定义的内存大小。 +![](../../../assets/csv3-test-memory-3.png) + + +### 获取测试用例代码 +测试用例代码在/opt/hygon/csv/csv3-memory-rw-test目录下 + +### 编译测试代码、安装测试内核驱动module + +``` +$ cd /opt/hygon/csv +$ sudo ./build_devkit.sh +$ cd /opt/hygon/csv/csv3-memory-rw-test/host-module +$ sudo insmod csv3_dev.ko +``` +编译完成的测试程序为/opt/hygon/csv/csv3-memory-rw-test/csv3_test目录下的csv3_test + +### 执行读取CSV3虚拟机内存地址测试 + +使用第一步骤中获取的CSV3虚拟机的内存地址,选取其中的一段内存区间进行内存读取测试。 + +例如选取CSV3虚拟机内存的第一段内存区间0x8c0000000,执行测试程序,尝试读取CSV3虚拟机内存。 +``` +$ sudo ./csv3_test --read_mem 0x8c0000000 --size 0x100 +``` +打印出读取到的数据全部为”FF”。 +![](../../../assets/csv3-test-memory-4.png) + +说明:第一步骤中获取的地址区间为分配给CSV3虚拟机使用的全部内存地址,其中部分地址在虚拟机启动和运行过程中可能会被作为共享内存使用,因此可能存在读取部分地址时,能够读取到内存中的数据,不显示为全FF的情况;可以忽略这块内存区间,换用其他地址区间测试。 diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/1-\347\216\257\345\242\203\346\220\255\345\273\272.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/1-\347\216\257\345\242\203\346\220\255\345\273\272.md" new file mode 100644 index 0000000000000000000000000000000000000000..6124ede34f543d9d95461d0f49a8a165e5a16ec3 --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/1-\347\216\257\345\242\203\346\220\255\345\273\272.md" @@ -0,0 +1,291 @@ +# 环境搭建 + +本文主要介绍如何搭建一套CSV机密容器环境。 + +> **注意:** 运行`CSV3`机密容器需要安全固件具有较高的版本,请参考[安全功能配置要求](https://gitee.com/hanliyang/openanolis_community/blob/master/sig/Hygon%20Arch/content/1-%E5%AE%89%E5%85%A8%E5%8A%9F%E8%83%BD%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE/0-%E5%AE%89%E5%85%A8%E5%8A%9F%E8%83%BD%E9%85%8D%E7%BD%AE%E8%A6%81%E6%B1%82.md)的**硬件配置要求章节**。 + +## 前提条件 + +### 安装系统并更新内核 + +请参考[2-1-安装CSV软件](https://openanolis.cn/sig/Hygon-Arch/doc/865622260278236994?lang=zh)准备软件环境。 + +## 安装机密容器组件 + +### 运行一键安装脚本 + +``` +sudo su root +cd /opt/hygon/csv/confidential-containers/scripts +./iso_install_for_k8s.sh +``` + +> 1. 关于该安装脚本的详细介绍请参考本文最下面的[附录](#附录); +> 2. 如何从源码编译并安装机密容器的各组件,包括kata-containers、qemu、Guest kernel等,请参考[5-源码编译机密容器各组件](https://openanolis.cn/sig/Hygon-Arch/doc/865622243115145008); + +## 部署机密容器测试环境 + +### 运行一键部署脚本 + +``` +cd /opt/hygon/csv/confidential-containers/scripts +sudo ./post_iso_install.sh +``` + +> 关于该部署脚本的详细介绍请参考[附录](#附录); + +### kubectl访问cluster权限设置 + +- 对于普通用户 + +``` +rm -rf $HOME/.kube +mkdir -p $HOME/.kube +sudo cp -f /etc/kubernetes/admin.conf $HOME/.kube/config +sudo chown $(id -u):$(id -g) $HOME/.kube/config +``` + +- 对于root用户 + +``` +export KUBECONFIG=/etc/kubernetes/admin.conf +``` + +## 附录 + +### 一、一键安装脚本的介绍 + +#### 1.1 加载必要的模块 + +将以下模块设置为系统预加载 + +``` +echo "br_netfilter" > /etc/modules-load.d/br_netfilter.conf +echo "vfio-pci" > /etc/modules-load.d/vfio.conf + +tee /etc/modules-load.d/vhost.conf < /etc/containerd/config.toml +sed -i 's#registry.k8s.io/pause#registry.cn-hangzhou.aliyuncs.com/google_containers/pause#g' etc/containerd/config.toml + +mkdir -p /etc/systemd/system/containerd.service.d +cat >>/etc/systemd/system/containerd.service.d/containerd-for-cc-override.conf<>/etc/containerd/config.toml< cert_chain.cert +sudo mv cert_chain.cert /opt/csv/ +``` + +#### 2.7 运行simple-kbs + +``` +cd /opt/simple-kbs +sudo docker compose up -d +麒麟系统docker 版本较低,命令如下: +sudo docker-compose up -d +``` + diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/10-\345\210\266\344\275\234\344\270\200\344\270\252\346\226\260\347\232\204\347\255\276\345\220\215\351\225\234\345\203\217\345\271\266\351\203\250\347\275\262.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/10-\345\210\266\344\275\234\344\270\200\344\270\252\346\226\260\347\232\204\347\255\276\345\220\215\351\225\234\345\203\217\345\271\266\351\203\250\347\275\262.md" new file mode 100644 index 0000000000000000000000000000000000000000..a68ffecd814b528942ff3b87956d0d1b09e035b6 --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/10-\345\210\266\344\275\234\344\270\200\344\270\252\346\226\260\347\232\204\347\255\276\345\220\215\351\225\234\345\203\217\345\271\266\351\203\250\347\275\262.md" @@ -0,0 +1,152 @@ +# 制作一个新的签名镜像并部署 + +本文主要为您介绍如何制作一个新的签名镜像,并部署pod。 + +## 准备镜像 + +> 示例中使用docker.io存放签名镜像 + +``` +# 使用自己的账号、密码登录 +sudo docker login +# 以busybox为例 +sudo docker pull busybox +# YOUR_USER替换为自己的用户名,YOUR_IMAGE替换为自己想要命名的image name +sudo docker image tag busybox docker.io/YOUR_USER/YOUR_IMAGE +sudo docker push docker.io/YOUR_USER/YOUR_IMAGE +``` + +## 使用cosign签名镜像 + +``` +cosign generate-key-pair +# 输入密码,密码是用来加密私钥的 +cosign login docker.io --username YOUR_USER +sudo cosign sign --key cosign.key docker.io/YOUR_USER/YOUR_IMAGE +``` + +## 自定义policy.json + +> 创建一个新的policy.json,自定义image的pull规则,如下面示例所示,注意keyPath对应的位置用于索引公钥。 + +``` +{ + "default": [{"type": "insecureAcceptAnything"}], + "transports": { + "docker": { + "docker.io/pawsonfang/mybusybox": [ + { + "type": "sigstoreSigned", + "keyPath": "kbs:///default/cosign-public-key/test" + } + ], + "docker.io/pawsonfang/busybox_signed": [ + { + "type": "sigstoreSigned", + "keyPath": "kbs:///default/cosign-public-key/test2" + } + ] + } + } +} +``` + +## 根据kbc_mod更新公钥和policy + +> 对于online_sev_kbc,将公钥和policy添加到数据库; +> +> 对于offline_fs_kbc,将公钥和policy更新到initrd中。 + +### online_sev_kbc + +- 获取simple-kbs的container id + + ``` + KBS_CID=$(sudo docker ps -aqf "name=^simple-kbs-server") + ``` + + + +- 更新policy文件和公钥文件到simple-kbs + + ``` + cd /opt/simple-kbs/resources + sudo docker cp /path/to/policy.json ${KBS_CID}:/usr/local/bin/resources/image_pull_policy.json + sudo docker cp /path/to/cosign.pub ${KBS_CID}:/usr/local/bin/resources/cosign2.pub + ``` + +- 设置数据库参数 + + ``` + KBS_DB_USER="kbsuser" + KBS_DB_PW="kbspassword" + KBS_DB="simple_kbs" + KBS_DB_TYPE="mysql" + KBS_DB_HOST=$(sudo docker network inspect simple-kbs_default \ + | jq -r '.[].Containers[] | select(.Name | test("simple-kbs[_-]db.*")).IPv4Address' \ + | sed "s|/.*$||g") + ``` + + 插入新的公钥keyid:resource_path信息到数据库中 + + ``` + mysql -u${KBS_DB_USER} -p${KBS_DB_PW} -h ${KBS_DB_HOST} -D ${KBS_DB} < ../initrd.new.img +gzip ../initrd.new.img +cd ../ && mv initrd.new.img.gz initrd.new.img +cp initrd.new.img /opt/confidential-containers/share/kata-containers/kata-containers-initrd-csv-hygon-gpu.img.offline_fs_kbc +``` + +#### 使用新的image启动pod,此处以online_sev_kbc为例 + +> YOUR_USER/YOUR_IMAGE替换为自己的镜像地址 + +``` +cat <<-EOF | kubectl apply -f - +apiVersion: v1 +kind: Pod +metadata: + labels: + run: test-sign-online2 + name: test-sign-online2 +spec: + containers: + - image: docker.io/YOUR_USER/YOUR_IMAGE + name: test-sign-online2 + imagePullPolicy: Always + dnsPolicy: ClusterFirst + restartPolicy: Never + runtimeClassName: kata-qemu-csv +EOF +``` + diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/11-\344\275\277\347\224\250\350\272\253\344\273\275\351\252\214\350\257\201\344\277\241\346\201\257\344\270\213\350\275\275\351\225\234\345\203\217.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/11-\344\275\277\347\224\250\350\272\253\344\273\275\351\252\214\350\257\201\344\277\241\346\201\257\344\270\213\350\275\275\351\225\234\345\203\217.md" new file mode 100644 index 0000000000000000000000000000000000000000..557459da1807e3f88f0e1559ad7236bc194b0b15 --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/11-\344\275\277\347\224\250\350\272\253\344\273\275\351\252\214\350\257\201\344\277\241\346\201\257\344\270\213\350\275\275\351\225\234\345\203\217.md" @@ -0,0 +1,88 @@ +# 使用身份验证信息下载镜像 + +> 对于一些私人仓库,身份验证信息通过后,才能下载镜像,所以需要添加账号的credential信息到kbs或initrd中。 +> + +## 添加您的账号信息到docker_auth_config.json + +- 首先获取账户名密码的base64编码 + +**下面的账号密码只是作为示例,请替换成客户自己的实际账号密码** + +``` +$ echo "pawsonfang:Passw0rd123" | base64 +cGF3c29uZmFuZzpQYXNzdzByZDEyMwo= +``` + +- 将base64编码更新到docker_auth_config.json + +``` +{ + "auths": { + "https://index.docker.io/v1/": { + "auth": "bGl1ZGFsaWJqOlBhc3N3MHJkIXFhego=" + }, + "quay.io": { + "auth": "bGl1ZGFsaWJqOlBhc3N3MHJkIXFhego=" + }, + "docker.io": { + "auth": "cGF3c29uZmFuZzpQYXNzdzByZDEyMwo=" + } + } +} +``` + +## 更新信息到kbs或initrd + +> 对于online_sev_kbc,更新信息到kbs中; +> +> 对于offline_fs_kbc,更新信息到initrd; +> +> offline_sev_kbs不支持该功能。 + +#### online_sev_kbc + +- 获取simple-kbs的container id + +``` +KBS_CID=$(sudo docker ps -aqf "name=^simple-kbs-server") +``` + +- 更新json文件到simple-kbs + +``` +cd /opt/simple-kbs/resources +sudo docker cp docker_auth_config.json ${KBS_CID}:/usr/local/bin/resources/docker_auth_config.json +``` + +#### offline_fs_kbc + +- 解包initrd + +``` +sudo su root +cp /opt/confidential-containers/share/kata-containers/kata-containers-initrd-csv-hygon-gpu.img.offline_fs_kbc ./initrd.img.gz +gunzip initrd.img.gz +mkdir initrd +cd initrd/ +cpio -ivmd < ../initrd.img +``` + +- 将新的json文件的base64更新到initrd中 + +``` +cat /path/to/docker_auth_config.json | base64 --wrap=0 +# 把输出更新到etc/aa-offline_fs_kbc-resources.json的default/credential/test字段 +``` + +- 打包initrd + +``` +sudo su root +cd initrd/ +find . | cpio -o -H newc > ../initrd.new.img +gzip ../initrd.new.img +cd ../ && mv initrd.new.img.gz initrd.new.img +cp initrd.new.img /opt/confidential-containers/share/kata-containers/kata-containers-initrd-csv-hygon-gpu.img.offline_fs_kbc +``` + diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/12-\351\235\236\345\212\240\345\257\206kata\347\233\264\351\200\232DCU.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/12-\351\235\236\345\212\240\345\257\206kata\347\233\264\351\200\232DCU.md" new file mode 100644 index 0000000000000000000000000000000000000000..34c90c4da9b184c557ae6ebf6a1691a343e8921f --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/12-\351\235\236\345\212\240\345\257\206kata\347\233\264\351\200\232DCU.md" @@ -0,0 +1,318 @@ +# 非加密kata直通DCU + +## 版本要求 + +`kata-containers` 只兼容使用`unix socket`的`containerd`,所以对于`containerd`有以下版本要求 + +| 版本 | 原因 | +| --------- | ------------------------------------------------------------ | +| >= V1.5.0 | `containerd`从`v1.5.0`正式开始使用`unix socket` | +| >= V1.4.3 | 为了修复`CVE-2020-15257`漏洞,从`V1.4.3`开始从`abstract socket`切换到`unix socket` | +| >= V1.3.9 | 为了修复`CVE-2020-15257`漏洞,从`V1.3.9`开始从`abstract socket`切换到`unix socket` | + +`containerd` 版本查看方法 + +``` +containerd -v +``` + +对于使用rke2的用户,版本推荐如下: + +| 版本 | 原因 | +| ----------- | ------------------------------------------------------------ | +| >= v1.22.3 | `Rke2` 从`v1.22.3`开始,将`containerd`升级为`v1.5.0+` | +| >= V1.20.15 | `v1.20.15`对应的`containerd`版本为`v1.4.12`,实测也可以兼容`kata-containers` | + + + +## BIOS & OS设置 + +#### 1. BIOS打开IOMMU + +使用DCU直通功能必须打开BIOS的IOMMU功能,具体请参考[0-硬件配置要求](https://openanolis.cn/sig/Hygon-Arch/doc/898824499700098972)。 + +#### 2. OS设置IOMMU为pt模式 + +``` +sudo su root +sed -i 's!\(^GRUB_CMDLINE_LINUX=.*\)"$!\1 iommu=pt"!' /etc/default/grub +update-grub +``` + +#### 3. 安装`hydcu_pci_fixup_header`模块 + +> `非加密kata直通DCU`不需要安装hygon内核,只需要安装该内核模块即可 + +``` +git clone https://gitee.com/anolis/hygon-devkit.git +cd hygon-devkit/csv/confidential-containers/pkg +unzip fixup-header-release-hydcu_pci_fixup_header.zip +cd fixup-header-release-hydcu_pci_fixup_header +make +sudo make install +``` + +#### 4. 重启后检查IOMMU设置成功 + +``` +sudo reboot +dmesg | grep -i IOMMU +``` + +得到类似如下的输出,表示IOMMU设置成功: + +``` +[ 0.626887] iommu: Default domain type: Passthrough (set via kernel command line) +[ 0.873056] pci 0000:00:00.2: AMD-Vi: IOMMU performance counters supported +[ 0.873112] pci 0000:40:00.2: AMD-Vi: IOMMU performance counters supported +[ 0.873157] pci 0000:00:01.0: Adding to iommu group 0 +[ 0.873172] pci 0000:00:01.2: Adding to iommu group 1 +[ 0.873187] pci 0000:00:01.4: Adding to iommu group 2 +[ 0.873207] pci 0000:00:02.0: Adding to iommu group 3 +``` + +## 安装和设置kata + +#### 1. 安装kata-containers + +``` +cd hygon-devkit/csv/confidential-containers/pkg +tar xvJf confidential-containers.tar.xz -C / +``` + +#### 2. `containerd`添加kata runtime + +``` +sudo su root +cd /var/lib/rancher/rke2/bin +ln -s /opt/confidential-containers/bin/containerd-shim-kata-v2 containerd-shim-kata-v2 +cd /var/lib/rancher/rke2/agent/etc/containerd +cp config.toml config.toml.tmpl + +cat >>config.toml.tmpl< 注意:示例中的1d94:53b7为第一步lspci -nn中打印出的值,请更新为自己设备的实际值。 + +``` +sudo su root +sed -i 's!\(^GRUB_CMDLINE_LINUX=.*\)"$!\1 vfio-pci.ids=1d94:53b7"!' /etc/default/grub +``` + +### 启动DCU直通的容器 + +- 启动容器 + +``` +cat <<-EOF | kubectl apply -f - +apiVersion: v1 +kind: Pod +metadata: + name: ubuntu-dcu +spec: + runtimeClassName: kata + containers: + - name: ubuntu-dcu + image: docker.io/pawsonfang/ubuntu-dcu:latest + command: ["tail", "-f", "/dev/null"] + resources: + limits: + dcu/a100: "1" + volumeMounts: + - mountPath: /opt/dtk + name: dtk + - mountPath: /dev + name: dev + securityContext: + privileged: true + volumes: + - name: dtk + hostPath: + path: /opt/dtk-22.04.2 + - name: dev + hostPath: + path: /dev +EOF +``` + +- 进入容器中,使用DCU之前,需要配置环境变量: + +``` +kubectl exec -it ubuntu-dcu -- bash +source /opt/dtk/env.sh +rocminfo +``` + +- 期望结果(能看到CPU和DCU两个设备): + +``` +hygon module is loaded +===================== +HSA System Attributes +===================== +Runtime Version: 1.1 +System Timestamp Freq.: 1000.000000MHz +Sig. Max Wait Duration: 18446744073709551615 (0xFFFFFFFFFFFFFFFF) (timestamp count) +Machine Model: LARGE +System Endianness: LITTLE + +========== +HSA Agents +========== +******* +Agent 1 +******* + Name: Hygon C86 3250 8-core Processor + Uuid: CPU-XX + Marketing Name: Hygon C86 3250 8-core Processor + Vendor Name: HygonGenuine + Feature: None specified + Profile: FULL_PROFILE + Float Round Mode: NEAR + . + . + . +******* +Agent 2 +******* + Name: ZIFANG + Uuid: GPU-XX + Marketing Name: C878186 + Vendor Name: HYGON + Feature: KERNEL_DISPATCH + Profile: BASE_PROFILE + Float Round Mode: NEAR + Max Queue Number: 128(0x80) + Queue Min Size: 4096(0x1000) + Queue Max Size: 131072(0x20000) + Queue Type: MULTI + Node: 1 + Device Type: DCU +. +. +. +*** Done *** +``` + +## diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/2-\346\265\213\350\257\225CSV\346\234\272\345\257\206\345\256\271\345\231\250.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/2-\346\265\213\350\257\225CSV\346\234\272\345\257\206\345\256\271\345\231\250.md" new file mode 100644 index 0000000000000000000000000000000000000000..48a83ab17f09ab01b78051b78b0f159b70cd589c --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/2-\346\265\213\350\257\225CSV\346\234\272\345\257\206\345\256\271\345\231\250.md" @@ -0,0 +1,347 @@ +# 测试CSV机密容器 + +## CSV机密容器基本特性测试 + +### 一、不基于CSV,运行一个普通容器 + +- 启动POD + +```shell +cat <<-EOF | kubectl apply -f - +apiVersion: v1 +kind: Pod +metadata: + labels: + run: nginx + name: nginx +spec: + containers: + - image: bitnami/nginx:1.22.0 + name: nginx + dnsPolicy: ClusterFirst + runtimeClassName: kata +EOF +``` + +- 预期结果: + +```shell +pod/nginx created +``` + +- 查看 pod 状态: + +```shell +kubectl get pods +``` + +- 预期结果如下,注意, STATUS 要是 Running 。 + +```shell +NAME READY STATUS RESTARTS AGE +nginx 1/1 Running 0 3m50s +``` + +### 二、运行一个CSV/CSV2/CSV3机密容器 +**该实践支持情况如下:** + +| 机密容器类型 | 是否支持 | +| --- | --- | +| CSV | 是 | +| CSV2 | 是 | +| CSV3 | 是 | + +- 编辑 kata 配置文件: + + - 设置机密容器为`CSV`、`CSV2`、`CSV3`的其中一种。 + + ```shell + # 对于CSV机密容器,执行以下语句 + sudo sed -i -e 's/^\(sev_guest_policy\) = .*$/\1 = 3/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + + # 对于CSV2机密容器,执行以下语句 + sudo sed -i -e 's/^\(sev_guest_policy\) = .*$/\1 = 7/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + + # 对于CSV3机密容器,执行以下语句 + sudo sed -i -e 's/^\(sev_guest_policy\) = .*$/\1 = 71/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + sudo sed -i -e 's/^\(vcpu_model\) = .*$/\1 = \"Dhyana\"/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + + - 关闭pre-attestation(如果需要使用该功能,请参考本文最下面的[增强特性](#增强特性)) + + ```shell + sudo sed -i -e 's/^\(guest_pre_attestation =\).*$/\1 false/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + + - initrd指向支持offline_fs_kbc模式的initrd(其他initrd为本文最下面的[增强特性](#增强特性)所准备) + + ```shell + sudo sed -i -e 's#^\(initrd\).*=.*$#\1 = \"/opt/confidential-containers/share/kata-containers/kata-containers-initrd-csv-hygon-gpu.img.offline_fs_kbc\"#g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + + - 禁用sev_kbc模式 + + `agent.https_proxy=http://ip:port agent.no_proxy=10.*.*.*,172.*.*.*` **不要直接拷贝,仔细阅读下面说明** + + ```shell + sudo sed -i -e 's#^\(kernel_params\).*=.*$#\1 = \"agent.https_proxy=http://ip:port agent.no_proxy=10.*.*.*,172.*.*.* agent.aa_kbc_params=offline_fs_kbc::null agent.enable_signature_verification=false \"#g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + + 1.测试示例中使用的是dockerhub 仓库镜像,由于国内网络目前访问不了dockerhub 需要使用代理,代理参数`agent.https_proxy=http://ip:port agent.no_proxy=10.*.*.*,172.*.*.*` **http://ip:port 改为客户自己实际代理地址,后续机密容器测试步骤都需要加代理,ip 不要设置为127.0.0.1本地地址** + + 2.如果没有代理,需要购买企业版本阿里云容器,本地制作好容器镜像push到阿里云仓库,企业版地址: + https://www.aliyun.com/product/acr?spm=5176.21213303.J_qCOwPWspKEuWcmp8qiZNQ.30.3f952f3d26uzeU&scm=20140722.S_product@@%E4%BA%91%E4%BA%A7%E5%93%81@@88099._.RL_%E4%BC%81%E4%B8%9A%E7%89%88%E5%AE%B9%E5%99%A8-LOC_search~UND~product~UND~item-OR_ser-V_3-RE_productNew-P0_4 + + 3.**如果上述两个条件都不满足,请搭建私有仓库**,搭建流程参考[2-9-3-机密容器](https://openanolis.cn/sig/Hygon-Arch/doc/1121587123561305791?lang=zh)中 **https私有仓库搭建** 章节 + + 4.**机密容器镜像是虚拟机通过image 模块直接从远端仓库获取的镜像,image 模块是社区为虚拟机定制的镜像管理模块,不支持类似主机端docker 在/etc/docker/daemon.json 文件中配置国内加速器的方式获取dockerhub仓库镜像** + + +- 启动POD + +```shell +cat <<-EOF | kubectl apply -f - +apiVersion: v1 +kind: Pod +metadata: + labels: + run: test-csv + name: test-csv +spec: + containers: + - image: docker.io/library/busybox:latest + name: test-csv + imagePullPolicy: Always + dnsPolicy: ClusterFirst + restartPolicy: Never + runtimeClassName: kata-qemu-csv +EOF +``` + +- 查看 pod 是否启动成功: + +```shell +kubectl get pods +``` + +- 预期结果如下: + +```shell +NAME READY STATUS RESTARTS AGE +test-csv 1/1 Running 0 146m +``` + +- 检查CSV/CSV2/CSV3已被使能: + + ```shell + # 对于CSV机密容器 + kubectl exec -it test-csv -- dmesg | grep "HYGON.* CSV" + + # 对于CSV2机密容器 + kubectl exec -it test-csv -- dmesg | grep "HYGON.* CSV2" + + # 对于CSV3机密容器 + kubectl exec -it test-csv -- dmesg | grep "HYGON.* CSV3" + ``` + +- 预期结果如下: + + ``` + # 对于CSV机密容器,预期为: + [ 0.036854] HYGON Memory Encryption Features active: CSV + 或 + [ 0.036854] HYGON CSV + + # 对于CSV2机密容器,预期为: + [ 0.036854] HYGON Memory Encryption Features active: CSV CSV2 + 或 + [ 0.036854] HYGON CSV2 + + # 对于CSV3机密容器,预期为: + [ 0.036854] HYGON Memory Encryption Features active: CSV CSV2 CSV3 + 或 + [ 0.036854] HYGON CSV3 + ``` + +#### 三、验证CSV/CSV2内存加密 +**该实践支持情况如下:** + +| 机密容器类型 | 是否支持 | 说明 | +| --- | --- | --- | +| CSV | 是 | - | +| CSV2 | 是 | - | +| CSV3 | 是 | CSV3验证内存加密的方法与CSV/CSV2有所区别,直接参考[测试CSV3内存隔离](https://gitee.com/anolis/community/blob/master/sig/Hygon%20Arch/content/2-CSV%E6%B5%8B%E8%AF%95%E6%96%87%E6%A1%A3/3-%E8%99%9A%E6%8B%9F%E6%9C%BA/9-%E6%B5%8B%E8%AF%95CSV3%E5%86%85%E5%AD%98%E9%9A%94%E7%A6%BB.md)即可。 | + +- dump内存确认内存已加密 + + ```shell + sudo /opt/hygon/csv/dump-kata-memory.sh crictl test-csv + ``` + +- 预期结果如下: + + ``` + dd if=/proc/139404/mem bs=4096 count=1 skip=(0x7fe83be00000/4096) | hexdump + dd: /proc/139404/mem: cannot skip to specified offset + 1+0 records in + 1+0 records out + 4096 bytes (4.1 kB, 4.0 KiB) copied, 7.6193e-05 s, 53.8 MB/s + 00000000 a7 d2 41 29 83 46 59 66 40 49 d5 c5 92 18 69 00 |..A).FYf@I....i.| + 00000010 f4 1a 63 f1 08 00 c6 50 81 c0 51 2d 40 d4 95 f9 |..c....P..Q-@...| + 00000020 18 03 c2 78 e9 e4 db c2 c5 90 92 93 d7 d2 fa 9e |...x............| + 00000030 18 03 c2 78 e9 e4 db c2 c5 90 92 93 d7 d2 fa 9e |...x............| + 00000040 c4 3f 45 c0 5b 0e a3 8b 4e b9 b3 6f 8d 39 9d ac |.?E.[...N..o.9..| + 00000050 c4 3f 45 c0 5b 0e a3 8b 4e b9 b3 6f 8d 39 9d ac |.?E.[...N..o.9..| + 00000060 c4 3f 45 c0 5b 0e a3 8b 4e b9 b3 6f 8d 39 9d ac |.?E.[...N..o.9..| + 00000070 c4 3f 45 c0 5b 0e a3 8b 4e b9 b3 6f 8d 39 9d ac |.?E.[...N..o.9..| + 00000080 62 f4 46 ea 22 03 92 ec 06 be 3c 20 78 2d 1e 8f |b.F.".....< x-..| + 00000090 62 f4 46 ea 22 03 92 ec 06 be 3c 20 78 2d 1e 8f |b.F.".....< x-..| + 000000a0 62 f4 46 ea 22 03 92 ec 06 be 3c 20 78 2d 1e 8f |b.F.".....< x-..| + 000000b0 62 f4 46 ea 22 03 92 ec 06 be 3c 20 78 2d 1e 8f |b.F.".....< x-..| + 000000c0 d9 a9 3a c1 19 5e 69 29 de d7 b7 c1 80 cf 43 e2 |..:..^i)......C.| + 000000d0 d9 a9 3a c1 19 5e 69 29 de d7 b7 c1 80 cf 43 e2 |..:..^i)......C.| + ``` + +#### 四、测试Runtime Attestation功能 +**该实践支持情况如下:** + +| 机密容器类型 | 是否支持 | +| --- | --- | +| CSV | 是 | +| CSV2 | 是 | +| CSV3 | 是 | + +- 部署CSV/CSV2/CSV3机密容器,把`attestation应用程序`和`csv-guest驱动`mount到容器中 + + ``` + cat <<-EOF | kubectl apply -f - + apiVersion: v1 + kind: Pod + metadata: + labels: + run: test-attestation + name: test-attestation + spec: + containers: + - image: docker.io/library/ubuntu:latest + name: test-attestation + imagePullPolicy: Always + volumeMounts: + - mountPath: /root/attestation + name: attestation + - mountPath: /dev + name: dev + volumes: + - name: attestation + hostPath: + path: /opt/hygon/csv/attestation + - name: dev + hostPath: + path: /dev + dnsPolicy: ClusterFirst + restartPolicy: Never + runtimeClassName: kata-qemu-csv + EOF + ``` + +- 查看 pod 是否启动成功: + + ``` + kubectl get pods + ``` + +- 预期结果如下: + + ``` + NAME READY STATUS RESTARTS AGE + test-attestation 1/1 Running 0 65s + ``` + + + +- 获取attestation report:ioctl-get-attestation执行会在其所在目录生成认证报告report.cert + + ``` + kubectl exec -it test-attestation -- bash + cd /root/attestation/ + ./ioctl-get-attestation + # 退出pod + exit + ``` + + 预期结果如下: + + ``` + get attestation report & save to ./report.cert + user data: 0x561a739f86b0 + data: + 75736572206461746100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + mnonce: + 67c6697351ff4aec29cdbaabf2fbe346 + hash: + cd01d9775f66a2fc94aa2df90441e66b233b4a2205d1ea54e8246df6792c7d7c + data: user data + mem.va: 561a739f86b0 + done + ``` + +- 验证attestation report:可以在任意设备上验证,验证report时会首先验证证书链,而证书链需要联网下载 + + ``` + cd /opt/hygon/csv/attestation + sudo chmod 666 report.cert + sudo ./verify-attestation true + ``` + + 预期结果如下: + + ``` + verify attestation report + load attestation report from ./report.cert + verify report + report.userdata: + 75736572206461746100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + report.mnonce: + 67c6697351ff4aec29cdbaabf2fbe346 + report.measure: + e4ea9eea6db32e45c331efe50683fc94bf83d296f5b1b74e75dc6ab126e343fb + report.sn: + 4e5a4139543032303832363035000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + verify: do verify + Signature: + r=6F88F8CB981C2DAB4262F7B2AA642655746C9D61B7CAE1D79AC7994A2452203E + s=D3A8EFE32979074D7E4C3EDEE90E35F5DB2AC5063F0CCF8663F8205A515B6D1E + SM2_do_verify success! + verify success + ``` + + verify-attestation会使用PEK公钥验证认证报告的签名,并且从证书服务器下载证书链验证HRK->HSK->CEK->PEK证书的签名,mnonce、userdata 获取报告和验证报告过程都会输出打印,请认证方检查确认两者是否一致。 +。 + +## 增强特性 + +#### 一、CSV独有的增强特性 + +**以下特性为相对于SEV、TDX,CSV机密容器所独有的特性:** + +| 特性 | 特性说明 | 限制 | +| --- | --- | --- | +| 复用ASID | 通过复用ASID,支持一台设备部署更多的机密容器,具体参考[3-测试ASID复用](https://openanolis.cn/sig/Hygon-Arch/doc/865622239407380268);| 1)只有海光2号和海光C86-3G支持;
2)**海光C86-4G支持500个虚拟机密钥,不支持该功能;**| +| 机密容器直通DCU | 将DCU直通进机密容器,加速机密运算,具体参考[4-测试直通DCU](https://openanolis.cn/sig/Hygon-Arch/doc/865622241026381614)。| 1)CSV/CSV2机密容器支持DCU直通;
2)**CSV3机密容器暂不支持DCU直通;** | + +#### 二、社区的增强特性 + +Confidential Containers社区为了更好的利用TEE来保护容器和数据,并交付云原生机密计算,提供了一些增强特性。CSV机密容器同样也支持这些特性,如: + +1. 使用pre-attestation来认证guest和注入密钥 +2. 使用加密或签名镜像来部署workload,保护镜像的完整性 +3. 支持用户自定义policy来验证Guest Firmware Measurement +4. 支持使用身份验证信息下载镜像 + +为了支持上述特性,社区引入了[simple-kbs](https://github.com/confidential-containers/simple-kbs),作为一个基础的key broker service。请参考以下文档来测试上述特性: + +1. [6-使用加密镜像来部署workload](https://openanolis.cn/sig/Hygon-Arch/doc/865622244851586866) +2. [7-使用签名镜像来部署workload](https://openanolis.cn/sig/Hygon-Arch/doc/865622246403479348) +3. [8-自定义Policy来验证Measurement](https://openanolis.cn/sig/Hygon-Arch/doc/865622248139921206) +4. [11-使用身份验证信息下载镜像](./11-使用身份验证信息下载镜像.md) + diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/3-\346\265\213\350\257\225ASID\345\244\215\347\224\250.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/3-\346\265\213\350\257\225ASID\345\244\215\347\224\250.md" new file mode 100644 index 0000000000000000000000000000000000000000..6546f63d3ed63e28147762ae3be9c689e84e5d0c --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/3-\346\265\213\350\257\225ASID\345\244\215\347\224\250.md" @@ -0,0 +1,100 @@ +# 测试ASID复用 +**麒麟系统不支持** + +## 功能描述 +**该实践支持情况如下:** + +| 机密容器类型 | 是否支持 | 特殊限制 | +| --- | --- | --- | +| CSV | 是 | **自海光C86-4G开始,不支持ASID复用** | +| CSV2 | 是 | **自海光C86-4G开始,不支持ASID复用** | +| CSV3 | **否** | - | + +海光2号、C86-3G CPU最多支持15个CSV ASID,而每个CSV机密容器需要占用1个ASID。为了满足同一台设备上同时运行超过15个CSV机密容器的需求,引入了ASID复用的功能。 + +该功能可以让同一个用户的多个CSV机密容器复用同一个ASID,虽然这种情况下,多个CSV机密容器共用同一个ASID索引的内存加密密钥,但是这些机密容器从属于同一个用户,不存在安全性问题。 + +使用参数user-id来指定用户,同一个ASID最多可以被64 个CSV kata容器复用。 + +## 测试用例 + +- 指定user-id + + ``` + sudo sed -i 's/#* *mem_encryption_user.*$/mem_encryption_user_id = "testuser"/' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + +- 创建pod部署文件 + + ``` + cat >>test-asid-reuse.yaml<DCU直通功能** 章节。 + +#### 2. 检查IOMMU设置成功 + +``` +dmesg | grep -i IOMMU +``` + +得到类似如下的输出,表示IOMMU设置成功: + +``` +[ 0.626887] iommu: Default domain type: Passthrough (set via kernel command line) +[ 0.873056] pci 0000:00:00.2: AMD-Vi: IOMMU performance counters supported +[ 0.873112] pci 0000:40:00.2: AMD-Vi: IOMMU performance counters supported +[ 0.873157] pci 0000:00:01.0: Adding to iommu group 0 +[ 0.873172] pci 0000:00:01.2: Adding to iommu group 1 +[ 0.873187] pci 0000:00:01.4: Adding to iommu group 2 +[ 0.873207] pci 0000:00:02.0: Adding to iommu group 3 +``` + +## 功能描述 + +把DCU直通进CSV机密容器中,使其处于可信执行环境中,在可信执行环境中借助DCU加速机密计算workload。 + +## 测试用例 + +### 修改kata配置文件 + +> 为了简化测试,此处选择禁用pre-attestation,但也可以同时使用DCU直通和pre-attestation等功能。 +> +> 如果需要使用该功能,请参考[6-使用加密镜像来部署workload](https://openanolis.cn/sig/Hygon-Arch/doc/865622244851586866)。 + +- 关闭pre-attestation + + ``` + sudo sed -i -e 's/^\(guest_pre_attestation =\).*$/\1 false/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv-dcu.toml + ``` + +- initrd指向支持offline_fs_kbc模式的initrd(其他initrd为社区增强特性准备) + + ``` + sudo sed -i -e 's#^\(initrd\).*=.*$#\1 = \"/opt/confidential-containers/share/kata-containers/kata-containers-initrd-csv-hygon-gpu.img.offline_fs_kbc\"#g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv-dcu.toml + ``` + +- 禁用sev_kbc模式 + + 由于国内网络目前访问不了dockerhub 需要使用代理,代理参数agent.https_proxy=http://ip:port agent.no_proxy=10.*.*.*,172.*.*.* http://ip:port 为代理地址 + ``` + sudo sed -i -e 's#^\(kernel_params\).*=.*$#\1 = \"agent.https_proxy=http://ip:port agent.no_proxy=10.*.*.*,172.*.*.* agent.aa_kbc_params=offline_fs_kbc::null agent.enable_signature_verification=false \"#g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv-dcu.toml + ``` +- 设置内存 + ``` + sudo sed -i "s/^default_memory *=.*\$/default_memory = 10240/g" /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv-dcu.toml + ``` +### 部署DCU直通环境 + +#### 1. 查找DCU设备 + +- 找到DCU设备 + + ``` + lspci -nn | grep -e "Display" -e "Co-processor" | grep "Haiguang" + ``` + +- 结果如下: + 如果是Z100卡,那么显示的是Display,如果是K100/K100-AI卡,显示的是Co-processor” + + ``` + $ lspci -nn | grep -e "Display" -e "Co-processor" | grep "Haiguang" + 03:00.0 Display controller: Chengdu Haiguang IC Design Co., Ltd. Device [1d94:53b7] (rev 01) + ``` + + `03:00.0`为该设备的设备标识,其完整信息为: `0000:03:00.0` + + +#### 2. 使用一键部署脚本,部署DCU环境 + +``` +cd /opt/hygon/csv/confidential-containers/scripts +# 参数请替换为上一步实际得到的id +sudo ./setup_dcu_passthrough.sh -d 0000:03:00.0 +``` + +该脚本主要实现以下功能: + +1. 把指定的DCU设备绑定到VFIO +2. 安装vfio-device-plugin,该插件负责与k8s交互,将vfio device直通进CSV机密容器 +3. 下载DTK,DTK文件较大,直接安装进容器镜像中,会导致镜像太大,本测试中,通过将DTK mount到容器中的方式,来使用 +4. 下载DCU驱动,安装到host上。这个步骤的目的是将/opt/hyhal目录挂载到容器中。 + +> 注意: 第4步安装驱动的过程中,如果询问是否更新rock、hyhal、vbios,一律选择'Y'或者'y'。 + +#### 3. (可选)上一步的设置,设备重启失效,想要永久生效,请做以下设置: + +> 注意:示例中的1d94:53b7为第一步lspci -nn中打印出的值,请更新为自己设备的实际值。 + +``` +sudo su root +sed -i 's!\(^GRUB_CMDLINE_LINUX=.*\)"$!\1 vfio-pci.ids=1d94:53b7"!' /etc/default/grub +``` + + + +### 启动DCU直通的容器 + +- 启动容器 + +``` +cat <<-EOF | kubectl apply -f - +apiVersion: v1 +kind: Pod +metadata: + name: ubuntu-dcu +spec: + runtimeClassName: kata-qemu-csv-dcu + containers: + - name: ubuntu-dcu + image: docker.io/pawsonfang/ubuntu-dcu:latest + command: ["tail", "-f", "/dev/null"] + resources: + limits: + dcu/a100: "1" + volumeMounts: + - mountPath: /opt/dtk + name: dtk + - mountPath: /opt/hyhal + name: hyhal + - mountPath: /dev + name: dev + securityContext: + privileged: true + volumes: + - name: dtk + hostPath: + path: /opt/dtk-24.04.1 + - name: hyhal + hostPath: + path: /opt/hyhal + - name: dev + hostPath: + path: /dev +EOF +``` + +- 进入容器中,使用DCU之前,需要配置环境变量: + +``` +kubectl exec -it ubuntu-dcu -- bash +HYCONTAINER_ENV=0 /opt/hyhal/bin/hymgr & +source /opt/dtk/env.sh +rocminfo +``` + +- 期望结果(能看到CPU和DCU两个设备): + +``` +hygon module is loaded +===================== +HSA System Attributes +===================== +Runtime Version: 1.1 +System Timestamp Freq.: 1000.000000MHz +Sig. Max Wait Duration: 18446744073709551615 (0xFFFFFFFFFFFFFFFF) (timestamp count) +Machine Model: LARGE +System Endianness: LITTLE + +========== +HSA Agents +========== +******* +Agent 1 +******* + Name: Hygon C86 3250 8-core Processor + Uuid: CPU-XX + Marketing Name: Hygon C86 3250 8-core Processor + Vendor Name: HygonGenuine + Feature: None specified + Profile: FULL_PROFILE + Float Round Mode: NEAR + . + . + . +******* +Agent 2 +******* + Name: ZIFANG + Uuid: GPU-XX + Marketing Name: C878186 + Vendor Name: HYGON + Feature: KERNEL_DISPATCH + Profile: BASE_PROFILE + Float Round Mode: NEAR + Max Queue Number: 128(0x80) + Queue Min Size: 4096(0x1000) + Queue Max Size: 131072(0x20000) + Queue Type: MULTI + Node: 1 + Device Type: DCU +. +. +. +*** Done *** +``` + +- 测试完恢复内存设置 + + ``` + sudo sed -i "s/^default_memory *=.*\$/default_memory = 2048/g" /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv-dcu.toml + ``` + +## 附录 + +### 制作DCU容器镜像的Dockerfile + +``` +FROM ubuntu:20.04 +RUN apt-get update \ + && apt-get install wget pciutils ocaml libelf-dev libnuma1 libdrm2 libdrm-amdgpu1 kmod build-essential -y +``` + diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/5-\346\272\220\347\240\201\347\274\226\350\257\221\346\234\272\345\257\206\345\256\271\345\231\250\345\220\204\347\273\204\344\273\266.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/5-\346\272\220\347\240\201\347\274\226\350\257\221\346\234\272\345\257\206\345\256\271\345\231\250\345\220\204\347\273\204\344\273\266.md" new file mode 100644 index 0000000000000000000000000000000000000000..2e0d9f00a07e0410ceec3abbc95195ade702a840 --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/5-\346\272\220\347\240\201\347\274\226\350\257\221\346\234\272\345\257\206\345\256\271\345\231\250\345\220\204\347\273\204\344\273\266.md" @@ -0,0 +1,148 @@ +# 源码编译机密容器各组件 + +## 准备kata-containers代码 + +- 下载源码 + + ``` + cd $HOME + git clone https://gitee.com/anolis/kata-containers -b CC-0.5.0-hygon + ``` + + +## 安装编译依赖 + +``` +wget https://go.dev/dl/go1.19.3.linux-amd64.tar.gz +sudo tar xvf go1.19.3.linux-amd64.tar.gz -C /usr/local/ +echo "export PATH=$PATH:/usr/local/go/bin" >> ~/.bashrc +source ~/.bashrc + +sudo snap install yq --channel=v3/stable +``` + +## kata-containers各组件编译 + +系统编译将/opt/hygon/csv/confidential-containers/pkg/confidential-containers.tar.xz 文件拷贝解压,编译好的组件安装到对应的目录重新打包,从而达到更新编译组件的目的。 + + +可以编译一个组件或者同时编译多个组件,多个组件编译命令类似如下 +./build_confidential_containers.sh -b runtime,qemu + +**注:多次独立编译只会替换编译的部分,如果想替换多个组件,将上一次编译生成的tar 包拷贝替换/opt/hygon/csv/confidential-containers/pkg/confidential-containers.tar.xz 进行重新编译** + +### kata-runtime编译安装 + +``` +cd $HOME/kata-containers/release +./build_confidential_containers.sh -b runtime +``` + +### kata-qemu编译安装 + +``` +cd $HOME/kata-containers/release +./build_confidential_containers.sh -b qemu +``` + +### kata-ovmf编译安装 + +``` +cd $HOME/kata-containers/release +./build_confidential_containers.sh -b ovmf +``` + +### 编译Guest Kernel + +``` +cd $HOME/kata-containers/release +./build_confidential_containers.sh -b csv_kernel +``` + + +### 制作initrd + +下面命令会制作出 online_sev_kbc,offline_sev_kbc,offline_fs_kbc 对应的 initrd +``` +cd $HOME/kata-containers/release +./build_confidential_containers.sh -b csv_initrd + +``` +### 编译文件说明 +编译会在release 目录下生成打包文件confidential-containers.tar.gz + +压缩文件目录说明 + +| 目录 | 说明 | +|------------|------------| +|opt/confidential-containers/bin/| kata 运行时和qemu 文件| +|opt/confidential-containers/share/ovmf/| ovmf 文件| +|opt/confidential-containers/share/kata-containers/| 内核和initrd 文件| +|opt/confidential-containers/share/defaults/kata-containers/|系统配置文件| + + +将新的confidential-containers.tar.gz拷贝到/opt/hygon/csv/confidential-containers/pkg/ 目录下使用 + + +### 修改initrd + +> 如果只是修改initrd中的文件,或者添加文件到initrd中,我们推荐解包再打包的方式。 + +#### 解包initrd + +``` +cp /opt/confidential-containers/share/kata-containers/kata-containers-initrd-csv-hygon-gpu.img.offline_fs_kbc ./initrd.img.gz +gunzip initrd.img.gz +mkdir initrd +cd initrd/ +cpio -ivmd < ../initrd.img +``` + +在initrd目录进行修改后,重新打包。 + +#### 打包initrd + +``` +cd initrd/ +find . | cpio -o -H newc > ../initrd.new.img +gzip ../initrd.new.img +cd ../ && mv initrd.new.img.gz initrd.new.img +cp initrd.new.img /opt/confidential-containers/share/kata-containers/kata-containers-initrd-csv-hygon-gpu.img.offline_fs_kbc +``` + +### 针对offline_fs_kbc,定制policy (`sev_kbc无需此步`) + +- 定制key信息到aa-offline_fs_kbc-keys.json,示例如下: + + ``` + { + "key_id1": "cGFzc3BocmFzZXdoaWNobmVlZHN0b2JlMzJieXRlcyE=", + "key_id2": "qyecaCQh/+ChjnO7poTn08w5WYFqz4piBPh1rVMmrEo=", + "key_id3": "sXnCqg66/XdMb6Lo+XkABR9v8b3ImJm9BwtxhOMVwmg=", + "key_id4": "nXHQzVVvpVm9OrpRGwOIJ53cyAv2IRphLjJkS0dusT0=", + "key_id5": "gsyZwJh9BI/0qrCvfGxqJudcgHPRnymCgcych2lNzyU=", + "key_id6": "+2Cr3LQ8sq3PQpXIRX7yUNIP4q1X7HczSkB/FHZWGwQ=", + "key_id7": "Y8jJ64qyDOV8+M2ZEyAAk58P6rDdnDGg3WNgn2ELdVU=", + "key_id8": "EfZNaUaszIjCgT6YtSLiaLDMdPBMtZNQXTrBf3DmiP0=", + "key_id9": "illVfAwybTUAazagcOy90wLzrMPQVm44fZWxyeigjxo=", + "key_id10": "1g3KtvGfyIjq+HZmsKYJ1tMzuB8f1RjS6H0ieNBHLV0=" + } + ``` + +- 定制resources信息到aa-offline_fs_kbc-resources.json,示例如下(各字段的详细信息参考[7-使用签名镜像来部署workload](7-使用签名镜像来部署workload.md)): + + ``` + { + "default/security-policy/test": "ewogICAgImRlZmF1bHQiOiBbeyJ0eXBlIjogImluc2VjdXJlQWNjZXB0QW55dGhpbmcifV0sIAogICAgInRyYW5zcG9ydHMiOiB7CiAgICAgICAgImRvY2tlciI6IHsKICAgICAgICAgICAgImRvY2tlci5pby9wYXdzb25mYW5nL215YnVzeWJveCI6IFsKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAidHlwZSI6ICJzaWdzdG9yZVNpZ25lZCIsCiAgICAgICAgICAgICAgICAgICAgImtleVBhdGgiOiAia2JzOi8vL2RlZmF1bHQvY29zaWduLXB1YmxpYy1rZXkvdGVzdCIKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgXSwKICAgICAgICAgICAgImRvY2tlcnByb3h5LmNvbS9wYXdzb25mYW5nL215YnVzeWJveCI6IFsKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAidHlwZSI6ICJzaWdzdG9yZVNpZ25lZCIsCiAgICAgICAgICAgICAgICAgICAgImtleVBhdGgiOiAia2JzOi8vL2RlZmF1bHQvY29zaWduLXB1YmxpYy1rZXkvdGVzdCIKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgXQogICAgICAgIH0KICAgIH0KfQo=", + "default/sigstore-config/test": "ZG9ja2VyOgogICAgcXVheS5pby9rYXRhLWNvbnRhaW5lcnMvY29uZmlkZW50aWFsLWNvbnRhaW5lcnM6CiAgICAgICAgc2lnc3RvcmU6IGZpbGU6Ly8vZXRjL2NvbnRhaW5lcnMvcXVheV92ZXJpZmljYXRpb24vc2lnbmF0dXJlcwogICAgICAgIHNpZ3N0b3JlLXN0YWdpbmc6IGZpbGU6Ly8vZXRjL2NvbnRhaW5lcnMvcXVheV92ZXJpZmljYXRpb24vc2lnbmF0dXJlcw==", + "default/gpg-public-config/test": "LS0tLS1CRUdJTiBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0tCgptUUlOQkdGTVZFZ0JFQUN6ZC9ISno2bnE4R0FqRm9XdDIwUGhBeTRScDhxNHFlRkUzSkorbHdoUHprSmRiTDNaClFKMzFURUNyYktVeW8zTElRMzFCNzVBWXczdm5FSVVPY3V0U0UxaThvNTU3SW94eGxHNFN3dGtSVmRVUGVFN2UKdElOMm1aKzJHd25nQW1KRUgxNWtNQUZzVVFhNG4rWE9WUU9aSTNRWWVsWWpMd0thbXFBa3dFdjAzSmpHaTIrbQo0a0ZITzBmMy9lc0pmZXhVd3hLMHdQazJ4emlvZ2FpTzN6NDViTkoxMDZwSC95NGhRMHBWbWZJSHpPVjZwRHN2ClVHcTFxdnZlL2dDRXFZZWYvcUgyNzJoRkdNTE1qRy8yOStwVmZ1bEJ2YnpiUUhNUHlIaTFBdTVwemJWVUhxOUEKOURoWXhmWllpN2MreXU5Y1h0cngzQmlXSG52NzlBRUtWZDhCdkVucE02dGNIOWMvVFJlakd6VjF0cThva05wMwpXaXp6T0ZzVXBpaXVYVVo5ZlVlQ0s5YnVEaXdsdDF2ZGQ2OG5RZ3o2YkdIOEZqbVd2UXU4eTNVZEZRSTUwQkNVCmVEeFZEcHIzRXhjNER6MWxnU0pNV0wya2NJRy8wVllGU2hkRXUxL2lnNmdLUlpGcm1XN2hnSU51V1ZwWUNoZGkKK0I3Rkg1UDhGUlBiN0YrZFdyY0o3M3A1WXJLMzhHbnpadTNtdmZSUnk5Q0FpU1NFNFpEd0JuMjMzSCtlMFFzWAptT2lIcW1LSVZTbnhVa1hoTktXWm9LUDVQRlBHWE9YSEFNaWRnWC8wT0UxOEc2WmREMEYvRVNuYVdUL2lwNzNNCk1EYU5tVENlL2JZdW9TZy9oVUdCMEtENUx2aFZaT01haTh1MkYwQnJFYWdPRnQ3SkZjbUVwd2pXWndBUkFRQUIKdEVsVGRHVjJaVzRnU0c5eWMyMWhiaUFvUjFCSElHdGxlU0JtYjNJZ2MybG5ibWx1WnlCcllYUmhJSFJsYzNRZwphVzFoWjJWektTQThjM1JsZG1WdVFIVnJMbWxpYlM1amIyMCtpUUpZQkJNQkNBQkNGaUVFWjdKS3JNUlpaNTRDCmc5ZnVXUGJ0Qis2bXRDa0ZBbUZNVkVnQ0d3TUZDUUhoTTRBRkN3a0lCd0lESWdJQkJoVUtDUWdMQWdRV0FnTUIKQWg0SEFoZUFBQW9KRUZqMjdRZnVwclFwc3ZBUC8zTit5RGRlRkRMaVdSS21YbEhzbWRuT3dlYVdxQjdzUWJ0SQpJTFh6RVFCY1pIWjFRNUxna0o2bzlHUlJlK0pPVmFsQUQ5QXdPQjg4Z0hNVVptR2hmQU05dnY3R3RWWGdpQkNmCi9mNDE0TTFueS9xMUgwZG1wRnF4b3FaYzlXNlhaU1pFVC8yNVFPUlMzYkxIK0dFdnQ4enZaUkFLVU9WRUhPZTQKbHRocmNuY21uaFd4ZWc0ZFJGWEZRczJZSW41VzZiOTd4SzN4emF0bDlyTVgwd2s4L2xweDlHQ0tLalZ3OVpQcwpUZ25kcmlMTnUzaGJOeWFXaEhlTHFUT1hEOUU0WUNjM3FMc0MvZW5Hclh6Si91bWdpaHUvRy9iNWFsZWZ6U09xCnh0MHI2ejdSbk85OXJVdEtDYW0rNUVEa0t6VXZoamdSM2oyTGtHWkMxZnFBTnQ2TEtPK0MwT3FtMEpUMm1UZGEKdGEveDdCdGozNktJYjN1TlNSdDJiRHJGWXhPajZzRnlQVlRVbHpOZ2l0bkszVHFJeG5teWlHZGhPVUcyc1p5OAowSTFaNHZaT0JGdzIzWE9qYzRUVGRWU29BbUxSZkhOeWZtYXlHbS9ja2xlTjV2T2xiVzlPOXREa0M0alo2WkZNCjFxZzEyUkxvS1dxRXRodmlzOVhzV0xieEFBaG0xbkZKV0VpTlhzdW1NUDc0U1cwLy9qYmRFT0xObzBXRG5TTmIKZ3U2a2hVYXJIR0dpUEJzeFc4cURGdXNIWFplMEpDSVFRUTBDZVh3T1owaXFINC9tQ0lKQnlId2dEdExnbnNUTQo2a2hnU2VhMXk1a3RRQnZSdU1QODg5ZWJQSEoyNjFqeUl5OXV5K25oaUt5cG9PK3lqMWYvUm5qNWtLS3Y3Mm5LCjV1RVNwSkJUCj1CN3ZRCi0tLS0tRU5EIFBHUCBQVUJMSUMgS0VZIEJMT0NLLS0tLS0K", + "default/cosign-public-key/test": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFYmV5S0pjWVJmK3VIdEQ0VFdMTU5US0R3Q0ordQpRdGJZZE5qbDVhS1QxZ3luSHFKQ1hqTm5SM3M5bDVRS3NJb21QeHd4Uk02Tkloc2xEK0JJamwwVDZnPT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==", + "default/credential/test": "ewogICAgImF1dGhzIjogewogICAgICAgICJkb2NrZXIuaW8iOiB7CiAgICAgICAgICAgICJhdXRoIjogImJHbDFaR0ZzYVdKcU9sQmhjM04zTUhKa0lYRmhlZ289IgogICAgICAgIH0sCiAgICAgICAgInF1YXkuaW8iOiB7CiAgICAgICAgICAgICJhdXRoIjogImJHbDFaR0ZzYVdKcU9sQmhjM04zTUhKa0lYRmhlZ289IgogICAgICAgIH0KICAgIH0KfQo=" + } + ``` + +- 将两个文件复制到rootfs/etc目录下 + + ``` + cp *.json ${ROOTFS_DIR}/etc/ + ``` \ No newline at end of file diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/6-\344\275\277\347\224\250\345\212\240\345\257\206\351\225\234\345\203\217\346\235\245\351\203\250\347\275\262workload.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/6-\344\275\277\347\224\250\345\212\240\345\257\206\351\225\234\345\203\217\346\235\245\351\203\250\347\275\262workload.md" new file mode 100644 index 0000000000000000000000000000000000000000..a1612b5dea1d76ce217610525264ee69395e41fd --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/6-\344\275\277\347\224\250\345\212\240\345\257\206\351\225\234\345\203\217\346\235\245\351\203\250\347\275\262workload.md" @@ -0,0 +1,185 @@ +# 使用加密镜像部署workload +**该实践支持情况如下:** + +| 机密容器类型 | 是否支持 | +| --- | --- | +| CSV | 是 | +| CSV2 | 是 | +| CSV3 | 是 | + +## 关于Attestation Agent及KBC + +**attestation agent 支持三种CSV平台相关的KBC,见下表:** + +| KBC模式 | 说明 | +| --- | --- | +| [offline_fs_kbc](https://github.com/confidential-containers/attestation-agent/tree/main/kbc/src/offline_fs_kbc) | offline fs KBC 事先把密钥放置在initrd中,用于验签容器镜像。缺点是每次更新密钥或policy,需要重新制作initrd。 | +| [offline_sev_kbc](https://github.com/confidential-containers/attestation-agent/tree/main/kbc/src/offline_sev_kbc) | offline sev KBC 在**运行时**不会与 Simple KBS 进行通信,而是使用在**VM Boot时期**通过QEMU注入的secret。该机制的缺点是对注入的 secret 长度有限制。 | +| [online_sev_kbc](https://github.com/confidential-containers/attestation-agent/tree/main/kbc/src/online_sev_kbc) | online sev KBC 在offline sev KBC的基础上,支持在**运行时**发出请求。online sev KBC 在VM Boot时期通过QEMU注入connection。注入的connection包含一个对称密钥,用于加密和验证 KBC 发出的在线请求。 该连接受 CSV秘密注入过程保护,该过程提供机密性、完整性并防止重放攻击。 simple-kbs 为每个连接生成一个新的对称密钥。 KBC 要求每个在线secret都带有随机 guid 以防止重放攻击。 | + +## 使用已知的加密镜像部署workload +**各KBC模式对于加密镜像的支持如下表所示:** + +| KBC模式 | 是否支持加密镜像 | +| --- | --- | +| online_sev_kbc | 是 | +| offline_sev_kbc | 是 | +| offline_fs_kbc | **否** | + +本文提供了一个简单的加密镜像( docker.io/pawsonfang/busybox:encrypted ),该镜像使用 simple kbs 已经存在的密钥来解密,同时对 policy 不进行校验。此加密镜像只作为测试使用,如您想用于自己的生产用例中,请参考文档[9-制作一个新的加密镜像并部署](https://openanolis.cn/sig/Hygon-Arch/doc/865622249784088376)。 + +### 基于online_sev_kbc运行加密容器 + +- 编辑 kata 配置文件: + + - 设置机密容器为`CSV`、`CSV2`、`CSV3`的其中一种。 + + ```shell + # 对于CSV机密容器,执行以下语句 + sudo sed -i -e 's/^\(sev_guest_policy\) = .*$/\1 = 3/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + + # 对于CSV2机密容器,执行以下语句 + sudo sed -i -e 's/^\(sev_guest_policy\) = .*$/\1 = 7/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + + # 对于CSV3机密容器,执行以下语句 + sudo sed -i -e 's/^\(sev_guest_policy\) = .*$/\1 = 71/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + sudo sed -i -e 's/^\(vcpu_model\) = .*$/\1 = \"Dhyana\"/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + + - 打开pre-attestation + + ```shell + sudo sed -i -e 's/^\(guest_pre_attestation =\).*$/\1 true/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + + - initrd指向支持online_sev_kbc的initrd + + ```shell + sudo sed -i -e 's#^\(initrd\).*=.*$#\1 = \"/opt/confidential-containers/share/kata-containers/kata-containers-initrd-csv-hygon-gpu.img.online_sev_kbc\"#g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + + - 设置kbs_mod为online模式 + + ```shell + sudo sed -i -e 's/^\(guest_pre_attestation_kbs_mode\).*=.*$/\1=\"online\"/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + + - 设置AA module 配置文件路径 + + 由于国内网络目前访问不了dockerhub 需要使用代理,代理参数agent.https_proxy=http://ip:port agent.no_proxy=10.*.*.*,172.*.*.* http://ip:port 为代理地址 + + ```shell + sudo sed -i -e 's#^\(kernel_params\).*=.*$#\1 = \"agent.https_proxy=http://ip:port agent.no_proxy=10.*.*.*,172.*.*.* agent.config_file=/etc/agent-config.toml agent.enable_signature_verification=false \"#g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + +- 启动POD + +```shell +cat <<-EOF | kubectl apply -f - +apiVersion: v1 +kind: Pod +metadata: + labels: + run: test-en-online + name: test-en-online +spec: + containers: + - image: docker.io/pawsonfang/busybox:encrypted + name: test-en-online + imagePullPolicy: Always + dnsPolicy: ClusterFirst + restartPolicy: Never + runtimeClassName: kata-qemu-csv +EOF +``` + +- 查看 pod 是否启动成功: + +```shell +kubectl get pod +``` + +- 预期结果如下: + +```shell +NAME READY STATUS RESTARTS AGE +test-en-online 1/1 Running 0 146m +``` + +#### 基于offline_sev_kbc运行加密容器 + +- 编辑 kata 配置文件: + + - 设置机密容器为`CSV`、`CSV2`、`CSV3`的其中一种。 + + ```shell + # 对于CSV机密容器,执行以下语句 + sudo sed -i -e 's/^\(sev_guest_policy\) = .*$/\1 = 3/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + + # 对于CSV2机密容器,执行以下语句 + sudo sed -i -e 's/^\(sev_guest_policy\) = .*$/\1 = 7/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + + # 对于CSV3机密容器,执行以下语句 + sudo sed -i -e 's/^\(sev_guest_policy\) = .*$/\1 = 71/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + sudo sed -i -e 's/^\(vcpu_model\) = .*$/\1 = \"Dhyana\"/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + + - 打开pre-attestation + + ```shell + sudo sed -i -e 's/^\(guest_pre_attestation =\).*$/\1 true/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + + - initrd指向支持offline_sev_kbc的initrd + + ```shell + sudo sed -i -e 's#^\(initrd\).*=.*$#\1 = \"/opt/confidential-containers/share/kata-containers/kata-containers-initrd-csv-hygon-gpu.img.offline_sev_kbc\"#g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + + - 设置kbs_mod为offline模式 + + ```shell + sudo sed -i -e 's/^\(guest_pre_attestation_kbs_mode\).*=.*$/\1=\"offline\"/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + + - 设置AA module 配置文件路径 + + ```shell + sudo sed -i -e 's#^\(kernel_params\).*=.*$#\1 = \"agent.https_proxy=http://ip:port agent.no_proxy=10.*.*.*,172.*.*.* agent.config_file=/etc/agent-config.toml agent.enable_signature_verification=false \"#g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + + +- 启动 Pod + +```shell +cat <<-EOF | kubectl apply -f - +apiVersion: v1 +kind: Pod +metadata: + labels: + run: test-en-offline + name: test-en-offline +spec: + containers: + - image: docker.io/pawsonfang/busybox:encrypted + name: test-en-offline + imagePullPolicy: Always + dnsPolicy: ClusterFirst + restartPolicy: Never + runtimeClassName: kata-qemu-csv +EOF +``` + +- 查看 pod 是否启动成功: + +```shell +kubectl get pod +``` + +- 预期结果如下: + +```shell +NAME READY STATUS RESTARTS AGE +test-en-offline 1/1 Running 0 31h +``` + diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/7-\344\275\277\347\224\250\347\255\276\345\220\215\351\225\234\345\203\217\346\235\245\351\203\250\347\275\262workload.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/7-\344\275\277\347\224\250\347\255\276\345\220\215\351\225\234\345\203\217\346\235\245\351\203\250\347\275\262workload.md" new file mode 100644 index 0000000000000000000000000000000000000000..73cbd315d889dc4d9afc2c6cb63fc55fd048105d --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/7-\344\275\277\347\224\250\347\255\276\345\220\215\351\225\234\345\203\217\346\235\245\351\203\250\347\275\262workload.md" @@ -0,0 +1,179 @@ +# 使用签名镜像部署workload +**该实践支持情况如下:** + +| 机密容器类型 | 是否支持 | +| --- | --- | +| CSV | 是 | +| CSV2 | 是 | +| CSV3 | 是 | + +## 关于Attestation Agent及KBC + +**attestation agent 支持三种CSV平台相关的KBC,见下表:** + +| KBC模式 | 说明 | +| --- | --- | +| [offline_fs_kbc](https://github.com/confidential-containers/attestation-agent/tree/main/kbc/src/offline_fs_kbc) | offline fs KBC 事先把密钥放置在initrd中,用于验签容器镜像。缺点是每次更新密钥或policy,需要重新制作initrd。 | +| [offline_sev_kbc](https://github.com/confidential-containers/attestation-agent/tree/main/kbc/src/offline_sev_kbc) | offline sev KBC 在**运行时**不会与 Simple KBS 进行通信,而是使用在**VM Boot时期**通过QEMU注入的secret。该机制的缺点是对注入的 secret 长度有限制。| +| [online_sev_kbc](https://github.com/confidential-containers/attestation-agent/tree/main/kbc/src/online_sev_kbc) | online sev KBC 在offline sev KBC的基础上,支持在**运行时**发出请求。online sev KBC 在VM Boot时期通过QEMU注入connection。注入的connection包含一个对称密钥,用于加密和验证 KBC 发出的在线请求。 该连接受 CSV秘密注入过程保护,该过程提供机密性、完整性并防止重放攻击。 simple-kbs 为每个连接生成一个新的对称密钥。 KBC 要求每个在线secret都带有随机 guid 以防止重放攻击。 | + +## 使用已知的签名镜像部署workload +**各KBC模式对于签名镜像的支持如下表所示:** + +| KBC模式 | 是否支持签名镜像 | +| --- | --- | +| online_sev_kbc | 是 | +| offline_sev_kbc | **否** | +| offline_fs_kbc | 是 | + +本文提供了一个简单的签名镜像( docker.io/pawsonfang/mybusybox ),该镜像可以使用已知的cosign公钥进行验签,同时对 policy 不进行校验。此签名镜像只作为测试使用,如您想用于自己的生产用例中,请参考文档[10-制作一个新的签名镜像并部署](https://openanolis.cn/sig/Hygon-Arch/doc/865622235909330728)。 + +#### 基于online_sev_kbc运行签名容器 + +- 编辑 kata 配置文件: + + - 设置机密容器为`CSV`、`CSV2`、`CSV3`的其中一种。 + + ```shell + # 对于CSV机密容器,执行以下语句 + sudo sed -i -e 's/^\(sev_guest_policy\) = .*$/\1 = 3/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + + # 对于CSV2机密容器,执行以下语句 + sudo sed -i -e 's/^\(sev_guest_policy\) = .*$/\1 = 7/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + + # 对于CSV3机密容器,执行以下语句 + sudo sed -i -e 's/^\(sev_guest_policy\) = .*$/\1 = 71/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + sudo sed -i -e 's/^\(vcpu_model\) = .*$/\1 = \"Dhyana\"/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + + - 打开pre-attestation + + ```shell + sudo sed -i -e 's/^\(guest_pre_attestation =\).*$/\1 true/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + + - initrd指向支持online_sev_kbc的initrd + + ```shell + sudo sed -i -e 's#^\(initrd\).*=.*$#\1 = \"/opt/confidential-containers/share/kata-containers/kata-containers-initrd-csv-hygon-gpu.img.online_sev_kbc\"#g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + + - 设置kbs_mod为online模式 + + ```shell + sudo sed -i -e 's/^\(guest_pre_attestation_kbs_mode\).*=.*$/\1=\"online\"/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + + - 使能验签功能 + + ```shell + sudo sed -i -e 's#^\(kernel_params\).*=.*$#\1 = \"agent.https_proxy=http://ip:port agent.no_proxy=10.*.*.*,172.*.*.* agent.config_file=/etc/agent-config.toml agent.enable_signature_verification=true \"#g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + +- 启动 Pod + +```shell +cat <<-EOF | kubectl apply -f - +apiVersion: v1 +kind: Pod +metadata: + labels: + run: test-sign-online + name: test-sign-online +spec: + containers: + - image: docker.io/pawsonfang/mybusybox + name: test-sign-online + imagePullPolicy: Always + dnsPolicy: ClusterFirst + restartPolicy: Never + runtimeClassName: kata-qemu-csv +EOF +``` + +- 查看 pod 是否启动成功: + +```shell +kubectl get pod +``` + +- 预期结果如下: + +```shell +NAME READY STATUS RESTARTS AGE +test-sign-online 1/1 Running 0 31h +``` + +#### 基于offline_fs_kbc运行签名容器 + +> offline_fs_kbc模式,是把验签公钥放在initrd中,不需要借助于simple-kbs,相应的,也就不支持pre_attestation + +- 编辑 kata 配置文件: + + - 设置机密容器为`CSV`、`CSV2`、`CSV3`的其中一种。 + + ```shell + # 对于CSV机密容器,执行以下语句 + sudo sed -i -e 's/^\(sev_guest_policy\) = .*$/\1 = 3/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + + # 对于CSV2机密容器,执行以下语句 + sudo sed -i -e 's/^\(sev_guest_policy\) = .*$/\1 = 7/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + + # 对于CSV3机密容器,执行以下语句 + sudo sed -i -e 's/^\(sev_guest_policy\) = .*$/\1 = 71/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + sudo sed -i -e 's/^\(vcpu_model\) = .*$/\1 = \"Dhyana\"/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + + - 关闭pre-attestation + + ```shell + sudo sed -i -e 's/^\(guest_pre_attestation =\).*$/\1 false/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + + - initrd指向支持offline_fs_kbc的initrd + + ```shell + sudo sed -i -e 's#^\(initrd\).*=.*$#\1 = \"/opt/confidential-containers/share/kata-containers/kata-containers-initrd-csv-hygon-gpu.img.offline_fs_kbc\"#g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + + - 使能验签功能,并更新kbc模式为offline_fs_kbc + + ```shell + sudo sed -i -e 's#^\(kernel_params\).*=.*$#\1 = \"agent.https_proxy=http://ip:port agent.no_proxy=10.*.*.*,172.*.*.* agent.aa_kbc_params=offline_fs_kbc::null agent.enable_signature_verification=true \"#g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml + ``` + +- 启动 Pod + +```shell +cat <<-EOF | kubectl apply -f - +apiVersion: v1 +kind: Pod +metadata: + labels: + run: test-sign-offline + name: test-sign-offline +spec: + containers: + - image: docker.io/pawsonfang/mybusybox + name: test-sign-offline + imagePullPolicy: Always + dnsPolicy: ClusterFirst + restartPolicy: Never + runtimeClassName: kata-qemu-csv +EOF +``` + +- 查看 pod 是否启动成功: + +```shell +kubectl get po +``` + +- 预期结果如下: + +```shell +NAME READY STATUS RESTARTS AGE +test-sign-offline 1/1 Running 0 31h +``` + +### diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/8-\350\207\252\345\256\232\344\271\211Policy\346\235\245\351\252\214\350\257\201Measurement.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/8-\350\207\252\345\256\232\344\271\211Policy\346\235\245\351\252\214\350\257\201Measurement.md" new file mode 100644 index 0000000000000000000000000000000000000000..f2d40fe24d421fdf631a08e21de99969cc8e02bf --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/8-\350\207\252\345\256\232\344\271\211Policy\346\235\245\351\252\214\350\257\201Measurement.md" @@ -0,0 +1,127 @@ +# 自定义policy来验证Guest Firmware Mesurement + +**该实践支持情况如下:** + +| 机密容器类型 | 是否支持 | +| --- | --- | +| CSV | 是 | +| CSV2 | 是 | +| CSV3 | 是 | + +## 关于policy + +**各KBC模式对于自定义policy验证Guest Firmware Measurement的支持情况见下表:** + +| KBC模式 | 是否支持自定义policy验证Guest Firmware Measurement | +| --- | --- | +| online_sev_kbc | 是 | +| offline_sev_kbc | 是 | +| offline_fs_kbc | **否** | + +- policy是在pre-attestation阶段进行校验的,offline_sev_kbc和online_sev_kbc两种模式都支持自定义policy,且方法相同。 +- policy的组成包括:digests、policies、api_major、api_minor、build_ids等信息。详情请参考[链接](https://github.com/confidential-containers/simple-kbs/blob/main/db/db-mysql.sql#L73)。 +- 本文以digests为例子,向用户展示如何注入自定义policy 。用户可以根据需求自定义Policy。 + +## 获取cmdline和Kata机密虚拟机vCPU个数 + +> 获取内核的append值(需要先启动一个offline_sev_kbc或online_sev_kbc的pod) + +```shell +nr_vcpus=0 +duration=$((SECONDS+30)) +set append + +while [ $SECONDS -lt $duration ]; do + qemu_process=$(ps aux | grep qemu | grep append || true) + if [ -n "${qemu_process}" ]; then + append=$(echo ${qemu_process} \ + | sed "s|.*-append \(.*$\)|\1|g" \ + | sed "s| -.*$||") + nr_vcpus=$(echo ${qemu_process} \ + | sed "s|.* -smp \([0-9]*\).*|\1|") + break + fi + sleep 1 +done + +echo "${append}" > cmdline_file +``` + +## 计算CSV/CSV2/CSV3 Guest Firmware Measurement + +> csv-measure.py是一个计算固件度量值的脚本,可以使用提供的 ovmf、initrd、kernel、cmdline等作为参数来计算 CSV/CSV2 guest固件测量值;对于CSV3 guest来说,除了需要提供 ovmf、initrd、kernel、cmdline,还需要提供虚拟机vCPU模型和vcpu个数作为参数来计算 guest固件度量值。 + +- 根据ovmf、kernel、initrd_path和cmdline_file的地址设置参数。 + - ovmf、kernel和initrd_path的地址请参考kata 的配置文件 + - kata 的配置文件路径:/opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml。 + + +```shell +ovmf_path="/opt/confidential-containers/share/ovmf/AMDSEV.fd" +kernel_path="/opt/confidential-containers/share/kata-containers/vmlinuz-csv.container" +initrd_path="/opt/confidential-containers/share/kata-containers/kata-containers-initrd-csv-hygon-gpu.img.online_sev_kbc" +cmdline_path=${PWD}/cmdline_file +``` + +- 使用csv-measure.py 来计算 CSV/CSV2/CSV3 guest 的Launch digest。 + + - 针对CSV/CSV2 guest计算固件度量值的方法如下。 + ```shell + # 计算measurement + measurement=$(/opt/hygon/csv/confidential-containers/scripts/csv-measure.py \ + --ovmf "${ovmf_path}" \ + --kernel "${kernel_path}" \ + --initrd "${initrd_path}" \ + --cmdline "${cmdline_path}" \ + ) + ``` + - 针对CSV3 guest计算固件度量值的方法如下。 + ```shell + # 计算measurement + measurement=$(/opt/hygon/csv/confidential-containers/scripts/csv-measure.py \ + --ovmf "${ovmf_path}" \ + --kernel "${kernel_path}" \ + --initrd "${initrd_path}" \ + --cmdline "${cmdline_path}" \ + --csv3 \ + --vcpumodel "Dhyana" \ + --smp ${nr_vcpus} + ) + ``` + +- 确认measurement计算成功 +```shell +echo $measurement +``` + +- 设置simple kbs 数据库参数 + +```shell +KBS_DB_USER="kbsuser" +KBS_DB_PW="kbspassword" +KBS_DB="simple_kbs" +KBS_DB_TYPE="mysql" +KBS_DB_HOST=$(sudo docker network inspect simple-kbs_default \ + | jq -r '.[].Containers[] | select(.Name | test("simple-kbs[_-]db.*")).IPv4Address' \ + | sed "s|/.*$||g") +``` + +- 由于本文使用的加密镜像( docker.io/pawsonfang/busybox:encrypted ),是采用 simple kbs 已经存在的密钥来解密,该镜像的 enc_key 值如下。用户需要根据加密镜像按需设置enc_key。 + +```shell +enc_key=C1z522QYM9YZDcz+7nstjYD2HNX1/2/okVStRA2ChDo= +``` + +- 将 自定义policy 注入 mysql 中。 + +```shell +# 安装依赖 +sudo apt install mysql-client jq -y +mysql -u${KBS_DB_USER} -p${KBS_DB_PW} -h ${KBS_DB_HOST} -D ${KBS_DB} < 再启动pod时,kata会向CSV固件获取度量值,与simple-kbs数据库的policy值进行对比。 diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/9-\345\210\266\344\275\234\344\270\200\344\270\252\346\226\260\347\232\204\345\212\240\345\257\206\351\225\234\345\203\217\345\271\266\351\203\250\347\275\262.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/9-\345\210\266\344\275\234\344\270\200\344\270\252\346\226\260\347\232\204\345\212\240\345\257\206\351\225\234\345\203\217\345\271\266\351\203\250\347\275\262.md" new file mode 100644 index 0000000000000000000000000000000000000000..0cdee96d51332306cd00cb416f13c28396759ca2 --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/4-KATA-3/9-\345\210\266\344\275\234\344\270\200\344\270\252\346\226\260\347\232\204\345\212\240\345\257\206\351\225\234\345\203\217\345\271\266\351\203\250\347\275\262.md" @@ -0,0 +1,176 @@ +# 制作一个新的加密镜像并部署 + +本文主要为您介绍如何制作一个新的加密镜像,并部署pod。 + +## 加密镜像 + +Attestation Agent可以启动一个grpc服务来支持对映像进行加密。克隆仓库: + +``` +attestation_agent_tag="v0.5.0" +git clone https://github.com/confidential-containers/attestation-agent.git +(cd attestation-agent && git checkout -b "branch_${attestation_agent_tag}" "${attestation_agent_tag}") +``` + +编译并启动CoCo Keyprovider(该应用会作为一个服务占用当前窗口进程): + +``` +# 安装依赖 +curl https://sh.rustup.rs -sSf | sh +source "$HOME/.cargo/env" +TODO +sudo apt install openssl-devel -y +# 编译并启动 +cd attestation-agent/coco_keyprovider +RUST_LOG=coco_keyprovider cargo run --release -- --socket 127.0.0.1:50000 +``` + +创建 Attestation Agent keyprovider: + +``` +cat > ocicrypt.conf < key1 +``` + +把你想要加密的镜像加密并拷贝到当前目录,本例中使用的是`busybox`镜像。其中密钥使用`keypath`指定,`keyid`此处设置为`kbs:///default/key/key_id2`,密钥算法设置为`A256GCM`,`——insecure-policy`标志用于连接到认证代理,不会影响项目的安全性。 + +``` +OCICRYPT_KEYPROVIDER_CONFIG=ocicrypt.conf skopeo copy --insecure-policy --encryption-key provider:attestation-agent:keypath=$(pwd)/key1::keyid=kbs:///default/key/key_id2::algorithm=A256GCM docker://busybox oci:busybox:encrypted +``` + +加密后,可以看到在当前目录下生成了`busybox`目录。 + +确认镜像确实已经被加密: + +``` +cat ./busybox/index.json | python3 -m json.tool +``` + +期望结果: + +``` +{ + "schemaVersion": 2, + "manifests": [ + { + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "digest": "sha256:f594fcb13ca12e4ebf400b5e8ab715cb4f30adb335b8e31366d61f5350029e6e", + "size": 1195, + "annotations": { + "org.opencontainers.image.ref.name": "encrypted" + } + } + ] +} +``` + +根据digest找到对应的manifest:`./busybox/blocs/sha256/73135775766027c5006e7744fa8007e812afec905064743c68b780dd49c1eeaf` + +``` +cat ./busybox/blobs/sha256/f594fcb13ca12e4ebf400b5e8ab715cb4f30adb335b8e31366d61f5350029e6e | python3 -m json.tool +``` + +期望结果: + +``` +{ + "schemaVersion": 2, + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "config": { + "mediaType": "application/vnd.oci.image.config.v1+json", + "digest": "sha256:3488e6e2e41e62fc51be840cd61d806d5b45defdb84a2e6c99ea8a0edb4b6cc7", + "size": 575 + }, + "layers": [ + { + "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip+encrypted", + "digest": "sha256:0dfdc90a4529ca0b38e575945748d6f8258ad2ea2cce8755b8a9f0e1566e447f", + "size": 2592227, + "annotations": { + "org.opencontainers.image.enc.keys.provider.attestation-agent": "eyJraWQiOiJrYnM6Ly8vZGVmYXVsdC90ZXN0LWtleS8xIiwid3JhcHBlZF9kYXRhIjoiLzNMeWhsdVE1aG42MVVjN0ZDM1BWTlNDUlV0YitLc1h5ZWhGTERtaUJlcUE4cStrcGgxbFpwckR4cjh0ck5RUFpxRDB2UlFobVFFWTM1YnV3R05VeGRINXdyeWtCa0x2OTFkSHFHMEJOY1FETVNhNTBBZFpqb00xTHQ0SUdIUDlZeEpGL3hmcWk4RFFBUmdXNjhpV3hlcWgxTFRMQ01hcUg5TzUxeXduYmcxTmJ3aFM0aXdkRSttMGRhOWwyTXpqeklrbjRtN3pWZUl6cFRVVHJuS0gyM1RmWmVWZUZsZVMxY0VscWhGdGw4bnZDYmphNlZyQlFYTzRFVVZUdjkvemxzS2xnRnl3aEhnL1VvUHBmMXMvY2RJPSIsIml2IjoiQUFBQUFBQUFBQUFBQUFBQSIsIndyYXBfdHlwZSI6IkEyNTZHQ00ifQ==", + "org.opencontainers.image.enc.pubopts": "eyJjaXBoZXIiOiJBRVNfMjU2X0NUUl9ITUFDX1NIQTI1NiIsImhtYWMiOiJqWHhYMGVWWGR2RHAxbVpxSHVXYzFJWGFwazhicmhKMHdpbDl5K3JLUXc4PSIsImNpcGhlcm9wdGlvbnMiOnt9fQ==" + } + } + ] +} +``` + +其中`mediaType`为`application/vnd.oci.image.layer.v1.tar+gzip+encrypted`,表示该layer已被加密。 + +## 上传镜像到远程的image registry + +记得把docker.io/myrepo替换为自己的仓库地址: + +``` +# 登录您的image registry,比如登录docker.io +skopeo login docker.io +# 上传镜像 +skopeo copy --insecure-policy oci:busybox:encrypted docker://docker.io/myrepo/busybox:encrypted +``` + +## 更新密钥到kbs + +- 设置数据库参数 + + ``` + KBS_DB_USER="kbsuser" + KBS_DB_PW="kbspassword" + KBS_DB="simple_kbs" + KBS_DB_TYPE="mysql" + KBS_DB_HOST=$(sudo docker network inspect simple-kbs_default \ + | jq -r '.[].Containers[] | select(.Name | test("simple-kbs[_-]db.*")).IPv4Address' \ + | sed "s|/.*$||g") + ``` + +- 获取加密密钥的base64 encode + +```shell +enc_key=$(cat key1 | base64) +echo $enc_key +``` + +- 将 加密密钥 注入 mysql 中。 + +```shell +mysql -u${KBS_DB_USER} -p${KBS_DB_PW} -h ${KBS_DB_HOST} -D ${KBS_DB} < 注意:`default/key/key_id2`要与skopeo参数相同;使用offline_sev_kbc时,要设置`configuration-qemu-csv.toml`中`guest_pre_attestation_keyset`的值为`KEYSET-2` + +## 使用新的加密镜像启动pod + +> myrepo替换为自己的仓库地址 + +``` +cat <<-EOF | kubectl apply -f - +apiVersion: v1 +kind: Pod +metadata: + labels: + run: test-en-online2 + name: test-en-online2 +spec: + containers: + - image: docker.io/myrepo/busybox:encrypted + name: test-en-online2 + imagePullPolicy: Always + dnsPolicy: ClusterFirst + restartPolicy: Never + runtimeClassName: kata-qemu-csv +EOF +``` + diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/5-KATA-2.5/1-\346\265\213\350\257\225CSV\345\212\240\345\257\206\345\256\271\345\231\250.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/5-KATA-2.5/1-\346\265\213\350\257\225CSV\345\212\240\345\257\206\345\256\271\345\231\250.md" new file mode 100644 index 0000000000000000000000000000000000000000..57d3dfccd6456882f4141ece395c38a119a6918e --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/5-KATA-2.5/1-\346\265\213\350\257\225CSV\345\212\240\345\257\206\345\256\271\345\231\250.md" @@ -0,0 +1,82 @@ +测试之前,请先安装CSV软件。 + +## 功能描述 +Kata容器运行在轻量级虚拟机里,CSV Kata容器将安全虚拟化技术与容器技术结合,将Kata容器运行在CSV TEE中,使Kata容器具有更强的安全性。 + +## 测试CSV Kata加密容器 + +### 安装kata +``` +$ cd ~/ +$ wget https://github.com/kata-containers/kata-containers/releases/download/2.5.2/kata-static-2.5.2-x86_64.tar.xz  +$ wget https://github.com/containerd/containerd/releases/download/v1.6.6/cri-containerd-cni-1.6.6-linux-amd64.tar.gz  +$ sudo /opt/hygon/csv/install_kata.sh +``` +### 更新kata runtime +``` +$ cd ~/ +$ wget https://go.dev/dl/go1.16.10.linux-amd64.tar.gz  +$ wget https://github.com/kata-containers/kata-containers/archive/refs/tags/2.5.2.tar.gz -O kata-2.5.2.tar.gz +$ sudo /opt/hygon/csv/update_kata.sh +``` +### 安装nerdctl +``` +$ wget https://github.com/containerd/nerdctl/releases/download/v0.23.0/nerdctl-0.23.0-linux-amd64.tar.gz  +$ sudo tar -C /usr/local/bin -xvf nerdctl-0.23.0-linux-amd64.tar.gz +``` +### 编译kata guest kernel +``` +$ cd ~/kata-containers-2.5.2/tools/packaging/kernel +$ sudo /opt/hygon/csv/build_kata_kernel.sh +``` +### 修改支持CSV KATA +``` +$ sudo /opt/hygon/csv/normal_to_csv_kata.sh +``` +### 编译kata guest rootfs +``` +$ cd ~/kata-containers-2.5.2/tools/osbuilder +$ sudo cp /opt/hygon/csv/dcu/* ./ +$ sudo ./dcu_rootfs.sh +$ sudo chroot ubuntu_rootfs +# cd root +# ./install_in_chroot.sh +# exit +$ sudo -E AGENT_INIT=yes ./image-builder/image_builder.sh ubuntu_rootfs +$ sudo cp kata-containers.img /opt/kata/share/kata-containers/kata-containers.img +``` +### 运行CSV kata容器 +``` +$ export CNI_PATH=/opt/cni/bin/ +$ sudo nerdctl pull ubuntu:20.04 +$ sudo -E nerdctl run --runtime io.containerd.run.kata.v2 -d  --name ubuntu-focal ubuntu:20.04 +``` +### 查看CSV kata容器的内存 +``` +$ sudo /opt/hygon/csv/dump-kata-memory.sh nerdctl ubuntu-focal +``` +内存数据如下图,可以看到CSV kata容器的内存被加密了。 + +图 1 CSV kata容器的内存数据 + + ![](../../../assets/csv6-1.png) + +## 验证CSV kata远程认证功能 +测试使用的容器内核集成了生成认证报告需要的内核驱动,驱动的源代码是csv-guest.c,如果用户需要使用自定义内核,需要将此驱动编译进内核。使用下面的命令启动加密容器。 +``` +$ sudo -E nerdctl run --runtime io.containerd.run.kata.v2 --mount type=bind,source=/dev,target=/dev,rw --mount type=bind,source=/mnt,target=/opt,bind-propagation=shared --rm -it --name ubuntu-focal ubuntu:20.04 bash +``` +启动成功后,在容器中检查设备节点/dev/csv-guest是否存在,如果设备节点不存在将无法获取认证报告。将ioctl-get-attestation程序拷贝到容器中执行。 +``` +$ sudo cp /opt/hygon/csv/attestation/ioctl-get-attestation /mnt/ +# cd /opt/ +# ./ioctl-get-attestation +``` +ioctl-get-attestation执行会生成认证报告report.cert,可以在任意机器上验证认证报告,验证证书链签名会从证书服务器下载证书,因此验证机器需要联网。这里使用主机验证认证报告,将报告拷贝到主机中验证。 +``` +$ sudo cp /opt/hygon/csv/attestation/verify-attestation /mnt/ +$ cd /mnt/ +$ sudo chmod 666 report.cert +$ sudo ./verify-attestation true +``` +verify-attestation会使用PEK公钥验证认证报告的签名,并且从证书服务器下载证书链验证HRK->HSK->CEK->PEK证书的签名,请检查程序输出的LOG确定每个步骤是否成功。 \ No newline at end of file diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/5-KATA-2.5/2-\346\265\213\350\257\225ASID\345\244\215\347\224\250.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/5-KATA-2.5/2-\346\265\213\350\257\225ASID\345\244\215\347\224\250.md" new file mode 100644 index 0000000000000000000000000000000000000000..e3001503885239c5c6a822e63899f76108d73c34 --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/5-KATA-2.5/2-\346\265\213\350\257\225ASID\345\244\215\347\224\250.md" @@ -0,0 +1,23 @@ +测试之前,请先完成CSV KATA加密容器测试。 + +## 功能描述 +2号、3号CPU最多支持15个CSV ASID,每个CSV kata容器使用1个ASID,为了同时运行超过15个CSV kata容器,可以让同一个用户的CSV kata容器复用ASID,相同ASID的CSV kata容器使用的内存加密密钥相同。参数user-id表示用户信息,同一个ASID最多可以被64 个CSV kata容器复用。 + +## 测试CSV Kata复用ASID + +### 配置user-id +``` +$ sudo sed -i 's/#* *mem_encryption_user.*$/mem_encryption_user_id = "testuser"/' /etc/kata-containers/configuration.toml +``` +### 运行20个CSV kata容器 +``` +$ i=1; while [ $i -le 20 ]; do sudo -E nerdctl run  --runtime io.containerd.run.kata.v2 --name csv-kata$i -d ubuntu:20.04; let i++; done +``` +### 检查运行的CSV kata容器个数 +``` +$ sudo nerdctl ps  | grep -c csv-kata +``` +检查完清除运行中的容器 +``` +$ sudo nerdctl rm -f `sudo nerdctl ps -a |grep csv-kata |awk '{print $1}'` +``` \ No newline at end of file diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/5-KATA-2.5/3-\346\265\213\350\257\225\347\233\264\351\200\232DCU.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/5-KATA-2.5/3-\346\265\213\350\257\225\347\233\264\351\200\232DCU.md" new file mode 100644 index 0000000000000000000000000000000000000000..a7e64996b4fe0e9aaa6534c741a677ea412218aa --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/5-KATA-2.5/3-\346\265\213\350\257\225\347\233\264\351\200\232DCU.md" @@ -0,0 +1,45 @@ +测试之前,请先完成CSV KATA加密容器测试。 + +## 功能描述 +类似于CSV虚拟机直通DCU卡,CSV kata容器也可以使用DCU卡。 + +## 测试CSV kata容器使用DCU卡 + +### 编译kata容器镜像 +``` +$ wget https://github.com/moby/buildkit/releases/download/v0.10.6/buildkit-v0.10.6.linux-amd64.tar.gz +$ sudo tar zxvf buildkit-v0.10.6.linux-amd64.tar.gz -C /usr/local/ +$ sudo su root +# buildkitd & +$ cd /opt/hygon/csv/dcu/ +$ nerdctl build -t kata-dcu:v1 -f Dockerfile . +``` +buildkitd 需要在单独窗口运行 + +### 修改kata配置文件支持VFIO +``` +$ sudo sed -i -e "s/#* *\(hotplug_vfio_on_root_bus\).*=.*$/\1 = true/g" /etc/kata-containers/configuration.toml +$ sudo sed -i -e "s/#* *\(pcie_root_port\).*=.*$/\1 = 1/g" /etc/kata-containers/configuration.toml +$ sudo sed -i -e "s/^\(kernel_modules\).*=.*$/\1 = \[\"hydcu\"\]/g" /etc/kata-containers/configuration.toml +``` +### 运行直通DCU卡的CSV kata容器 +示例DCU卡的VFIO设备号是/dev/vfio/16。 +``` +$ export CNI_PATH=/opt/cni/bin/ +$ sudo -E nerdctl run --privileged --security-opt privileged-without-host-devices --runtime io.containerd.run.kata.v2 --device /dev/vfio/16 --mount type=bind,source=/dev,target=/dev,rw --mount type=bind,source=/mnt,target=/app,bind-propagation=shared --rm -it --name ubuntu-focal kata-dcu:v1 +``` +### 在CSV kata容器中运行DCU测试程序 + +HOST 下载测试集 +``` +$ cd /mnt +$ sudo git clone https://github.com/ROCm-Developer-Tools/HIP-Examples.git +``` + +容器中进入共享目录,编译运行测试集 +``` +# cd /app/HIP-Examples/vectorAdd +# source /opt/dtk-24.04/env.sh +# make clean;make +# ./vectoradd_hip.exe +``` diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/5-KATA-2.5/4-\346\265\213\350\257\225k8s\351\203\250\347\275\262CSV\346\234\272\345\257\206\345\256\271\345\231\250.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/5-KATA-2.5/4-\346\265\213\350\257\225k8s\351\203\250\347\275\262CSV\346\234\272\345\257\206\345\256\271\345\231\250.md" new file mode 100644 index 0000000000000000000000000000000000000000..ef3d89ef99ae15a0639fed5ac8b51a5cdb2f50f6 --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/5-KATA-2.5/4-\346\265\213\350\257\225k8s\351\203\250\347\275\262CSV\346\234\272\345\257\206\345\256\271\345\231\250.md" @@ -0,0 +1,50 @@ +测试之前,请先完成CSV KATA加密容器测试。 + +## 功能描述 +在K8s 上启动CSV KATA 容器,验证远程认证功能。 + +## 启动容器 + +部署k8s环境 +``` +$ cd /opt/hygon/csv/ +$ sudo ./k8s.sh +``` +hostip 为对应的部署本机ip地址,hostname 为主机名称。 +``` +$ sed -i 's/advertiseAddress:.*/advertiseAddress: hostip/g' /opt/hygon/csv/kubeadm-config.yaml +$ sed -i 's/name:.*/name: hostname/g' /opt/hygon/csv/kubeadm-config.yaml +``` +初始化k8s,添加kata runtimeClass +``` +$ cd /opt/hygon/csv/ +$ ./deploy_k8s_kata.sh +``` +启动kata 容器 +``` +$ kubectl apply -f ubuntu-kata.yml +``` + +## 验证CSV kata远程认证功能 +启动成功后,在容器中检查设备节点/dev/csv-guest是否存在,如果设备节点不存在将无法获取认证报告。将ioctl-get-attestation程序拷贝到容器中执行。 + +host端 +``` +$ kubectl cp /opt/hygon/csv/attestation/ioctl-get-attestation ubuntu-kata:/opt +$ kubectl exec ubuntu-kata -it bash +``` + +容器端 + +``` +# cd /opt/ +# ./ioctl-get-attestation +``` +ioctl-get-attestation执行会生成认证报告report.cert,可以在任意机器上验证认证报告,验证证书链签名会从证书服务器下载证书,因此验证机器需要联网。这里使用主机验证认证报告,将报告拷贝到主机中验证。 + +``` +$ kubectl cp ubuntu-kata:opt/report.cert ./report.cert +$ sudo chmod 666 report.cert +$ /opt/hygon/csv/attestation/verify-attestation true +``` +verify-attestation会使用PEK公钥验证认证报告的签名,并且从证书服务器下载证书链验证HRK->HSK->CEK->PEK证书的签名,请检查程序输出的LOG确定每个步骤是否成功。 diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/9-FAQ/1-\345\256\211\345\205\250\345\206\205\345\255\230\345\212\240\345\257\206.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/9-FAQ/1-\345\256\211\345\205\250\345\206\205\345\255\230\345\212\240\345\257\206.md" new file mode 100644 index 0000000000000000000000000000000000000000..d6a3171b67d9e435c09cba710ef1d45e5d520760 --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/9-FAQ/1-\345\256\211\345\205\250\345\206\205\345\255\230\345\212\240\345\257\206.md" @@ -0,0 +1,32 @@ +# 安全内存加密 FAQ + +#### Q: 海光内存加密采用什么算法 + +A: 海光内存加密采用国密 SM4 算法 + +#### Q: 海光安全内存加密技术和 CSV 是什么关系 + +A: 海光安全内存加密技术用来加密主机内存,主机上运行的所有程序使用同一个内存加密密钥。 CSV 技术用来加密虚拟机内存,每个 CSV 虚拟机拥有自己的内存加密密钥,不同的 CSV 虚拟机使用的密钥各不相同。 + +#### Q: 打开安全内存加密后,外设能正常访问加密内存吗 + +A: 安全内存加密技术通过页表项中的 C bit 控制是否加密该页表项指向的内存,C bit 默认是物理地址中的第 47 位。C=1 表示此页内存被加密,C=0 表示此页内存不加密。外设通过 DMA 访问加密内存时,只要正确设置内存地址 C=1 就可以正常访问。不支持 64 位物理地址的外设,通过 IOMMU 也可以正常访问加密内存。 + +#### Q: 海光安全内存加密技术和海光密码协处理器是什么关系 + +A: 海光密码协处理器是高性能国密运算硬件引擎,支持 SM2、SM3、SM4 运算加速。安全内存加密技术使用的 SM4 加密模块是集成在内存控制器中的硬件模块,和密码协处理器没有关系。 + +#### Q: 打开安全内存加密后,海光密码协处理器能正常访问加密内存吗 + +A: 只要正确设置内存地址的 C bit,海光密码协处理器可以正常访问加密内存。 + +#### Q: 使能SME之后,出现RAID卡swiotlb_alloc失败 + +A: 该问题,通常是以前的RAID卡只支持32位寻址,不支持更高的,所以使能SME时,必须同时使能IOMMU: + +1. 首先检查BIOS IOMMU是否已使能 +2. 其次,排查内核IOMMU是否已使能,根据内核版本的不通,排查方法不同: +3. 5.10 内核:看下cmdline是否使能了iommu=pt,如果使能了,请关闭 +4. 4.19 内核,看下内核编译是否使能了 CONFIG_IOMMU_DEFAULT_PASSTHROUGH,如果使能了,采用以下任意方式解决(二选一): + 1. 重新编译内核以禁用 + 2. 内核cmdline添加:iommu.passthrough=off iommu=nopt diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/9-FAQ/2-\346\234\272\345\257\206\350\231\232\346\213\237\346\234\272.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/9-FAQ/2-\346\234\272\345\257\206\350\231\232\346\213\237\346\234\272.md" new file mode 100644 index 0000000000000000000000000000000000000000..f099bba1cf2763fbf237211b5671fc84fe2808bb --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/9-FAQ/2-\346\234\272\345\257\206\350\231\232\346\213\237\346\234\272.md" @@ -0,0 +1,102 @@ +# 虚拟机 FAQ + +#### Q: 同时能运行多少个 CSV 虚拟机 + +海光 2 号、3号 CPU 最多能同时运行 15 个 CSV 虚拟机,C86-4G支持同时运行`500`个CSV虚拟机 + +#### Q: CSV 虚拟机支持设备直通吗 + +CSV 虚拟机支持设备直通,可以通过 VFIO 将网卡等设备分配给 CSV 虚拟机使用。为了保证 CSV 虚拟机加密内存的安全性,CPU 硬件阻止设备访问 CSV 虚拟机的加密内存,设备只能访问非加密内存,设备驱动通过 bounce buffer 机制将数据从加密内存拷贝到非加密内存实现正常访问。 + +#### Q: CSV虚拟机直通两张DCU卡时,一张直通成功,一张直通失败 + +PciMMio预留的bar空间不够,修改qemu参数:name=opt/ovmf/X-PciMmio64Mb,string=131072 + +#### Q: CSV虚拟机中rocm-smi显示DCU占用率为100%,但实际未跑业务 + +A: DCU目前不支持RESET,虚拟机直通时会调用RESET接口,导致DCU卡异常。workarroud方案:主机安装`hydcu_pci_fixup_header`,该驱动会屏蔽DCU RESET接口 + +#### Q: CSV虚拟机是否支持 data sealing的功能 + +A: CSV加密虚拟机是支持密钥封印功能的,CSV机密容器暂不支持。 + +#### Q: csv-guest.c内核中编译方法 + +A: 参考 https://gitee.com/anolis/cloud-kernel/blob/devel-5.10/drivers/virt/Kconfig + +#### Q: gemu-system-x86 64: -netdev bridge,br=virbr0,id=net0: bridge helper failed +A: 创建 /etc/qemu/bridge.conf,添加allow virbr0 在文件中 + +#### Q: { "execute": "pmemsave", "arguments": {"val": 0, "size": 256, "filename": "csv.txt"} } 出现 Permission denied + +A: 可能是已经生成过对应的文件,将文件删除重新尝试 + +#### Q: csv 虚拟机启动不了排查流程 + +- 检查固件信息 + ``` + $ sudo hag general check + firewalld: inactive + selinux: Disabled + kernel version: 5.10.134-csv + model name: Hygon C86 3250 8-core Processor + Hygon C86 3250 8-core Processor + is Hygon CPU: YES + SME: enabled + CSV: enabled + /dev/sev: exist + psp bl version: 1.2.112.0 + csv api version: 1.3 + firmware version: 2229 + is HGSC imported: YES + TKM: enabled + chip id: NZA9T01100405 + /dev/tdm: exist + TDM: enabled + tdm api version: 1.4 + /dev/tpm0: exist + tpm_acpi: HYGT0101 + /dev/tcm0: nonexist + tcm_acpi: nonexist + check command success! + ``` + 1)**firmware version** C86-3G 机器版本要求不低于**1837**, + C86-4G 机器版本要求不低于**2089** ,机器型号参考[1-0 安全功能配置要求](https://openanolis.cn/sig/Hygon-Arch/doc/1076446632387394260?lang=zh) **硬件配置要求** 章节, + 如果条件不满足,请联系厂商确认bios是否包含安全固件功能 + + 2)如果SME 和 CSV 都是disabled状态,请参考[1-0 安全功能配置要求](https://openanolis.cn/sig/Hygon-Arch/doc/1076446632387394260?lang=zh) **BIOS安装及设置要求** 章节检查 SMEE 是否开启 + + +- 查看内核版本 + + 内核必须是社区文档提供内核,具体请参考[1-1-安装操作系统和内核](https://openanolis.cn/sig/Hygon-Arch/doc/865622272844371792) + +- 查看主机内核参数 + ``` + $ cat /proc/cmdline + 内容必须包含kvm-amd.sev=1 kvm-amd.sev_es=1 ,如果是启动csv3虚拟机还必须包含csv_mem_percentage=50 如果没有在/etc/default/grub 中设置使其生效 + ``` + **csv_mem_percentage=50** 中**50** 表示cma内存占用整个内存的百分比,可以根据需要调整 +- 检查通用安全证书是否导入 + + 请参考[1-2-导入通用安全证书](https://openanolis.cn/sig/Hygon-Arch/doc/865622274698254162)导入通用安全证书。 + +- 检查内核config 配置 + + /boot/config-5.10.134-csv 配置文件中,如下宏应该为如下状态 + ``` + CONFIG_CRYPTO_DEV_CCP=y + CONFIG_AMD_MEM_ENCRYPT=y + CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT=y + ``` + 如果不一致请进行修改重新编译 +- 查看/sys/module/kvm_amd/parameters/sev 值 + ``` + $ cat /sys/module/kvm_amd/parameters/sev + 1 + ``` + 上面的内容值必须是1 + + #### Q: 原生麒麟虚拟机使用-device virtio-net-pci,netdev=net0,romfile= 网络参数启动卡主 + + A: 使用 -device virtio-net-pci,netdev=net0,disable-legacy=on,iommu_platform=on,romfile= 参数进行替换 \ No newline at end of file diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/9-FAQ/3-\346\234\272\345\257\206\345\256\271\345\231\250.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/9-FAQ/3-\346\234\272\345\257\206\345\256\271\345\231\250.md" new file mode 100644 index 0000000000000000000000000000000000000000..d9516398eef6fe9b237b86e66161ecdac00a269a --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/9-FAQ/3-\346\234\272\345\257\206\345\256\271\345\231\250.md" @@ -0,0 +1,289 @@ +# 机密容器 FAQ + +#### Q: CSV 机密容器的工作原理是什么 + +A: CSV 机密容器使用了 3 个底层技术:KATA 容器技术、海光 CSV 安全虚拟化技术和 RATS-TLS 技术。KATA 容器运行在虚拟机中,使用独立的内核,比普通容器的安全性更高。KATA 容器结合 CSV 技术使容器运行在CSV 虚拟机中,CSV 虚拟机使用 CPU 独立的 TLB、Cache 等资源,并且虚拟机内存被硬件加密,主机无法访问,进一步提高容器的安全性。CSV 虚拟机结合 RATS-TLS 技术实现了容器运行环境的远程认证功能,RATS-TLS 证书中嵌入了 CSV 虚拟机远程认证报告,认证报告使用海光 CPU 芯片密钥签名,认证通过证明容器运行在安全的 CSV 虚拟机中,TLS 公钥可信,可用于容器镜像解密等传输协议。 + +#### Q: CSV 机密容器pull镜像 网络失败排查流程 + +- 确认主机上能否访问外网 +``` +$ curl -I www.google.com +HTTP/1.1 200 OK +Transfer-Encoding: chunked +Cache-Control: private +Connection: keep-alive +Content-Security-Policy-Report-Only: object-src 'none';base-uri 'self';script-src 'nonce-av2HGf3bKW-3lOmpVG8kCQ' 'strict-dynamic' 'report-sample' 'unsafe-eval' 'unsafe-inline' https: http:;report-uri https://csp.withgoogle.com/csp/gws/other-hp +Content-Type: text/html; charset=ISO-8859-1 +Date: Wed, 27 Nov 2024 06:04:33 GMT +Expires: Wed, 27 Nov 2024 06:04:33 GMT +Keep-Alive: timeout=4 +P3p: CP="This is not a P3P policy! See g.co/p3phelp for more info." +Proxy-Connection: keep-alive +Server: gws +Set-Cookie: AEC=AZ6Zc-VU8r_ZysfVX952pnbMtFMmWoYb2NRjGrApWp72qUQYdDB7vExHgQ; expires=Mon, 26-May-2025 06:04:33 GMT; path=/; domain=.google.com; Secure; HttpOnly; SameSite=lax +Set-Cookie: NID=519=iVFq4dhKfrAvxkSdV2OycQaqItZkWZzltjrM7HVU3MNSbbQx4360W8C2Q4bmKUqR5TkbQlNIKvQcUKZF_zxJjN7CtG3c4P5tTphgm2IIhiG1coM_-FvUlPs0xL7gCQbE8Ow7RUb7P90ecrtUn_wPsbY7N7T-mPilpH4Y8_BJ0DaWI8od-T9TuT2_Mr2Eb-E; expires=Thu, 29-May-2025 06:04:33 GMT; path=/; domain=.google.com; HttpOnly +X-Frame-Options: SAMEORIGIN +X-Xss-Protection: 0 +``` +上述表示可以访问外网,否则检查主机网络 +- 排查kata机密虚拟机网络 + +打开虚拟机 debug console,启动容器之前添加如下配置 +``` +$ sudo sed -i -e 's/^# *\(enable_debug\).*=.*$/\1 = true/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml +$ sudo sed -i -e 's/^kernel_params = "\(.*\)"/kernel_params = "\1 agent.log=debug initcall_debug"/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml +$ sudo sed -i -e 's/^# *\(use_legacy_serial\).*=.*$/\1 = true/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml +$ sudo sed -i -e 's/^# *\(debug_console_enabled\).*=.*$/\1 = true/g' /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv.toml +``` +获取虚拟机的sandbox id + +``` +$ ps -elf |grep sandbox +/opt/confidential-containers/bin/qemu-system-x86_64 -name sandbox-b66feaa98fcacfa8fe0b40c8472189cb20043c8269b23bf5c1da710f20be00a1 -uuid d113bb06-f05e-4e35-a407-4d6e827370b8 ......... + +``` +使用sandbox id登录虚拟机 +``` +$ sudo /opt/confidential-containers/bin/kata-runtime exec b66feaa98fcacfa8fe0b40c8472189cb20043c8269b23bf5c1da710f20be00a1 +``` +查看虚拟机和主机网络连通性 +``` +# exec <> /dev/tcp/host_ip/22 +# +``` +查看虚拟机和代理的连通性 +``` +# exec <> /dev/tcp/proxy_ip/port +# +``` +查看虚拟机和百度的连通性 +``` +# exec <> /dev/tcp/www.baidu.com/443 +# +``` +1.命令无任何输出,但是打印出下一个bash命令提示符,说明网络状态正常连通 + +2.connection refused意味着端口关闭 + +3.命令无任何输出,且不打印下一个bash命令提示符,意味着网络不通 + +执行完如果再执行命名遇到卡主的情况,通过exec 再新的终端重新登录 + +- 访问国内阿里云等仓库不要配置代理 + +访问阿里云等国内仓库kernel_params 配置参数 不要设置agent.https_proxy 和agent.no_proxy 等代理地址 + +#### Q: 拉取较大镜像时,需要将内存配置较大以适应较大的镜像 +配置方法如下: + +``` +$ sudo sed -i "s/^default_memory *=.*\$/default_memory = 10240/g" /opt/confidential-containers/share/defaults/kata-containers/configuration-qemu-csv-dcu.toml +``` +**10240** 为设置内存的大小,客户根据实际情况调整 + +#### Q: https私有仓库搭建 +如下步骤作为搭建私有仓库参考,主机系统Anolis OS 8.4 + +- 拉取镜像 + ``` + sudo docker pull registry:2.7.0 + ``` +- 生成密码文件 + user password 为仓库账号密码,根据需求自行调整 + ``` + # mkdir -p /docker/registry/auth + # docker run --entrypoint htpasswd registry:2.7.0 -Bbn user password >> /docker/registry/auth/htpasswd + ``` +- 设置配置文件 +``` + # mkdir -p /docker/registry/config + # cat > /docker/registry/config/config.yml < openssl.cnf < cert_chain.cert +# mv -f cert_chain.cert /opt/csv/ +``` +注:**如果机器不能联网**,需要将hag csv export_cert_chain 步骤使用[2-3-5-测试CSV虚拟机迁移](https://openanolis.cn/sig/Hygon-Arch/doc/944532750000611833) 中 **离线导出证书** 章节步骤进行替换制作证书 + +修复后重新行测试 diff --git "a/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/9-FAQ/4-\350\277\234\347\250\213\350\256\244\350\257\201.md" "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/9-FAQ/4-\350\277\234\347\250\213\350\256\244\350\257\201.md" new file mode 100644 index 0000000000000000000000000000000000000000..7204f823b68a7f84429d1be0c92d8f42966d4aa3 --- /dev/null +++ "b/sig/Hygon Arch/content/2-CSV\346\265\213\350\257\225\346\226\207\346\241\243/9-FAQ/4-\350\277\234\347\250\213\350\256\244\350\257\201.md" @@ -0,0 +1,33 @@ +# 远程认证 FAQ + +#### Q: 远程认证报告中mnonce,data,hash分别是什么 + +A: mnonce和data是用户的输入,作为对报告的完整性保护,mnonce会作为HMAC运算的key,data会放在report中返回(可以为空)。hash就是HMAC完整性运算的结果 + +#### Q: 如何下载海光芯片证书 + +A: 可以通过网站 [https://cert.hygon.cn](https://cert.hygon.cn/) 下载海光芯片证书。芯片序列号通过运行海光安全工具 hag 获取。 + +#### Q: 生成、验证远程证明时是否需要连外网? + +A: 生成和验证都不需要外网, 验证过程中可以在外面下载好证书,拷贝到机器上做验证使用 + +##### 离线下载证书流程 +- 获取cpu chip id +``` +$ sudo hag general get_id +chip id is T6N0580001081701 +get_id command success! + +[general] Command successful! +``` +- 手动下载该芯片的HSK_CEK证书 +``` +$ curl -s -f -o hsk_cek.cert https://cert.hygon.cn/hsk_cek?snumber=T6N0580001081701 +``` +- 手动下载HRK证书 +``` +curl -s -f -o ./hrk.cert https://cert.hygon.cn/hrk +``` + +然后将证书拷贝到验证程序同一个目录下进行验证 \ No newline at end of file diff --git "a/sig/Hygon Arch/content/3-HCT\346\265\213\350\257\225\346\226\207\346\241\243/1-HCT\347\224\250\346\210\267\346\211\213\345\206\214.md" "b/sig/Hygon Arch/content/3-HCT\346\265\213\350\257\225\346\226\207\346\241\243/1-HCT\347\224\250\346\210\267\346\211\213\345\206\214.md" new file mode 100644 index 0000000000000000000000000000000000000000..3832c49f121dc43a68a6698b2e82d9bced933b36 --- /dev/null +++ "b/sig/Hygon Arch/content/3-HCT\346\265\213\350\257\225\346\226\207\346\241\243/1-HCT\347\224\250\346\210\267\346\211\213\345\206\214.md" @@ -0,0 +1,216 @@ +# **1. 概要** + +## **1.1. HCT简介** + +海光密码技术(HCT, Hygon Cryptographic Technology)是基于海光密码协处理器和密码指令集自主设计研发的一套密码算法加速软件开发套件。HCT充分利用海光平台密码加速特性,整合底层海光密码计算资源,为用户上层应用提供高性能密码计算能力。用户无需了解底层细节就可以轻松使用海光平台高性能密码计算能力,显著提升密码应用的性能。此外,HCT通过OpenSSL标准接口对外提供密码计算能力,完美兼容OpenSSL生态,具有良好的易用性和可移植性。用户可以方便的将已有项目代码迁移到海光平台,从而大幅缩短项目开发时间。 + +## **1.2. 主要内容** + +本文通过实施功能测试和性能测试的方式,展示了HCT在7285 CPU双路服务器上的使用方法。 + +## **1.3. 测试环境** + +| 组件 | 版本信息 | +|--------------|-----------------------| +| CPU | Hygon C86 7265 | +| 内存 | 128GB DDR4 | +| 操作系统内核 | Linux kernel 5.10 | +| 操作系统 | Ubuntu 18.04 | +| gcc | 7.5.0 | +| OpenSSL | 1.1.1c | +| numa | 2.0.12 | +| HCT套件 | hct_2.1.0.20241030_release | + +# **2. HCT下载和环境配置** + +## **2.1. 下载HCT开发套件** + +官方发布的HCT密码计算套件位于gitee的hygon-devkit仓库: + +``` +git clone "https://gitee.com/anolis/hygon-devkit.git" +``` + +HCT密码计算套件的目录结构如下: + + +``` +hygon-devkit/ + ├─ hct + ├──pkg + │ ├── hct_1.0.0.20230224_rc + │ ├── hct_1.0.1.20230512_rc + │ ├── hct_1.1.0.20230730_rc + │ ├── hct_1.1.1.20230930_rc + │ ├── hct_2.0.0.20240430_release + | └── hct_2.1.0.20241030_release + └── README.md +``` + +- pkg目录:内含各版本hct密码计算套件。 + +- README.md文件:有关HCT的简单情况。 + +## **2.2. 环境配置** + +1\. 安装需要依赖的软件库 + +1) numa库 + +Ubuntu: + +``` +sudo apt install libnuma-dev +``` + +Centos: + +``` +sudo yum install numactl -y +``` + +2) openssl库 + +系统中如果存在支持国密的openssl-1.1.xx,无需特地安装openssl-1.1.1c。 + +``` +wget "https://www.openssl.org/source/old/1.1.1/openssl-1.1.1c.tar.gz" +tar -zxvf openssl-1.1.1c.tar.gz +cd openssl-1.1.1c +./config --prefix=/usr/local +make +sudo make install +``` + +**注意:** `--prefix=/usr/local`会将openssl-1.1.1c安装到/usr/local路径下,可结合具体需求更改此安装路径。 + +3) uuid库 + +Ubuntu: + +``` +sudo apt install uuid-dev +``` + +Centos: + +``` +sudo yum install libuuid-devel -y +``` + +2\. 安装HCT开发套件 + +Centos: + +``` +cd hct/pkg/hct_2.1.0.20241030_release +sudo rpm -ivh --nodeps hct-2.1.0-2024-1030-release.x86_64.rpm +``` + +**注意:** 安装时必须加上`--nodeps`选项。 + +Ubuntu: + +``` +cd hct/pkg/hct_2.1.0.20241030_release +sudo dpkg -i hct-2.1.0-2024-1030-release.x86_64.deb +``` + +3\. 安装HCT内核模块 + +**编译安装HCT内核模块要求内核版本在4.10及以上。** + +请将hct_2.1.0.20241030_release目录(如果使用其他版本HCT,请找到对应版本目录)下的Makefile文件下载到任意空目录中,并在该目录下执行以下命令编译并安装HCT内核模块。 + +``` +make +sudo make install +``` + +**注意:** modprobe前请确保系统内只有一份HCT内核模块 + +4\. 执行配置,绑定CCP + +``` +sudo /opt/hygon/hct/hct/script/hctconfig start +``` + + + +# **3. 测试** + +## **3.1. 功能测试** + +``` +cd /opt/hygon/hct/bin +./hct_test +``` + +## **3.2. 性能测试** + +``` +cd /opt/hygon/hct/bin + +#同步多进程CCP硬件计算测试 +./hct_speed -elapsed -engine hct -multi 128 -seconds 10 -cmd ccp sm2enc +./hct_speed -elapsed -engine hct -multi 128 -seconds 10 -cmd ccp sm2sign +./hct_speed -elapsed -engine hct -multi 128 -seconds 10 -cmd ccp -bytes 1024 -evp sm3 +./hct_speed -elapsed -engine hct -multi 128 -seconds 10 -cmd ccp -bytes 1024 -evp sm4 + +#同步多进程CPU软件计算测试 +./hct_speed -elapsed -engine hct -multi 128 -seconds 10 -cmd sw_avx sm2enc +./hct_speed -elapsed -engine hct -multi 128 -seconds 10 -cmd sw_avx sm2sign +./hct_speed -elapsed -engine hct -multi 128 -seconds 10 -cmd sw_avx -bytes 1024 -evp sm3 +./hct_speed -elapsed -engine hct -multi 128 -seconds 10 -cmd sw_avx -bytes 1024 -evp sm4 + +# 异步多进程CCP硬件计算测试 +./hct_speed -elapsed -engine hct -multi 128 -async_jobs 512 -seconds 10 -cmd ccp sm2enc +./hct_speed -elapsed -engine hct -multi 128 -async_jobs 512 -seconds 10 -cmd ccp sm2sign +./hct_speed -elapsed -engine hct -multi 128 -async_jobs 512 -seconds 10 -cmd ccp -bytes 1024 -evp sm3 +./hct_speed -elapsed -engine hct -multi 128 -async_jobs 512 -seconds 10 -cmd ccp -bytes 1024 -evp sm4 + +#同步多线程CCP硬件计算测试 +./hct_speed -elapsed -engine hct -multi-thread -multi 128 -seconds 10 -cmd ccp sm2enc +./hct_speed -elapsed -engine hct -multi-thread -multi 128 -seconds 10 -cmd ccp sm2sign +./hct_speed -elapsed -engine hct -multi-thread -multi 128 -seconds 10 -cmd ccp -bytes 1024 -evp sm3 +./hct_speed -elapsed -engine hct -multi-thread -multi 128 -seconds 10 -cmd ccp -bytes 1024 -evp sm4 +``` + +**Tips:** hct_speed各个参数说明以及所有用法均可通过`./hct_speed --help`进行查询 + +# **4. 利用hct套件开发** + +HCT通过 openssl 标准接口(EVP)向应用提供接口,使用HCT套件时,通过`e=ENGINE_by_id("hct")`选择密码引擎为hct,然后直接通过openssl标准(EVP)接口即可完成对HCT密码计算套件的调用。 + + +# **5. 注意事项** +1\. HCT在hct_1.1.0.20230730_rc之后(包括该版本)的版本中,优化了证书检查机制(海光3号系列芯片),可以在非sudo权限下使用HCT。该功能需要BIOS支持,故在3号芯片上需升级BIOS到支持新证书检查功能的版本。 +__另外部分旧有的BIOS也可以采用在线升级的方式更新BIOS,详情如下:__ +``` +操作提示: + Ⅰ. 检查BIOS版本是否为2.1.0.4以上版本 + Ⅱ. 参考:https://openanolis.cn/sig/Hygon-Arch/doc/865622274698254162 安装通用证书 + Ⅲ. 从 https://gitee.com/anolis/hygon-devkit.git 仓库中的bin目录中获得hag程序 + Ⅳ. 运行./hag general download_firmware +``` + +2\. 如果BIOS支持,可以将PSP CCP配置给C86使用,BIOS设置步骤如下: +``` + Ⅰ. 进入BIOS,选择“HYGON CBS”,进入“Moksha Common Options” + Ⅱ. 在“Available PSP CCP VQ Count”中输入4 +``` +**说明:CPU芯片中包含两类CCP协处理器,一类为PSP CCP,一类为NTB CCP,通常BIOS只会将NTB CCP配置给用户使用,PSP CCP一般用于可信计算场景。如果BIOS支持将PSP CCP配置给用户(C86)使用,那么HCT就可以获得更多的协处理器资源,表现出更高的性能。** + +3\. hct_2.0.0.20240430_release版本之后支持noiommu使用场景,支持2M大页和1G大页两种模式,可参考如下提示使用 +``` +提示: + Ⅰ. 确保内核CONFIG_VFIO_NOIOMMU配置为打开状态 + Ⅱ. 需要关闭iommu及配置2M大页(如要使用1G大页模式,把配置中'2M'对应地改为'1G'即可): mem_encrypt=off amd_iommu=off default_hugepagesz=2M hugepagesz=2M hugepages=2048 + Ⅲ. 打开noiommu模式: echo 1 > /sys/module/vfio/parameters/enable_unsafe_noiommu_mode + Ⅳ. 以vfio-pci模式绑定ccp: ./hctconfig start -m vfio-pci + Ⅴ. 若开启了内存加密,即在grub中配置了sme=on,则需要加载hct.ko,否则该功能无法正常使用 +``` + +4\. hct_2.1.0.20241030_release版本相较于以往版本,在用户态代码(hct.so和libhcts.so)和内核模块代码(hct.c)均有较多改动,建议这两部分同步进行更新,若升级此版本时,只更新用户态代码或只更新内核模块代码,则可能出现异常 + +5\. hct_2.1.0.20241030_release版本支持openssl-3.0.xx,可根据需要选择对应的openssl版本进行安装,步骤同2.2节中安装openssl-1.1.1c \ No newline at end of file diff --git "a/sig/Hygon Arch/content/3-HCT\346\265\213\350\257\225\346\226\207\346\241\243/10-\345\216\206\345\217\262\346\226\207\346\241\243/1-\345\257\206\351\222\245\347\256\241\347\220\206\347\231\275\347\232\256\344\271\246.md" "b/sig/Hygon Arch/content/3-HCT\346\265\213\350\257\225\346\226\207\346\241\243/10-\345\216\206\345\217\262\346\226\207\346\241\243/1-\345\257\206\351\222\245\347\256\241\347\220\206\347\231\275\347\232\256\344\271\246.md" new file mode 100644 index 0000000000000000000000000000000000000000..0b7b6d5bbba405e9fecb91bb33cdb68cf81a3c8e --- /dev/null +++ "b/sig/Hygon Arch/content/3-HCT\346\265\213\350\257\225\346\226\207\346\241\243/10-\345\216\206\345\217\262\346\226\207\346\241\243/1-\345\257\206\351\222\245\347\256\241\347\220\206\347\231\275\347\232\256\344\271\246.md" @@ -0,0 +1,76 @@ +## 简介 +密码相关应用除了要求提供高效的密码运算能力外,还往往需要一种安全有效的密钥管理能力,密钥的安全是安全的基础,密钥如果被窃取则安全无从谈起。目前大量应用的密钥管理方式存在着简单粗放的问题,有的甚至把密钥以明文形式直接存储在文件系统中,密钥的安全存在巨大的隐患。密码技术的广泛应用迫切需要一种既安全又易用的密钥管理使用方式。 + +## CPU密钥管理优势 +传统的密钥管理方案通常使用单独的密码卡,通过PCIE等外接于主板上,与CPU通过总线连接。传统方案增加硬件成本的同时,加大了主板硬件设计的复杂度,也增加了暴露面,容易受总线类物理攻击。 +CPU利用内置安全处理器对密钥管理做了相关支持与拓展,在CPU内部实现了TKM模块(Trusted Key Management Module),相比传统方案具有如下优势: +1. 无需主板硬件支持,通用性强,且无额外硬件成本; +2. 功能内置于CPU,有效抵抗外部物理攻击; +3. 集成国密硬件引擎CCP,密码运算更高效; +4. 模块内置于CPU,可以通过证书链对其设备进行背书; +5. 技术国产化,自主可控 + +## 安全处理器 +TKM基于CPU内置安全处理器实现。如图一所示,CPU内置了一个独立的安全处理器。 + + 图一 CPU架构图 + + ![](../../../assets/cpu_arch-1.png) + +安全处理器具有以下特点: +- 具有自己独立的资源,外部(包括C86核心)不可访问; +- 具有很高的系统权限,它可以访问所有的系统资源,包括CPU控制,系统内存及外设等; +- 系统上电时先于C86核心首先启动,C86核心何时启动由其决定,受其控制; +- 安全处理器的初始化代码固化在芯片内部,不可更改,初始代码对后续代码进行合法性和完整性验证,确保安全可靠; +- C86核心通过固定的硬件接口与安全处理器通讯。 +安全处理器的上述特点非常适合实现密钥管理等相关应用。 + +## 国密硬件引擎CCP +密钥管理是密码运算密集型技术,CPU内置了国密硬件引擎CCP对密码运算提供硬件加速,支持常用的密码算法,包括对称,非对称,Hash等。对称密码用来进行加解密及计算消息验证码HMAC,非对称密码用来进行签名验签及共享密钥生成等,Hash用来度量及被签名等。 + +使用CCP进行密码运算不占用CPU资源。CPU片内CCP有两种类型,一种供安全处理器使用,支持TKM等模块内部的密码运算;一种供C86核心使用,用来支持纯算力的密码运算。两种CCP全面为密钥管理模块密码运算提供加速。 + +## TKM系统架构 +如图二所示,CPU基于安全处理器和密码协处理器CCP实现了“可信密钥管理模块”TKM(Trusted Key Management Module),用户把密钥存储在TKM内部,外部不可见。用户使用时只需指定密钥在TKM内部的索引或句柄,通过调用TKM提供的业务接口高效的完成密码运算。TKM可以达到用户对密钥“可用不可见”的效果,实现对密钥的保护。 + +软件接口层,TKM提供私有的TKM高性能接口,同时提供了符合GM/T 0018标准的SDF接口。 + +图二 TKM架构图 + ![](../../../assets/tkm_arch-1.png) + +## TKM主要功能 +### 一、 密钥管理功能 +1. 密钥生成:支持密钥由内部随机生成,采用TRNG硬件真随机数源。 +2. 密钥协商:支持密钥协商的方式生成共享密钥 +3. 密钥派生:支持基于HMAC算法派生模式的密钥派生 +4. 密钥导入:支持密钥从外部导入 +5. 密钥导出:支持密钥以密文形式导出 +6. 密钥更新:支持内部密钥的更新,包括对称非对称密钥 +7. 密钥销毁:支持销毁除设备密钥外所有密钥 +8. 密钥备份与恢复:支持以安全的方式备份所有内部密钥为密钥镜像,以及从密钥镜像恢复所有密钥。备份恢复支持三种方式: +- (1)仅支持同一个设备上备份恢复; +- (2)仅支持同一代CPU间备份恢复; +- (3)支持不同代CPU间备份恢复。 +### 二、 密码运算功能 +1. 对称加解密:支持SM4/AES对称加解密,支持ECB、CBC、CFB、OFB、CTR模式 +2. 非对称加解密:支持SM2/RSA算法加解密 +3. 签名验签:支持SM2/RSA算法签名验签 +4. 哈希计算:支持SM3算法的哈希计算 +5. 消息鉴别码:支持基于SM3/SHA算法的HMAC产生与验证 +6. CMAC运算:支持基于SM4/AES算法的CMAC运算 +7. 数字信封:支持数字信封的方式对数据进行加解密 +8. 随机数产生:支持基于硬件的真随机数产生 + +## TKM虚拟化支持 +支持物理主机使用TKM的同时,通过TKM虚拟化技术虚拟出多个vTKM实例,支持虚拟机内使用vTKM,主要特性如下: +1. 虚拟机内使用vTKM,vTKM提供与主机TKM相同的密钥管理与密码运算功能; +2. vTKM实例之间相互隔离,每个vTKM实例代表一个独立的密钥空间。 +3. 支持每个虚拟机独占一个vTKM实例,拥有自己独立的密钥资源,相互之间不可访问,也支持多个虚拟机共享同一个vTKM实例,共享同一个密钥空间; + +## TKM应用场景 +TKM支持在各种不同的环境下使用,如图三所示,支持在主机、虚拟机、机密虚拟机、容器、机密容器上同时使用。 + +图三 TKM使用环境 + ![](../../../assets/tkm_scene-1.png) +TKM的应用场景包括密码机服务器、工控系统、KMS以及各种通用系统中的密钥管理等,根据需要基于TKM接口也可以进一步封装符合相关标准的接口。TKM提供的GM/T 0018标准接口,即SDF接口,可广泛应用在专用的密码设备中,比如服务器密码机、签名验签服务器、VPN服务器等;另外,在需要密码服务的节点上使用支持TKM的海光服务器,改变原有通过网络访问池化密码资源的方式,通过本地密码资源直接访问,实现一种“分布式密码计算”方式,进而降低成本、降低网络带宽占用、优化性能。 + diff --git "a/sig/Hygon Arch/content/3-HCT\346\265\213\350\257\225\346\226\207\346\241\243/2-\345\257\206\351\222\245\347\256\241\347\220\206\345\212\237\350\203\275\346\265\213\350\257\225.md" "b/sig/Hygon Arch/content/3-HCT\346\265\213\350\257\225\346\226\207\346\241\243/2-\345\257\206\351\222\245\347\256\241\347\220\206\345\212\237\350\203\275\346\265\213\350\257\225.md" new file mode 100644 index 0000000000000000000000000000000000000000..2d5d850b9a58e1d4692e48aa1dfb8504f3f296dc --- /dev/null +++ "b/sig/Hygon Arch/content/3-HCT\346\265\213\350\257\225\346\226\207\346\241\243/2-\345\257\206\351\222\245\347\256\241\347\220\206\345\212\237\350\203\275\346\265\213\350\257\225.md" @@ -0,0 +1,796 @@ +## 1.概述 + +海光HCT密码技术除了提供基于CCP密码协处理器和指令集的密码运算加速外,还提供了符合国密认证要求的TKM密钥管理功能。TKM实现了完整的密钥生命周期管理,包括密钥生成、存储、使用、导入导出、备份恢复、销毁等操作。通过TKM用户可以安全的管理并使用密钥,实现对密钥的“可用不可见”。 + +本文档对TKM常用的应用场景进行说明,通过该文档用户可以对TKM常用的使用场景有个基本的了解,使用场景全部通过管理工具hag来完成,使用该文档对hag以及其他环境要求如下表: + +**表1** **TKM功能测试配置要求** + +| 配置 | 要求 | 备注 | +|--------------|-----------------------|-----| +| CPU | Hygon C86-3G及以上 | | +| BIOS | 海光BIOS PI2.1.0.4,并且安全固件版本大于1881 | [安全固件动态升级方法](https://openanolis.cn/sig/Hygon-Arch/doc/922794991552872684) | +| hag | 1881或以上 | [hag工具下载链接](https://gitee.com/anolis/hygon-devkit/raw/master/bin/hag)| +| glibc | 2.17或以上 | | + +## 2.版本基本说明 +### 2.1 安全固件不同版本的功能支持情况 +| **版本号** | **支持的功能** | +|------------|--------------------------------| +| 1881 | 基本功能 | +| 2070 | 支持虚拟化密钥隔离 | +| 2131 | 支持海光CSV虚拟机中使用TKM | +| 2210 | 性能优化 +### 2.2 安全固件版本的检查方式 + +安全固件版本的检查方式,可以通过hag命令进行检查: + +``` +$ sudo hag general check +``` +![fw_version](../../assets/general_check_fw_version.png) + +图中输出的firmware_version字段表示安全固件的版本。而hag工具的版本检查方式为: + +``` +$ sudo hag general version +``` + +输出的Version字段表示hag工具的版本 +### 2.3 通用安全证书导入说明 + +- 检查机器是否已导入支持使用TKM的通用证书,可以通过hag命令进行检查: +``` +$ sudo hag general check +``` +![fw_version](../../assets/TKM/hgsc_tkm.png) + +图中输出的TKM字段为enabled时表示已通过通用证书使能TKM。 + +- 若TKM已使能,跳过这步,否则请参考文档[通用安全功能使能方法](https://openanolis.cn/sig/Hygon-Arch/doc/865622274698254162)使能TKM,TKM功能在通用安全证书导入成功后才能使用。 + +- 通用证书导入成功后,除重刷BIOS操作外,无需再次导入证书。 + +### 2.4 Hag TKM命令查看 + +执行如下命令获取TKM支持的命令: +``` +$ sudo hag tkm help +``` +命令正确执行的结果如下图,TKM支持的命令分类显示。主要分为以下几项:设备管理命令、密钥管理命令、非对称操作命令、对称操作命令、哈希算法命令、其他命令。 + + 图 1 获取Hag tkm支持的命令信息 + + ![](../../assets/TKM/tkm-1.png) + +如需使用其中的单个命令,可以通过--help参数查看命令使用方法,如查看sm2_sign命令使用方法: +``` +$ sudo hag tkm sm2_sign --help +``` +## 3.TKM典型应用场景说明与验证 + +**各场景说明均使用hag工具来进行演示,应用密钥应用场景说明中,由于应用密钥由固件内部分配,因此每次操作分配的句柄可能不同,实际操作时请以实际返回句柄为准。** + +### 3.1.初始化 + +公共使用部分数据初始配置: +``` +$ echo 87654321 | xxd -r -ps > intl.auth +$ echo 12345678 | xxd -r -ps > intl2.auth +$ echo 11223344 | xxd -r -ps > apk.auth +$ echo 0123456789abcdeffedcba9876543210 | xxd -r -ps > iv.data +$ echo 12345678 | xxd -r -ps > sys.auth +$ sudo hag tkm rand_get -len 32 -out data32.plain +$ sudo hag tkm rand_get -len 64 -out data64.plain +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-2.png) + +### 3.2.外部密钥派发到TKM设备场景 + +**场景说明:** + +用户在使用中有将自己密钥明文派发到TKM设备内部密钥槽位的需求,派发后密钥掉电不丢失,这里对该应用场景进行示例说明,基本过程如下图所示,首先通过TKM接口在TKM内部生成一对非对称密钥对作为父密钥对,接着用户准备好将要派发的密钥明文,调用TKM接口导出父密钥对公钥,用户使用该公钥对将要派发的密钥明文进行加密得到密钥密文,调用TKM导入接口导入密钥密文并指定使用父密钥对的私钥解密装载,装载成功后该密钥被装入TKM设备密钥槽位并返回对应密钥索引信息,用户可以通过该索引来完成需要的基于TKM设备的密码运算 + + ![](../../assets/TKM/tkm-3.png) + +**操作过程说明:** + +(1)在TKM设备产生sm2加密内部密钥作为父密钥,用户生成需要派发的密钥明文文件,这里派发一个sm4密钥,使用父密钥对应公钥在用户侧进行加密,之后调用TKM导入接口将sm4密钥密文派发到TKM设备,指定使用对应的父密钥私钥进行解密,装载槽位根据idx参数指定,这里为999号槽位。 +``` +$ sudo hag tkm intl_key_gen -type sm2enc -idx 1000 -auth intl.auth +$ sudo hag tkm rand_get -len 16 -out intlkey16.plain +$ sudo hag tkm pubkey_enc_ekey -type sm4 -handle 0xb0003e8 -in intlkey16.plain -out kek_enc_key.bin +$ sudo hag tkm key_import -phandle 0xb0003e8 -pauth intl.auth -key kek_enc_key.bin -idx 999 -auth intl2.auth +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-4.png) + +(2)派发完成,清理操作环境,销毁派发的密钥以及父密钥 +``` +$ sudo rm -rf kek_enc_key.bin intlkey16.plain +$ sudo hag tkm key_destroy -handle 0x20003e7 -auth intl2.auth +$ sudo hag tkm key_destroy -handle 0xb0003e8 -auth intl.auth +``` +命令执行的结果如下图: + + ![](../../assets/TKM/tkm-5.png) + +### 3.3.TKM密钥迁移到另一台TKM设备场景 + +用户在使用TKM设备中,有将一台设备密钥迁移到另一台设备的需求,这里共提供三种迁移场景供用户参考。(只有具有导出属性的密钥才支持导出迁移,未配置该属性则密钥不允许导出) + +#### 3.3.1 迁移场景一:sm2公钥加密导出,私钥解密导入迁移 + +**场景说明:** + +该场景使用了非对称密钥的公私钥特性来实现,需要导出密钥的机器这里称为S,需要导入装载密钥的机器这里称为D,用户通过在机器D产生一对sm2密钥对,导出其公钥在机器S调用TKM的ecc公钥加密密钥导出接口,即可将机器S的目标句柄对应的密钥加密导出,之后用户在机器D调用TKM导入装载接口导入密钥密文并指定sm2私钥解密,即可将机器S的密钥迁移到机器D,如下图所示为一个基本的过程。这里在密钥迁移成功后做了一个简单的测试来验证密钥被成功迁移,即指定机器S原密钥加密一段数据,使用机器D迁移后的密钥解密,通过对比明文与解密后的明文是否一致即可进一步验证密钥迁移的正确性。 + + ![](../../assets/TKM/tkm-6.png) + +**操作过程说明:** + +(1)在机器S端生成待导出密钥,该密钥需要配置exportable属性,否则无法被加密导出接口导出; +``` +$ sudo hag tkm intl_key_gen -type sm4 -idx 666 -auth intl.auth -attr exportable +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-7.png) + +(2)在机器D端生成一对sm2父密钥,记录密钥返回索引,并导出其公钥,将公钥传递到机器S; +``` +$ sudo hag tkm intl_key_gen -type sm2enc -idx 1000 -auth intl.auth +$ sudo hag tkm pubkey_export -handle 0xb0003e8 -out sm2_pubkey.bin +``` +命令执行的结果如下图: + + ![](../../assets/TKM/tkm-8.png) + +(3)机器S使用从机器D收到的公钥以及待导出密钥对应索引值调用ecc加密导出接口获取密文密钥,并使用待导出密钥对一段数据明文进行加密,将数据明文以及加密后的数据密文传递到机器D; +``` +$ ls -l +$ sudo hag tkm ecc_enc_key_export -pub sm2_pubkey.bin -handle 0x200029a -auth intl.auth -out ex_enckey.bin +$ sudo hag tkm sm4 -handle 0x200029a -auth intl.auth -iv iv.data -in data64.plain -out enc_data.bin -e -m ecb -p pkcs7 +``` +命令执行的结果如下图: + + ![](../../assets/TKM/tkm-9.png) + +(4)机器D调用密钥导入接口导入从机器S收到的密钥密文并指定其使用sm2父密钥私钥解密装载,记录装载成功后返回的装载密钥索引,密钥迁移成功。使用装载密钥索引解密从机器S收到的数据密文,得到解密明文;将解密明文与数据明文对比,若一致表示迁移正常,否则迁移密钥异常; +``` +$ ls -l +$ sudo hag tkm key_import -phandle 0xb0003e8 -pauth intl.auth -key ex_enckey.bin -idx 666 -auth intl.auth +$ sudo hag tkm sm4 -handle 0x200029a -auth intl.auth -iv iv.data -in enc_data.bin -out dec_data.bin -d -m ecb -p pkcs7 +$ sudo cmp -b data64.plain dec_data.bin && echo $? +``` +命令执行的结果如下图: + + ![](../../assets/TKM/tkm-10.png) + +(5)机器S与机器D清理测试环境 + +机器S清理: +``` +$ sudo rm -rf enc_data.bin ex_enckey.bin sm2_pubkey.bin +$ sudo hag tkm key_destroy -handle 0x200029a -auth intl.auth +``` +命令执行的结果如下图: + + ![](../../assets/TKM/tkm-11.png) + +机器D清理: +``` +$ sudo rm -rf dec_data.bin enc_data.bin ex_enckey.bin sm2_pubkey.bin +$ sudo hag tkm key_destroy -handle 0x200029a -auth intl.auth +$ sudo hag tkm key_destroy -handle 0xb0003e8 -auth intl.auth +``` +命令执行的结果如下图: + + ![](../../assets/TKM/tkm-12.png) + +#### 3.3.2 迁移场景二:rsa公钥加密导出,私钥解密导入迁移 + +**场景说明:** + +该场景与迁移场景一基本类似,不同之处为非对称密钥使用应用密钥RSA来实现,需要先在TKM设备产生一个RSA应用密钥,之后过程与场景一基本相同(SM2也可以使用应用密钥来完成密钥迁移,过程与通过RSA过程基本一致,不再赘述)。 + +**操作过程说明:** + +(1)在机器S端生成待导出密钥,该密钥需要配置exportable属性,否则无法被加密导出接口导出; +``` +$ sudo hag tkm intl_key_gen -type sm4 -idx 666 -auth intl.auth -attr exportable +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-13.png) + +(2)在机器D端生成一对RSA父密钥,记录密钥返回句柄,并导出其公钥,将公钥传递到机器S; +``` +$ sudo hag tkm intl_key_gen -type sm4 -idx 1000 -auth intl.auth +$ sudo hag tkm app_key_gen -type rsa2048 -phandle 0x20003e8 -pauth intl.auth -out rsa2048_enc_key.bin -pad +$ sudo hag tkm key_import -phandle 0x20003e8 -pauth intl.auth -key rsa2048_enc_key.bin -auth apk.auth -pad +$ sudo hag tkm pubkey_export -handle 0x90000001 -out rsa_pubkey.bin +``` +命令执行的结果如下图: + + ![](../../assets/TKM/tkm-14.png) + +(3)机器S使用从机器D收到的公钥以及待导出密钥对应索引值调用RSA加密导出接口获取密文密钥,并使用待导出密钥对一段数据明文进行加密,将数据明文以及加密后的数据密文传递到机器D; +``` +$ ls -l +$ sudo hag tkm rsa_enc_key_export -pub rsa_pubkey.bin -handle 0x200029a -auth intl.auth -out ex_enckey.bin +$ sudo hag tkm sm4 -handle 0x200029a -auth intl.auth -iv iv.data -in data64.plain -out enc_data.bin -e -m ecb -p pkcs7 +``` +命令执行的结果如下图: + +![](../../assets/TKM/tkm-15.png) + +(4)机器D调用密钥导入接口导入从机器S收到的密钥密文并指定其使用RSA父密钥私钥解密装载,记录装载成功后返回的装载密钥索引,密钥迁移成功。使用装载密钥索引解密从机器S收到的数据密文,得到解密明文;将解密明文与数据明文对比,若一致表示迁移正常,否则迁移密钥异常; +``` +$ ls -l +$ sudo hag tkm key_import -phandle 0x90000001 -pauth apk.auth -key ex_enckey.bin -idx 666 -auth intl.auth +$ sudo hag tkm sm4 -handle 0x200029a -auth intl.auth -iv iv.data -in enc_data.bin -out dec_data.bin -d -m ecb -p pkcs7 +$ sudo cmp -b data64.plain dec_data.bin && echo $? +``` +命令执行的结果如下图: + + ![](../../assets/TKM/tkm-16.png) + +(5)机器S与机器D清理测试环境 + +机器S清理: +``` +$ sudo rm -rf enc_data.bin ex_enckey.bin rsa_pubkey.bin +$ sudo hag tkm key_destroy -handle 0x200029a -auth intl.auth +``` +命令执行的结果如下图: + + ![](../../assets/TKM/tkm-17.png) + +机器D清理: +``` +$ sudo rm -rf dec_data.bin enc_data.bin ex_enckey.bin rsa2048_enc_key.bin rsa_pubkey.bin +$ sudo hag tkm key_destroy -handle 0x90000001 -auth apk.auth +$ sudo hag tkm key_destroy -handle 0x200029a -auth intl.auth +$ sudo hag tkm key_destroy -handle 0x20003e8 -auth intl.auth +``` +命令执行的结果如下图: + + ![](../../assets/TKM/tkm-18.png) + +#### 3.3.3 迁移场景三:派发对称密钥加密导出、解密导入迁移 + +**场景说明:** + +该场景根据对称密钥算法特性,首先通过派发过程,保证两台机器中有相同的密钥,之后分别使用相同密钥对应的句柄分别对需要迁移的密钥进行加密导出与解密导入装载,最后通过对装载后的密钥进行基本的加解密测试来验证迁移密钥的正确性,基本过程如下图所示。 + + ![](../../assets/TKM/tkm-19.png) + +**操作过程说明:** + +(1)在机器S端生成待导出密钥,该密钥需要配置exportable属性,否则无法被加密导出接口导出; +``` +$ sudo hag tkm intl_key_gen -type sm4 -idx 666 -auth intl.auth -attr exportable +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-20.png) + +(2)分别在机器S与机器D端派发相同的密钥到设备内部; + +机器S派发密钥: +``` +$ echo fedcba98765432100123456789abcdef | xxd -r -ps > intlkey16.plain +$ sudo hag tkm intl_key_gen -type sm2enc -idx 1000 -auth intl.auth +$ sudo hag tkm pubkey_enc_ekey -type sm4 -handle 0xb0003e8 -in intlkey16.plain -out kek_enc_key.bin +$ sudo hag tkm key_import -phandle 0xb0003e8 -pauth intl.auth -key kek_enc_key.bin -idx 999 -auth intl.auth +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-21.png) + +机器D派发密钥: +``` +$ echo fedcba98765432100123456789abcdef | xxd -r -ps > intlkey16.plain +$ sudo hag tkm intl_key_gen -type sm2enc -idx 1000 -auth intl.auth +$ sudo hag tkm pubkey_enc_ekey -type sm4 -handle 0xb0003e8 -in intlkey16.plain -out kek_enc_key.bin +$ sudo hag tkm key_import -phandle 0xb0003e8 -pauth intl.auth -key kek_enc_key.bin -idx 999 -auth intl.auth +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-22.png) + +(3)机器S指定使用派发密钥调用对称加密导出接口获得密文密钥,并使用待导出密钥对一段数据明文进行加密,将密文密钥、数据明文以及加密后的数据密文传递到机器D; +``` +$ sudo hag tkm symkey_enc_key_export -phandle 0x20003e7 -pauth intl.auth -handle 0x200029a -auth intl.auth -out ex_enckey.bin +$ sudo hag tkm sm4 -handle 0x200029a -auth intl.auth -iv iv.data -in data64.plain -out enc_data.bin -e -m ecb -p pkcs7 +$ ls -l +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-23.png) + +(4)机器D调用密钥导入接口导入从机器S收到的密钥密文并指定其使用派发密钥解密装载,记录装载成功后返回的装载密钥索引,密钥迁移成功。使用装载密钥索引解密从机器S收到的数据密文,得到解密明文;将解密明文与数据明文对比,若一致表示迁移正常,否则迁移密钥异常; +``` +$ ls -l +$ sudo hag tkm key_import -phandle 0x20003e7 -pauth intl.auth -key ex_enckey.bin -idx 666 -auth intl.auth +$ sudo hag tkm sm4 -handle 0x200029a -auth intl.auth -iv iv.data -in enc_data.bin -out dec_data.bin -d -m ecb -p pkcs7 +$ sudo cmp -b data64.plain dec_data.bin && echo $? +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-24.png) + +(5)机器S与机器D清理测试环境。 + +机器S清理: +``` +$ sudo rm -rf enc_data.bin ex_enckey.bin intlkey16.plain kek_enc_key.bin +$ sudo hag tkm key_destroy -handle 0x200029a -auth intl.auth +$ sudo hag tkm key_destroy -handle 0x20003e7 -auth intl.auth +$ sudo hag tkm key_destroy -handle 0xb0003e8 -auth intl.auth +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-25.png) + +机器D清理: +``` +$ sudo rm -rf dec_data.bin enc_data.bin ex_enckey.bin intlkey16.plain kek_enc_key.bin +$ sudo hag tkm key_destroy -handle 0x200029a -auth intl.auth +$ sudo hag tkm key_destroy -handle 0x20003e7 -auth intl.auth +$ sudo hag tkm key_destroy -handle 0xb0003e8 -auth intl.auth +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-26.png) + +### 3.4.sm4应用密钥加解密场景 + +**场景说明:** + +sm4应用密钥加解密逻辑如下图所示,首先调用TKM接口生成一个内部对称密钥作为父密钥,然后调用TKM密钥生成加密导出接口生成并导出应用密钥,应用密钥指定使用父密钥加密,密钥类型根据需要设置,导出的密文应用密钥用户可以自行存储,在需要使用时,调用TKM导入接口导入装载密文应用密钥到TKM设备,导入成功后TKM设备返回应用密钥句柄,用户通过该句柄即可调用TKM加解密接口完成加解密数据操作。 + +![](../../assets/TKM/tkm-27.png) + +**操作过程说明:** + +(1)基于内部密钥产生并装载应用密钥获得sm4应用密钥句柄 +``` +$ sudo hag tkm intl_key_gen -type sm4 -idx 1000 -auth intl.auth +$ sudo hag tkm app_key_gen -type sm4 -phandle 0x20003e8 -pauth intl.auth -out sm4_enc_key.bin +$ sudo hag tkm key_import -phandle 0x20003e8 -pauth intl.auth -key sm4_enc_key.bin -auth apk.auth +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-28.png) + +(2)传入sm4应用密钥句柄使用其对应密钥进行对称加解密 +``` +$ sudo hag tkm sm4 -handle 0x82000003 -auth apk.auth -iv iv.data -in data64.plain -out enc_data.bin -e -m cfb +$ sudo hag tkm sm4 -handle 0x82000003 -auth apk.auth -iv iv.data -in enc_data.bin -out dec_plain.bin -d -m cfb +$ sudo cmp -b data64.plain dec_plain.bin && echo $? +``` +命令执行的结果如下图: + + ![](../../assets/TKM/tkm-29.png) + +(3)清理测试环境,销毁密钥 +``` +$ sudo hag tkm key_destroy -handle 0x82000003 -auth apk.auth +$ sudo rm -rf sm4_enc_key.bin enc_data.bin dec_plain.bin +$ sudo hag tkm key_destroy -handle 0x20003e8 -auth intl.auth +``` +命令执行的结果如下图: + + ![](../../assets/TKM/tkm-30.png) + +### 3.5.sm2应用密钥签名验签场景 + +**场景说明:** + +sm2应用密钥签名验签逻辑如下图所示,首先调用TKM接口生成一个内部对称密钥作为父密钥,然后调用TKM密钥生成加密导出接口生成并导出应用密钥,应用密钥指定使用父密钥加密,密钥类型根据需要设置,导出的密文应用密钥用户可以自行存储,在需要使用时,调用TKM导入接口导入装载密文应用密钥到TKM设备,导入成功后TKM设备返回应用密钥句柄,用户通过该句柄即可调用TKM接口完成签名验签操作。 + + ![](../../assets/TKM/tkm-31.png) + +**操作过程说明:** + +(1)基于内部密钥产生并装载应用密钥获得sm2应用密钥句柄 +``` +$ sudo hag tkm intl_key_gen -type sm4 -idx 1000 -auth intl.auth +$ sudo hag tkm app_key_gen -type sm2 -phandle 0x20003e8 -pauth intl.auth -out sm2_enc_key.bin +$ sudo hag tkm key_import -phandle 0x20003e8 -pauth intl.auth -key sm2_enc_key.bin -auth apk.auth +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-32.png) + +(2)传入sm2应用密钥句柄使用其对应密钥进行签名验签 +``` +$ sudo hag tkm sm2_sign -handle 0x89000003 -auth apk.auth -in data32.plain -out sm2_sign.bin +$ sudo hag tkm pubkey_export -handle 0x89000003 -out sm2_pubkey.bin +$ sudo hag tkm sm2_verify -dgst data32.plain -pub sm2_pubkey.bin -sig sm2_sign.bin +``` +命令执行的结果如下图: + + ![](../../assets/TKM/tkm-33.png) + +(3)清理测试环境,销毁密钥 +``` +$ sudo rm -rf sm2_enc_key.bin sm2_sign.bin sm2_pubkey.bin +$ sudo hag tkm key_destroy -handle 0x89000003 -auth apk.auth +$ sudo hag tkm key_destroy -handle 0x20003e8 -auth intl.auth +``` +命令执行的结果如下图: + + ![](../../assets/TKM/tkm-34.png) + +### 3.6.sm2应用密钥加密解密场景 + +**场景说明:** + +sm2应用密钥加解密逻辑如下图所示,首先调用TKM接口生成一个内部对称密钥作为父密钥,然后调用TKM密钥生成加密导出接口生成并导出应用密钥,应用密钥指定使用父密钥加密,密钥类型根据需要设置,导出的密文应用密钥用户可以自行存储,在需要使用时,调用TKM导入接口导入装载密文应用密钥到TKM设备,导入成功后TKM设备返回应用密钥句柄,用户通过该句柄即可调用TKM接口完成加解密操作。 + + ![](../../assets/TKM/tkm-35.png) + +**操作过程说明:** + +(1)基于内部密钥产生并装载应用密钥获得sm2应用密钥句柄 +``` +$ sudo hag tkm intl_key_gen -type sm4 -idx 1000 -auth intl.auth +$ sudo hag tkm app_key_gen -type sm2 -phandle 0x20003e8 -pauth intl.auth -out sm2_enc_key.bin +$ sudo hag tkm key_import -phandle 0x20003e8 -pauth intl.auth -key sm2_enc_key.bin -auth apk.auth +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-36.png) + +(2)传入sm2应用密钥句柄使用其对应密钥进行加密解密 +``` +$ sudo hag tkm pubkey_export -handle 0x89000008 -out sm2_pubkey.bin +$ sudo hag tkm sm2_enc -in data32.plain -pub sm2_pubkey.bin -out sm2_enc_data.bin +$ sudo hag tkm sm2_dec -handle 0x89000008 -auth apk.auth -in sm2_enc_data.bin -out sm2_dec_data.bin +$ sudo cmp -b data32.plain sm2_dec_data.bin && echo $? +``` +命令执行的结果如下图: + + ![](../../assets/TKM/tkm-37.png) + +(3)清理测试环境,销毁密钥 +``` +$ sudo rm -rf sm2_enc_key.bin sm2_pubkey.bin sm2_enc_data.bin sm2_dec_data.bin +$ sudo hag tkm key_destroy -handle 0x89000008 -auth apk.auth +$ sudo hag tkm key_destroy -handle 0x20003e8 -auth intl.auth +``` +命令执行的结果如下图: + + ![](../../assets/TKM/tkm-38.png) + +### 3.7.rsa应用密钥签名验签场景 + +**场景说明:** + +rsa应用密钥签名验签逻辑如下图所示,首先调用TKM接口生成一个内部对称密钥作为父密钥,然后调用TKM密钥生成加密导出接口生成并导出应用密钥,应用密钥指定使用父密钥加密,密钥类型根据需要设置,导出的密文应用密钥用户可以自行存储,在需要使用时,调用TKM导入接口导入装载密文应用密钥到TKM设备,导入成功后TKM设备返回应用密钥句柄,用户通过该句柄即可调用TKM接口完成签名验签操作。 + + ![](../../assets/TKM/tkm-39.png) + +**操作过程说明:** + +(1)基于内部密钥产生并装载应用密钥获得rsa应用密钥句柄 +``` +$ sudo hag tkm intl_key_gen -type sm4 -idx 1000 -auth intl.auth +$ sudo hag tkm app_key_gen -type rsa2048 -phandle 0x20003e8 -pauth intl.auth -out rsa2048_enc_key.bin -pad +$ sudo hag tkm key_import -phandle 0x20003e8 -pauth intl.auth -key rsa2048_enc_key.bin -auth apk.auth -pad +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-40.png) + +(2)传入rsa应用密钥句柄使用其对应密钥进行签名验签 +``` +$ sudo hag tkm rsa_sign -handle 0x90000001 -auth apk.auth -in data32.plain -out rsa_sign_out.bin -hash sha256 +$ sudo hag tkm pubkey_export -handle 0x90000001 -out rsa_pubkey.bin +$ sudo hag tkm rsa_verify -in data32.plain -pub rsa_pubkey.bin -sig rsa_sign_out.bin -hash sha256 +``` +命令执行的结果如下图: + + ![](../../assets/TKM/tkm-41.png) + +(3)清理测试环境,销毁密钥 +``` +$ sudo rm -rf rsa2048_enc_key.bin rsa_sign_out.bin rsa_pubkey.bin +$ sudo hag tkm key_destroy -handle 0x90000001 -auth apk.auth +$ sudo hag tkm key_destroy -handle 0x20003e8 -auth intl.auth +``` +命令执行的结果如下图: + + ![](../../assets/TKM/tkm-42.png) + +### 3.8.rsa应用密钥加密解密场景 + +**场景说明:** + +rsa应用密钥签名验签逻辑如下图所示,首先调用TKM接口生成一个内部对称密钥作为父密钥,然后调用TKM密钥生成加密导出接口生成并导出应用密钥,应用密钥指定使用父密钥加密,密钥类型根据需要设置,导出的密文应用密钥用户可以自行存储,在需要使用时,调用TKM导入接口导入装载密文应用密钥到TKM设备,导入成功后TKM设备返回应用密钥句柄,用户通过该句柄即可调用TKM接口完成加解密操作。 + + ![](../../assets/TKM/tkm-43.png) + +**操作过程说明:** + +(1)基于内部密钥产生并装载应用密钥获得rsa应用密钥句柄 +``` +$ sudo hag tkm intl_key_gen -type sm4 -idx 1000 -auth intl.auth +$ sudo hag tkm app_key_gen -type rsa2048 -phandle 0x20003e8 -pauth intl.auth -out rsa2048_enc_key.bin -pad +$ sudo hag tkm key_import -phandle 0x20003e8 -pauth intl.auth -key rsa2048_enc_key.bin -auth apk.auth -pad +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-44.png) + +(2)传入rsa应用密钥句柄使用其对应密钥进行加密解密 +``` +$ sudo hag tkm pubkey_export -handle 0x90000001 -out rsa_pubkey.bin +$ sudo hag tkm rsa_enc -in data32.plain -pub rsa_pubkey.bin -out rsa_enc_data.bin +$ sudo hag tkm rsa_dec -handle 0x90000001 -auth apk.auth -in rsa_enc_data.bin -out rsa_dec_data.bin +$ sudo cmp -b data32.plain rsa_dec_data.bin && echo $? +``` +命令执行的结果如下图: + + ![](../../assets/TKM/tkm-45.png) + +(3)清理测试环境,销毁密钥 +``` +$ sudo rm -rf rsa2048_enc_key.bin rsa_pubkey.bin rsa_dec_data.bin  rsa_enc_data.bin +$ sudo hag tkm key_destroy -handle 0x90000001 -auth apk.auth +$ sudo hag tkm key_destroy -handle 0x20003e8 -auth intl.auth +``` +命令执行的结果如下图: + + ![](../../assets/TKM/tkm-46.png) + +### 3.9.密钥协商应用场景验证(hag与固件build_id为1828及以上版本支持) + +**场景说明:** + +用户在使用TKM设备中,有基于两台机器的密钥协商需求。该场景使用了sm2的密钥协商算法来实现密钥协商,角色为requestor的机器这里称为S,角色为responser的机器这里称为D,根据密钥协商算法该场景设计流程如下图所示,首先调用TKM相关分别在机器S与机器D生成密钥协商需要的主密钥与临时密钥,并导出公钥;同时分别确定自己的uid信息,将uid、主密钥公钥、临时密钥公钥在两台机器中进行交换;各机器分别使用自己机器主密钥与临时密钥对应的索引或句柄以及对方的公钥信息、自己uid、对方uid进行密钥协商并生成协商密钥,同时通过检查s1与sa初步确定协商的正确性。 + +这里在密钥协商成功后做了一个简单的测试来验证被协商的密钥时相同的,即指定机器S协商密钥加密一段数据,使用机器D协商的密钥解密,通过对比明文与解密后的明文是否一致即可进一步验证密钥协商的正确性。 + + ![](../../assets/TKM/tkm-47.png) + +**操作过程说明:** + +(1)在机器S端生成主密钥与临时密钥,并导出其公钥; +``` +$ sudo hag tkm intl_key_gen -type sm2enc -idx 1000 -auth intl.auth +$ sudo hag tkm intl_key_gen -type sm2enc -idx 1001 -auth intl.auth +$ sudo hag tkm pubkey_export -handle 0xb0003e8 -out Pkey_S.bin +$ sudo hag tkm pubkey_export -handle 0xb0003e9 -out TmpPkey_S.bin +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-48.png) + +(2)在机器D端生成主密钥与临时密钥,并导出其公钥; +``` +$ sudo hag tkm intl_key_gen -type sm2enc -idx 1100 -auth intl.auth +$ sudo hag tkm intl_key_gen -type sm2enc -idx 1101 -auth intl.auth +$ sudo hag tkm pubkey_export -handle 0xb00044c -out Pkey_D.bin +$ sudo hag tkm pubkey_export -handle 0xb00044d -out TmpPkey_D.bin +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-49.png) + +(3)机器S与D交换公钥以及uid后,调用密钥协商命令协商密钥;协商完成后检查s1与sa初步验证协商正确性;并通过协商密钥句柄对一个测试数据进行加密,并将加密明文与密文发送到机器D; +``` +$ sudo hag tkm ecc_sharedkey_gen -role requestor -key1 0xb0003e8 -auth1 intl.auth -key2 0xb0003e9 -auth2 intl.auth -pub1_other Pkey_D.bin -pub2_other TmpPkey_D.bin -type sm4 -auth_setting apk.auth -uid_self 1234 -uid_other abcd -attr none -dgst_s1 dgst_s1.bin -dgst_sa dgst_sa.bin +$ sudo cmp -b dgst_s1.bin dgst_sa.bin && echo $? +$ sudo hag tkm sm4 -handle 0x82000003 -auth apk.auth -iv iv.data -in data64.plain -out enc_data.bin -e -m cfb +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-50.png) + +(4)机器D与S交换公钥以及uid后,调用密钥协商命令协商密钥;协商完成后检查s1与sa初步验证协商正确性;并通过协商密钥句柄对机器D提供的数据密文进行解密,解密后通过验证解密明文与加密明文是否相同从而进一步验证密钥协商的正确性; +``` +$ sudo hag tkm ecc_sharedkey_gen -role responser -key1 0xb00044c -auth1 intl.auth -key2 0xb00044d -auth2 intl.auth -pub1_other Pkey_S.bin -pub2_other TmpPkey_S.bin -type sm4 -auth_setting apk.auth -uid_self abcd -uid_other 1234 -attr none -dgst_s1 dgst_s1.bin -dgst_sa dgst_sa.bin +$ sudo cmp -b dgst_s1.bin dgst_sa.bin && echo $? +$ sudo hag tkm sm4 -handle 0x82000003 -auth apk.auth -iv iv.data -in enc_data.bin -out dec_plain.bin -d -m cfb +$ sudo cmp -b data64.plain dec_plain.bin && echo $? +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-51.png) + +(5)机器S与机器D清理测试环境; + +机器S清理: +``` +$ sudo rm -rf dgst_s1.bin dgst_sa.bin Pkey_D.bin Pkey_S.bin TmpPkey_D.bin TmpPkey_S.bin enc_data.bin +$ sudo hag tkm key_destroy -handle 0x82000001 -auth apk.auth +$ sudo hag tkm key_destroy -handle 0xb0003e8 -auth intl.auth +$ sudo hag tkm key_destroy -handle 0xb0003e9 -auth intl.auth +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-52.png) + +机器D清理: +``` +$ sudo rm -rf dgst_s1.bin dgst_sa.bin Pkey_D.bin Pkey_S.bin TmpPkey_D.bin TmpPkey_S.bin enc_data.bin +$ sudo hag tkm key_destroy -handle 0x82000002 -auth apk.auth +$ sudo hag tkm key_destroy -handle 0xb00044c -auth intl.auth +$ sudo hag tkm key_destroy -handle 0xb00044d -auth intl.auth +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-53.png) + +### 3.10.内部密钥备份与恢复场景(hag与固件build_id为1877及以上版本支持) + +用户在使用TKM设备中,有将一台设备所有内部密钥备份恢复到另一台设备的需求,这里共提供三种场景供用户参考。 + +#### 3.10.1 备份恢复场景一:同一CPU备份与恢复 + +**场景说明:** + +该场景通过使用CPU内唯一机密信息派生密钥,由该密钥对内部密钥进行加密及完整性保护,从而支持将设备内所有内部密钥备份,且仅支持在该设备内恢复,其他设备由于CPU内唯一机密信息不同,派生出来的密钥也将不同,因此将无法通过该密钥镜像进行恢复,如下图所示为一个基本的过程。这里在密钥恢复成功后做了一个简单的测试来验证密钥被成功恢复,即指定机器原密钥加密一段数据,使用机器恢复后的密钥解密,通过对比明文与解密后的明文是否一致即可进一步验证密钥备份恢复的正确性。 + +  ![](../../assets/TKM/tkm-54.png) + +**操作过程说明:** + +(1)在机器中生成待备份密钥,这里以类型为sm4索引为666号密钥为例,然后使用该密钥对一段数据明文进行加密; +``` +$ sudo hag tkm intl_key_gen -type sm4 -idx 666 -auth intl.auth +$ sudo hag tkm sm4 -handle 0x200029a -auth intl.auth -iv iv.data -in data64.plain -out enc_data.bin -e -m ecb -p pkcs7 +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-55.png) + +(2)调用密钥备份接口对上一步生成的sm4密钥进行备份,备份成功后,将上一步生成的sm4密钥销毁; +``` +$ sudo hag tkm key_backup -auth sys.auth -scheme same_cpu -outfile key_same_cpu.bin +$ sudo hag tkm key_destroy -handle 0x200029a -auth intl.auth +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-56.png) + +(3)调用密钥恢复接口对密钥进行恢复,密钥恢复成功后,使用被恢复的sm4密钥解密备份前的数据密文,得到解密明文;将解密明文与数据明文对比,若一致表示恢复正常,否则恢复密钥异常; +``` +$ sudo hag tkm key_restore -auth sys.auth -scheme same_cpu -infile key_same_cpu.bin +$ sudo hag tkm sm4 -handle 0x200029a -auth intl.auth -iv iv.data -in enc_data.bin -out dec_data.bin -d -m ecb -p pkcs7 +$ sudo cmp -b data64.plain dec_data.bin && echo $? +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-57.png) + +(4)清理测试环境。 +``` +$ sudo rm -rf enc_data.bin dec_data.bin key_same_cpu.bin +$ sudo hag tkm key_destroy -handle 0x200029a -auth intl.auth +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-58.png) + +#### 3.10.2 备份恢复场景二:同一代CPU备份与恢复 + +**场景说明:** + +该场景通过使用同一代CPU相同的密钥,由该密钥对内部密钥进行加密及完整性保护,从而支持将设备S内所有内部密钥备份,且在同一代的CPU的D设备内恢复,如下图所示为一个基本的过程。这里在密钥备份恢复成功后做了一个简单的测试来验证密钥被成功在另一台设备恢复,即指定机器S原密钥加密一段数据,使用机器D恢复后的密钥解密,通过对比明文与解密后的明文是否一致即可进一步验证密钥恢复的正确性。 + + ![](../../assets/TKM/tkm-59.png)  + +**操作过程说明:** + +(1)在机器S中生成待备份密钥,这里以类型为sm4索引为666号密钥为例,然后使用该密钥对一段数据明文进行加密,加密成功后,调用备份接口对机器S密钥进行备份,并将加密数据密文、备份密钥文件传递给机器D用于恢复验证; +``` +$ sudo hag tkm intl_key_gen -type sm4 -idx 666 -auth intl.auth +$ sudo hag tkm sm4 -handle 0x200029a -auth intl.auth -iv iv.data -in data64.plain -out enc_data.bin -e -m ecb -p pkcs7 +$ sudo hag tkm key_backup -auth sys.auth -scheme same_gen -outfile key_same_gen.bin +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-60.png) + +(2)机器D使用从机器S获取的备份密钥文件调用恢复接口进行恢复,并使用恢复后的密钥解密从机器S收到的数据密文,得到解密明文;将解密明文与数据明文对比,若一致表示恢复正常,否则恢复密钥异常; +``` +$ sudo hag tkm key_restore -auth sys.auth -scheme same_gen -infile key_same_gen.bin +$ sudo hag tkm sm4 -handle 0x200029a -auth intl.auth -iv iv.data -in enc_data.bin -out dec_data.bin -d -m ecb -p pkcs7 +$ sudo cmp -b data64.plain dec_data.bin && echo $? +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-61.png) + +(3)机器S与机器D清理测试环境。 + +机器S清理: +``` +$ sudo rm -rf enc_data.bin key_same_gen.bin +$ sudo hag tkm key_destroy -handle 0x200029a -auth intl.auth +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-62.png) + +机器D清理: +``` +$ sudo rm -rf dec_data.bin enc_data.bin key_same_gen.bin +$ sudo hag tkm key_destroy -handle 0x200029a -auth intl.auth +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-63.png) + +#### 3.10.3 备份恢复场景三:设备证书方式备份与恢复 + +**场景说明:** + +该场景通过使用TKM设备证书,由恢复机器D将自己证书链提供给机器S,机器S首先对其进行证书链验证,验证通过后使用其TKM设备证书中的公钥在设备内通过密钥协商方式生成密钥,并将协商共享数据导出供后续机器D使用,之后使用该生成密钥对内部密钥进行加密及完整性保护,从而支持将设备S内所有内部密钥备份;在机器D恢复时,设备将会首先使用自己的设备私钥以及S传递的共享数据计算出协商密钥,之后该协商密钥对备份的密钥文件进行解密恢复,如下图所示为一个基本的过程。这里在密钥备份恢复成功后做了一个简单的测试来验证密钥被成功在另一台设备恢复,即指定机器S原密钥加密一段数据,使用机器D恢复后的密钥解密,通过对比明文与解密后的明文是否一致即可进一步验证密钥恢复的正确性。 + + ![](../../assets/TKM/tkm-64.png) + +**操作过程说明:** + +(1)机器D首先获取自己的证书链文件,并将自身证书链文件提供给机器S; +``` +$ sudo hag tkm cert_chain_get -cert_type sign -outfile certchain.bin +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-65.png) + +(2)在机器S中生成待备份密钥,这里以类型为sm4索引为666号密钥为例,然后使用该密钥对一段数据明文进行加密,加密成功后,调用备份接口对机器S密钥进行备份,并将加密数据密文、备份密钥文件、共享数据文件传递给机器D用于恢复验证; +``` +$ sudo hag tkm intl_key_gen -type sm4 -idx 666 -auth intl.auth +$ sudo hag tkm sm4 -handle 0x200029a -auth intl.auth -iv iv.data -in data64.plain -out enc_data.bin -e -m ecb -p pkcs7 +$ sudo hag tkm key_backup -auth sys.auth -scheme dev_cert -outfile key_dev_cert.bin -cert certchain.bin -sharedfile shared_data.bin +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-66.png) + +(3)机器D使用从机器S获取的备份密钥文件、共享数据文件调用恢复接口进行密钥恢复,并使用恢复后的密钥解密从机器S收到的数据密文,得到解密明文;将解密明文与数据明文对比,若一致表示恢复正常,否则恢复密钥异常; +``` +$ sudo hag tkm key_restore -auth sys.auth -scheme dev_cert -infile key_dev_cert.bin -sharedfile shared_data.bin +$ sudo hag tkm sm4 -handle 0x200029a -auth intl.auth -iv iv.data -in enc_data.bin -out dec_data.bin -d -m ecb -p pkcs7 +$ sudo cmp -b data64.plain dec_data.bin && echo $? +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-67.png) + +(4)机器S与机器D清理测试环境 + +机器S清理: +``` +$ sudo rm -rf enc_data.bin shared_data.bin key_dev_cert.bin +$ sudo hag tkm key_destroy -handle 0x200029a -auth intl.auth +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-68.png) + +机器D清理: +``` +$ sudo rm -rf key_dev_cert.bin shared_data.bin dec_data.bin enc_data.bin +$ sudo hag tkm key_destroy -handle 0x200029a -auth intl.auth +``` +命令正确执行的结果如下图: + + ![](../../assets/TKM/tkm-69.png) + +### 3.11.环境清理 + +清理公共部分初始化的数据 +``` +$ sudo rm -rf intl.auth intl2.auth apk.auth iv.data data32.plain data64.plain sys.auth +``` diff --git "a/sig/Hygon Arch/content/3-HCT\346\265\213\350\257\225\346\226\207\346\241\243/3-HCT\350\231\232\346\213\237\345\214\226\346\214\207\345\257\274\346\226\207\346\241\243.md" "b/sig/Hygon Arch/content/3-HCT\346\265\213\350\257\225\346\226\207\346\241\243/3-HCT\350\231\232\346\213\237\345\214\226\346\214\207\345\257\274\346\226\207\346\241\243.md" new file mode 100644 index 0000000000000000000000000000000000000000..bbfbf0f6450ed2048855b178968c5b267b3bb2a1 --- /dev/null +++ "b/sig/Hygon Arch/content/3-HCT\346\265\213\350\257\225\346\226\207\346\241\243/3-HCT\350\231\232\346\213\237\345\214\226\346\214\207\345\257\274\346\226\207\346\241\243.md" @@ -0,0 +1,330 @@ +## 1. 宿主机环境准备 +测试环境 + +| 组件 | 版本信息 | +|--------------|-----------------------| +| CPU | Hygon C86 7265 | +| 操作系统 | Ubuntu 18.04 | +| 操作系统内核 | Linux kernel 5.16.20 | +| OpenSSL | 1.1.1c | +| libvirt | 5.8.0 | +| HCT套件 | hct_2.1.0.20241030_release | + +### 1.1 安装HCT开发包 +参照[《HCT用户手册》](./1-HCT用户手册.md)在宿主机中搭建开发环境,当主机HCT环境验证通过后,请通过下列命令重新绑定HCT驱动: + +``` +$ sudo /opt/hygon/hct/hct/script/hctconfig stop +$ sudo /opt/hygon/hct/hct/script/hctconfig start -p 16 -q 128 +``` +此处-p 16是创建16个宿主机使用的mdev设备,-q 128是创建128个虚拟机使用的mdev,用户可根据需求自行修改。 + +**如需启动带vTKM功能的虚拟机,请先参照[《海光SDF接口用户手册》](./5-海光SDF接口用户手册.md)6.2节确认安装支持vTKM的内核与QEMU版本。** + + +### 1.2 编译安装qemu +安装qemu编译所需的软件。 +``` +$ sudo apt install libnuma-dev libpixman-1-dev -y +``` +从如下链接获取支持HCT虚拟化功能的qemu源码,本文档以qemu-6.2.0为例,用户可根据需求切换qemu的版本号:https://gitee.com/anolis/hygon-qemu +Tips:当前支持的版本有:2.12.0, 4.1.0, 6.2.0, 7.2.0。支持hct虚拟化功能的commit-id如下: + +| 版本 | commit-id | +|-----------------|-----------------------| +|2.12.0 | 4647a04c4d18101bac28f1f4b565ff4030f1a1ae
949469447da28932384cfa8a3dfe9b567806320c
f105775ec610cff1982a14ec766d236ad55b5109 | +|4.1.0 | 5e27416a21450f54f4d4eb040532069771f1b5d3
32097e5ec58f70d59022321ad5752e4c46863c2b
a841c63f46321d1937d0e41c5cc76076b5bad2be| +|6.2.0 | 1886abda05f878303b140a345d53ffd899675be6
b046474dbc2560434dc1d2f4485b8b474d7d23e0
77e0f539ef8daacd27ea0f77dfed4b3a5c35d610| +|7.2.0 | 6e868fb05ab96a27d26aaa71ecbf99352f29a5e5
950ae0538455f3505e9935807f4c1d1511674eb4
21e118a70be9fac634f9910aa0029e4cdcdc94f1| + +**如需使用vTKM完整功能,请获取如下patch(当前仅支持6.2.0版本)** + +| 版本 | commit-id | +|-----------------|-----------------------| +|6.2.0 |9b4396f8c8db6ebef8bd0b315d6649365123db0e(支持密钥隔离)
76a47a90f9ecee19f86039fdea992c7d5c1f4d22 (CSV虚拟机功能支持)
c5b9286549f37f14e8ddbfb7831a6b7d125b1f65(CSV虚拟机功能支持)
da768933bfcec318425f788524b792e58bdf51ad (CSV虚拟机功能支持)| + + +qemu源码下载完成后执行如下命令进行编译安装。如使用7.2.0版本,请安装libslirp-dev,并在./configure后加上--enable-slirp参数。 +``` +$ cd hygon-qemu +$ mkdir ../output +$ ./configure --target-list=x86_64-softmmu --prefix="`pwd`/../output/qemu-output" +$ make -j$(getconf _NPROCESSORS_ONLN) --print-directory +$ make -j$(getconf _NPROCESSORS_ONLN) install +``` +编译完成之后可以在output中看到相关的文件。 +``` +$ tree ../output +``` +![](../../assets/HCT/HCT_VM1.png) +## 2. 虚拟机环境准备 +### 2.1 制作虚拟机镜像 +下载操作系统镜像。 +``` +$ cd .. +$ mkdir iso +$ cd iso +$ wget http://mirrors.aliyun.com/ubuntu-releases/18.04/ubuntu-18.04.6-live-server-amd64.iso +``` +用如下命令创建一个大小为20G的虚拟磁盘。 +``` +$ ../output/qemu-output/bin/qemu-img create -f qcow2 hct.qcow2 20G +``` +启动虚拟机,在创建好的虚拟磁盘中安装操作系统。 +``` +$ sudo ../output/qemu-output/bin/qemu-system-x86_64 -enable-kvm -m 4096 -smp 8 -boot d -drive file=hct.qcow2,if=virtio,index=0,media=disk,format=qcow2 -drive file=ubuntu-18.04.6-live-server-amd64.iso,index=1,media=cdrom -vnc localhost:1 +``` +另外打开一个终端,通过VNC软件连接到虚拟机,这里用的是Mobaxterm终端软件 + xtightvncviewer,用户可自行选择。 +``` +$ sudo apt install xtightvncviewer +$ xtightvncviewer +``` +在弹出的窗口中输入localhost:1。 + +![](../../assets/HCT/HCT_VM2.png) + +进入虚拟机的界面后开始安装操作系统。 + +![](../../assets/HCT/HCT_VM3.png) + +### 2.2 启动带HCT功能的虚拟机 +操作系统安装完成后先关闭原来的虚拟机,并通过如下命令开启虚拟机。 +``` +$ /opt/hygon/hct/hct/script/start_qemu.py -q ../output/qemu-output/bin/qemu-system-x86_64 -n 1 -i hct.qcow2 +``` +-q后的参数为qemu可执行程序,可根据安装位置自行指定,默认为系统目录下的qemu-system-x86_64;-n后的参数为启动虚拟机的数量;-i后的参数为装有操作系统的虚拟磁盘,需要指定路径。 +![](../../assets/HCT/HCT_VM11.png) + +**如需启动带vTKM功能的虚拟机,先使用hag工具创建vid。并在脚本后请加--vid {vid_num} 参数。** +``` +$ cd /opt/hygon/bin +$ sudo ./hag tkm vtkm_create -mode shared //若需要使用密钥隔离vTKM,模式配置为exclusive +$ /opt/hygon/hct/hct/script/start_qemu.py -q ../output/qemu-output/bin/qemu-system-x86_64 -n 1 -i hct.qcow2 --vid 1 +``` +![](../../assets/HCT/HCT_VM17.png) + + + +虚拟机成功启动后,使用如下命令查询虚拟机状态及对应端口号。 +``` +$ /opt/hygon/hct/hct/script/start_qemu.py -s +``` +![](../../assets/HCT/HCT_VM4.png) + +通过ssh,指定2220端口,登录到虚拟机。 + +``` +$ ssh -p 2220 hygon@localhost +``` +![](../../assets/HCT/HCT_VM5.png) + +注意,此后的操作如无特殊说明,均在虚拟机中执行。 +安装依赖软件。安装软件前请保持虚拟机和宿主机的apt源一致。 +``` +$ sudo apt install -y make build-essential python +``` + +### 2.3 虚拟机环境准备 +将HCT开发包拷贝到虚拟机,并安装。 +``` +$ scp -r {hostuser}@{hostip}:{file_path}/hygon-devkit/hct/pkg/{hct_version} ./ +$ cd {hct_version} +$ sudo dpkg -i *.deb +``` +![](../../assets/HCT/HCT_VM6.png) + +编译安装HCT内核模块。 +``` +$ make +$ sudo make install +$ sudo modprobe hct +``` +![](../../assets/HCT/HCT_VM7.png) +配置noiommu功能。 +``` +$ sudo modprobe vfio +$ sudo modprobe vfio-pci +$ sudo bash -c "echo 1 > /sys/module/vfio/parameters/enable_unsafe_noiommu_mode" +``` +用如下命令检查是否设置成功。 + +``` +$ cat /sys/module/vfio/parameters/enable_unsafe_noiommu_mode +``` +![](../../assets/HCT/HCT_VM8.png) + +**如需验证vTKM功能,请先参照[《海光SDF接口用户手册》](./5-海光SDF接口用户手册.md) 2.2节,在虚拟机中安装对应的deb/rpm包。** + +## 3. 功能测试 +### 3.1 HCT功能测试 +将CCP设备绑定到vfio-pci驱动。 +``` +$ sudo /opt/hygon/hct/hct/script/hctconfig start -m vfio-pci +``` +执行基本功能测试。 +``` +$ sudo /opt/hygon/hct/bin/hct_test +``` +![](../../assets/HCT/HCT_VM9.png) +``` +$ sudo /opt/hygon/hct/bin/hct_speed -elapsed -engine hct -multi 1 -seconds 10 sm2enc +``` + +![](../../assets/HCT/HCT_VM10.png) + +### 3.2 vTKM功能测试 +如无vTKM功能需求,可跳过。 + +#### 3.2.1 vTKM基本环境验证 +执行任意一个TKM命令,确认在虚拟机环境下已可以使用TKM,这里以hag tkm dev_info_get为例,执行成功可以说明vTKM基本环境已搭建完成。 + +![虚拟机下TKM命令运行](../../assets/TKM/vTKM_dev_info.png) + +#### 3.2.2 SDF基本环境验证 +请参照[《海光SDF接口用户手册》](./5-海光SDF接口用户手册.md) 第3节,在虚拟机中验证基本SDF接口,执行成功可以说明虚拟机下SDF环境已搭建完成。 + +## 4. 备注 +### 4.1 注意事项 +虚拟机与宿主机一样,都支持1G和2M内存大页,默认为2M,如需使用1G内存大页,可参考[《HCT用户手册》](./1-HCT用户手册.md)。 +### 4.2 虚拟机启动参数 +start_qemu.py启动虚拟机的参数为 ../output/qemu-output/bin/qemu-system-x86_64 --enable-kvm -cpu host -name hct_test_vm_0 -net user,hostfwd=tcp::2220-:22 -net nic -vnc :0 -hda /home/lixin/workspace/qemu_hct/sys_image/hct.qcow2 -m 12G -smp 36 -object memory-backend-ram,id=mem0,size=4G,policy=bind,host-nodes=2 -numa node,memdev=mem0,cpus=0-5,cpus=18-23,nodeid=0 -object memory-backend-ram,id=mem1,size=4G,policy=bind,host-nodes=4 -numa node,memdev=mem1,cpus=6-11,cpus=24-29,nodeid=1 -object memory-backend-ram,id=mem2,size=4G,policy=bind,host-nodes=6 -numa node,memdev=mem2,cpus=12-17,cpus=30-35,nodeid=2 -device hct,sysfsdev=/sys/bus/mdev/devices/e6cba2aa-7778-4f87-a962-7e3953ce2367 -device hct,sysfsdev=/sys/bus/mdev/devices/60b0cf7e-9a95-4dfb-956a-d2b5b23d0fcd -daemonize + +**若使用带vTKM的虚拟机,则需要包含-device psp,vid=1参数,vid值根据实际vid号输入** + +| 参数 | 解释 | +|--------------------|-----------------------| +|--enable-kvm |启用KVM加速,可以提高虚拟机的性能| +|-cpu host |指定虚拟机中的CPU与宿主机CPU相同 | +|-name hct_test_vm_0 |设置虚拟机别名为 hct_test_vm_0| +|-net user,hostfwd=tcp::2220-:22|为虚拟机设置网络,将宿主机的2222端口映射到虚拟机的22端口(用于SSH连接)| +|-net nic |为虚拟机添加一个网络接口| +|-hda {yourpath}/hct.qcow2 |虚拟机的硬盘| +|-m 12G |为虚拟机分配12GB的内存| +|-smp 36 |设置虚拟机的CPU核心数为36| +|-object memory-backend-ram,id=mem0,size=4G,policy=bind,host-nodes=2 |创建一个内存对象,分配4G内存,并将它绑定在宿主机的numa2上| +|-numa node,memdev=mem0,cpus=0-5,cpus=18-23,nodeid=0 |创建一个numa节点,关联内存,并指定与vcpu关联| +|-device hct,sysfsdev=/sys/bus/mdev/devices/{uuid} |虚拟机中添加一个hct设备 | +|-daemonize |后台运行虚拟机 | +|-device psp,vid=1 |启动带vTKM的虚拟机,该虚拟机绑定vid为1对应的密钥空间 | + +## 5. libvirt中使用虚拟机 +使用前请自行安装4.5及以上版本的libvirt。可参考官方文档https://libvirt.org/docs.html +### 5.1 配置文件修改 + +编辑/etc/libvirt/qemu.conf,并设置用户参数。 +``` +user = "root" +group = "root" +``` +![](../../assets/HCT/HCT_VM12.png) + +安装libvirt及lxml的python插件。 +``` +$ sudo pip3 install libvirt-python +$ sudo pip3 install lxml +``` +更新/etc/libvirt/qemu.conf中的cgroup_device_acl设备列表。 +``` +$ sudo /opt/hygon/hct/hct/script/start_qemu.py --update_qemu_conf +``` +如需使用vTKM功能,请在cgroup_device_acl中加入"/dev/hygon_psp_config"设备。 + +重启libvirt服务。 + +``` +$ sudo service libvirtd restart +``` + +### 5.2 导入虚拟机 +导入新的虚拟机,并查看状态。 +``` +$ sudo virsh define test.xml +$ sudo virsh list --all +``` +![](../../assets/HCT/HCT_VM15.png) + +如需使用vTKM功能,请在test.xml中的部分加入 +。 + +### 5.3 更新xml配置 +更新xml中的hct设备。 +``` +$ sudo /opt/hygon/hct/hct/script/start_qemu.py --update_xml hct_test01 +``` +![](../../assets/HCT/HCT_VM14.png) + +启动虚拟机。 +``` +$ sudo virsh start hct_test01 +``` +![](../../assets/HCT/HCT_VM16.png) + +虚拟机开启后可通过ssh或是vnc登录。 + +### 5.4 xml示例配置 +如下为启动一个hct功能虚拟机的基本配置,仅供参考。注意将配置中emulatorsource file中的{your_path}替换成真实路径。如需在其他虚拟机配置中使用hct,确保配置文件中存在qemu:commandline即可。 +``` + + hct_test01 + 16 + 16 + 32 + + /machine + + + hvm + + + + destroy + restart + destroy + + /{your_path}/qemu-system-x86_64 + + + + + + +
+ + + +
+ + + + + + + +