From 68871272a17586f3457da68a33d8322d1277a8a9 Mon Sep 17 00:00:00 2001 From: zhaohaidan Date: Wed, 12 Jul 2023 12:33:46 +0800 Subject: [PATCH 01/57] plat/Makefile.uk: port plat raspi --- plat/Makefile.uk | 1 + 1 file changed, 1 insertion(+) diff --git a/plat/Makefile.uk b/plat/Makefile.uk index a248ac60..ed2b7c0c 100644 --- a/plat/Makefile.uk +++ b/plat/Makefile.uk @@ -5,3 +5,4 @@ UK_PLAT_DRIVERS_BASE:= $(UK_PLAT_BASE)/drivers $(eval $(call import_lib,$(UK_PLAT_BASE)/xen)) $(eval $(call import_lib,$(UK_PLAT_BASE)/kvm)) $(eval $(call import_lib,$(UK_PLAT_BASE)/linuxu)) +$(eval $(call import_lib,$(UK_PLAT_BASE)/raspi)) -- Gitee From bcb8387d2bcc273845ee65c41b6817aef1a7e11d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E6=B5=B7=E4=B8=B9?= Date: Wed, 2 Aug 2023 04:31:38 +0000 Subject: [PATCH 02/57] unikraft/.gitee: add pr template MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 赵海丹 --- .gitee/PULL_REQUEST_TEMPLATE.zh-CN.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .gitee/PULL_REQUEST_TEMPLATE.zh-CN.md diff --git a/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md b/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md new file mode 100644 index 00000000..d33aca61 --- /dev/null +++ b/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md @@ -0,0 +1,8 @@ +// PR标题格式:#pingcode需求ID 模块名:PR概述,如:
+// #TEN1 plat/kvm/x86: Remove .intrstack section
+// #TEN2 build: add debug symbols and common sections to all linkers
+ + +### 修改原因 (目的、解决的问题等) +### 修改内容 (整体或分文件描述修改内容) +### 测试场景 (新增或改动可能影响的功能。测试截图请贴在PR评论区) -- Gitee From 0bd94a22184b6dde8e16a299451a37beeea1cdc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E6=B5=B7=E4=B8=B9?= Date: Mon, 18 Sep 2023 07:05:47 +0000 Subject: [PATCH 03/57] unikraft/LICENSE: add license MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 赵海丹 --- LICENSE | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. -- Gitee From d8174ce5be809e14aedc942c8972a43174f283a1 Mon Sep 17 00:00:00 2001 From: 1788594346 <13290132+wu-shifang@user.noreply.gitee.com> Date: Mon, 18 Sep 2023 14:43:23 +0800 Subject: [PATCH 04/57] ci/scripts: add a script to check PR title --- ci/scripts/check_pr_title.sh | 44 ++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100755 ci/scripts/check_pr_title.sh diff --git a/ci/scripts/check_pr_title.sh b/ci/scripts/check_pr_title.sh new file mode 100755 index 00000000..a1fcec1f --- /dev/null +++ b/ci/scripts/check_pr_title.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +# Copyright 2023 Hangzhou Yingyi Technology Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# 本脚本用于检测PR标题是否符合规范,需遵循格式 +# "#TEN-A B:" 或 "#TEN-A B/C:" 或 "#TEN-A B/C[D]:" 或 "#TEN-A B1/C, B2/D:" +# A为TenonOS项目编号(纯数字) +# B为"lib"、"app"、"plat"、"arch"、"build"、"ci"之一 +# C为细化模块名(任意字母、数字、'-'的组合) +# D为备注(任意字母、数字、'-'的组合) +# C、D参数可选 +# ex1: #TEN-666 build: change build rules +# ex2: #TEN-666 app/helloworld: add helloworld function +# ex3: #TEN-666 lib/posix-time: fix a bug +# ex4: #TEN-666 plat/raspi[bugFix]: Improve performance +# ex5: #TEN-666 plat/raspi, lib/ukvmem: Adapt changes from uk v0.15 +story_id='^#TEN-[1-9][0-9]*' +module='(lib|app|plat|arch|build|ci)' +sub_module='(/[-0-9a-zA-Z]+(\[[-0-9a-zA-Z]+])?)?' + +title_exp="${story_id} ${module}${sub_module}(, ${module}${sub_module})*: " + +if [[ ! $1 =~ $title_exp ]] ;then + echo -e "check PR title fail!! PR标题格式错误\n" + echo -e "$1\n" + echo "示例:\"#TEN-A B:\" 或 \"#TEN-A B/C:\" 或 \ +\"#TEN-A B/C[D]:\" 或 \"#TEN-A B1/C, B2/D:\"" + echo "需匹配正则表达式: $title_exp" + exit 1 +fi + +echo "check PR title success!!" -- Gitee From ed218f760de665cbf8ef2e36ac5d76e9369e1185 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E6=B5=B7=E4=B8=B9?= Date: Wed, 27 Sep 2023 09:02:53 +0000 Subject: [PATCH 05/57] unikraft/.gitee: update pull template MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 赵海丹 --- .gitee/PULL_REQUEST_TEMPLATE.zh-CN.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md b/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md index d33aca61..db303a29 100644 --- a/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md +++ b/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md @@ -1,8 +1,10 @@ -// PR标题格式:#pingcode需求ID 模块名:PR概述,如:
-// #TEN1 plat/kvm/x86: Remove .intrstack section
-// #TEN2 build: add debug symbols and common sections to all linkers
+##### 修改原因:(目的、解决的问题等) +##### 修改内容:(整体或分文件描述修改内容) +##### 测试场景:(新增或改动可能影响的功能,对测试情况做简要说明。测试截图请贴在PR评论区) - -### 修改原因 (目的、解决的问题等) -### 修改内容 (整体或分文件描述修改内容) -### 测试场景 (新增或改动可能影响的功能。测试截图请贴在PR评论区) +##### 以下内容非必须 +##### 相关PR:(若有需列明) +##### 相关Issue:(若有需列明) +##### 兼容性说明:(是否无法兼容已发布的版本) +##### API/接口变更:(若修改了现有的API/函数定义,需要做出说明) +##### 其他: -- Gitee From 4c83936c82e1359841c61d2e94a248b503cdaa21 Mon Sep 17 00:00:00 2001 From: 1788594346 <13290132+wu-shifang@user.noreply.gitee.com> Date: Tue, 19 Sep 2023 11:55:50 +0800 Subject: [PATCH 06/57] ci: add a pipeline file and other support files for ci testing Signed-off-by: 1788594346 <13290132+wu-shifang@user.noreply.gitee.com> --- ci/.jenkinsfile | 537 ++++++++++++++++++++++++++++ ci/defconfigs/linuxu-arm64 | 20 ++ ci/defconfigs/linuxu-x86_64 | 19 + ci/defconfigs/raspi-arm64-libc-test | 42 +++ ci/defconfigs/raspi-arm64-uktest | 22 ++ ci/defconfigs/xen-x86_64 | 16 + 6 files changed, 656 insertions(+) create mode 100644 ci/.jenkinsfile create mode 100644 ci/defconfigs/linuxu-arm64 create mode 100644 ci/defconfigs/linuxu-x86_64 create mode 100644 ci/defconfigs/raspi-arm64-libc-test create mode 100644 ci/defconfigs/raspi-arm64-uktest create mode 100644 ci/defconfigs/xen-x86_64 diff --git a/ci/.jenkinsfile b/ci/.jenkinsfile new file mode 100644 index 00000000..3dd8dcf2 --- /dev/null +++ b/ci/.jenkinsfile @@ -0,0 +1,537 @@ +/* Copyright 2023 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* 返回给gitee PR评论信息字符串 */ +string ret = "" + +/* 库相关 */ +string gitAppHelloWorldURL = "git@gitee.com:yingyitech/app-helloworld.git" +string gitPlatRaspiUrl = "https://gitee.com/yingyitech/plat-raspi.git" +string gitLibMuslUrl = "git@gitee.com:yingyitech/lib-musl.git" +string gitLibcTestUrl = "git@gitee.com:yingyitech/lib-libc-test.git" + +/* XEN配置文件内容 */ +string xenConfig = """ +name = 'helloworld' +vcpus = '1' +memory = '4' +kernel = 'build/run_xen-x86_64_xen-x86_64.dbg' +""" + +/* fc配置文件内容 */ +string fcJson = """ +{ + "boot-source": { + "kernel_image_path": "build/helloworld_fc-x86_64", + "boot_args": "helloworld_fc-x86_64 " + }, + "drives": [], + "machine-config": { + "vcpu_count": 1, + "mem_size_mib": 64, + "smt": false, + "track_dirty_pages": false + }, + "cpu-config": null, + "balloon": null, + "vsock": null, + "logger": { + "log_path": "/tmp/firecracker.log", + "level": "Debug", + "show_level": true, + "show_log_origin": true + }, + "metrics": null, + "mmds-config": null, + "entropy": null +} +""" + +/* 任务统计变量初始化 + * tolNum -> 本pipeline文件总测试任务数 + * exeNum -> 预期执行任务数 + * sucNum -> 成功任务数 + * failNum -> 失败任务数 + */ +int tolNum = 10 +int exeNum = 0 +int sucNum = 0 +int failNum = 0 +if (env.giteeActionType == "NOTE" && env.giteeTriggerPhrase.contains("skip_check")) { + tolNum-- +} + +/* pipeline 定义了整个测试流程中的工作 */ +pipeline { + /* agent 为指定终端执行测试,any为任一均可 */ + agent any + + /* options 为自定义设置选项 */ + options { + /* 控制台打印增加时间戳 */ + timestamps() + } + + /* stages 为pipeline需要的步骤集 */ + stages { + /* stage 定义一个名为'***'的单个构建步骤 */ + stage('开始CI测试,通知PR评论') { + /* 如果评论指令是help则获取help菜单,不执行测试任务 */ + when { + not { + expression {env.giteeActionType == "NOTE" && (env.giteeTriggerPhrase[0..3] == "help")} + } + } + steps { + /* addGiteeMRComment 可以向指定PR新增评论 */ + addGiteeMRComment comment: "开始CI测试,任务编号:" + env.BUILD_NUMBER + "\n任务链接:" + env.JOB_DISPLAY_URL + } + } + stage('初始化公共代码仓') { + when { + not { + expression {env.giteeActionType == "NOTE" && (env.giteeTriggerPhrase[0..3] == "help")} + } + } + steps { + /* script 块可以调用groovy方法 */ + script { + /* 调用shell脚本,执行check测试。使用NAME = sh()形式可以防止shell脚本出错直接退出stage */ + result = sh(script: """ + #!/bin/bash + cd $WORKSPACE + git clone $gitAppHelloWorldURL + cd app-helloworld + # 获取以下两次commit的中defconfig文件 + git cherry-pick -n 06ee0b7 438ca02 + mkdir .unikraft .unikraft/unikraft + cd - + # 将unikraft拷贝至app-helloworld/.unikraft/unikraft中 + cp -r `ls |grep -v 'app-helloworld'|xargs` app-helloworld/.unikraft/unikraft + git clone $gitPlatRaspiUrl app-helloworld/.unikraft/unikraft/plat/raspi + # 为每个测试项建立独立目录 + mkdir ut_self-test ut_libc-test run_qemu-x86_64 run_qemu-arm64 run_xen-x86_64 run_fc-x86_64 run_linuxu-x86_64 run_linuxu-arm64 + cp -r app-helloworld/. ut_libc-test + cp -r app-helloworld/. run_qemu-x86_64 + cp -r app-helloworld/. run_qemu-arm64 + cp -r app-helloworld/. run_xen-x86_64 + cp -r app-helloworld/. run_fc-x86_64 + cp -r app-helloworld/. run_linuxu-x86_64 + cp -r app-helloworld/. run_linuxu-arm64 + """, returnStatus: true) + if (result != 0) { + ret = "初始化代码仓失败,详见任务链接" + error '初始化代码仓失败' + } + } + } + } + stage('PR标题合法性检查') { + when { + not { + expression {env.giteeActionType == "NOTE" && (env.giteeTriggerPhrase[0..3] == "help")} + } + } + steps { + script { + exeNum++ + result = sh(script: ''' + #!/bin/sh + cd $WORKSPACE + ./ci/scripts/check_pr_title.sh "$giteePullRequestTitle" + ''', returnStatus: true) + /* 结果分支处理,将信息添加至ret中 */ + if (result == 0) { + sucNum++ + ret = ret + "|PR标题合法性检查|成功||" + } else { + failNum++ + ret = ret + "|PR标题合法性检查|**失败**|PR标题详细要求见任务链接|" + error 'PR标题合法性检查失败' + } + } + } + } + /* check测试步骤,进行commit信息规范与patch增量代码规范检查 */ + /* unikraft社区commit描述推荐格式 [selector]/[component name]: [Your short message] + * exp: lib/uktest: selftest + * 社区检查脚本只检查是否含有":",原则上commit信息需要符合社区规定 + */ + stage('社区commit规范检查') { + /* when 块可以控制本stage执行条件,此处当PR评论内容不为test_skip_check时才执行 */ + when { + not { + expression {env.giteeActionType == "NOTE" && + ((env.giteeTriggerPhrase[0..3] == "help") || (env.giteeTriggerPhrase.contains("skip_check")))} + } + } + steps { + script { + exeNum++ + result = sh(script: ''' + #!/bin/sh + cd $WORKSPACE + git format-patch HEAD~1 + ./support/scripts/checkpatch.pl ./000* --no-signoff + ''', returnStatus: true) + if (result == 0) { + sucNum++ + ret = ret + "\n|社区commit信息与代码规范检查|成功||" + } else { + failNum++ + ret = ret + "\n|社区commit信息与代码规范检查|**失败**|具体规范要求见任务链接|" + error '社区commit信息与代码规范检查失败' + } + } + } + } + + stage('初始化libmusl代码仓') { + steps { + /* script 块可以调用groovy方法 */ + script { + /* 调用shell脚本,执行check测试。使用NAME = sh()形式可以防止shell脚本出错直接退出stage */ + result = sh(script: """ + #!/bin/bash + cd $WORKSPACE/ut_libc-test + git clone $gitAppHelloWorldURL + git clone $gitLibMuslUrl .unikraft/libs/musl + git clone $gitLibcTestUrl .unikraft/libs/libc-test + # 将musl库与libc-test库编入Makefile + sed -i '/^LIBS/{s/\$/\$(UK_LIBS)\\/musl:\$(UK_LIBS)\\/libc-test/}' Makefile + # 将libc-test库依赖的源码URL改为官网URL,源码URL下载不稳定 + sed -i '/LIBLIBCTEST_URL/s/git:\\/\\/nsz.repo.hu:49100\\/repo\\/libc-test/git:\\/\\/repo.or.cz\\/libc-test/g' .unikraft/libs/libc-test/Makefile.uk + # uktest测试库也需要musl编入 + cd .. + cp -r ut_libc-test/. ut_self-test + """, returnStatus: true) + if (result != 0) { + ret = ret + "\n\n初始化libmusl失败,详见任务链接" + error '初始化libmusl失败' + } + } + } + } + + /* UT测试步骤,打开uktest,测试是否可以通过libc测试与自验用例集 */ + stage('UT测试') { + when { + not { + expression {env.giteeActionType == "NOTE" && (env.giteeTriggerPhrase[0..3] == "help")} + } + } + /* failFast 设置是否其中一个stage失败则立即停止此parallel所有任务 */ + failFast false + /* parallel 并行开始stage */ + parallel { + stage('libc-test') { + steps { + /* 初始化make config配置 */ + script { + exeNum++ + result = sh(script: ''' + #!/bin/bash + cd $WORKSPACE/ut_libc-test + make defconfig UK_DEFCONFIG=$PWD/.unikraft/unikraft/ci/defconfigs/raspi-arm64-libc-test + ''', returnStatus: true) + if (result != 0) { + failNum++ + ret = ret + "\n|UT测试|**libc-test失败**|初始化make config配置失败|" + error '初始化make config配置失败!' + } + } + /* make & run*/ + script { + result = sh(script: ''' + cd $WORKSPACE/ut_libc-test + # 编译unikraft, make & run流程 + make + qemu-system-aarch64 -cpu cortex-a53 -machine raspi3b -nodefaults -display none -pidfile $WORKSPACE/libc-test$BUILD_NUMBER.pid -serial file:$WORKSPACE/libc-test$BUILD_NUMBER.out -kernel build/kernel8.img -append verbose & + # 后台运行,等待15s + sleep 15s + ''', returnStatus: true) + if (result == 0) { + resultCheck = sh(script: ''' + cd $WORKSPACE/ + # 如果输出文件中包含Hello world!则判断运行成功 + cat $WORKSPACE/libc-test$BUILD_NUMBER.out + grep -q "Hello" $WORKSPACE/libc-test$BUILD_NUMBER.out + ''', returnStatus: true) + if (resultCheck == 0) { + sucNum++ + ret = ret + "\n|UT测试|libc-test成功||" + } else { + failNum++ + ret = ret + "\n|UT测试|**libc-test失败**|运行失败,详见任务链接|" + error 'UT测试运行libc-test失败!' + } + } else { + failNum++ + ret = ret + "\n|UT测试|**libc-test失败**|make命令失败,详见任务链接|" + error 'UT测试libc-test make失败!' + } + } + } + } + stage('self-test') { + steps { + /* 初始化make config配置 */ + script { + exeNum++ + result = sh(script: ''' + cd $WORKSPACE/ut_self-test + make defconfig UK_DEFCONFIG=$PWD/.unikraft/unikraft/ci/defconfigs/raspi-arm64-uktest + ''', returnStatus: true) + if (result != 0) { + failNum++ + ret = ret + "\n|UT测试|**self-test失败**|初始化make config配置失败|" + error '初始化make config配置失败!' + } + } + /* make & run*/ + script { + result = sh(script: ''' + cd $WORKSPACE/ut_self-test + # 编译unikraft, make & run流程 + make + qemu-system-aarch64 -cpu cortex-a53 -machine raspi3b -nodefaults -display none -pidfile $WORKSPACE/self-test$BUILD_NUMBER.pid -serial file:$WORKSPACE/self-test$BUILD_NUMBER.out -kernel build/kernel8.img -append verbose & + # 后台运行,等待15s + sleep 15s + ''', returnStatus: true) + if (result == 0) { + resultCheck = sh(script: ''' + cd $WORKSPACE/ + # 如果输出文件中包含Hello world!则判断运行成功 + cat $WORKSPACE/self-test$BUILD_NUMBER.out + grep -q "Hello" $WORKSPACE/self-test$BUILD_NUMBER.out + ''', returnStatus: true) + if (resultCheck == 0) { + sucNum++ + ret = ret + "\n|UT测试|self-test成功||" + } else { + failNum++ + ret = ret + "\n|UT测试|**self-test失败**|运行失败,详见任务链接|" + error 'UT测试self-test运行失败!' + } + } else { + failNum++ + ret = ret + "\n|UT测试|**self-test失败**|make命令失败,详见任务链接|" + error 'UT测试self-test make失败!' + } + } + } + } + } + } + + /* 兼容性测试步骤,测试是否影响到支持的其他平台与架构 */ + stage('兼容性测试') { + when { + not { + expression {env.giteeActionType == "NOTE" && (env.giteeTriggerPhrase[0..3] == "help")} + } + } + failFast false + parallel { + stage('helloworld (qemu, x86_64)') { + steps { + script { + exeNum++ + result = sh(script:''' + cd $WORKSPACE/run_qemu-x86_64 + UK_DEFCONFIG=\$PWD/.config.helloworld-qemu-x86_64 make defconfig + make + qemu-system-x86_64 -kernel build/helloworld_qemu-x86_64 -nographic + ''', returnStatus: true) + if (result == 0) { + sucNum++ + ret = ret + "\n|兼容性测试|helloworld (qemu, x86_64)成功||" + } else { + failNum++ + ret = ret + "\n|兼容性测试|**helloworld (qemu, x86_64)失败**|运行失败,详见任务链接|" + error '兼容性测试 helloworld (qemu, x86_64) 失败!' + } + } + } + } + + stage('helloworld (qemu, arm64)') { + steps { + script { + exeNum++ + result = sh(script:''' + cd $WORKSPACE/run_qemu-arm64 + UK_DEFCONFIG=\$PWD/.config.helloworld-qemu-aarch64 make defconfig + make + qemu-system-aarch64 -kernel build/helloworld_qemu-arm64 -nographic -machine virt -cpu cortex-a57 + ''', returnStatus: true) + if (result == 0) { + sucNum++ + ret = ret + "\n|兼容性测试|helloworld (qemu, arm64)成功||" + } else { + failNum++ + ret = ret + "\n|兼容性测试|**helloworld (qemu, arm64)失败**|运行失败,详见任务链接|" + error '兼容性测试 helloworld (qemu, arm64) 失败!' + } + } + } + } + + stage('helloworld (xen, x86_64)') { + steps { + script { + exeNum++ + result = sh(script:""" + #!/bin/bash + cd $WORKSPACE/run_xen-x86_64 + cat>helloworld.cfg<fc-x86_64.json<|执行指定测试任务|(null) - - - - - - 执行默认测试任务" + + "
skip_check - - 不运行代码规范检查" + + "
save - - - - - - 保存本次测试工作区文件" + + "|test后可跟零个或多个入参,用空格分隔
譬如```test skip_check save```|" + + "\n|\\|回评本表所示帮助内容|无|输入```help```即可|" + } else { + /* 如果评论含有test save,则保存工作区文件 */ + if (env.giteeActionType == "NOTE" && env.giteeTriggerPhrase.contains("save")) { + result = sh(script:""" + #!/bin/bash + cd $WORKSPACE/.. + mv $WORKSPACE CI_unikraft_cache_$BUILD_NUMBER + """, returnStatus: true) + ret = ret + "\n\n文件保存至CI_unikraft_cache_" + env.BUILD_NUMBER + } + int untestedNum = tolNum - exeNum + addGiteeMRComment comment: "结束CI测试,计划测试" + "**$tolNum**" + "项-->已经测试" + "**$exeNum**" + "项:成功" + "**$sucNum**" + "项,失败" + "**$failNum**" + "项;未测试" + "**$untestedNum**项" + + "\n|任务名|测试状态|备注|\n|-|-|-|" + + "\n" + ret + + "\n\n任务链接:" + env.JOB_DISPLAY_URL + } + deleteDir() + } + } + } +} diff --git a/ci/defconfigs/linuxu-arm64 b/ci/defconfigs/linuxu-arm64 new file mode 100644 index 00000000..2d9080ee --- /dev/null +++ b/ci/defconfigs/linuxu-arm64 @@ -0,0 +1,20 @@ +# Copyright 2023 Hangzhou Yingyi Technology Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +CONFIG_ARCH_ARM_64=y +CONFIG_MCPU_ARM64_GENERIC=y +CONFIG_PLAT_LINUXU=y +CONFIG_LINUXU_DEFAULT_HEAPMB=4 +CONFIG_LINUXU_MAX_IRQ_HANDLER_ENTRIES=8 +CONFIG_UKPLAT_LCPU_MAXCOUNT=1 diff --git a/ci/defconfigs/linuxu-x86_64 b/ci/defconfigs/linuxu-x86_64 new file mode 100644 index 00000000..44d157b6 --- /dev/null +++ b/ci/defconfigs/linuxu-x86_64 @@ -0,0 +1,19 @@ +# Copyright 2023 Hangzhou Yingyi Technology Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +CONFIG_PLAT_LINUXU=y +CONFIG_LINUXU_DEFAULT_HEAPMB=4 +CONFIG_LINUXU_MAX_IRQ_HANDLER_ENTRIES=8 +CONFIG_UKPLAT_LCPU_MAXCOUNT=1 +CONFIG_HZ=100 diff --git a/ci/defconfigs/raspi-arm64-libc-test b/ci/defconfigs/raspi-arm64-libc-test new file mode 100644 index 00000000..56f71f94 --- /dev/null +++ b/ci/defconfigs/raspi-arm64-libc-test @@ -0,0 +1,42 @@ +# Copyright 2023 Hangzhou Yingyi Technology Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +CONFIG_ARCH_ARM_64=y +CONFIG_MCPU_ARM64_GENERIC=y +# CONFIG_ARM64_ERRATUM_858921 is not set +CONFIG_PLAT_RASPI=y +CONFIG_LIBMUSL=y +CONFIG_LIBLIBCTEST=y +CONFIG_LIBLIBCTEST_STRING_TESTS=y +CONFIG_LIBLIBCTEST_PTHREAD_TESTS=y +CONFIG_LIBLIBCTEST_CONVERSION_TESTS=y +CONFIG_LIBLIBCTEST_REGEX_TESTS=y +CONFIG_LIBLIBCTEST_NETWORK_TESTS=y +CONFIG_LIBLIBCTEST_SORT_TESTS=y +CONFIG_LIBLIBCTEST_STRUCTURE_SEARCH_TESTS=y +CONFIG_LIBLIBCTEST_SEMAPHORE_TESTS=y +CONFIG_LIBLIBCTEST_RANDOM_TESTS=y +CONFIG_LIBLIBCTEST_CRYPT_TESTS=y +CONFIG_LIBLIBCTEST_ENV_TESTS=y +CONFIG_LIBLIBCTEST_MALLOC_TESTS=y +CONFIG_LIBLIBCTEST_ICONV_TESTS=y +CONFIG_LIBLIBCTEST_UDIV_TESTS=y +CONFIG_LIBLIBCTEST_MBFUNC_TESTS=y +CONFIG_LIBLIBCTEST_FPCLASSIFY_TESTS=y +CONFIG_LIBLIBCTEST_POSIX_SPAWN_TESTS=y +CONFIG_LIBLIBCTEST_ACCESS_TESTS=y +CONFIG_LIBUKTEST=y +# CONFIG_LIBUKTEST_ALL is not set +CONFIG_LIBUKDEBUG_PRINTK_INFO=y +# CONFIG_LIBUKDEBUG_PRINTK_CRIT is not set diff --git a/ci/defconfigs/raspi-arm64-uktest b/ci/defconfigs/raspi-arm64-uktest new file mode 100644 index 00000000..c4f65ab1 --- /dev/null +++ b/ci/defconfigs/raspi-arm64-uktest @@ -0,0 +1,22 @@ +# Copyright 2023 Hangzhou Yingyi Technology Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +CONFIG_ARCH_ARM_64=y +CONFIG_MCPU_ARM64_GENERIC=y +# CONFIG_ARM64_ERRATUM_858921 is not set +CONFIG_PLAT_RASPI=y +CONFIG_LIBMUSL=y +CONFIG_LIBUKTEST=y +CONFIG_LIBUKDEBUG_PRINTK_INFO=y +# CONFIG_LIBUKDEBUG_PRINTK_CRIT is not set diff --git a/ci/defconfigs/xen-x86_64 b/ci/defconfigs/xen-x86_64 new file mode 100644 index 00000000..26d06d41 --- /dev/null +++ b/ci/defconfigs/xen-x86_64 @@ -0,0 +1,16 @@ +# Copyright 2023 Hangzhou Yingyi Technology Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +CONFIG_ARCH_X86_64=y +CONFIG_PLAT_XEN=y -- Gitee From 1ca99a7a74127b6ea97627542907feacbea5bc20 Mon Sep 17 00:00:00 2001 From: 1788594346 <13290132+wu-shifang@user.noreply.gitee.com> Date: Mon, 16 Oct 2023 18:05:55 +0800 Subject: [PATCH 07/57] ci: fix a bug in check stage Signed-off-by: 1788594346 <13290132+wu-shifang@user.noreply.gitee.com> --- ci/.jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/.jenkinsfile b/ci/.jenkinsfile index 3dd8dcf2..1cd5fbab 100644 --- a/ci/.jenkinsfile +++ b/ci/.jenkinsfile @@ -184,7 +184,7 @@ pipeline { #!/bin/sh cd $WORKSPACE git format-patch HEAD~1 - ./support/scripts/checkpatch.pl ./000* --no-signoff + ./support/scripts/checkpatch.uk ./000* --no-signoff ''', returnStatus: true) if (result == 0) { sucNum++ -- Gitee From fd5ecd72cf83a417fc0eceef88853830363db987 Mon Sep 17 00:00:00 2001 From: Yifan Zhang Date: Wed, 8 Nov 2023 12:14:22 +0800 Subject: [PATCH 08/57] lib/sched:[upstream][doc]api docs for sched lib --- lib/uksched/include/uk/sched.h | 133 ++++++++++- lib/uksched/include/uk/sched_impl.h | 11 +- lib/uksched/include/uk/thread.h | 327 ++++++++++++++++++++++++++-- 3 files changed, 450 insertions(+), 21 deletions(-) diff --git a/lib/uksched/include/uk/sched.h b/lib/uksched/include/uk/sched.h index c9a03c9f..8d5ee4d2 100644 --- a/lib/uksched/include/uk/sched.h +++ b/lib/uksched/include/uk/sched.h @@ -113,8 +113,27 @@ static inline void uk_sched_yield(void) s->yield(s); } +/** + * Add thread to a scheduler + * + * @param s + * Destination scheduler (required) + * @param t + * Thread to be added (required) + * @return + * - (=0): Successfully added + * - (>0): Failed added + */ int uk_sched_thread_add(struct uk_sched *s, struct uk_thread *t); +/** + * Remove a thread from the scheduler + * + * @param t + * thread to remove (required) + * @return + * - (0): Successfully removed + */ int uk_sched_thread_remove(struct uk_thread *t); static inline void uk_sched_thread_blocked(struct uk_thread *t) @@ -163,6 +182,11 @@ static inline const struct uk_thread *uk_sched_idle_thread(struct uk_sched *s, /** * Create a main thread from current context and call thread starter function + * @param s + * Scheduler to be started (required) + * @return + * - (0): Successfully started + * < (0): Failed started */ int uk_sched_start(struct uk_sched *sched); @@ -211,8 +235,37 @@ struct uk_thread *uk_sched_thread_create_fn0(struct uk_sched *s, uk_thread_dtor_t dtor); /** - * Similar to `uk_sched_thread_create_fn0()` but with a thread function - * accepting one argument + * Allocates a uk_thread and assigns it to a scheduler. + * Similar to `uk_thread_create_fn0()`, general-purpose registers are reset + * on thread start. + * + * @param s + * Reference to scheduler that will execute the thread after creation + * (required) + * @param fn1 + * Thread entry function (required) + * @param argp + * Args for thread entry function + * @param stack_len + * Size of the thread stack. If set to 0, a default stack size is used + * for the stack allocation. + * @param no_uktls + * If set, no memory is allocated for a TLS. Functions must not use + * any TLS variables. + * @param no_ectx + * If set, no memory is allocated for saving/restoring extended CPU + * context state (e.g., floating point, vector registers). In such a + * case, no extended context is saved nor restored on thread switches. + * Executed functions must be ISR-safe. + * @param name + * Optional name for the thread + * @param priv + * Reference to external data that corresponds to this thread + * @param dtor + * Destructor that is called when this thread is released + * @return + * - (NULL): Allocation failed + * - Reference to created uk_thread */ struct uk_thread *uk_sched_thread_create_fn1(struct uk_sched *s, uk_thread_fn1_t fn1, @@ -226,8 +279,39 @@ struct uk_thread *uk_sched_thread_create_fn1(struct uk_sched *s, uk_thread_dtor_t dtor); /** - * Similar to `uk_sched_thread_create_fn0()` but with a thread function - * accepting two arguments + * Allocates a uk_thread and assigns it to a scheduler. + * Similar to `uk_thread_create_fn0()`, general-purpose registers are reset + * on thread start. + * + * @param s + * Reference to scheduler that will execute the thread after creation + * (required) + * @param fn1 + * Thread entry function (required) + * @param argp + * Args for thread entry function + * @param argp1 + * Second args for thread entry function + * @param stack_len + * Size of the thread stack. If set to 0, a default stack size is used + * for the stack allocation. + * @param no_uktls + * If set, no memory is allocated for a TLS. Functions must not use + * any TLS variables. + * @param no_ectx + * If set, no memory is allocated for saving/restoring extended CPU + * context state (e.g., floating point, vector registers). In such a + * case, no extended context is saved nor restored on thread switches. + * Executed functions must be ISR-safe. + * @param name + * Optional name for the thread + * @param priv + * Reference to external data that corresponds to this thread + * @param dtor + * Destructor that is called when this thread is released + * @return + * - (NULL): Allocation failed + * - Reference to created uk_thread */ struct uk_thread *uk_sched_thread_create_fn2(struct uk_sched *s, uk_thread_fn2_t fn2, @@ -251,19 +335,54 @@ struct uk_thread *uk_sched_thread_create_fn2(struct uk_sched *s, #define uk_sched_foreach_thread_safe(sched, itr, tmp) \ UK_TAILQ_FOREACH_SAFE((itr), &(sched)->thread_list, thread_list, (tmp)) +/** + * Dump all threads from the scheduler + * + * @param klvl + * Output level + * @param s + * Scheduler from where threads are dumped + * @return + * NULL + */ void uk_sched_dumpk_threads(int klvl, struct uk_sched *s); +/** + * Sleep current thread + * + * @param nsec + * Time period to sleep + * @return + * NULL + */ void uk_sched_thread_sleep(__nsec nsec); -/* Exits the current thread context */ +/** + * Exits the current thread context + * @return + * NULL + */ void uk_sched_thread_exit(void) __noreturn; -/* Exits the current thread and runs the given routine when releasing the +/** + * Exits the current thread and runs the given routine when releasing the * thread from garbage collection context. + * @param gc_fn + * Gc function to be excuted when the thread is collected + * @param gc_argp + * Input args for gc function + * @return + * NULL */ void uk_sched_thread_exit2(uk_thread_gc_t gc_fn, void *gc_argp) __noreturn; -/* Terminates another thread */ +/** + * Terminates another thread + * @param thread + * Thread to be terminated (required) + * @return + * NULL + */ void uk_sched_thread_terminate(struct uk_thread *thread); #ifdef __cplusplus diff --git a/lib/uksched/include/uk/sched_impl.h b/lib/uksched/include/uk/sched_impl.h index 926b6f10..2aca7c4b 100644 --- a/lib/uksched/include/uk/sched_impl.h +++ b/lib/uksched/include/uk/sched_impl.h @@ -50,6 +50,14 @@ extern "C" { extern struct uk_sched *uk_sched_head; +/** + * Register a new scheduler to the list the existing schedulers + * + * @param s + * Scheduler to be registered(required) + * @return + * - (0): Successfully registered + */ int uk_sched_register(struct uk_sched *s); #define uk_sched_init(s, start_func, yield_func, \ @@ -78,7 +86,8 @@ int uk_sched_register(struct uk_sched *s); /** * Releases self-exited threads (garbage collection) - * + * @param s + * Scheduler where exited threads are collected (required) * @return * - (0): No work was done * - (>0): Number of threads that were cleaned up diff --git a/lib/uksched/include/uk/thread.h b/lib/uksched/include/uk/thread.h index cfa8eee6..5bc71e8b 100644 --- a/lib/uksched/include/uk/thread.h +++ b/lib/uksched/include/uk/thread.h @@ -174,6 +174,11 @@ struct uk_thread *uk_thread_current(void) /* NOTE: Setting a thread as EXITED cannot be undone. */ /* NOTE: Never change the EXIT flag manually. Trnasition to exit state reqiures * the terminate funcrtiomns to be called. + * Handles to exit state transition and calls termtab + * @param t + * Thread to be set as exited + * @return + * NULL */ void uk_thread_set_exited(struct uk_thread *t); @@ -285,8 +290,42 @@ int uk_thread_init_bare_fn0(struct uk_thread *t, uk_thread_dtor_t dtor); /** - * Similar to `uk_thread_init_bare_fn0()` but with a thread function accepting - * one argument + * Initializes a given uk_thread structure. Such a thread can then be + * assigned to a scheduler. When the thread starts, the general-purpose + * registers are reset. The thread is set with + * `UK_THREADF_RUNNABLE`. + * NOTE: On releasing, only the destructor `dtor` is called, + * no memory is released. + * + * @param t + * Reference to uk_thread structure to initialize + * @param fn + * Thread entry function (required) + * @param argp + * Thread entry function argument (required) + * @param sp + * Architecture stack pointer (stack is required) + * @param tlsp + * Architecture pointer to TLS. If set to NULL, the thread cannot + * access thread-local variables. + * @param is_uktls + * Indicates that the given TLS pointer (`tlsp` must be != 0x0) + * points to a TLS derived from the Unikraft system TLS template. + * @param ectx + * Reference to memory for saving/restoring extended CPU context + * (e.g., floating point, vector registers). If set to `NULL`, no + * extended context is saved nor restored on thread switches. + * Executed functions must be ISR-safe. `UK_THREADF_ECTX` is set + * when ectx is given. + * @param name + * Optional reference to a name for the thread + * @param priv + * Reference to external data that corresponds to this thread + * @param dtor + * Destructor that is called when this thread is released + * @return + * - (0): Successfully initialized + * - (<0): Negative value with error code */ int uk_thread_init_bare_fn1(struct uk_thread *t, uk_thread_fn1_t fn, @@ -301,8 +340,44 @@ int uk_thread_init_bare_fn1(struct uk_thread *t, uk_thread_dtor_t dtor); /** - * Similar to `uk_thread_init_bare_fn0()` but with a thread function accepting - * two arguments + * Initializes a given uk_thread structure. Such a thread can then be + * assigned to a scheduler. When the thread starts, the general-purpose + * registers are reset. The thread is set with + * `UK_THREADF_RUNNABLE`. + * NOTE: On releasing, only the destructor `dtor` is called, + * no memory is released. + * + * @param t + * Reference to uk_thread structure to initialize + * @param fn + * Thread entry function (required) + * @param argp + * Thread entry function argument (required) + * @param argp1 + * Second thread entry function argument (required) + * @param sp + * Architecture stack pointer (stack is required) + * @param tlsp + * Architecture pointer to TLS. If set to NULL, the thread cannot + * access thread-local variables. + * @param is_uktls + * Indicates that the given TLS pointer (`tlsp` must be != 0x0) + * points to a TLS derived from the Unikraft system TLS template. + * @param ectx + * Reference to memory for saving/restoring extended CPU context + * (e.g., floating point, vector registers). If set to `NULL`, no + * extended context is saved nor restored on thread switches. + * Executed functions must be ISR-safe. `UK_THREADF_ECTX` is set + * when ectx is given. + * @param name + * Optional reference to a name for the thread + * @param priv + * Reference to external data that corresponds to this thread + * @param dtor + * Destructor that is called when this thread is released + * @return + * - (0): Successfully initialized + * - (<0): Negative value with error code */ int uk_thread_init_bare_fn2(struct uk_thread *t, uk_thread_fn2_t fn, @@ -374,8 +449,45 @@ int uk_thread_init_fn0(struct uk_thread *t, uk_thread_dtor_t dtor); /** - * Similar to `uk_thread_init_fn0()` but with a thread function accepting - * one argument + * Initializes a `uk_thread` structure and allocates stack and optionally TLS. + * Such a thread can then be assigned to a scheduler. When the thread starts, + * the general-purpose registers are reset. + * + * @param t + * Reference to uk_thread structure to initialize + * @param fn + * Thread entry function (required) + * @param argp + * Thread entry function argument (required) + * @param a_stack + * Reference to an allocator for allocating a stack (required) + * @param stack_len + * Size of the thread stack. If set to 0, a default stack size is used + * for the allocation. + * @param a_uktls + * Reference to an allocator for allocating (Unikraft) thread local storage. + * In case `custom_ectx` is not set, space for extended CPU context state + * is allocated together with the TLS. If `NULL` is passed, a thread without + * TLS is allocated (and without ectx if `custom_ectx` is not set + * (see arguments `custom_ectx`, `ectx`). + * @param custom_ectx + * Do not allocate ectx together with TLS. Use next parameter as reference + * to load and store ectx. + * @param ectx + * This parameter is only used if `custom_ectx` is set. If set to `NULL` + * no memory is available for saving/restoring extended CPU context state + * (e.g., floating point, vector registers). In such a case, no ectx can + * be saved nor restored on thread switches. + * Executed functions must be ISR-safe and UK_THREADF_ECTX is not set. + * @param name + * Optional name for the thread, can be `NULL` + * @param priv + * Reference to external data that corresponds to this thread + * @param dtor + * Destructor that is called when this thread is released + * @return + * - (0): Successfully initialized + * - (<0): Negative value with error code */ int uk_thread_init_fn1(struct uk_thread *t, uk_thread_fn1_t fn, @@ -392,8 +504,47 @@ int uk_thread_init_fn1(struct uk_thread *t, uk_thread_dtor_t dtor); /** - * Similar to `uk_thread_init_fn0()` but with a thread function accepting - * two arguments + * Initializes a `uk_thread` structure and allocates stack and optionally TLS. + * Such a thread can then be assigned to a scheduler. When the thread starts, + * the general-purpose registers are reset. + * + * @param t + * Reference to uk_thread structure to initialize + * @param fn + * Thread entry function (required) + * @param argp + * Thread entry function argument + * @param argp1 + * Second thread entry function argument + * @param a_stack + * Reference to an allocator for allocating a stack (required) + * @param stack_len + * Size of the thread stack. If set to 0, a default stack size is used + * for the allocation. + * @param a_uktls + * Reference to an allocator for allocating (Unikraft) thread local storage. + * In case `custom_ectx` is not set, space for extended CPU context state + * is allocated together with the TLS. If `NULL` is passed, a thread without + * TLS is allocated (and without ectx if `custom_ectx` is not set + * (see arguments `custom_ectx`, `ectx`). + * @param custom_ectx + * Do not allocate ectx together with TLS. Use next parameter as reference + * to load and store ectx. + * @param ectx + * This parameter is only used if `custom_ectx` is set. If set to `NULL` + * no memory is available for saving/restoring extended CPU context state + * (e.g., floating point, vector registers). In such a case, no ectx can + * be saved nor restored on thread switches. + * Executed functions must be ISR-safe and UK_THREADF_ECTX is not set. + * @param name + * Optional name for the thread, can be `NULL` + * @param priv + * Reference to external data that corresponds to this thread + * @param dtor + * Destructor that is called when this thread is released + * @return + * - (0): Successfully initialized + * - (<0): Negative value with error code */ int uk_thread_init_fn2(struct uk_thread *t, uk_thread_fn2_t fn, @@ -546,14 +697,64 @@ struct uk_thread *uk_thread_create_container2(struct uk_alloc *a, void *priv, uk_thread_dtor_t dtor); -/* +/** * Helper functions for initializing a thread container and setting it * as runnable + * + * @param t + * Thread to create a container + * @param ip + * Instruction pointer. When `ip != NULL`, the flag + * UK_THREADF_RUNNABLE is set. + * @return + * NULL */ void uk_thread_container_init_bare(struct uk_thread *t, uintptr_t ip); + +/** + * Helper functions for initializing a thread container and setting it + * as runnable + * + * @param t + * Thread to create a container + * @param fn + * Thread entry function (required) + * @return + * NULL + */ void uk_thread_container_init_fn0(struct uk_thread *t, uk_thread_fn0_t fn); + +/** + * Helper functions for initializing a thread container and setting it + * as runnable + * + * @param t + * Thread to create a container + * @param fn + * Thread entry function (required) + * @param argp + * Thread entry function args(required) + * @return + * NULL + */ void uk_thread_container_init_fn1(struct uk_thread *t, uk_thread_fn1_t fn, void *argp); + +/** + * Helper functions for initializing a thread container and setting it + * as runnable + * + * @param t + * Thread to create a container + * @param fn + * Thread entry function (required) + * @param argp + * Thread entry function args(required) + * @param argp1 + * Second thread entry function args(required) + * @return + * NULL + */ void uk_thread_container_init_fn2(struct uk_thread *t, uk_thread_fn2_t fn, void *argp0, void *argp1); @@ -608,8 +809,38 @@ struct uk_thread *uk_thread_create_fn0(struct uk_alloc *a, uk_thread_dtor_t dtor); /** - * Similar to `uk_thread_create_fn0()` but with a thread function accepting - * one argument + * Allocates a raw uk_thread structure. Such a thread can then be assigned + * to a scheduler. When the thread starts, the general-purpose registers are + * reset. + * + * @param a + * Reference to an allocator (required) + * @param fn + * Thread entry function (required) + * @param argp + * Thread entry function argument(required) + * @param a_stack + * Reference to an allocator for allocating a stack (required) + * @param stack_len + * Size of the thread stack. If set to 0, a default stack size is used + * for the stack allocation. + * @param a_uktls + * Reference to an allocator for allocating (Unikraft) thread local storage. + * If `NULL` is passed, a thread without TLS is allocated. + * @param no_ectx + * If set, no memory is allocated for saving/restoring extended CPU + * context state (e.g., floating point, vector registers). In such a + * case, no extended context is saved nor restored on thread switches. + * Executed functions must be ISR-safe. + * @param name + * Optional name for the thread + * @param priv + * Reference to external data that corresponds to this thread + * @param dtor + * Destructor that is called when this thread is released + * @return + * - (NULL): Allocation failed + * - Reference to initialized uk_thread */ struct uk_thread *uk_thread_create_fn1(struct uk_alloc *a, uk_thread_fn1_t fn, void *argp, @@ -624,8 +855,40 @@ struct uk_thread *uk_thread_create_fn1(struct uk_alloc *a, uk_thread_dtor_t dtor); /** - * Similar to `uk_thread_create_fn0()` but with a thread function accepting - * two arguments + * Allocates a raw uk_thread structure. Such a thread can then be assigned + * to a scheduler. When the thread starts, the general-purpose registers are + * reset. + * + * @param a + * Reference to an allocator (required) + * @param fn + * Thread entry function (required) + * @param argp + * Thread entry function argument(required) + * @param argp1 + * Second thread entry function argument(required) + * @param a_stack + * Reference to an allocator for allocating a stack (required) + * @param stack_len + * Size of the thread stack. If set to 0, a default stack size is used + * for the stack allocation. + * @param a_uktls + * Reference to an allocator for allocating (Unikraft) thread local storage. + * If `NULL` is passed, a thread without TLS is allocated. + * @param no_ectx + * If set, no memory is allocated for saving/restoring extended CPU + * context state (e.g., floating point, vector registers). In such a + * case, no extended context is saved nor restored on thread switches. + * Executed functions must be ISR-safe. + * @param name + * Optional name for the thread + * @param priv + * Reference to external data that corresponds to this thread + * @param dtor + * Destructor that is called when this thread is released + * @return + * - (NULL): Allocation failed + * - Reference to initialized uk_thread */ struct uk_thread *uk_thread_create_fn2(struct uk_alloc *a, uk_thread_fn2_t fn, @@ -640,10 +903,48 @@ struct uk_thread *uk_thread_create_fn2(struct uk_alloc *a, void *priv, uk_thread_dtor_t dtor); +/* Release a thread,set as exited and free memory + * @param t + * Thread to be released + * @return + * NULL + */ void uk_thread_release(struct uk_thread *t); + +/* Set the thread as blocked and assign a wake-up time + * @param thread + * Thread to be blocked + * @param until + * Wake-up time + * @return + * NULL + */ void uk_thread_block_until(struct uk_thread *thread, __snsec until); + +/* Set the thread as blocked and assign a timeout + * @param thread + * Thread to be blocked + * @param nsec + * Woken at monotonic clock time plus nsec + * @return + * NULL + */ void uk_thread_block_timeout(struct uk_thread *thread, __nsec nsec); + +/* Set the thread as blocked and without wake-up time + * @param thread + * Thread to be blocked + * @return + * NULL + */ void uk_thread_block(struct uk_thread *thread); + +/* Wake a thread as long as it is not runnable + * @param thread + * Thread to be blocked + * @return + * NULL + */ void uk_thread_wake(struct uk_thread *thread); /** -- Gitee From 47a898e9673db259df2995b395177fb6bcc89e41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E6=B5=B7=E4=B8=B9?= Date: Wed, 8 Nov 2023 07:13:07 +0000 Subject: [PATCH 09/57] unikraft/.gitee: update .gitee/PULL_REQUEST_TEMPLATE.zh-CN.md. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 赵海丹 --- .gitee/PULL_REQUEST_TEMPLATE.zh-CN.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md b/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md index db303a29..459fa64b 100644 --- a/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md +++ b/.gitee/PULL_REQUEST_TEMPLATE.zh-CN.md @@ -1,6 +1,7 @@ ##### 修改原因:(目的、解决的问题等) ##### 修改内容:(整体或分文件描述修改内容) ##### 测试场景:(新增或改动可能影响的功能,对测试情况做简要说明。测试截图请贴在PR评论区) +##### Pingcode需求连接:(与PR标题中的需求ID对应,将连接地址贴在这里) ##### 以下内容非必须 ##### 相关PR:(若有需列明) -- Gitee From 44f31f95c679ed6b7e26a8f778bc4fe9278dcc9b Mon Sep 17 00:00:00 2001 From: shy Date: Tue, 17 Oct 2023 16:33:21 +0800 Subject: [PATCH 10/57] lib/posix-process: [upstream][bugfix]Cancel clearing tlsp to read TLS variables normally Signed-off-by: shy --- lib/posix-process/clone.c | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/posix-process/clone.c b/lib/posix-process/clone.c index eaaad70d..e2874047 100644 --- a/lib/posix-process/clone.c +++ b/lib/posix-process/clone.c @@ -449,7 +449,6 @@ static int _clone(struct clone_args *cl_args, size_t cl_args_len, * NOTE: If SETTLS is not set, we do not activate any TLS although * an Unikraft TLS was allocated. */ - child->tlsp = (flags & CLONE_SETTLS) ? cl_args->tls : 0x0; uk_pr_debug("Child is going to wake up with TLS pointer set to: %p (%s TLS)\n", (void *) child->tlsp, (child->tlsp != child->uktlsp) ? "custom" : "Unikraft"); -- Gitee From 15760cfc68ac8ff22b3765422a3ece093b4a8d39 Mon Sep 17 00:00:00 2001 From: Yifan Zhang Date: Wed, 8 Nov 2023 14:34:16 +0800 Subject: [PATCH 11/57] support/scripts: [upstream][doc]scripts for generating docs --- .gitignore | 1 + support/scripts/gen_api_doc.sh | 84 +++++++++++++++++++++ support/scripts/gen_api_doc_config.template | 21 ++++++ support/scripts/gen_unikraft_api_doc.sh | 26 +++++++ 4 files changed, 132 insertions(+) create mode 100644 support/scripts/gen_api_doc.sh create mode 100644 support/scripts/gen_api_doc_config.template create mode 100644 support/scripts/gen_unikraft_api_doc.sh diff --git a/.gitignore b/.gitignore index eb49ae48..88512ec7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /build +/doc/api /doc/build /doc/guides/_static /doc/guides/_templates diff --git a/support/scripts/gen_api_doc.sh b/support/scripts/gen_api_doc.sh new file mode 100644 index 00000000..39b78a61 --- /dev/null +++ b/support/scripts/gen_api_doc.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env bash +# +# Copyright Hangzhou Yingyi Technology Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +################################################################################ +# use rules +################################################################################ +# execute this script followed by the directory of the files +# e.g. bash gen_api_doc.sh /home/user/unikaft/lib/uktest + +# read input args +# directorys where files are indexed and read to generate docs +inputdir=$1 +outputdir=$2 + +# initializing build environment + +pwd=$(/usr/bin/pwd) +workspace=$pwd/workspace-$(date +%s) +mkdir -p $workspace + +_SELF=$( readlink -f "$0" ) +BASE=$( dirname "${_SELF}" ) + +# workspace is a temporary folder to store modified config files +workspace=$BASE/workspace-$(date +%s) +mkdir -p $workspace + + +pushd $workspace + +function isCmdExist() { + local cmd="$1" + + which "$cmd" >/dev/null 2>&1 + if [ $? -eq 0 ]; then + return 0 + fi + + return -1 +} + +# precheck +# check if doxygen exists +isCmdExist doxygen +ret=$? +if [ "$ret" -ne "0" ]; then + apt-get install doxygen + echo "doxygen installed" +else + echo "doxygen exists" +fi + +# check if directories exists +if [ ! -d $inputdir ];then + echo "input directory does not exist" + return -1 +fi +if [ ! -d $outputdir ];then + echo "input directory does not exist" + return -1 +fi + +# generate doxygen config file +cp $BASE/gen_api_doc_config.template $workspace/gen_api_doc_config +sed -i "s|{{INPUT_DIR}}|$inputdir|g" $workspace/gen_api_doc_config +sed -i "s|{{OUTPUT_DIR}}|$outputdir|g" $workspace/gen_api_doc_config + +# generate docs +doxygen $workspace/gen_api_doc_config + +# clean workspace +rm -rf $workspace diff --git a/support/scripts/gen_api_doc_config.template b/support/scripts/gen_api_doc_config.template new file mode 100644 index 00000000..7a2bd016 --- /dev/null +++ b/support/scripts/gen_api_doc_config.template @@ -0,0 +1,21 @@ +# Doxyfile 1.9.8 + +OUTPUT_DIRECTORY = {{OUTPUT_DIR}} +OPTIMIZE_OUTPUT_FOR_C = YES +EXTRACT_ALL = YES +HIDE_SCOPE_NAMES = YES +INPUT = {{INPUT_DIR}} +RECURSIVE = YES +STRIP_CODE_COMMENTS = NO +REFERENCES_LINK_SOURCE = NO +PDF_HYPERLINKS = NO +GENERATE_AUTOGEN_DEF = YES +CLASS_GRAPH = NO +COLLABORATION_GRAPH = NO +CALL_GRAPH = YES +CALLER_GRAPH = YES +GRAPHICAL_HIERARCHY = NO +GENERATE_HTML = YES +GENERATE_LATEX = NO +GENERATE_MAN = NO +HAVE_DOT = NO \ No newline at end of file diff --git a/support/scripts/gen_unikraft_api_doc.sh b/support/scripts/gen_unikraft_api_doc.sh new file mode 100644 index 00000000..06eda88b --- /dev/null +++ b/support/scripts/gen_unikraft_api_doc.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# +# Copyright Hangzhou Yingyi Technology Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +SHELL_FOLDER=$(cd "$(dirname "$0")";pwd) +UK_ROOT=$( dirname "${SHELL_FOLDER}/../../../" ) +pushd $UK_ROOT + +#generate outputdir to store api docs +mkdir -p doc/api +outputdir=$UK_ROOT/doc/api +inputdir=$UK_ROOT + +bash -e $SHELL_FOLDER/gen_api_doc.sh $inputdir $outputdir -- Gitee From eecff70c2f5e442d26d2dbae1380cfd3eabffc62 Mon Sep 17 00:00:00 2001 From: Yifan Zhang Date: Thu, 9 Nov 2023 11:03:46 +0800 Subject: [PATCH 12/57] support/scripts: [upstream][doc]append titles and comment for docs --- support/scripts/gen_api_doc_config.template | 2 ++ 1 file changed, 2 insertions(+) diff --git a/support/scripts/gen_api_doc_config.template b/support/scripts/gen_api_doc_config.template index 7a2bd016..80d8db52 100644 --- a/support/scripts/gen_api_doc_config.template +++ b/support/scripts/gen_api_doc_config.template @@ -1,5 +1,7 @@ # Doxyfile 1.9.8 +PROJECT_NAME = Unikraft +PROJECT_BRIEF = "Unikraft document" OUTPUT_DIRECTORY = {{OUTPUT_DIR}} OPTIMIZE_OUTPUT_FOR_C = YES EXTRACT_ALL = YES -- Gitee From b3ad79fe9e3bea87ca9c12b047a60a3993765117 Mon Sep 17 00:00:00 2001 From: Yifan Zhang Date: Thu, 9 Nov 2023 09:47:19 +0800 Subject: [PATCH 13/57] lib/sched: [upstream][test]tests for sched lib --- lib/uksched/Config.uk | 4 +- lib/uksched/Makefile.uk | 6 + lib/uksched/tests/test_sched.c | 250 +++++++++++++++++++++++++++++++++ 3 files changed, 259 insertions(+), 1 deletion(-) create mode 100644 lib/uksched/tests/test_sched.c diff --git a/lib/uksched/Config.uk b/lib/uksched/Config.uk index 8e0c90e6..d0b1751c 100644 --- a/lib/uksched/Config.uk +++ b/lib/uksched/Config.uk @@ -11,8 +11,10 @@ if LIBUKSCHED config LIBUKSCHED_TCB_INIT bool default n - config LIBUKSCHED_DEBUG bool "Enable debug messages" default n + config LIBUKSCHED_TEST + bool "Enable unit tests" + default n endif diff --git a/lib/uksched/Makefile.uk b/lib/uksched/Makefile.uk index 24eef7ab..9ebf7337 100644 --- a/lib/uksched/Makefile.uk +++ b/lib/uksched/Makefile.uk @@ -18,3 +18,9 @@ LIBUKSCHED_SRCS-y += $(LIBUKSCHED_BASE)/extra.ld UK_PROVIDED_SYSCALLS-$(CONFIG_LIBUKSCHED) += sched_yield-0 UK_PROVIDED_SYSCALLS-$(CONFIG_LIBUKSCHED) += sched_getaffinity-3 UK_PROVIDED_SYSCALLS-$(CONFIG_LIBUKSCHED) += sched_setaffinity-3 + +ifneq ($(filter y,$(CONFIG_LIBUKSCHED_TEST) $(CONFIG_LIBUKTEST_ALL)),) + +LIBUKSCHED_SRCS-y += $(LIBUKSCHED_BASE)/tests/test_sched.c + +endif diff --git a/lib/uksched/tests/test_sched.c b/lib/uksched/tests/test_sched.c new file mode 100644 index 00000000..9b390f7c --- /dev/null +++ b/lib/uksched/tests/test_sched.c @@ -0,0 +1,250 @@ +/* Copyright 2023 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +UK_TESTCASE(uksched, test_sched_register) +{ + /*初始化返回值*/ + int ret; + struct uk_alloc *a = uk_alloc_get_default(); + struct uk_sched *node1 = uk_schedcoop_create(a); + struct uk_sched *node2 = uk_schedcoop_create(a); + + ret = uk_sched_register(node1); + // when the list is empty + UK_TEST_EXPECT_SNUM_EQ(ret, 0); + UK_TEST_EXPECT_NULL(node1->next); + // register another node,node1 should have tails + ret = uk_sched_register(node2); + UK_TEST_EXPECT_NOT_NULL(node1->next); + UK_TEST_EXPECT_PTR_EQ(node1->next, node2); +} + + +UK_TESTCASE(uksched, test_sched_gc) +{ + /*初始化返回值*/ + int ret; + struct uk_alloc *a = uk_alloc_get_default(); + struct uk_sched *s = uk_schedcoop_create(a); + uintptr_t tlsp; + struct uk_thread *t, *tmp; + + tlsp = ukplat_tlsp_get(); + struct uk_thread *main_thread = uk_thread_create_bare( + s->a, 0x0, 0x0, tlsp, !(!tlsp), false, "init", NULL, NULL); + ret = uk_sched_thread_add(s, main_thread); + //mock: a thread runs and exit + uk_thread_set_exited(main_thread); + UK_TAILQ_INSERT_TAIL(&s->exited_threads, main_thread, queue); + main_thread->sched = NULL; + + ret = uk_sched_thread_gc(s); + + uk_sched_foreach_thread_safe(s, t, tmp) { + UK_TEST_EXPECT_SNUM_NQ(t, main_thread); + } + UK_TEST_EXPECT_SNUM_EQ(ret, 1); +} + + +UK_TESTCASE(uksched, test_thread_release) +{ + struct uk_alloc *a = uk_alloc_get_default(); + struct uk_sched *s = uk_schedcoop_create(a); + uintptr_t tlsp; + + tlsp = ukplat_tlsp_get(); + struct uk_thread *main_thread = uk_thread_create_bare( + s->a, 0x0, 0x0, tlsp, !(!tlsp), false, "init", NULL, NULL); + uk_thread_release(main_thread); + UK_TEST_EXPECT_SNUM_EQ(uk_thread_is_exited(main_thread), + UK_THREADF_EXITED); + UK_TEST_EXPECT_NULL(main_thread->_mem.stack_a); + UK_TEST_EXPECT_NULL(main_thread->_mem.uktls); + UK_TEST_EXPECT_NULL(main_thread->_mem.uktls_a); +} + +UK_TESTCASE(uksched, test_thread_block_no_timeout_then_wake) +{ + struct uk_alloc *a = uk_alloc_get_default(); + struct uk_sched *s = uk_schedcoop_create(a); + uintptr_t tlsp; + + tlsp = ukplat_tlsp_get(); + struct uk_thread *main_thread = uk_thread_create_bare( + s->a, 0x0, 0x0, tlsp, !(!tlsp), false, "init", NULL, NULL); + uk_thread_set_runnable(main_thread); + uk_thread_block(main_thread); + UK_TEST_EXPECT_SNUM_EQ(uk_thread_is_runnable(main_thread), 0); + uk_thread_wake(main_thread); + // TODO:add test for irq-safe operation。 + UK_TEST_EXPECT_SNUM_EQ(uk_thread_is_runnable(main_thread), 1); + UK_TEST_EXPECT_SNUM_EQ(main_thread->wakeup_time, 0LL); +} + +UK_TESTCASE(uksched, test_thread_set_exited) +{ + struct uk_alloc *a = uk_alloc_get_default(); + struct uk_sched *s = uk_schedcoop_create(a); + uintptr_t tlsp; + + tlsp = ukplat_tlsp_get(); + struct uk_thread *main_thread = uk_thread_create_bare( + s->a, 0x0, 0x0, tlsp, !(!tlsp), false, "init", NULL, NULL); + uk_thread_set_exited(main_thread); + UK_TEST_EXPECT_SNUM_EQ(uk_thread_is_exited(main_thread), + UK_THREADF_EXITED); +} + + +UK_TESTCASE(uksched, test_sched_thread_sleep) +{ + /*初始化返回值*/ + int ret; + struct uk_alloc *a = uk_alloc_get_default(); + struct uk_sched *s = uk_schedcoop_create(a); + uintptr_t tlsp; + + tlsp = ukplat_tlsp_get(); + + struct uk_thread *main_thread = uk_thread_create_bare( + s->a, 0x0, 0x0, tlsp, !(!tlsp), false, "init", NULL, NULL); + ret = uk_sched_thread_add(s, main_thread); + + time_t begin = ukplat_monotonic_clock(); + + uk_sched_thread_sleep(1000000000); + + time_t end = ukplat_monotonic_clock(); + + UK_TEST_EXPECT_SNUM_EQ((end-begin)/1000000000, 1); +} + +static __noreturn void idle_thread_fn(void *argp) +{} + +UK_TESTCASE(uksched, test_thread_init) +{ + struct uk_alloc *a = uk_alloc_get_default(); + struct schedcoop { + struct uk_sched sched; + struct uk_thread_list run_queue; + struct uk_thread_list sleep_queue; + + struct uk_thread idle; + __nsec idle_return_time; + }; + struct schedcoop *c = NULL; + int rc; + + uk_pr_info("Initializing cooperative scheduler\n"); + c = uk_zalloc(a, sizeof(struct schedcoop)); + + UK_TAILQ_INIT(&c->run_queue); + UK_TAILQ_INIT(&c->sleep_queue); + + /* Create idle thread */ + rc = uk_thread_init_fn1(&c->idle, idle_thread_fn, (void *)c, a, + STACK_SIZE, a, false, NULL, "idle", NULL, NULL); + UK_TEST_EXPECT_SNUM_EQ(rc, 0); +} + + +static __noreturn void entry_fn(void *arg) +{ +} + +UK_TESTCASE(uksched, test_uk_sched_thread_create) +{ + //these threads are created by sched + struct uk_thread *thread1, *thread0, *thread2; + //these threads are created by threads + struct uk_thread *thread3, *thread4, *thread5; + + + struct uk_alloc *a = uk_alloc_get_default(); + struct uk_sched *s = uk_schedcoop_create(a); + + thread0 = uk_sched_thread_create_fn0((s), + (entry_fn), + 0x0, 0, 0, ("Waiter"), ((void *)0), ((void *)0)); + thread1 = uk_sched_thread_create_fn1((s), + (entry_fn), (void *)(((void *)0)), + 0x0, 0, 0, ("Waiter"), ((void *)0), ((void *)0)); + thread2 = uk_sched_thread_create_fn2((s), + (entry_fn), (void *)(((void *)0)), (void *)(((void *)0)), + 0x0, 0, 0, ("Waiter"), ((void *)0), ((void *)0)); + + thread3 = uk_thread_create_fn0(s->a, + (entry_fn), + s->a_stack, 0x0, 0 ? NULL : s->a_uktls, 0, + ("Waiter"), ((void *)0), ((void *)0)); + thread4 = uk_thread_create_fn1(s->a, + (entry_fn), (void *)(((void *)0)), + s->a_stack, 0x0, 0 ? NULL : s->a_uktls, 0, + ("Waiter"), ((void *)0), ((void *)0)); + thread5 = uk_thread_create_fn2(s->a, + (entry_fn), (void *)(((void *)0)), (void *)(((void *)0)), + s->a_stack, 0x0, 0 ? NULL : s->a_uktls, 0, + ("Waiter"), ((void *)0), ((void *)0)); + + UK_TEST_EXPECT_NOT_NULL(thread0); + UK_TEST_EXPECT_NOT_NULL(thread1); + UK_TEST_EXPECT_NOT_NULL(thread2); + UK_TEST_EXPECT_NOT_NULL(thread3); + UK_TEST_EXPECT_NOT_NULL(thread4); + UK_TEST_EXPECT_NOT_NULL(thread5); +} + +UK_TESTCASE(uksched, test_uk_thread_create_and_init) +{ + struct uk_alloc *a = uk_alloc_get_default(); + struct uk_sched *s = uk_schedcoop_create(a); + struct uk_thread *t0 = uk_thread_create_container(a, s->a_stack, 0x0, + s->a_uktls, 0, ("Waiter"), ((void *)0), ((void *)0)); + struct uk_thread *t1 = uk_thread_create_container(a, s->a_stack, 0x0, + s->a_uktls, 0, ("Waiter"), ((void *)0), ((void *)0)); + struct uk_thread *t2 = uk_thread_create_container(a, s->a_stack, 0x0, + s->a_uktls, 0, ("Waiter"), ((void *)0), ((void *)0)); + struct uk_thread *t3 = uk_thread_create_container2(a, 1, 1, 0, 0, + ("Waiter"), ((void *)0), ((void *)0)); + UK_TEST_EXPECT_NOT_NULL(t0); + uk_thread_container_init_fn1(t1, entry_fn, (void *)(((void *)0))); + UK_TEST_EXPECT_SNUM_NQ(uk_thread_is_runnable(t1), 0); + uk_thread_container_init_fn0(t0, + entry_fn); + UK_TEST_EXPECT_SNUM_NQ(uk_thread_is_runnable(t0), 0); + uk_thread_container_init_fn2(t2, + entry_fn, (void *)(((void *)0)), (void *)(((void *)0))); + UK_TEST_EXPECT_SNUM_NQ(uk_thread_is_runnable(t2), 0); + uk_thread_container_init_bare(t3, 1); + UK_TEST_EXPECT_SNUM_NQ(uk_thread_is_runnable(t3), 0); +} + + +uk_testsuite_register(uksched, NULL); -- Gitee From 9ec9da55a84a81eb97fc50451b4352bc750f3a5e Mon Sep 17 00:00:00 2001 From: shy Date: Thu, 16 Nov 2023 17:46:10 +0800 Subject: [PATCH 14/57] support/kconfig: Provides the testconfig function for make Signed-off-by: shy --- Makefile | 16 +++++ support/kconfig/tests/conftest.py | 109 +++++++++++++++++++++++++++++- 2 files changed, 122 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index b936d11e..8c01cd46 100644 --- a/Makefile +++ b/Makefile @@ -1066,6 +1066,22 @@ endif .PHONY: defconfig savedefconfig +# parameter T: test case for 'make testconfig' +# Set T variable if not already done on the command line; +ifeq ("$(origin T)", "command line") +TEST_CONFIG_CASES := support/kconfig/tests/$(T) +else +TEST_CONFIG_CASES := support/kconfig/tests +endif + +testconfig: $(KCONFIG_DIR)/conf + CONFIG_="CONFIG_" python3 -B -m pytest $(CONFIG_UK_BASE)/$(TEST_CONFIG_CASES) \ + --BASE_PATH=$(CONFIG_UK_BASE) \ + -o cache_dir=$(abspath $(KCONFIG_DIR)/tests/.cache)\ + $(if $(findstring 1,$(KBUILD_VERBOSE)),--capture=no) + +.PHONY: defconfig savedefconfig silentoldconfig testconfig + # Regenerate $(KCONFIG_AUTOHEADER) whenever $(UK_CONFIG) changed $(KCONFIG_AUTOHEADER): $(UK_CONFIG_OUT) $(KCONFIG_DIR)/conf $(call verbose_cmd,GEN,config.h, \ diff --git a/support/kconfig/tests/conftest.py b/support/kconfig/tests/conftest.py index 0345ef6e..8b97ad7d 100644 --- a/support/kconfig/tests/conftest.py +++ b/support/kconfig/tests/conftest.py @@ -15,8 +15,8 @@ import shutil import subprocess import tempfile -CONF_PATH = os.path.abspath(os.path.join('scripts', 'kconfig', 'conf')) - +def pytest_addoption(parser): + parser.addoption("--BASE_PATH") class Conf: """Kconfig runner and result checker. @@ -34,6 +34,8 @@ class Conf: """ # the directory of the test being run self._test_dir = os.path.dirname(str(request.fspath)) + self.CONF_PATH = os.path.join(request.config.getoption("--BASE_PATH"),\ + 'build', 'kconfig', 'conf') # runners def _run_conf(self, mode, dot_config=None, out_file='.config', @@ -48,7 +50,7 @@ class Conf: extra_env: additional environments returncode: exit status of the Kconfig executable """ - command = [CONF_PATH, mode, 'Kconfig'] + command = [self.CONF_PATH, mode, 'Kconfig'] # Override 'srctree' environment to make the test as the top directory extra_env['srctree'] = self._test_dir @@ -62,6 +64,20 @@ class Conf: shutil.copyfile(os.path.join(self._test_dir, dot_config), os.path.join(temp_dir, '.config')) + if 'KCONFIG_EXTEND_AUTOCONFIG' in extra_env: + extend_config = extra_env['KCONFIG_EXTEND_AUTOCONFIG'] + extra_env['KCONFIG_EXTEND_AUTOCONFIG'] = \ + os.path.join(temp_dir, extra_env['KCONFIG_EXTEND_AUTOCONFIG']) + + if 'KCONFIG_EXTEND_AUTOHEADER' in extra_env: + extend_autoconf = extra_env['KCONFIG_EXTEND_AUTOHEADER'] + extra_env['KCONFIG_EXTEND_AUTOHEADER'] = \ + os.path.join(temp_dir, extra_env['KCONFIG_EXTEND_AUTOHEADER']) + + if 'KCONFIG_EXTEND_TEMPLATE' in extra_env: + extra_env['KCONFIG_EXTEND_TEMPLATE'] = \ + os.path.join(self._test_dir, extra_env['KCONFIG_EXTEND_TEMPLATE']) + ps = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, @@ -92,6 +108,28 @@ class Conf: else: self.config = None + if self.retcode == 0 and 'KCONFIG_EXTEND_CONFIG_ENABLE' in extra_env \ + and extra_env['KCONFIG_EXTEND_CONFIG_ENABLE']== 'y': + if 'KCONFIG_EXTEND_TEMPLATE' not in extra_env \ + or os.path.exists(extra_env['KCONFIG_EXTEND_TEMPLATE']): + if 'KCONFIG_EXTEND_AUTOCONFIG' in extra_env: + with open(extra_env['KCONFIG_EXTEND_AUTOCONFIG']) as f: + self.extend_config = f.read() + else: + extend_config='.extend.config' + with open(os.path.join(temp_dir, 'include/config/.extend.config')) as f: + self.extend_config = f.read() + if 'KCONFIG_EXTEND_AUTOHEADER' in extra_env: + with open(extra_env['KCONFIG_EXTEND_AUTOHEADER']) as f: + self.extend_autoconf = f.read() + else: + extend_autoconf='extend_autoconf.h' + with open(os.path.join(temp_dir, 'include/config/extend_autoconf.h')) as f: + self.extend_autoconf = f.read() + else: + self.extend_config = None + self.extend_autoconf = None + # Logging: # Pytest captures the following information by default. In failure # of tests, the captured log will be displayed. This will be useful to @@ -111,8 +149,40 @@ class Conf: print("[output for '{}']".format(out_file)) print(self.config) + if self.extend_config is not None: + print("[output for '{}']".format(extend_config)) + print(self.extend_config) + + if self.extend_autoconf is not None: + print("[output for '{}']".format(extend_autoconf)) + print(self.extend_autoconf) + return self.retcode + + def build_extend_config(self, mode,extend_config=None, extend_autoconf=None, + dot_config=None, in_keys=None): + extra_env = {'KCONFIG_EXTEND_NAME':'EXTEND', + 'KCONFIG_EXTEND_CONFIG_ENABLE':'y'} + if extend_config is not None: + extra_env['KCONFIG_EXTEND_AUTOCONFIG'] = extend_config + if extend_autoconf is not None: + extra_env['KCONFIG_EXTEND_AUTOHEADER'] = extend_autoconf + return self._run_conf(mode=mode, dot_config=dot_config, + interactive=True, in_keys=in_keys, + extra_env=extra_env) + + def render_extend_config(self, mode,extend_template=None, + dot_config=None, in_keys=None): + extra_env = {'KCONFIG_EXTEND_NAME':'EXTEND', + 'KCONFIG_EXTEND_CONFIG_ENABLE':'y' + } + if extend_template is not None: + extra_env['KCONFIG_EXTEND_TEMPLATE'] = extend_template + return self._run_conf(mode=mode, dot_config=dot_config, + interactive=True, in_keys=in_keys, + extra_env=extra_env) + def oldaskconfig(self, dot_config=None, in_keys=None): """Run oldaskconfig. @@ -285,6 +355,39 @@ class Conf: return self._matches('stderr', expected) + + def extend_config_contains(self, expected): + """Check if resulted extend configuration contains expected data. + + expected: file that contains the expected data + returncode: True if result contains the expected data, False otherwise + """ + return self._contains('extend_config', expected) + + def extend_config_matches(self, expected): + """Check if resulted extend configuration exactly matches expected data. + + expected: file that contains the expected data + returncode: True if result matches the expected data, False otherwise + """ + return self._matches('extend_config', expected) + + def extend_autoconf_contains(self, expected): + """Check if resulted extend configuration contains expected data. + + expected: file that contains the expected data + returncode: True if result contains the expected data, False otherwise + """ + return self._contains('extend_autoconf', expected) + + def extend_autoconf_matches(self, expected): + """Check if resulted extend configuration exactly matches expected data. + + expected: file that contains the expected data + returncode: True if result matches the expected data, False otherwise + """ + return self._matches('extend_autoconf', expected) + @pytest.fixture(scope="module") def conf(request): """Create a Conf instance and provide it to test functions.""" -- Gitee From 83a7001d61b25b06fd0c56757c96e465ce8fca18 Mon Sep 17 00:00:00 2001 From: shy Date: Thu, 16 Nov 2023 17:46:16 +0800 Subject: [PATCH 15/57] support/kconfig: [upstream][test]Provide tastconfig with a test case to test the extend file Signed-off-by: shy --- support/kconfig/tests/extend_config/Kconfig | 23 ++++++ .../kconfig/tests/extend_config/__init__.py | 73 +++++++++++++++++++ .../tests/extend_config/app_header_template | 16 ++++ .../extend_config/app_header_template_empty | 0 support/kconfig/tests/extend_config/config | 2 + ...expected_extend_error_path_template_stderr | 2 + .../expected_extend_notemplate_autoconf | 8 ++ .../expected_extend_notemplate_config | 6 ++ .../expected_extend_old_autoconf | 6 ++ .../extend_config/expected_extend_old_config | 6 ++ .../expected_extend_template_autoconf | 20 +++++ .../expected_extend_template_config | 6 ++ 12 files changed, 168 insertions(+) create mode 100644 support/kconfig/tests/extend_config/Kconfig create mode 100644 support/kconfig/tests/extend_config/__init__.py create mode 100644 support/kconfig/tests/extend_config/app_header_template create mode 100644 support/kconfig/tests/extend_config/app_header_template_empty create mode 100644 support/kconfig/tests/extend_config/config create mode 100644 support/kconfig/tests/extend_config/expected_extend_error_path_template_stderr create mode 100644 support/kconfig/tests/extend_config/expected_extend_notemplate_autoconf create mode 100644 support/kconfig/tests/extend_config/expected_extend_notemplate_config create mode 100644 support/kconfig/tests/extend_config/expected_extend_old_autoconf create mode 100644 support/kconfig/tests/extend_config/expected_extend_old_config create mode 100644 support/kconfig/tests/extend_config/expected_extend_template_autoconf create mode 100644 support/kconfig/tests/extend_config/expected_extend_template_config diff --git a/support/kconfig/tests/extend_config/Kconfig b/support/kconfig/tests/extend_config/Kconfig new file mode 100644 index 00000000..6728ae0f --- /dev/null +++ b/support/kconfig/tests/extend_config/Kconfig @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0 + +menu "Command selection" +config EXTEND_BUILDIN_COMMAND_KILL + bool "kill" + default y + help + This is a symbol,default y. + Provide to testconfig as a test case. + Verify that the generated extend file meets the requirements + Is not a true config.uk + configuration item + +config EXTEND_BUILDIN_COMMAND_PS + bool "ps" + default n + help + This is a symbol,default n. + Provide to testconfig as a test case. + Verify that the generated extend file meets the requirements + Is not a true config.uk + configuration item +endmenu diff --git a/support/kconfig/tests/extend_config/__init__.py b/support/kconfig/tests/extend_config/__init__.py new file mode 100644 index 00000000..0e0d1dbb --- /dev/null +++ b/support/kconfig/tests/extend_config/__init__.py @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: GPL-2.0 + +""" +测试:提供.config文件,测试oldconfig命令下生成extend文件是否符合预期 +""" +def test_extend_old(conf): + + assert conf.build_extend_config(mode='--oldconfig', dot_config='config') == 0 + assert conf.extend_config_contains('expected_extend_old_config') + assert conf.extend_autoconf_contains('expected_extend_old_autoconf') + +""" +测试:测试allyesconfig命令下生成extend文件是否符合预期 +""" +def test_extend_allyes(conf): + + assert conf.build_extend_config(mode='--allyesconfig') == 0 + assert conf.extend_config_contains('expected_extend_notemplate_config') + assert conf.extend_autoconf_contains('expected_extend_notemplate_autoconf') + +""" +测试:提供指定的.config与autoconf.h文件生成路径,将所需的文件按指定路径生成 +""" +def test_extend_buildpath(conf): + + assert conf.build_extend_config(mode='--allyesconfig', + extend_autoconf='.config', + extend_config='autoconf.h') == 0 + assert conf.extend_config_contains('expected_extend_notemplate_config') + assert conf.extend_autoconf_contains('expected_extend_notemplate_autoconf') + + +""" +测试:正确提供模版文件 +""" +def test_extend_template(conf): + + assert conf.render_extend_config(mode='--allyesconfig', + extend_template='app_header_template') == 0 + assert conf.extend_config_contains('expected_extend_template_config') + assert conf.extend_autoconf_contains('expected_extend_template_autoconf') + +""" +测试:提供模版文件,但模版文件内容为空 +""" +def test_extend_empty_template(conf): + + assert conf.render_extend_config(mode='--allyesconfig', + extend_template='app_header_template_empty') == 0 + assert conf.extend_config_contains('expected_extend_notemplate_config') + assert conf.extend_autoconf_contains('expected_extend_notemplate_autoconf') + +""" +测试:未提供模版文件 +""" +def test_extend_no_template(conf): + + assert conf.render_extend_config(mode='--allyesconfig') == 0 + assert conf.extend_config_contains('expected_extend_notemplate_config') + assert conf.extend_autoconf_contains('expected_extend_notemplate_autoconf') + +""" +测试:提供模版文件路径错误 +""" +def test_extend_error_path_template(conf): + + assert conf.render_extend_config(mode='--allyesconfig', + extend_template='error_path') == 0 + assert conf.stderr_contains('expected_extend_error_path_template_stderr') + + + + diff --git a/support/kconfig/tests/extend_config/app_header_template b/support/kconfig/tests/extend_config/app_header_template new file mode 100644 index 00000000..a918045d --- /dev/null +++ b/support/kconfig/tests/extend_config/app_header_template @@ -0,0 +1,16 @@ + +#undef CONFIG_%1$s +#define ENABLE_%1$s 0 +#define IF_%1$s(...) +#define IF_NOT_%1$s(...) __VA_ARGS__ + + + +#define ENABLE_%1$s 1 +#ifdef MAKE_SUID +# define IF_%1$s(...) __VA_ARGS__ "CONFIG_%1$s" +#else +# define IF_%1$s(...) __VA_ARGS__ +#endif + + diff --git a/support/kconfig/tests/extend_config/app_header_template_empty b/support/kconfig/tests/extend_config/app_header_template_empty new file mode 100644 index 00000000..e69de29b diff --git a/support/kconfig/tests/extend_config/config b/support/kconfig/tests/extend_config/config new file mode 100644 index 00000000..2ee521a0 --- /dev/null +++ b/support/kconfig/tests/extend_config/config @@ -0,0 +1,2 @@ +# CONFIG_EXTEND_BUILDIN_COMMAND_KILL is not set +# CONFIG_EXTEND_BUILDIN_COMMAND_PS is not set \ No newline at end of file diff --git a/support/kconfig/tests/extend_config/expected_extend_error_path_template_stderr b/support/kconfig/tests/extend_config/expected_extend_error_path_template_stderr new file mode 100644 index 00000000..24419e3d --- /dev/null +++ b/support/kconfig/tests/extend_config/expected_extend_error_path_template_stderr @@ -0,0 +1,2 @@ +Error while opening template file. +Please check your template file path diff --git a/support/kconfig/tests/extend_config/expected_extend_notemplate_autoconf b/support/kconfig/tests/extend_config/expected_extend_notemplate_autoconf new file mode 100644 index 00000000..61129cfc --- /dev/null +++ b/support/kconfig/tests/extend_config/expected_extend_notemplate_autoconf @@ -0,0 +1,8 @@ +/* + * + * Automatically generated file; DO NOT EDIT. + * Main menu + * + */ +#define CONFIG_BUILDIN_COMMAND_KILL 1 +#define CONFIG_BUILDIN_COMMAND_PS 1 \ No newline at end of file diff --git a/support/kconfig/tests/extend_config/expected_extend_notemplate_config b/support/kconfig/tests/extend_config/expected_extend_notemplate_config new file mode 100644 index 00000000..3150c209 --- /dev/null +++ b/support/kconfig/tests/extend_config/expected_extend_notemplate_config @@ -0,0 +1,6 @@ +# +# Automatically generated file; DO NOT EDIT. +# Main menu +# +CONFIG_BUILDIN_COMMAND_KILL=y +CONFIG_BUILDIN_COMMAND_PS=y diff --git a/support/kconfig/tests/extend_config/expected_extend_old_autoconf b/support/kconfig/tests/extend_config/expected_extend_old_autoconf new file mode 100644 index 00000000..a795fe54 --- /dev/null +++ b/support/kconfig/tests/extend_config/expected_extend_old_autoconf @@ -0,0 +1,6 @@ +/* + * + * Automatically generated file; DO NOT EDIT. + * Main menu + * + */ diff --git a/support/kconfig/tests/extend_config/expected_extend_old_config b/support/kconfig/tests/extend_config/expected_extend_old_config new file mode 100644 index 00000000..64fdc458 --- /dev/null +++ b/support/kconfig/tests/extend_config/expected_extend_old_config @@ -0,0 +1,6 @@ +# +# Automatically generated file; DO NOT EDIT. +# Main menu +# +# CONFIG_BUILDIN_COMMAND_KILL is not set +# CONFIG_BUILDIN_COMMAND_PS is not set diff --git a/support/kconfig/tests/extend_config/expected_extend_template_autoconf b/support/kconfig/tests/extend_config/expected_extend_template_autoconf new file mode 100644 index 00000000..c0708dcb --- /dev/null +++ b/support/kconfig/tests/extend_config/expected_extend_template_autoconf @@ -0,0 +1,20 @@ +/* + * + * Automatically generated file; DO NOT EDIT. + * Main menu + * + */ +#define CONFIG_BUILDIN_COMMAND_KILL 1 +#define ENABLE_BUILDIN_COMMAND_KILL 1 +#ifdef MAKE_SUID +# define IF_BUILDIN_COMMAND_KILL(...) __VA_ARGS__ "CONFIG_BUILDIN_COMMAND_KILL" +#else +# define IF_BUILDIN_COMMAND_KILL(...) __VA_ARGS__ +#endif +#define CONFIG_BUILDIN_COMMAND_PS 1 +#define ENABLE_BUILDIN_COMMAND_PS 1 +#ifdef MAKE_SUID +# define IF_BUILDIN_COMMAND_PS(...) __VA_ARGS__ "CONFIG_BUILDIN_COMMAND_PS" +#else +# define IF_BUILDIN_COMMAND_PS(...) __VA_ARGS__ +#endif \ No newline at end of file diff --git a/support/kconfig/tests/extend_config/expected_extend_template_config b/support/kconfig/tests/extend_config/expected_extend_template_config new file mode 100644 index 00000000..3150c209 --- /dev/null +++ b/support/kconfig/tests/extend_config/expected_extend_template_config @@ -0,0 +1,6 @@ +# +# Automatically generated file; DO NOT EDIT. +# Main menu +# +CONFIG_BUILDIN_COMMAND_KILL=y +CONFIG_BUILDIN_COMMAND_PS=y -- Gitee From 1c6572e6991b6c24740703e5c813902b80115f9a Mon Sep 17 00:00:00 2001 From: 1788594346 <13290132+wu-shifang@user.noreply.gitee.com> Date: Mon, 30 Oct 2023 11:47:04 +0800 Subject: [PATCH 16/57] build: support app config files Signed-off-by: 1788594346 <13290132+wu-shifang@user.noreply.gitee.com> --- support/kconfig/confdata.c | 399 ++++++++++++++++++++++++++++++++++++- support/kconfig/lkc.h | 41 ++++ support/kconfig/mconf.c | 9 +- 3 files changed, 446 insertions(+), 3 deletions(-) diff --git a/support/kconfig/confdata.c b/support/kconfig/confdata.c index 6006154d..eec159d7 100644 --- a/support/kconfig/confdata.c +++ b/support/kconfig/confdata.c @@ -233,6 +233,20 @@ static const char *conf_get_autoconfig_name(void) return name ? name : "include/config/auto.conf"; } +/* + * func: 获取拓展目录的config文件路径 + * param: void + * return: char *name 编译目录下Makefile文件中 + * KCONFIG_EXTEND_AUTOCONFIG宏 + * 若无则为"include/config/.extend.config" + */ +static const char *conf_get_extend_autoconfig_name(void) +{ + char *name = getenv("KCONFIG_EXTEND_AUTOCONFIG"); + + return name ? name : "include/config/.extend.config"; +} + char *conf_get_default_confname(void) { static char fullname[PATH_MAX+1]; @@ -701,6 +715,34 @@ header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) } +/* + * func: 在自动生成的头文件中写入时间宏 + * param: FILE *fp 写入的文件指针 + * const char *m_timestamp_format_c 模版中time宏名 + * return: void + */ +static void +header_print_time(FILE *fp, const char *m_timestamp_format_c) +{ + time_t now; + struct tm *build_time; + size_t ret; + + time(&now); + build_time = localtime(&now); + + char buf[strlen(m_timestamp_format_c) + + sizeof("\"YYYY-MM-DD HH:MM:SS \"\n") + TIMEZONE_LEN]; + + ret = strftime(buf, sizeof(buf), "\"%Y-%m-%d %H:%M:%S %Z\"\n", + build_time); + + if (ret == 0) + strftime(buf, sizeof(buf), "\"%Y-%m-%d %H:%M:%S\"\n", + build_time); + fprintf(fp, m_timestamp_format_c, buf); +} + static void header_print_comment(FILE *fp, const char *value, void *arg) { @@ -723,12 +765,116 @@ header_print_comment(FILE *fp, const char *value, void *arg) fprintf(fp, " */\n"); } +/* + * func: 写入自动生成头文件的注释格式 + * param: FILE *fp 需要写入的文件指针 + * const char *value 注释内容 + * void *arg 模板结构体指针 + * return: void + */ +static void +extend_header_print_comment(FILE *fp, const char *value, void *arg) +{ + header_print_comment(fp, value, NULL); + + /* 在拓展目录侧生成配置文件时添加时间宏 */ + const char *extend_dep = getenv("KCONFIG_EXTEND_CONFIG_ENABLE"); + + /* 判断拓展模块是否需额外生成头文件 */ + /* 判断模板中是否有time段 */ + if (extend_dep && (strcmp(extend_dep, "y") == 0) && + (((struct template *)arg)->m_timestamp_offset_c != -1)) + /* 在头文件第一行定义时间宏 */ + header_print_time(fp, ((struct template *)arg)->data + + ((struct template *)arg)->m_timestamp_offset_c); +} + +/* + * func: 在拓展目录下的自动生成头文件中写入配置内容: + * 过滤unikraft配置 + * 生成对应的宏定义逻辑 + * param: FILE *fp 自动生成头文件指针 + * struct symbol *sym 指向config结束生成的哈希表 + * const char *value 具体配置项的值'Y'("CONFIG_XXX=Y") + * void *arg 模板结构体指针 + * return: void + */ +static void +extend_header_print_symbol(FILE *fp, struct symbol *sym, + const char *value, void *arg) +{ + const char *suffix = ""; + const char *prefix = ""; + const char *temp_val = ""; + + /* 处理 CONFIG_XXX=n 场景 */ + if (((sym->type == S_BOOLEAN) || (sym->type == S_TRISTATE)) && + (*value == 'n')) { + /* 判断模板中是否有unset段,有则输出模板内容 */ + if (((struct template *)arg)->m_unset_offset_s != -1) + fprintf(fp, ((struct template *)arg)->data + + ((struct template *)arg)->m_unset_offset_s, + sym->name); + return; + } + + /* 处理 CONFIG_XXX=y / CONFIG_XXX= 场景 */ + /* 根据不同变量类型与变量的值作不同的转换 */ + switch (sym->type) { + /* 处理只有y/n逻辑的配置,简单输出1/0即可 */ + case S_BOOLEAN: + case S_TRISTATE: + switch (*value) { + case 'm': + suffix = "_MODULE"; + default: + /* 选项类型为bool,则CONFIG宏值为1 */ + /* 输出#define CONFIG_XXX 1*/ + temp_val = "1"; + break; + } + break; + /* 值如果为十六进制,值前缀加"=0x" */ + case S_HEX: + if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X')) + prefix = "0x"; + temp_val = (char *)value; + break; + /* 值如果为字符串或者整型,使用value即可 */ + case S_STRING: + case S_INT: + temp_val = (char *)value; + break; + default: + break; + } + /* 无论模板如何,拓展目录下都会输出一行默认宏 */ + /* #define CONFIG_XXX */ + fprintf(fp, "#define CONFIG_%s%s %s%s\n", sym->name, suffix, + prefix, temp_val); + /* 向app头文件中输出模板内容 */ + /* 判断模板中是否有set段 */ + if (((struct template *)arg)->m_set_offset_s != -1) + fprintf(fp, (const char *)((struct template *)arg)->data + + ((struct template *)arg)->m_set_offset_s, sym->name); +} + static struct conf_printer header_printer_cb = { .print_symbol = header_print_symbol, .print_comment = header_print_comment, }; +/* + * 给拓展目录下自动生成头文件写入配置的函数表 + * extend_header_print_symbol写入配置内容 + * extend_header_print_symbol写入注释 + */ +static struct conf_printer extend_header_printer_cb = { + .print_symbol = extend_header_print_symbol, + .print_comment = extend_header_print_comment, +}; + /* * Tristate printer * @@ -1071,13 +1217,170 @@ static int conf_touch_deps(void) return 0; } +/* + * func: 判断模板中单行文本是否为标识符 + * param: char *data 需判断的单行文本 + * return: enum TEMPLATE_MODE_IDENTIFIER 目前文件读取的状态 + */ +static inline int get_template_identifier(char *data) +{ + if (strcmp(data, "\n") == 0) + return MODULE_IDENTIFIER_TIMESTAMP; + else if (strcmp(data, "\n") == 0) + return MODULE_IDENTIFIER_TIMESTAMP_END; + else if (strcmp(data, "\n") == 0) + return MODULE_IDENTIFIER_SET; + else if (strcmp(data, "\n") == 0) + return MODULE_IDENTIFIER_SET_END; + else if (strcmp(data, "\n") == 0) + return MODULE_IDENTIFIER_UNSET; + else if (strcmp(data, "\n") == 0) + return MODULE_IDENTIFIER_UNSET_END; + return RAW_DATA; +} + +/* + * func: app的头文件模板数据初始化 + * 读取模板数据并放入结构体template_data中 + * param: FILE *fp 模板文件 + * struct template *template_data 模板数据结构体指针 + * return: 0 成功 + * 1 错误-文件不存在或者格式不符合要求 + * 文件格式(模块顺序不影响读取): + * + * ... + * + * + * ... + * + * + * ... + * + */ +static int +extend_template_init(FILE *fp, struct template *template_data) +{ + char line[EXTEND_TEMPLATE_FILE_LEN]; + int length; + /* in_module标识此模块是否处理完毕 */ + int in_module = 0; + /* offset存储已经处理的有效数据长度 */ + int offset = 0; + /* prev_identifier标识上一个处理的模块 */ + enum TEMPLATE_MODE_IDENTIFIER prev_identifier = RAW_DATA; + enum TEMPLATE_MODE_IDENTIFIER mode; + + /* 解析模板文件 */ + while (fgets(line, EXTEND_TEMPLATE_FILE_LEN, fp)) { + length = strlen(line); + mode = get_template_identifier(line); + switch (mode) { + case MODULE_IDENTIFIER_TIMESTAMP: + if ((in_module != 0) || + (template_data->m_timestamp_offset_c != -1)) + return 1; + in_module = 1; + prev_identifier = MODULE_IDENTIFIER_TIMESTAMP; + template_data->m_timestamp_offset_c = offset; + break; + case MODULE_IDENTIFIER_TIMESTAMP_END: + if ((in_module == 0) || + (prev_identifier != MODULE_IDENTIFIER_TIMESTAMP)) + return 1; + in_module = 0; + *(template_data->data + offset) = '\0'; + offset++; + break; + case MODULE_IDENTIFIER_SET: + if ((in_module != 0) || + (template_data->m_set_offset_s != -1)) + return 1; + in_module = 1; + prev_identifier = MODULE_IDENTIFIER_SET; + template_data->m_set_offset_s = offset; + break; + case MODULE_IDENTIFIER_SET_END: + if ((in_module == 0) || + (prev_identifier != MODULE_IDENTIFIER_SET)) + return 1; + in_module = 0; + *(template_data->data + offset) = '\0'; + offset++; + break; + case MODULE_IDENTIFIER_UNSET: + if ((in_module != 0) || + (template_data->m_unset_offset_s != -1)) + return 1; + in_module = 1; + prev_identifier = MODULE_IDENTIFIER_UNSET; + template_data->m_unset_offset_s = offset; + break; + case MODULE_IDENTIFIER_UNSET_END: + if ((in_module == 0) || + (prev_identifier != MODULE_IDENTIFIER_UNSET)) + return 1; + in_module = 0; + *(template_data->data + offset) = '\0'; + offset++; + break; + default: + if (in_module != 0) { + if (offset > EXTEND_TEMPLATE_FILE_MAX) { + /* 文件大小超512bytes报错 */ + return 1; + } + memcpy(template_data->data + offset, line, + length); + offset += length; + } + break; + } + } + + if (in_module != 0) { + fprintf(stderr, + "\ntemplate file misses termination identifier or\n" + "The last bit of the file is not a enter\n"); + return 1; + } + return 0; +} + +/* + * func: 创建并根据配置项更新:unikraft下的config文件 + * 自动生成的头文件 + * tristate.config文件 + * (可选)拓展目录下的config文件 + * param: int overwrite 本次操作是否为覆写 + * return: 0-成功 + * 1-失败 + */ int conf_write_autoconf(int overwrite) { struct symbol *sym; const char *name; const char *autoconf_name = conf_get_autoconfig_name(); - FILE *out, *tristate, *out_h; - int i; + const char *extend_autoconf_name = conf_get_extend_autoconfig_name(); + FILE *out, *tristate, *out_h, *out_extend_h, *out_extend; + FILE *template_fp; + struct template *template_data; + const char *extend_name, *extend_dep, *extend_template_name; + int i, extend_enable; + + /* KCONFIG_EXTEND_CONFIG_ENABLE=y则向拓展目录输出配置文件 */ + extend_dep = getenv("KCONFIG_EXTEND_CONFIG_ENABLE"); + if ((extend_dep) && (strcmp(extend_dep, "y") == 0)) { + extend_template_name = getenv("KCONFIG_EXTEND_TEMPLATE"); + extend_enable = 1; + extend_name = getenv("KCONFIG_EXTEND_NAME"); + if (extend_name == NULL) { + fprintf(stderr, + "\nError while getting extend name.\n" + "Please define KCONFIG_EXTEND_NAME\n"); + return 1; + } + } else + extend_enable = 0; if (!overwrite && is_present(autoconf_name)) return 0; @@ -1106,6 +1409,54 @@ int conf_write_autoconf(int overwrite) return 1; } + if (extend_enable) { + /* 给模板数据申请固定buffer */ + template_data = (struct template *) + malloc(sizeof(template_data)); + template_data->data = (char *)malloc(EXTEND_TEMPLATE_FILE_MAX); + /* 初始化模板数据偏移 */ + template_data->m_timestamp_offset_c = -1; + template_data->m_set_offset_s = -1; + template_data->m_unset_offset_s = -1; + if (extend_template_name) { + template_fp = fopen(extend_template_name, "rb"); + if (!template_fp) { + /* 不存在模板文件报错 */ + fprintf(stderr, + "\nError while opening template file.\n" + "Please check your template file path\n"); + goto err_handle_extend_file; + } else if (extend_template_init(template_fp, + template_data)) { + /* extend_template_init */ + /* 初始化模板数据template_data */ + fprintf(stderr, + "\nError while initializing template file.\n" + "Please check that the contents of your file conform to the format\n" + "and file size is less than 512 bytes\n"); + fclose(template_fp); + goto err_handle_extend_file; + } + fclose(template_fp); + } + out_extend_h = fopen(".extend.tmpconfig.h", "w"); + if (!out_extend_h) { + fprintf(stderr, + "\nError while creating auto-config head file.\n"); + goto err_handle_extend_file; + } + out_extend = fopen(".extend.tmpconfig", "w"); + if (!out_extend) { + fprintf(stderr, + "\nError while creating auto-config config file.\n"); + fclose(out_extend_h); + goto err_handle_extend_file; + } + conf_write_heading(out_extend_h, &extend_header_printer_cb, + (void *)template_data); + conf_write_heading(out_extend, &kconfig_printer_cb, NULL); + } + conf_write_heading(out, &kconfig_printer_cb, NULL); conf_write_heading(tristate, &tristate_printer_cb, NULL); @@ -1123,10 +1474,45 @@ int conf_write_autoconf(int overwrite) conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); conf_write_symbol(out_h, sym, &header_printer_cb, NULL); + + if (extend_enable) { + if (strstr(sym->name, extend_name)) { + /* 右移sys->name,去除名称 */ + sym->name += (strlen(extend_name) + 1); + conf_write_symbol(out_extend_h, sym, + &extend_header_printer_cb, + (void *)template_data); + conf_write_symbol(out_extend, sym, + &kconfig_printer_cb, + NULL); + /* 还原sys->name,不影响后续使用 */ + sym->name -= (strlen(extend_name) + 1); + } + } } + fclose(out); fclose(tristate); fclose(out_h); + if (extend_enable) { + /* 释放模板buffer */ + free(template_data->data); + free(template_data); + fclose(out_extend_h); + fclose(out_extend); + + name = getenv("KCONFIG_EXTEND_AUTOHEADER"); + if (!name) + name = "include/config/extend_autoconf.h"; + if (make_parent_dir(name)) + return 1; + if (rename(".extend.tmpconfig.h", name)) + return 1; + if (make_parent_dir(extend_autoconf_name)) + return 1; + if (rename(".extend.tmpconfig", extend_autoconf_name)) + return 1; + } name = getenv("KCONFIG_AUTOHEADER"); if (!name) @@ -1154,6 +1540,15 @@ int conf_write_autoconf(int overwrite) return 1; return 0; + + /* extend功能异常处理入口 */ +err_handle_extend_file: + free(template_data->data); + free(template_data); + fclose(out_h); + fclose(tristate); + fclose(out); + return 1; } static int sym_change_count; diff --git a/support/kconfig/lkc.h b/support/kconfig/lkc.h index 69d2c77a..2949f90a 100644 --- a/support/kconfig/lkc.h +++ b/support/kconfig/lkc.h @@ -49,6 +49,47 @@ int zconf_lineno(void); const char *zconf_curname(void); /* confdata.c */ +/* 拓展模板文件大小限制(byte) */ +#define EXTEND_TEMPLATE_FILE_MAX 512 +/* 拓展模板文件单行读取缓存长度 */ +#define EXTEND_TEMPLATE_FILE_LEN 80 +/* c库strftime输出附加空间大小(byte) */ +#define TIMEZONE_LEN 13 +/* + * TEMPLATE_MODE_IDENTIFIER为模板内容标识符 + * 拓展模板内容分为三部分:timestamp、set、unset + * timestamp,存储时间宏 + * set/unset,存储配置模板内容 + */ +enum TEMPLATE_MODE_IDENTIFIER { + RAW_DATA, + MODULE_IDENTIFIER_TIMESTAMP, + MODULE_IDENTIFIER_TIMESTAMP_END, + MODULE_IDENTIFIER_SET, + MODULE_IDENTIFIER_SET_END, + MODULE_IDENTIFIER_UNSET, + MODULE_IDENTIFIER_UNSET_END +}; +/* + * 拓展模板结构体template + * XXX_c为comment阶段调用(每个头文件只调用一次) + * XXX_s为symbol阶段调用(每行config调用一次) + * char *data 存储模板数据buffer + * int m_timestamp_offset_c 模板数据time宏名的偏移 + * timestamp为时间宏名称 + * int m_set_offset_s 模板数据set内容的偏移 + * set为自动生成头文件中 + * 需要配置选项的宏定义格式 + * int m_unset_offset_s 模板数据unset内容的偏移 + * unset为自动生成头文件中 + * 不需要配置选项的宏定义格式 + */ +struct template { + char *data; + int m_timestamp_offset_c; + int m_set_offset_s; + int m_unset_offset_s; +}; const char *conf_get_configname(void); char *conf_get_default_confname(void); void sym_set_change_count(int count); diff --git a/support/kconfig/mconf.c b/support/kconfig/mconf.c index 53c4a62b..accb1bf1 100644 --- a/support/kconfig/mconf.c +++ b/support/kconfig/mconf.c @@ -973,7 +973,14 @@ static int handle_exit(void) "\n\n"); return 1; } - conf_write_autoconf(0); + /* 新增对自动生成文件的失败逻辑判断 */ + /* 文件不存在/模板文件内容规范错误触发 */ + if (conf_write_autoconf(0) != 0) { + fprintf(stderr, + "\nError while Generating auto-config files.\n" + "Please make sure that your template file is valid\n\n"); + return 1; + } /* fall through */ case -1: if (!silent) -- Gitee From 23e5d345caf7b04dd7372b6ffb2d2073af26b366 Mon Sep 17 00:00:00 2001 From: 1788594346 Date: Sat, 18 Nov 2023 16:18:03 +0800 Subject: [PATCH 17/57] build: test cases for template config files Signed-off-by: 1788594346 --- Makefile | 9 +- support/kconfig/Makefile | 4 + support/kconfig/Makefile.br | 7 +- .../c_tests/extend_config/confdata_test.c | 1234 +++++++++++++++++ .../c_tests/extend_config/confdata_test.h | 38 + .../extend_config/def_test_files/config.test | 45 + .../extend_config/def_test_files/defconfig | 10 + .../def_test_files/expected_config_not_set | 12 + .../expected_err_info_err_format | 4 + .../expected_err_info_err_template_path | 3 + .../def_test_files/expected_err_info_no_name | 3 + .../expected_extend_config_def_conf_path | 9 + .../expected_extend_config_incomplete_format | 9 + .../expected_extend_config_no_template_path | 9 + .../def_test_files/expected_extend_config_set | 9 + .../expected_extend_header_def_conf_path | 39 + .../expected_extend_header_incomplete_format | 38 + .../expected_extend_header_no_template_path | 10 + .../def_test_files/expected_extend_header_set | 39 + .../def_test_files/expected_header_not_set | 14 + .../def_test_files/src_template_file_oversize | 61 + .../src_template_incomplete_format | 16 + .../src_template_miss_end_identifier | 18 + .../src_template_miss_start_identifier | 18 + .../src_template_mutidefined_identifier | 23 + .../extend_config/def_test_files/std_template | 19 + 26 files changed, 1696 insertions(+), 4 deletions(-) create mode 100644 support/kconfig/c_tests/extend_config/confdata_test.c create mode 100644 support/kconfig/c_tests/extend_config/confdata_test.h create mode 100644 support/kconfig/c_tests/extend_config/def_test_files/config.test create mode 100644 support/kconfig/c_tests/extend_config/def_test_files/defconfig create mode 100644 support/kconfig/c_tests/extend_config/def_test_files/expected_config_not_set create mode 100644 support/kconfig/c_tests/extend_config/def_test_files/expected_err_info_err_format create mode 100644 support/kconfig/c_tests/extend_config/def_test_files/expected_err_info_err_template_path create mode 100644 support/kconfig/c_tests/extend_config/def_test_files/expected_err_info_no_name create mode 100644 support/kconfig/c_tests/extend_config/def_test_files/expected_extend_config_def_conf_path create mode 100644 support/kconfig/c_tests/extend_config/def_test_files/expected_extend_config_incomplete_format create mode 100644 support/kconfig/c_tests/extend_config/def_test_files/expected_extend_config_no_template_path create mode 100644 support/kconfig/c_tests/extend_config/def_test_files/expected_extend_config_set create mode 100644 support/kconfig/c_tests/extend_config/def_test_files/expected_extend_header_def_conf_path create mode 100644 support/kconfig/c_tests/extend_config/def_test_files/expected_extend_header_incomplete_format create mode 100644 support/kconfig/c_tests/extend_config/def_test_files/expected_extend_header_no_template_path create mode 100644 support/kconfig/c_tests/extend_config/def_test_files/expected_extend_header_set create mode 100644 support/kconfig/c_tests/extend_config/def_test_files/expected_header_not_set create mode 100644 support/kconfig/c_tests/extend_config/def_test_files/src_template_file_oversize create mode 100644 support/kconfig/c_tests/extend_config/def_test_files/src_template_incomplete_format create mode 100644 support/kconfig/c_tests/extend_config/def_test_files/src_template_miss_end_identifier create mode 100644 support/kconfig/c_tests/extend_config/def_test_files/src_template_miss_start_identifier create mode 100644 support/kconfig/c_tests/extend_config/def_test_files/src_template_mutidefined_identifier create mode 100644 support/kconfig/c_tests/extend_config/def_test_files/std_template diff --git a/Makefile b/Makefile index 8c01cd46..613f0d94 100644 --- a/Makefile +++ b/Makefile @@ -877,7 +877,7 @@ HOSTCFLAGS = $(CFLAGS_FOR_BUILD) export HOSTCFLAGS ifeq ($(HOSTOSENV),Linux) -KCONFIG_TOOLS = conf mconf gconf nconf qconf +KCONFIG_TOOLS = conf mconf gconf nconf qconf fixdep confdata_test KCONFIG_TOOLS := $(addprefix $(KCONFIG_DIR)/,$(KCONFIG_TOOLS)) $(KCONFIG_TOOLS): @@ -1080,7 +1080,12 @@ testconfig: $(KCONFIG_DIR)/conf -o cache_dir=$(abspath $(KCONFIG_DIR)/tests/.cache)\ $(if $(findstring 1,$(KBUILD_VERBOSE)),--capture=no) -.PHONY: defconfig savedefconfig silentoldconfig testconfig +testextendconfig: $(KCONFIG_DIR)/confdata_test + @$(CP) -r $(CONFIG)/c_tests/extend_config/def_test_files $(KCONFIG_DIR)/def_test_files + @$(COMMON_CONFIG_ENV) $< $(CONFIG_CONFIG_IN) + @$(COMMON_CONFIG_ENV) $(SCRIPTS_DIR)/configupdate $(UK_CONFIG) $(UK_CONFIG_OUT) + +.PHONY: defconfig savedefconfig silentoldconfig testconfig testextendconfig # Regenerate $(KCONFIG_AUTOHEADER) whenever $(UK_CONFIG) changed $(KCONFIG_AUTOHEADER): $(UK_CONFIG_OUT) $(KCONFIG_DIR)/conf diff --git a/support/kconfig/Makefile b/support/kconfig/Makefile index 7b532c5f..d036c51f 100644 --- a/support/kconfig/Makefile +++ b/support/kconfig/Makefile @@ -156,6 +156,10 @@ conf-objs := conf.o $(common-objs) hostprogs-y += nconf nconf-objs := nconf.o nconf.gui.o $(common-objs) +#confdata_test: Used for test confdata.c +hostprogs-y += confdata_test +confdata_test-objs := confdata_test.o $(common-objs) + HOSTLDLIBS_nconf = $(shell . $(obj)/nconf-cfg && echo $$libs) HOSTCFLAGS_nconf.o = $(shell . $(obj)/nconf-cfg && echo $$cflags) HOSTCFLAGS_nconf.gui.o = $(shell . $(obj)/nconf-cfg && echo $$cflags) diff --git a/support/kconfig/Makefile.br b/support/kconfig/Makefile.br index 4057390f..f6e87472 100644 --- a/support/kconfig/Makefile.br +++ b/support/kconfig/Makefile.br @@ -83,10 +83,13 @@ $(call multi_depend,$(host-cmulti), , -objs) quiet_cmd_host-cobjs = HOSTCC $@ cmd_host-cobjs = $(HOSTCC) $(hostc_flags) $(HOSTCFLAGS_$(@F))\ -c -o $@ $< -$(filter-out %.tab.o, $(filter-out %.lex.o,$(host-cobjs))): $(obj)/%.o:\ +$(filter-out $(obj)/confdata_test.o, $(filter-out %.tab.o, $(filter-out %.lex.o,$(host-cobjs)))): $(obj)/%.o:\ $(src)/%.c $(obj)/fixdep FORCE $(call if_changed_dep,host-cobjs) +$(filter $(obj)/confdata_test.o, $(host-cobjs)): $(obj)/%.o: $(src)/c_tests/extend_config/%.c $(obj)/fixdep FORCE + $(call if_changed_dep,host-cobjs) + $(filter %.lex.o,$(host-cobjs)): $(obj)/%.lex.o: $(obj)/%.lex.c $(obj)/fixdep FORCE $(call if_changed_dep,host-cobjs) @@ -133,7 +136,7 @@ $(host-cxxshobjs): $(obj)/%.o: $(src)/%.c $(obj)/fixdep FORCE clean: $(Q)rm -f $(addprefix $(obj)/,$(clean-files)) distclean: clean - $(Q)rm -f $(addprefix $(obj)/,$(lxdialog) $(conf-objs) $(mconf-objs) $(kxgettext-objs) \ + $(Q)rm -f $(addprefix $(obj)/,$(lxdialog) $(conf-objs) $(confdata_test-objs) $(mconf-objs) $(kxgettext-objs) \ $(hostprogs-y) $(qconf-cxxobjs) $(qconf-objs) $(gconf-objs) \ mconf .depend) diff --git a/support/kconfig/c_tests/extend_config/confdata_test.c b/support/kconfig/c_tests/extend_config/confdata_test.c new file mode 100644 index 00000000..c8da4cb7 --- /dev/null +++ b/support/kconfig/c_tests/extend_config/confdata_test.c @@ -0,0 +1,1234 @@ +/* Copyright 2023 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "confdata_test.h" +#include "../../lkc.h" + +static struct property local_prompt = {0}; + +/* 测试函数指针 */ +typedef int (*test_func)(void); + +/* 文件对比函数,相同返回0,不一致返回1 */ +static int compare_file(FILE *dest_fp, FILE *src_fp) +{ + int dest_word, src_word; + + /* 比较每个字符asic码 */ + while ((dest_word = fgetc(dest_fp)) != EOF && + (src_word = fgetc(src_fp)) != EOF) { + if (dest_word != src_word) + return 1; + } + + /* 如果目标文件读取结束,对比文件需要再读一位 */ + if (dest_word == EOF) + src_word = fgetc(src_fp); + + /* 目标文件与对比文件同时结束才算对比成功 */ + if ((dest_word == EOF) && (src_word == EOF)) + return 0; + else + return 1; +} + +/* 判断dest中是否完全包含src内容,是返回0,否则返回1 */ +/* 要求读取的文件大小不大于1024bytes,否则返回-1 */ +static int is_file_contains(FILE *dest_fp, FILE *src_fp) +{ + char dest_line[FILE_LEN]; + char src_line[FILE_LEN]; + char dest_data[FILE_MAX]; + char src_data[FILE_MAX]; + int length; + int offset = 0; + + /* 读取dest文件 */ + while (fgets(dest_line, FILE_LEN, dest_fp) != NULL) { + length = strlen(dest_line); + if (offset + length > FILE_MAX) { + ERR_PRINT(); + return -1; + } + memcpy(dest_data + offset, dest_line, length); + offset += length; + } + *(dest_data + offset++) = '\0'; + + /* 读取src文件 */ + offset = 0; + while (fgets(src_line, FILE_LEN, src_fp) != NULL) { + length = strlen(src_line); + if (offset + length > FILE_MAX) { + ERR_PRINT(); + return -1; + } + memcpy(src_data + offset, src_line, length); + offset += length; + } + *(src_data + offset++) = '\0'; + + /* 判断是否包含 */ + if (strstr(dest_data, src_data) != NULL) + return 0; + else + return 1; +} + +/* 删除文件夹里所有目录及文件,删除成功返回0,否则返回1 */ +static int remove_dir(const char *dest_dir) +{ + char cur_dir[] = "."; + char up_dir[] = ".."; + char dir_name[REMOVE_DIR_PATH_MAX + 1]; + DIR *dirp; + struct dirent *dp; + struct stat dir_stat; + + /* 参数传递进来的目录不存在,直接返回 */ + if (access(dest_dir, F_OK) != 0) { + ERR_PRINT(); + return 0; + } + + /* 获取目录属性失败,直接返回 */ + if (stat(dest_dir, &dir_stat) < 0) { + ERR_PRINT(); + return 1; + } + + if (S_ISREG(dir_stat.st_mode)) + /* 普通文件直接删除 */ + remove(dest_dir); + else if (S_ISDIR(dir_stat.st_mode)) { + /* 目录文件,递归删除目录中内容 */ + dirp = opendir(dest_dir); + while ((dp = readdir(dirp)) != NULL) { + if ((strcmp(cur_dir, dp->d_name)) == 0 || + (strcmp(up_dir, dp->d_name)) == 0) + /* 忽略 . 和 .. */ + continue; + sprintf(dir_name, "%s/%s", dest_dir, dp->d_name); + /* 递归删除 */ + remove_dir(dir_name); + } + closedir(dirp); + /* 删除空目录 */ + rmdir(dest_dir); + } else { + fprintf(stderr, "unknown file type!"); + ERR_PRINT(); + } + + return 0; +} + +/* 测试场景初始化 */ +/* 成功返回0,否则返回1 */ +static int test_case_init(void) +{ + rootmenu.prompt = &local_prompt; + + const char *defconfig_file = "kconfig/def_test_files/defconfig"; + const char *config_file = "kconfig/def_test_files/config.test"; + + /* 解析config文件 */ + conf_parse(config_file); + + /* 读取默认配置 */ + if (conf_read(defconfig_file)) { + ERR_PRINT(); + return 1; + } + + /* 设置默认配置 */ + conf_set_all_new_symbols(def_default); + + /* 写入全局环境变量 */ + if (conf_write(NULL)) { + ERR_PRINT(); + return 1; + } + rootmenu.prompt->text = "test"; +} + +/* 测试用例c_test_extend_not_set */ +static int test_case_extend_not_set(void) +{ + FILE *expeced_config_fp, *expeced_header_fp; + FILE *src_config_fp, *src_header_fp; + int ret = 1; + + printf("test :c_test_extend_not_set->begin!\n"); + /* 1 用例依赖环境初始化 */ + ret = mkdir("c_test_extend_not_set", FOLDER_PERMMISION); + if (ret != 0) { + ERR_PRINT(); + return 1; + } + ret = 1; + setenv("KCONFIG_EXTEND_CONFIG_ENABLE", "n", 1); + setenv("KCONFIG_AUTOCONFIG", "c_test_extend_not_set/auto.conf", 1); + setenv("KCONFIG_AUTOHEADER", "c_test_extend_not_set/_config.h", 1); + setenv("KCONFIG_TRISTATE", "c_test_extend_not_set/tristate.config", 1); + + /* 2 调用conf_write_autoconf,执行用例 */ + ret = conf_write_autoconf(0); + if (ret != 0) { + /* 执行出错,打印错误位置,恢复环境 */ + ERR_PRINT(); + goto err_reset_env; + } + ret = 1; + + /* 3 判断输出文件是否符合预期 */ + /* 3.1 读取头文件与配置文件 */ + expeced_config_fp = + fopen("kconfig/def_test_files/expected_config_not_set", "r"); + if (expeced_config_fp == NULL) { + ERR_PRINT(); + goto err_reset_env; + } + + expeced_header_fp = + fopen("kconfig/def_test_files/expected_header_not_set", "r"); + if (expeced_header_fp == NULL) { + ERR_PRINT(); + goto err_handle_expeced_header_file; + } + + src_config_fp = fopen("c_test_extend_not_set/auto.conf", "r"); + if (src_config_fp == NULL) { + ERR_PRINT(); + goto err_handle_src_config_file; + } + + src_header_fp = fopen("c_test_extend_not_set/_config.h", "r"); + if (src_header_fp == NULL) { + ERR_PRINT(); + goto err_handle_src_header_file; + } + + /* 3.2 将生成的配置文件与预期结果作比较 */ + ret = compare_file(expeced_config_fp, src_config_fp); + if (ret != 0) { + ERR_PRINT(); + goto err_reset_all; + } + ret = 1; + + ret = compare_file(expeced_header_fp, src_header_fp); + if (ret != 0) { + ERR_PRINT(); + goto err_reset_all; + } + fclose(expeced_header_fp); + fclose(src_header_fp); + fclose(expeced_config_fp); + fclose(src_config_fp); + + /* 4 用例执行完成,恢复环境 */ + unsetenv("KCONFIG_EXTEND_CONFIG_ENABLE"); + unsetenv("KCONFIG_AUTOCONFIG"); + unsetenv("KCONFIG_AUTOHEADER"); + unsetenv("KCONFIG_TRISTATE"); + remove_dir("c_test_extend_not_set"); + + printf("------c_test_extend_not_set->success!\n"); + return 0; + + /* 5 错误处理入口 */ +err_reset_all: + fclose(src_header_fp); +err_handle_src_header_file: + fclose(src_config_fp); +err_handle_src_config_file: + fclose(expeced_header_fp); +err_handle_expeced_header_file: + fclose(expeced_config_fp); +err_reset_env: + unsetenv("KCONFIG_EXTEND_CONFIG_ENABLE"); + unsetenv("KCONFIG_AUTOCONFIG"); + unsetenv("KCONFIG_AUTOHEADER"); + unsetenv("KCONFIG_TRISTATE"); + remove_dir("c_test_extend_not_set"); + + printf("------c_test_extend_not_set->fail!!\n"); + return 1; +} + +/* 测试用例c_test_extend_set */ +static int test_case_extend_set(void) +{ + FILE *expeced_config_fp, *expeced_header_fp; + FILE *src_config_fp, *src_header_fp; + int ret = 1; + + printf("test :c_test_extend_set->begin!\n"); + /* 1 用例依赖环境初始化 */ + ret = mkdir("c_test_extend_set", FOLDER_PERMMISION); + if (ret != 0) { + ERR_PRINT(); + return 1; + } + ret = 1; + setenv("KCONFIG_EXTEND_CONFIG_ENABLE", "y", 1); + setenv("KCONFIG_AUTOCONFIG", "c_test_extend_set/auto.conf", 1); + setenv("KCONFIG_AUTOHEADER", "c_test_extend_set/_config.h", 1); + setenv("KCONFIG_TRISTATE", "c_test_extend_set/tristate.config", 1); + setenv("KCONFIG_EXTEND_NAME", "EXTENDTEST", 1); + setenv("KCONFIG_EXTEND_TEMPLATE", "kconfig/def_test_files/std_template", + 1); + setenv("KCONFIG_EXTEND_AUTOCONFIG", + "c_test_extend_set/.extend.config", 1); + setenv("KCONFIG_EXTEND_AUTOHEADER", "c_test_extend_set/autoconf.h", 1); + + /* 2 调用conf_write_autoconf,执行用例 */ + ret = conf_write_autoconf(0); + if (ret != 0) { + /* 执行出错,打印错误位置,恢复环境 */ + ERR_PRINT(); + goto err_reset_env; + } + ret = 1; + + /* 3 判断输出文件是否符合预期 */ + /* 3.1 读取头文件与配置文件 */ + expeced_config_fp = + fopen("kconfig/def_test_files/expected_extend_config_set", + "r"); + if (expeced_config_fp == NULL) { + ERR_PRINT(); + goto err_reset_env; + } + + expeced_header_fp = + fopen("kconfig/def_test_files/expected_extend_header_set", + "r"); + if (expeced_header_fp == NULL) { + ERR_PRINT(); + goto err_handle_expeced_header_file; + } + + src_config_fp = fopen("c_test_extend_set/.extend.config", "r"); + if (src_config_fp == NULL) { + ERR_PRINT(); + goto err_handle_src_config_file; + } + + src_header_fp = fopen("c_test_extend_set/autoconf.h", "r"); + if (src_header_fp == NULL) { + ERR_PRINT(); + goto err_handle_src_header_file; + } + + /* 3.2 将生成的配置文件与预期结果作比较 */ + ret = compare_file(expeced_config_fp, src_config_fp); + if (ret != 0) { + ERR_PRINT(); + goto err_reset_all; + } + ret = 1; + + ret = compare_file(expeced_header_fp, src_header_fp); + if (ret != 0) { + ERR_PRINT(); + goto err_reset_all; + } + fclose(expeced_header_fp); + fclose(src_header_fp); + fclose(expeced_config_fp); + fclose(src_config_fp); + + /* 4 用例执行完成,恢复环境 */ + unsetenv("KCONFIG_EXTEND_CONFIG_ENABLE"); + unsetenv("KCONFIG_AUTOCONFIG"); + unsetenv("KCONFIG_AUTOHEADER"); + unsetenv("KCONFIG_TRISTATE"); + unsetenv("KCONFIG_EXTEND_NAME"); + unsetenv("KCONFIG_EXTEND_TEMPLATE"); + unsetenv("KCONFIG_EXTEND_AUTOCONFIG"); + unsetenv("KCONFIG_EXTEND_AUTOHEADER"); + remove_dir("c_test_extend_set"); + + printf("------c_test_extend_set->success!\n"); + return 0; + + /* 5 错误处理入口 */ +err_reset_all: + fclose(src_header_fp); +err_handle_src_header_file: + fclose(src_config_fp); +err_handle_src_config_file: + fclose(expeced_header_fp); +err_handle_expeced_header_file: + fclose(expeced_config_fp); +err_reset_env: + unsetenv("KCONFIG_EXTEND_CONFIG_ENABLE"); + unsetenv("KCONFIG_AUTOCONFIG"); + unsetenv("KCONFIG_AUTOHEADER"); + unsetenv("KCONFIG_TRISTATE"); + unsetenv("KCONFIG_EXTEND_NAME"); + unsetenv("KCONFIG_EXTEND_TEMPLATE"); + unsetenv("KCONFIG_EXTEND_AUTOCONFIG"); + unsetenv("KCONFIG_EXTEND_AUTOHEADER"); + remove_dir("c_test_extend_set"); + + printf("------c_test_extend_set->fail!!\n"); + return 1; +} + +/* 测试用例c_test_extend_no_template_path */ +static int test_case_extend_no_template_path(void) +{ + FILE *expeced_config_fp, *expeced_header_fp; + FILE *src_config_fp, *src_header_fp; + int ret = 1; + + printf("test :c_test_extend_no_template_path->begin!\n"); + /* 1 用例依赖环境初始化 */ + ret = mkdir("c_test_extend_no_template_path", FOLDER_PERMMISION); + if (ret != 0) { + ERR_PRINT(); + return 1; + } + ret = 1; + setenv("KCONFIG_EXTEND_CONFIG_ENABLE", "y", 1); + setenv("KCONFIG_AUTOCONFIG", + "c_test_extend_no_template_path/auto.conf", 1); + setenv("KCONFIG_AUTOHEADER", + "c_test_extend_no_template_path/_config.h", 1); + setenv("KCONFIG_TRISTATE", + "c_test_extend_no_template_path/tristate.config", 1); + setenv("KCONFIG_EXTEND_NAME", "EXTENDTEST", 1); + setenv("KCONFIG_EXTEND_AUTOCONFIG", + "c_test_extend_no_template_path/.extend.config", 1); + setenv("KCONFIG_EXTEND_AUTOHEADER", + "c_test_extend_no_template_path/autoconf.h", 1); + + /* 2 调用conf_write_autoconf,执行用例 */ + ret = conf_write_autoconf(0); + if (ret != 0) { + /* 执行出错,打印错误位置,恢复环境 */ + ERR_PRINT(); + goto err_reset_env; + } + ret = 1; + + /* 3 判断输出文件是否符合预期 */ + /* 3.1 读取头文件与配置文件 */ + expeced_config_fp = + fopen("kconfig/def_test_files/expected_extend_config_no_template_path", + "r"); + if (expeced_config_fp == NULL) { + ERR_PRINT(); + goto err_reset_env; + } + + expeced_header_fp = + fopen("kconfig/def_test_files/expected_extend_header_no_template_path", + "r"); + if (expeced_header_fp == NULL) { + ERR_PRINT(); + goto err_handle_expeced_header_file; + } + + src_config_fp = fopen("c_test_extend_no_template_path/.extend.config", + "r"); + if (src_config_fp == NULL) { + ERR_PRINT(); + goto err_handle_src_config_file; + } + + src_header_fp = fopen("c_test_extend_no_template_path/autoconf.h", "r"); + if (src_header_fp == NULL) { + ERR_PRINT(); + goto err_handle_src_header_file; + } + + /* 3.2 将生成的配置文件与预期结果作比较 */ + ret = compare_file(expeced_config_fp, src_config_fp); + if (ret != 0) { + ERR_PRINT(); + goto err_reset_all; + } + ret = 1; + + ret = compare_file(expeced_header_fp, src_header_fp); + if (ret != 0) { + ERR_PRINT(); + goto err_reset_all; + } + fclose(expeced_config_fp); + fclose(src_config_fp); + fclose(expeced_header_fp); + fclose(src_header_fp); + + /* 4 用例执行完成,恢复环境 */ + unsetenv("KCONFIG_EXTEND_CONFIG_ENABLE"); + unsetenv("KCONFIG_AUTOCONFIG"); + unsetenv("KCONFIG_AUTOHEADER"); + unsetenv("KCONFIG_TRISTATE"); + unsetenv("KCONFIG_EXTEND_NAME"); + unsetenv("KCONFIG_EXTEND_AUTOCONFIG"); + unsetenv("KCONFIG_EXTEND_AUTOHEADER"); + remove_dir("c_test_extend_no_template_path"); + + printf("------c_test_extend_no_template_path->success!\n"); + return 0; + + /* 5 错误处理入口 */ +err_reset_all: + fclose(src_header_fp); +err_handle_src_header_file: + fclose(src_config_fp); +err_handle_src_config_file: + fclose(expeced_header_fp); +err_handle_expeced_header_file: + fclose(expeced_config_fp); +err_reset_env: + unsetenv("KCONFIG_EXTEND_CONFIG_ENABLE"); + unsetenv("KCONFIG_AUTOCONFIG"); + unsetenv("KCONFIG_AUTOHEADER"); + unsetenv("KCONFIG_TRISTATE"); + unsetenv("KCONFIG_EXTEND_NAME"); + unsetenv("KCONFIG_EXTEND_AUTOCONFIG"); + unsetenv("KCONFIG_EXTEND_AUTOHEADER"); + remove_dir("c_test_extend_no_template_path"); + + printf("------c_test_extend_no_template_path->fail!!\n"); + return 1; +} + +/* 测试用例c_test_extend_err_template_path */ +static int test_case_extend_err_template_path(void) +{ + FILE *expeced_err_fp, *src_err_fp; + int ret = 1; + + printf("test :c_test_extend_err_template_path->begin!\n"); + /* 1 用例依赖环境初始化 */ + ret = mkdir("c_test_extend_err_template_path", FOLDER_PERMMISION); + if (ret != 0) { + ERR_PRINT(); + /* 恢复stderr重定向 */ + fclose(stderr); + freopen("/dev/tty", "w", stderr); + return 1; + } + /* 将stderr重定向至文件中 */ + if (freopen("c_test_extend_err_template_path/err.log", "w", stderr) == + NULL) { + ERR_PRINT(); + return 1; + } + setenv("KCONFIG_EXTEND_CONFIG_ENABLE", "y", 1); + setenv("KCONFIG_AUTOCONFIG", + "c_test_extend_err_template_path/auto.conf", 1); + setenv("KCONFIG_AUTOHEADER", + "c_test_extend_err_template_path/_config.h", 1); + setenv("KCONFIG_TRISTATE", + "c_test_extend_err_template_path/tristate.config", 1); + setenv("KCONFIG_EXTEND_NAME", "EXTENDTEST", 1); + setenv("KCONFIG_EXTEND_TEMPLATE", "std_template", 1); + setenv("KCONFIG_EXTEND_AUTOCONFIG", + "c_test_extend_err_template_path/.extend.config", 1); + setenv("KCONFIG_EXTEND_AUTOHEADER", + "c_test_extend_err_template_path/autoconf.h", 1); + + /* 2 调用conf_write_autoconf,执行用例 */ + ret = conf_write_autoconf(0); + fclose(stderr); + freopen("/dev/tty", "w", stderr); + if (ret == 0) { + /* 执行正确不符合预期 */ + ERR_PRINT(); + goto err_reset_env; + } + + /* 3 判断输出文件是否符合预期 */ + /* 3.1 读取错误日志 */ + expeced_err_fp = fopen( + "kconfig/def_test_files/expected_err_info_err_template_path", + "r"); + if (expeced_err_fp == NULL) { + ERR_PRINT(); + goto err_reset_env; + } + + src_err_fp = fopen("c_test_extend_err_template_path/err.log", "r"); + if (src_err_fp == NULL) { + ERR_PRINT(); + goto err_handle_src_err_file; + } + + /* 3.2 检测err输出是否包含预期错误 */ + ret = is_file_contains(src_err_fp, expeced_err_fp); + if (ret == 1) { + ERR_PRINT(); + goto err_reset_all; + } else if (ret == -1) { + /* err文本大于512bytes限制单独报错 */ + ERR_PRINT(); + goto err_reset_all; + } + fclose(src_err_fp); + fclose(expeced_err_fp); + + /* 4 用例执行完成,恢复环境 */ + unsetenv("KCONFIG_EXTEND_CONFIG_ENABLE"); + unsetenv("KCONFIG_AUTOCONFIG"); + unsetenv("KCONFIG_AUTOHEADER"); + unsetenv("KCONFIG_TRISTATE"); + unsetenv("KCONFIG_EXTEND_NAME"); + unsetenv("KCONFIG_EXTEND_TEMPLATE"); + unsetenv("KCONFIG_EXTEND_AUTOCONFIG"); + unsetenv("KCONFIG_EXTEND_AUTOHEADER"); + remove_dir("c_test_extend_err_template_path"); + + printf("------c_test_extend_err_template_path->success!\n"); + return 0; + + /* 5 错误处理入口 */ +err_reset_all: + fclose(src_err_fp); +err_handle_src_err_file: + fclose(expeced_err_fp); +err_reset_env: + unsetenv("KCONFIG_EXTEND_CONFIG_ENABLE"); + unsetenv("KCONFIG_AUTOCONFIG"); + unsetenv("KCONFIG_AUTOHEADER"); + unsetenv("KCONFIG_TRISTATE"); + unsetenv("KCONFIG_EXTEND_NAME"); + unsetenv("KCONFIG_EXTEND_TEMPLATE"); + unsetenv("KCONFIG_EXTEND_AUTOCONFIG"); + unsetenv("KCONFIG_EXTEND_AUTOHEADER"); + remove_dir("c_test_extend_err_template_path"); + + printf("------c_test_extend_err_template_path->fail!!\n"); + return 1; +} + +/* 测试用例c_test_extend_def_conf_path */ +static int test_case_extend_def_conf_path(void) +{ + FILE *expeced_config_fp, *expeced_header_fp; + FILE *src_config_fp, *src_header_fp; + int ret = 1; + + printf("test :c_test_extend_def_conf_path->begin!\n"); + /* 1 用例依赖环境初始化 */ + ret = mkdir("c_test_extend_def_conf_path", FOLDER_PERMMISION); + if (ret != 0) { + ERR_PRINT(); + return 1; + } + ret = 1; + setenv("KCONFIG_EXTEND_CONFIG_ENABLE", "y", 1); + setenv("KCONFIG_AUTOCONFIG", + "c_test_extend_def_conf_path/auto.conf", 1); + setenv("KCONFIG_AUTOHEADER", + "c_test_extend_def_conf_path/_config.h", 1); + setenv("KCONFIG_TRISTATE", + "c_test_extend_def_conf_path/tristate.config", 1); + setenv("KCONFIG_EXTEND_NAME", "EXTENDTEST", 1); + setenv("KCONFIG_EXTEND_TEMPLATE", "kconfig/def_test_files/std_template", + 1); + + /* 2 调用conf_write_autoconf,执行用例 */ + ret = conf_write_autoconf(0); + if (ret != 0) { + /* 执行出错,打印错误位置,恢复环境 */ + ERR_PRINT(); + goto err_reset_env; + } + ret = 1; + + /* 3 判断输出文件是否符合预期 */ + /* 3.1 读取头文件与配置文件 */ + expeced_config_fp = fopen( + "kconfig/def_test_files/expected_extend_config_def_conf_path", + "r"); + if (expeced_config_fp == NULL) { + ERR_PRINT(); + goto err_reset_env; + } + + expeced_header_fp = fopen( + "kconfig/def_test_files/expected_extend_header_def_conf_path", + "r"); + if (expeced_header_fp == NULL) { + ERR_PRINT(); + goto err_handle_expeced_header_file; + } + + src_config_fp = fopen("include/config/.extend.config", "r"); + if (src_config_fp == NULL) { + ERR_PRINT(); + goto err_handle_src_config_file; + } + + src_header_fp = fopen("include/config/extend_autoconf.h", "r"); + if (src_header_fp == NULL) { + ERR_PRINT(); + goto err_handle_src_header_file; + } + + /* 3.2 将生成的配置文件与预期结果作比较 */ + ret = compare_file(expeced_config_fp, src_config_fp); + if (ret != 0) { + ERR_PRINT(); + goto err_reset_all; + } + ret = 1; + + ret = compare_file(expeced_header_fp, src_header_fp); + if (ret != 0) { + ERR_PRINT(); + goto err_reset_all; + } + fclose(expeced_config_fp); + fclose(src_config_fp); + fclose(expeced_header_fp); + fclose(src_header_fp); + + /* 4 用例执行完成,恢复环境 */ + unsetenv("KCONFIG_EXTEND_CONFIG_ENABLE"); + unsetenv("KCONFIG_AUTOCONFIG"); + unsetenv("KCONFIG_AUTOHEADER"); + unsetenv("KCONFIG_TRISTATE"); + unsetenv("KCONFIG_EXTEND_NAME"); + unsetenv("KCONFIG_EXTEND_TEMPLATE"); + remove_dir("c_test_extend_def_conf_path"); + + printf("------c_test_extend_def_conf_path->success!\n"); + return 0; + + /* 5 错误处理入口 */ +err_reset_all: + fclose(src_header_fp); +err_handle_src_header_file: + fclose(src_config_fp); +err_handle_src_config_file: + fclose(expeced_header_fp); +err_handle_expeced_header_file: + fclose(expeced_config_fp); +err_reset_env: + unsetenv("KCONFIG_EXTEND_CONFIG_ENABLE"); + unsetenv("KCONFIG_AUTOCONFIG"); + unsetenv("KCONFIG_AUTOHEADER"); + unsetenv("KCONFIG_TRISTATE"); + unsetenv("KCONFIG_EXTEND_NAME"); + unsetenv("KCONFIG_EXTEND_TEMPLATE"); + remove_dir("c_test_extend_def_conf_path"); + + printf("------c_test_extend_def_conf_path->fail!!\n"); + return 1; +} + +/* 测试用例c_test_extend_no_name */ +static int test_case_extend_no_name(void) +{ + FILE *expeced_err_fp, *src_err_fp; + int ret = 0; + + printf("test :c_test_extend_no_name->begin!\n"); + /* 1 用例依赖环境初始化 */ + ret = mkdir("c_test_extend_no_name", FOLDER_PERMMISION); + if (ret != 0) { + ERR_PRINT(); + /* 恢复stderr重定向 */ + fclose(stderr); + freopen("/dev/tty", "w", stderr); + return 1; + } + /* 将stderr重定向至文件中 */ + if (freopen("c_test_extend_no_name/err.log", "w", stderr) == NULL) { + ERR_PRINT(); + return 1; + } + setenv("KCONFIG_EXTEND_CONFIG_ENABLE", "y", 1); + + /* 2 调用conf_write_autoconf,执行用例 */ + ret = conf_write_autoconf(0); + fclose(stderr); + freopen("/dev/tty", "w", stderr); + if (ret == 0) { + /* 执行正确不符合预期 */ + ERR_PRINT(); + goto err_reset_env; + } + + /* 3 判断输出文件是否符合预期 */ + /* 3.1 读取错误日志 */ + expeced_err_fp = fopen( + "kconfig/def_test_files/expected_err_info_no_name", + "r"); + if (expeced_err_fp == NULL) { + ERR_PRINT(); + goto err_reset_env; + } + + src_err_fp = fopen("c_test_extend_no_name/err.log", "r"); + if (src_err_fp == NULL) { + ERR_PRINT(); + goto err_handle_src_err_file; + } + + /* 3.2 检测err输出是否包含预期错误 */ + ret = is_file_contains(src_err_fp, expeced_err_fp); + if (ret == 1) { + ERR_PRINT(); + goto err_reset_all; + } else if (ret == -1) { + ERR_PRINT(); + goto err_reset_all; + } + fclose(src_err_fp); + fclose(expeced_err_fp); + + /* 4 用例执行完成,恢复环境 */ + unsetenv("KCONFIG_EXTEND_CONFIG_ENABLE"); + remove_dir("c_test_extend_no_name"); + + printf("------c_test_extend_no_name->success!\n"); + return 0; + + /* 5 错误处理入口 */ +err_reset_all: + fclose(src_err_fp); +err_handle_src_err_file: + fclose(expeced_err_fp); +err_reset_env: + unsetenv("KCONFIG_EXTEND_CONFIG_ENABLE"); + remove_dir("c_test_extend_no_name"); + + printf("------c_test_extend_no_name->fail!!\n"); + return 1; +} + +/* 测试用例c_test_extend_err_format */ +static int test_case_extend_err_format(void) +{ + FILE *expeced_err_fp, *src_err_fp; + int ret = 1; + + printf("test :c_test_extend_err_format->begin!\n"); + /* 1 用例依赖环境初始化 */ + ret = mkdir("c_test_extend_err_format", FOLDER_PERMMISION); + if (ret != 0) { + ERR_PRINT(); + /* 恢复stderr重定向 */ + fclose(stderr); + freopen("/dev/tty", "w", stderr); + return 1; + } + /* 将stderr重定向至文件中 */ + if (freopen("c_test_extend_err_format/miss_start_identifier_err.log", + "w", stderr) == NULL) { + ERR_PRINT(); + return 1; + } + setenv("KCONFIG_EXTEND_CONFIG_ENABLE", "y", 1); + setenv("KCONFIG_AUTOCONFIG", "c_test_extend_err_format/auto.conf", 1); + setenv("KCONFIG_AUTOHEADER", "c_test_extend_err_format/_config.h", 1); + setenv("KCONFIG_TRISTATE", + "c_test_extend_err_format/tristate.config", 1); + setenv("KCONFIG_EXTEND_NAME", "EXTENDTEST", 1); + setenv("KCONFIG_EXTEND_TEMPLATE", + "kconfig/def_test_files/src_template_miss_start_identifier", 1); + setenv("KCONFIG_EXTEND_AUTOCONFIG", + "c_test_extend_err_format/.extend.config", 1); + setenv("KCONFIG_EXTEND_AUTOHEADER", + "c_test_extend_err_format/autoconf.h", 1); + + /* 2 调用conf_write_autoconf,执行用例 */ + /* 2.1 模板数据格式缺失头标识符 */ + ret = conf_write_autoconf(0); + if (ret == 0) { + /* 执行正确不符合预期 */ + fclose(stderr); + freopen("/dev/tty", "w", stderr); + ERR_PRINT(); + goto err_reset_env; + } + + /* 2.2 模板数据格式缺失尾标识符 */ + setenv("KCONFIG_EXTEND_TEMPLATE", + "kconfig/def_test_files/src_template_miss_end_identifier", 1); + if (freopen("c_test_extend_err_format/miss_end_identifier_err.log", "w", + stderr) == NULL) { + ERR_PRINT(); + return 1; + } + ret = conf_write_autoconf(0); + if (ret == 0) { + /* 执行正确不符合预期 */ + fclose(stderr); + freopen("/dev/tty", "w", stderr); + ERR_PRINT(); + goto err_reset_env; + } + + /* 2.3 模板数据同一组标识符重复出现 */ + setenv("KCONFIG_EXTEND_TEMPLATE", + "kconfig/def_test_files/src_template_mutidefined_identifier", 1); + if (freopen("c_test_extend_err_format/mutidefined_identifier_err.log", + "w", stderr) == NULL) { + ERR_PRINT(); + return 1; + } + ret = conf_write_autoconf(0); + if (ret == 0) { + /* 执行正确不符合预期 */ + fclose(stderr); + freopen("/dev/tty", "w", stderr); + ERR_PRINT(); + goto err_reset_env; + } + + /* 2.4 模板有效数据大小超过512bytes */ + setenv("KCONFIG_EXTEND_TEMPLATE", + "kconfig/def_test_files/src_template_file_oversize", 1); + if (freopen("c_test_extend_err_format/file_oversize_err.log", + "w", stderr) == NULL) { + ERR_PRINT(); + return 1; + } + ret = conf_write_autoconf(0); + if (ret == 0) { + /* 执行正确不符合预期 */ + fclose(stderr); + freopen("/dev/tty", "w", stderr); + ERR_PRINT(); + goto err_reset_env; + } + fclose(stderr); + freopen("/dev/tty", "w", stderr); + + /* 3 判断输出文件是否符合预期 */ + /* 读取错误日志并比较 */ + /* 3.1 模板数据格式缺失头标识符 */ + expeced_err_fp = fopen( + "kconfig/def_test_files/expected_err_info_err_format", + "r"); + if (expeced_err_fp == NULL) { + ERR_PRINT(); + goto err_reset_env; + } + + src_err_fp = fopen( + "c_test_extend_err_format/miss_start_identifier_err.log", + "r"); + if (src_err_fp == NULL) { + ERR_PRINT(); + goto err_handle_src_err_file; + } + + ret = is_file_contains(src_err_fp, expeced_err_fp); + if (ret != 0) { + ERR_PRINT(); + goto err_reset_all; + } + + fclose(src_err_fp); + fclose(expeced_err_fp); + + /* 3.2 模板数据格式缺失尾标识符 */ + expeced_err_fp = fopen( + "kconfig/def_test_files/expected_err_info_err_format", + "r"); + if (expeced_err_fp == NULL) { + ERR_PRINT(); + goto err_reset_env; + } + + src_err_fp = fopen( + "c_test_extend_err_format/miss_end_identifier_err.log", + "r"); + if (src_err_fp == NULL) { + ERR_PRINT(); + goto err_handle_src_err_file; + } + + ret = is_file_contains(src_err_fp, expeced_err_fp); + if (ret != 0) { + ERR_PRINT(); + goto err_reset_all; + } + + fclose(src_err_fp); + fclose(expeced_err_fp); + + /* 3.3 模板数据同一组标识符重复出现 */ + expeced_err_fp = fopen( + "kconfig/def_test_files/expected_err_info_err_format", + "r"); + if (expeced_err_fp == NULL) { + ERR_PRINT(); + goto err_reset_env; + } + + src_err_fp = fopen( + "c_test_extend_err_format/mutidefined_identifier_err.log", + "r"); + if (src_err_fp == NULL) { + ERR_PRINT(); + goto err_handle_src_err_file; + } + + ret = is_file_contains(src_err_fp, expeced_err_fp); + if (ret != 0) { + ERR_PRINT(); + goto err_reset_all; + } + + fclose(src_err_fp); + fclose(expeced_err_fp); + + /* 3.4 模板有效数据大小超过512bytes */ + expeced_err_fp = fopen( + "kconfig/def_test_files/expected_err_info_err_format", + "r"); + if (expeced_err_fp == NULL) { + ERR_PRINT(); + goto err_reset_env; + } + + src_err_fp = fopen("c_test_extend_err_format/file_oversize_err.log", + "r"); + if (src_err_fp == NULL) { + ERR_PRINT(); + goto err_handle_src_err_file; + } + + ret = is_file_contains(src_err_fp, expeced_err_fp); + if (ret != 0) { + ERR_PRINT(); + goto err_reset_all; + } + fclose(src_err_fp); + fclose(expeced_err_fp); + + /* 4 用例执行完成,恢复环境 */ + unsetenv("KCONFIG_EXTEND_CONFIG_ENABLE"); + unsetenv("KCONFIG_AUTOCONFIG"); + unsetenv("KCONFIG_AUTOHEADER"); + unsetenv("KCONFIG_TRISTATE"); + unsetenv("KCONFIG_EXTEND_NAME"); + unsetenv("KCONFIG_EXTEND_TEMPLATE"); + unsetenv("KCONFIG_EXTEND_AUTOCONFIG"); + unsetenv("KCONFIG_EXTEND_AUTOHEADER"); + remove_dir("c_test_extend_err_format"); + + printf("------c_test_extend_err_format->success!\n"); + return 0; + + /* 5 错误处理入口 */ +err_reset_all: + fclose(src_err_fp); +err_handle_src_err_file: + fclose(expeced_err_fp); +err_reset_env: + unsetenv("KCONFIG_EXTEND_CONFIG_ENABLE"); + unsetenv("KCONFIG_AUTOCONFIG"); + unsetenv("KCONFIG_AUTOHEADER"); + unsetenv("KCONFIG_TRISTATE"); + unsetenv("KCONFIG_EXTEND_NAME"); + unsetenv("KCONFIG_EXTEND_TEMPLATE"); + unsetenv("KCONFIG_EXTEND_AUTOCONFIG"); + unsetenv("KCONFIG_EXTEND_AUTOHEADER"); + remove_dir("c_test_extend_err_format"); + + printf("------c_test_extend_err_format->fail!!\n"); + return 1; +} + +/* 测试用例c_test_extend_incomplete_format */ +static int test_case_extend_incomplete_format(void) +{ + FILE *expeced_config_fp, *expeced_header_fp; + FILE *src_config_fp, *src_header_fp; + int ret = 1; + + printf("test :c_test_extend_incomplete_format->begin!\n"); + /* 1 用例依赖环境初始化 */ + ret = mkdir("c_test_extend_incomplete_format", FOLDER_PERMMISION); + if (ret != 0) { + ERR_PRINT(); + return 1; + } + ret = 1; + setenv("KCONFIG_EXTEND_CONFIG_ENABLE", "y", 1); + setenv("KCONFIG_AUTOCONFIG", + "c_test_extend_incomplete_format/auto.conf", 1); + setenv("KCONFIG_AUTOHEADER", + "c_test_extend_incomplete_format/_config.h", 1); + setenv("KCONFIG_TRISTATE", + "c_test_extend_incomplete_format/tristate.config", 1); + setenv("KCONFIG_EXTEND_NAME", "EXTENDTEST", 1); + setenv("KCONFIG_EXTEND_TEMPLATE", + "kconfig/def_test_files/src_template_incomplete_format", 1); + setenv("KCONFIG_EXTEND_AUTOCONFIG", + "c_test_extend_incomplete_format/.extend.config", 1); + setenv("KCONFIG_EXTEND_AUTOHEADER", + "c_test_extend_incomplete_format/autoconf.h", 1); + + /* 2 调用conf_write_autoconf,执行用例 */ + ret = conf_write_autoconf(0); + if (ret != 0) { + /* 执行出错,打印错误位置,恢复环境 */ + ERR_PRINT(); + goto err_reset_env; + } + ret = 1; + + /* 3 判断输出文件是否符合预期 */ + /* 3.1 读取头文件与配置文件 */ + expeced_config_fp = + fopen( + "kconfig/def_test_files/expected_extend_config_incomplete_format", + "r"); + if (expeced_config_fp == NULL) { + ERR_PRINT(); + goto err_reset_env; + } + + expeced_header_fp = + fopen( + "kconfig/def_test_files/expected_extend_header_incomplete_format", + "r"); + if (expeced_header_fp == NULL) { + ERR_PRINT(); + goto err_handle_expeced_header_file; + } + + src_config_fp = fopen("c_test_extend_incomplete_format/.extend.config", + "r"); + if (src_config_fp == NULL) { + ERR_PRINT(); + goto err_handle_src_config_file; + } + + src_header_fp = fopen("c_test_extend_incomplete_format/autoconf.h", + "r"); + if (src_header_fp == NULL) { + ERR_PRINT(); + goto err_handle_src_header_file; + } + + /* 3.2 将生成的配置文件与预期结果作比较 */ + ret = compare_file(expeced_config_fp, src_config_fp); + if (ret != 0) { + ERR_PRINT(); + goto err_reset_all; + } + ret = 1; + + ret = compare_file(expeced_header_fp, src_header_fp); + if (ret != 0) { + ERR_PRINT(); + goto err_reset_all; + } + fclose(expeced_config_fp); + fclose(expeced_header_fp); + fclose(src_config_fp); + fclose(src_header_fp); + + /* 4 用例执行完成,恢复环境 */ + unsetenv("KCONFIG_EXTEND_CONFIG_ENABLE"); + unsetenv("KCONFIG_AUTOCONFIG"); + unsetenv("KCONFIG_AUTOHEADER"); + unsetenv("KCONFIG_TRISTATE"); + unsetenv("KCONFIG_EXTEND_NAME"); + unsetenv("KCONFIG_EXTEND_TEMPLATE"); + unsetenv("KCONFIG_EXTEND_AUTOCONFIG"); + unsetenv("KCONFIG_EXTEND_AUTOHEADER"); + remove_dir("c_test_extend_incomplete_format"); + + printf("------c_test_extend_incomplete_format->success!\n"); + return 0; + + /* 5 错误处理入口 */ +err_reset_all: + fclose(src_header_fp); +err_handle_src_header_file: + fclose(src_config_fp); +err_handle_src_config_file: + fclose(expeced_header_fp); +err_handle_expeced_header_file: + fclose(expeced_config_fp); +err_reset_env: + unsetenv("KCONFIG_EXTEND_CONFIG_ENABLE"); + unsetenv("KCONFIG_AUTOCONFIG"); + unsetenv("KCONFIG_AUTOHEADER"); + unsetenv("KCONFIG_TRISTATE"); + unsetenv("KCONFIG_EXTEND_NAME"); + unsetenv("KCONFIG_EXTEND_TEMPLATE"); + unsetenv("KCONFIG_EXTEND_AUTOCONFIG"); + unsetenv("KCONFIG_EXTEND_AUTOHEADER"); + remove_dir("c_test_extend_incomplete_format"); + + printf("------c_test_extend_incomplete_format->fail!!\n"); + return 1; +} + +/* c白盒测试主函数 */ +int main(void) +{ + /* 测试函数数组 */ + test_func test_case_table[] = {test_case_extend_not_set, + test_case_extend_set, + test_case_extend_no_template_path, + test_case_extend_err_template_path, + test_case_extend_def_conf_path, + test_case_extend_no_name, + test_case_extend_err_format, + test_case_extend_incomplete_format}; + int test_case_num = sizeof(test_case_table) / sizeof(test_func); + int test_case_suc_num = 0; + int test_case_fail_num = 0; + + printf("\n---C test begin---\n"); + /* 初始化测试场景 */ + test_case_init(); + + /* 轮询调用每个测试函数 */ + for (int i = 0; i < test_case_num; i++) { + if (test_case_table[i]() != 0) + test_case_fail_num++; + else + test_case_suc_num++; + } + printf("-success test cases:%d\n-fail test cases:%d\n", + test_case_suc_num, test_case_fail_num); + printf("---C test end---\n"); + + /* 恢复环境 */ + remove("../.config"); + + if (test_case_fail_num != 0) + return 1; + else + return 0; +} diff --git a/support/kconfig/c_tests/extend_config/confdata_test.h b/support/kconfig/c_tests/extend_config/confdata_test.h new file mode 100644 index 00000000..5a19a4a5 --- /dev/null +++ b/support/kconfig/c_tests/extend_config/confdata_test.h @@ -0,0 +1,38 @@ +/* Copyright 2023 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CONFDATA_TEST_H +#define CONFDATA_TEST_H + +/* 测试用例失败错误信息打印 */ +#define ERR_PRINT() \ + do { \ + printf("**fail test case info**\n"); \ + printf("*file: %s\n", __FILE__); \ + printf("*func: %s\n", __func__); \ + printf("*line: %d\n", __LINE__); \ + printf("**end**\n"); \ + } while (0) + +/* case创建各自的文件夹,权限设置为可读/写 */ +#define FOLDER_PERMMISION 0755 +/* 流读取文件的单行最大缓存 */ +#define FILE_LEN 80 +/* 流读取文件的总缓存大小 */ +#define FILE_MAX 512 +/* 需要删除文件的路径最大长度 */ +#define REMOVE_DIR_PATH_MAX 256 + +#endif diff --git a/support/kconfig/c_tests/extend_config/def_test_files/config.test b/support/kconfig/c_tests/extend_config/def_test_files/config.test new file mode 100644 index 00000000..f1763d5f --- /dev/null +++ b/support/kconfig/c_tests/extend_config/def_test_files/config.test @@ -0,0 +1,45 @@ +# +# For a description of the syntax of this configuration file, +# see https://www.kernel.org/doc/Documentation/kbuild/Config.in-language.txt. +# +mainmenu "Unikraft/$(UK_FULLVERSION) Configuration" + +config TEST_BOOL_Y + bool "bool y" + default y + +config TEST_BOOL_N + bool "bool n" + default n + +config TEST_STRING + string "string" + default "This is a test string." + +config TEST_INT + int "int" + default 8 + +config TEST_HEX + hex "hex" + default 0x10 + +config EXTENDTEST_BOOL_Y + bool "bool y" + default y + +config EXTENDTEST_BOOL_N + bool "bool n" + default n + +config EXTENDTEST_STRING + string "string" + default "This is a test string." + +config EXTENDTEST_INT + int "int" + default 8 + +config EXTENDTEST_HEX + hex "hex" + default 0x1000 diff --git a/support/kconfig/c_tests/extend_config/def_test_files/defconfig b/support/kconfig/c_tests/extend_config/def_test_files/defconfig new file mode 100644 index 00000000..922d1827 --- /dev/null +++ b/support/kconfig/c_tests/extend_config/def_test_files/defconfig @@ -0,0 +1,10 @@ +CONFIG_TEST_BOOL_Y=y +# CONFIG_TEST_BOOL_N is not set +CONFIG_TEST_STRING="This is a test string." +CONFIG_TEST_INT=8 +CONFIG_TEST_HEX=0x10 +CONFIG_EXTENDTEST_BOOL_Y=y +# CONFIG_EXTENDTEST_BOOL_N is not set +CONFIG_EXTENDTEST_STRING="This is a test string." +CONFIG_EXTENDTEST_INT=8 +CONFIG_EXTENDTEST_HEX=0x1000 diff --git a/support/kconfig/c_tests/extend_config/def_test_files/expected_config_not_set b/support/kconfig/c_tests/extend_config/def_test_files/expected_config_not_set new file mode 100644 index 00000000..480eeb14 --- /dev/null +++ b/support/kconfig/c_tests/extend_config/def_test_files/expected_config_not_set @@ -0,0 +1,12 @@ +# +# Automatically generated file; DO NOT EDIT. +# test +# +CONFIG_TEST_HEX=0x10 +CONFIG_EXTENDTEST_HEX=0x1000 +CONFIG_TEST_INT=8 +CONFIG_EXTENDTEST_STRING="This is a test string." +CONFIG_TEST_BOOL_Y=y +CONFIG_TEST_STRING="This is a test string." +CONFIG_EXTENDTEST_BOOL_Y=y +CONFIG_EXTENDTEST_INT=8 diff --git a/support/kconfig/c_tests/extend_config/def_test_files/expected_err_info_err_format b/support/kconfig/c_tests/extend_config/def_test_files/expected_err_info_err_format new file mode 100644 index 00000000..0ef9b441 --- /dev/null +++ b/support/kconfig/c_tests/extend_config/def_test_files/expected_err_info_err_format @@ -0,0 +1,4 @@ + +Error while initializing template file. +Please check that the contents of your file conform to the format +and file size is less than 512 bytes diff --git a/support/kconfig/c_tests/extend_config/def_test_files/expected_err_info_err_template_path b/support/kconfig/c_tests/extend_config/def_test_files/expected_err_info_err_template_path new file mode 100644 index 00000000..bc7e2f25 --- /dev/null +++ b/support/kconfig/c_tests/extend_config/def_test_files/expected_err_info_err_template_path @@ -0,0 +1,3 @@ + +Error while opening template file. +Please check your template file path diff --git a/support/kconfig/c_tests/extend_config/def_test_files/expected_err_info_no_name b/support/kconfig/c_tests/extend_config/def_test_files/expected_err_info_no_name new file mode 100644 index 00000000..80942870 --- /dev/null +++ b/support/kconfig/c_tests/extend_config/def_test_files/expected_err_info_no_name @@ -0,0 +1,3 @@ + +Error while getting extend name. +Please define KCONFIG_EXTEND_NAME diff --git a/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_config_def_conf_path b/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_config_def_conf_path new file mode 100644 index 00000000..ab7ce618 --- /dev/null +++ b/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_config_def_conf_path @@ -0,0 +1,9 @@ +# +# Automatically generated file; DO NOT EDIT. +# test +# +CONFIG_HEX=0x1000 +# CONFIG_BOOL_N is not set +CONFIG_STRING="This is a test string." +CONFIG_BOOL_Y=y +CONFIG_INT=8 diff --git a/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_config_incomplete_format b/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_config_incomplete_format new file mode 100644 index 00000000..ab7ce618 --- /dev/null +++ b/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_config_incomplete_format @@ -0,0 +1,9 @@ +# +# Automatically generated file; DO NOT EDIT. +# test +# +CONFIG_HEX=0x1000 +# CONFIG_BOOL_N is not set +CONFIG_STRING="This is a test string." +CONFIG_BOOL_Y=y +CONFIG_INT=8 diff --git a/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_config_no_template_path b/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_config_no_template_path new file mode 100644 index 00000000..ab7ce618 --- /dev/null +++ b/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_config_no_template_path @@ -0,0 +1,9 @@ +# +# Automatically generated file; DO NOT EDIT. +# test +# +CONFIG_HEX=0x1000 +# CONFIG_BOOL_N is not set +CONFIG_STRING="This is a test string." +CONFIG_BOOL_Y=y +CONFIG_INT=8 diff --git a/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_config_set b/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_config_set new file mode 100644 index 00000000..ab7ce618 --- /dev/null +++ b/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_config_set @@ -0,0 +1,9 @@ +# +# Automatically generated file; DO NOT EDIT. +# test +# +CONFIG_HEX=0x1000 +# CONFIG_BOOL_N is not set +CONFIG_STRING="This is a test string." +CONFIG_BOOL_Y=y +CONFIG_INT=8 diff --git a/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_header_def_conf_path b/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_header_def_conf_path new file mode 100644 index 00000000..3cddf8f3 --- /dev/null +++ b/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_header_def_conf_path @@ -0,0 +1,39 @@ +/* + * + * Automatically generated file; DO NOT EDIT. + * test + * + */ +#define AUTOCONF_TIMESTAMP +#define CONFIG_HEX 0x1000 +#define ENABLE_HEX 1 +#ifdef MAKE_SUID +# define IF_HEX(...) __VA_ARGS__ "CONFIG_HEX" +#else +# define IF_HEX(...) __VA_ARGS__ +#endif +#undef CONFIG_BOOL_N +#define ENABLE_BOOL_N 0 +#define IF_BOOL_N(...) +#define IF_NOT_BOOL_N(...) __VA_ARGS__ +#define CONFIG_STRING "This is a test string." +#define ENABLE_STRING 1 +#ifdef MAKE_SUID +# define IF_STRING(...) __VA_ARGS__ "CONFIG_STRING" +#else +# define IF_STRING(...) __VA_ARGS__ +#endif +#define CONFIG_BOOL_Y 1 +#define ENABLE_BOOL_Y 1 +#ifdef MAKE_SUID +# define IF_BOOL_Y(...) __VA_ARGS__ "CONFIG_BOOL_Y" +#else +# define IF_BOOL_Y(...) __VA_ARGS__ +#endif +#define CONFIG_INT 8 +#define ENABLE_INT 1 +#ifdef MAKE_SUID +# define IF_INT(...) __VA_ARGS__ "CONFIG_INT" +#else +# define IF_INT(...) __VA_ARGS__ +#endif diff --git a/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_header_incomplete_format b/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_header_incomplete_format new file mode 100644 index 00000000..749d63f0 --- /dev/null +++ b/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_header_incomplete_format @@ -0,0 +1,38 @@ +/* + * + * Automatically generated file; DO NOT EDIT. + * test + * + */ +#define CONFIG_HEX 0x1000 +#define ENABLE_HEX 1 +#ifdef MAKE_SUID +# define IF_HEX(...) __VA_ARGS__ "CONFIG_HEX" +#else +# define IF_HEX(...) __VA_ARGS__ +#endif +#undef CONFIG_BOOL_N +#define ENABLE_BOOL_N 0 +#define IF_BOOL_N(...) +#define IF_NOT_BOOL_N(...) __VA_ARGS__ +#define CONFIG_STRING "This is a test string." +#define ENABLE_STRING 1 +#ifdef MAKE_SUID +# define IF_STRING(...) __VA_ARGS__ "CONFIG_STRING" +#else +# define IF_STRING(...) __VA_ARGS__ +#endif +#define CONFIG_BOOL_Y 1 +#define ENABLE_BOOL_Y 1 +#ifdef MAKE_SUID +# define IF_BOOL_Y(...) __VA_ARGS__ "CONFIG_BOOL_Y" +#else +# define IF_BOOL_Y(...) __VA_ARGS__ +#endif +#define CONFIG_INT 8 +#define ENABLE_INT 1 +#ifdef MAKE_SUID +# define IF_INT(...) __VA_ARGS__ "CONFIG_INT" +#else +# define IF_INT(...) __VA_ARGS__ +#endif diff --git a/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_header_no_template_path b/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_header_no_template_path new file mode 100644 index 00000000..65618234 --- /dev/null +++ b/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_header_no_template_path @@ -0,0 +1,10 @@ +/* + * + * Automatically generated file; DO NOT EDIT. + * test + * + */ +#define CONFIG_HEX 0x1000 +#define CONFIG_STRING "This is a test string." +#define CONFIG_BOOL_Y 1 +#define CONFIG_INT 8 diff --git a/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_header_set b/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_header_set new file mode 100644 index 00000000..3cddf8f3 --- /dev/null +++ b/support/kconfig/c_tests/extend_config/def_test_files/expected_extend_header_set @@ -0,0 +1,39 @@ +/* + * + * Automatically generated file; DO NOT EDIT. + * test + * + */ +#define AUTOCONF_TIMESTAMP +#define CONFIG_HEX 0x1000 +#define ENABLE_HEX 1 +#ifdef MAKE_SUID +# define IF_HEX(...) __VA_ARGS__ "CONFIG_HEX" +#else +# define IF_HEX(...) __VA_ARGS__ +#endif +#undef CONFIG_BOOL_N +#define ENABLE_BOOL_N 0 +#define IF_BOOL_N(...) +#define IF_NOT_BOOL_N(...) __VA_ARGS__ +#define CONFIG_STRING "This is a test string." +#define ENABLE_STRING 1 +#ifdef MAKE_SUID +# define IF_STRING(...) __VA_ARGS__ "CONFIG_STRING" +#else +# define IF_STRING(...) __VA_ARGS__ +#endif +#define CONFIG_BOOL_Y 1 +#define ENABLE_BOOL_Y 1 +#ifdef MAKE_SUID +# define IF_BOOL_Y(...) __VA_ARGS__ "CONFIG_BOOL_Y" +#else +# define IF_BOOL_Y(...) __VA_ARGS__ +#endif +#define CONFIG_INT 8 +#define ENABLE_INT 1 +#ifdef MAKE_SUID +# define IF_INT(...) __VA_ARGS__ "CONFIG_INT" +#else +# define IF_INT(...) __VA_ARGS__ +#endif diff --git a/support/kconfig/c_tests/extend_config/def_test_files/expected_header_not_set b/support/kconfig/c_tests/extend_config/def_test_files/expected_header_not_set new file mode 100644 index 00000000..5503968b --- /dev/null +++ b/support/kconfig/c_tests/extend_config/def_test_files/expected_header_not_set @@ -0,0 +1,14 @@ +/* + * + * Automatically generated file; DO NOT EDIT. + * test + * + */ +#define CONFIG_TEST_HEX 0x10 +#define CONFIG_EXTENDTEST_HEX 0x1000 +#define CONFIG_TEST_INT 8 +#define CONFIG_EXTENDTEST_STRING "This is a test string." +#define CONFIG_TEST_BOOL_Y 1 +#define CONFIG_TEST_STRING "This is a test string." +#define CONFIG_EXTENDTEST_BOOL_Y 1 +#define CONFIG_EXTENDTEST_INT 8 diff --git a/support/kconfig/c_tests/extend_config/def_test_files/src_template_file_oversize b/support/kconfig/c_tests/extend_config/def_test_files/src_template_file_oversize new file mode 100644 index 00000000..bd5e7b95 --- /dev/null +++ b/support/kconfig/c_tests/extend_config/def_test_files/src_template_file_oversize @@ -0,0 +1,61 @@ + +#define AUTOCONF_TIMESTAMP + + + +#define ENABLE_%1$s 1 +#ifdef MAKE_SUID +# define IF_%1$s(...) __VA_ARGS__ "CONFIG_%1$s" +#else +# define IF_%1$s(...) __VA_ARGS__ +#endif +#define ENABLE_%1$s 1 +#ifdef MAKE_SUID +# define IF_%1$s(...) __VA_ARGS__ "CONFIG_%1$s" +#else +# define IF_%1$s(...) __VA_ARGS__ +#endif +#define ENABLE_%1$s 1 +#ifdef MAKE_SUID +# define IF_%1$s(...) __VA_ARGS__ "CONFIG_%1$s" +#else +# define IF_%1$s(...) __VA_ARGS__ +#endif +#define ENABLE_%1$s 1 +#ifdef MAKE_SUID +# define IF_%1$s(...) __VA_ARGS__ "CONFIG_%1$s" +#else +# define IF_%1$s(...) __VA_ARGS__ +#endif +#define ENABLE_%1$s 1 +#ifdef MAKE_SUID +# define IF_%1$s(...) __VA_ARGS__ "CONFIG_%1$s" +#else +# define IF_%1$s(...) __VA_ARGS__ +#endif +#define ENABLE_%1$s 1 +#ifdef MAKE_SUID +# define IF_%1$s(...) __VA_ARGS__ "CONFIG_%1$s" +#else +# define IF_%1$s(...) __VA_ARGS__ +#endif +#define ENABLE_%1$s 1 +#ifdef MAKE_SUID +# define IF_%1$s(...) __VA_ARGS__ "CONFIG_%1$s" +#else +# define IF_%1$s(...) __VA_ARGS__ +#endif +#define ENABLE_%1$s 1 +#ifdef MAKE_SUID +# define IF_%1$s(...) __VA_ARGS__ "CONFIG_%1$s" +#else +# define IF_%1$s(...) __VA_ARGS__ +#endif + + + +#undef CONFIG_%1$s +#define ENABLE_%1$s 0 +#define IF_%1$s(...) +#define IF_NOT_%1$s(...) __VA_ARGS__ + diff --git a/support/kconfig/c_tests/extend_config/def_test_files/src_template_incomplete_format b/support/kconfig/c_tests/extend_config/def_test_files/src_template_incomplete_format new file mode 100644 index 00000000..dbd477db --- /dev/null +++ b/support/kconfig/c_tests/extend_config/def_test_files/src_template_incomplete_format @@ -0,0 +1,16 @@ + + +#define ENABLE_%1$s 1 +#ifdef MAKE_SUID +# define IF_%1$s(...) __VA_ARGS__ "CONFIG_%1$s" +#else +# define IF_%1$s(...) __VA_ARGS__ +#endif + + + +#undef CONFIG_%1$s +#define ENABLE_%1$s 0 +#define IF_%1$s(...) +#define IF_NOT_%1$s(...) __VA_ARGS__ + diff --git a/support/kconfig/c_tests/extend_config/def_test_files/src_template_miss_end_identifier b/support/kconfig/c_tests/extend_config/def_test_files/src_template_miss_end_identifier new file mode 100644 index 00000000..7e84b9d2 --- /dev/null +++ b/support/kconfig/c_tests/extend_config/def_test_files/src_template_miss_end_identifier @@ -0,0 +1,18 @@ + +#define AUTOCONF_TIMESTAMP + + +#define ENABLE_%1$s 1 +#ifdef MAKE_SUID +# define IF_%1$s(...) __VA_ARGS__ "CONFIG_%1$s" +#else +# define IF_%1$s(...) __VA_ARGS__ +#endif + + + +#undef CONFIG_%1$s +#define ENABLE_%1$s 0 +#define IF_%1$s(...) +#define IF_NOT_%1$s(...) __VA_ARGS__ + diff --git a/support/kconfig/c_tests/extend_config/def_test_files/src_template_miss_start_identifier b/support/kconfig/c_tests/extend_config/def_test_files/src_template_miss_start_identifier new file mode 100644 index 00000000..bdaa6b72 --- /dev/null +++ b/support/kconfig/c_tests/extend_config/def_test_files/src_template_miss_start_identifier @@ -0,0 +1,18 @@ +#define AUTOCONF_TIMESTAMP + + + +#define ENABLE_%1$s 1 +#ifdef MAKE_SUID +# define IF_%1$s(...) __VA_ARGS__ "CONFIG_%1$s" +#else +# define IF_%1$s(...) __VA_ARGS__ +#endif + + + +#undef CONFIG_%1$s +#define ENABLE_%1$s 0 +#define IF_%1$s(...) +#define IF_NOT_%1$s(...) __VA_ARGS__ + diff --git a/support/kconfig/c_tests/extend_config/def_test_files/src_template_mutidefined_identifier b/support/kconfig/c_tests/extend_config/def_test_files/src_template_mutidefined_identifier new file mode 100644 index 00000000..5d9d282b --- /dev/null +++ b/support/kconfig/c_tests/extend_config/def_test_files/src_template_mutidefined_identifier @@ -0,0 +1,23 @@ + +#define AUTOCONF_TIMESTAMP + + + +#define AUTOCONF_TIMESTAMP + + + +#define ENABLE_%1$s 1 +#ifdef MAKE_SUID +# define IF_%1$s(...) __VA_ARGS__ "CONFIG_%1$s" +#else +# define IF_%1$s(...) __VA_ARGS__ +#endif + + + +#undef CONFIG_%1$s +#define ENABLE_%1$s 0 +#define IF_%1$s(...) +#define IF_NOT_%1$s(...) __VA_ARGS__ + diff --git a/support/kconfig/c_tests/extend_config/def_test_files/std_template b/support/kconfig/c_tests/extend_config/def_test_files/std_template new file mode 100644 index 00000000..b99a9571 --- /dev/null +++ b/support/kconfig/c_tests/extend_config/def_test_files/std_template @@ -0,0 +1,19 @@ + +#define AUTOCONF_TIMESTAMP + + + +#define ENABLE_%1$s 1 +#ifdef MAKE_SUID +# define IF_%1$s(...) __VA_ARGS__ "CONFIG_%1$s" +#else +# define IF_%1$s(...) __VA_ARGS__ +#endif + + + +#undef CONFIG_%1$s +#define ENABLE_%1$s 0 +#define IF_%1$s(...) +#define IF_NOT_%1$s(...) __VA_ARGS__ + -- Gitee From c7d311f1d1653ed3601121e8aee4ee94cb88bf9b Mon Sep 17 00:00:00 2001 From: crazykev Date: Tue, 14 Nov 2023 08:33:10 +0800 Subject: [PATCH 18/57] plat/common: [upstream][bugfix]Fix getting address-cells/size-cells MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These code should broken when dtb provide a none default address-cells or size-cells. According to Sect 2.3.5 of [1]: "The #address-cells and #size-cells properties may be used in any device node that has children in the devicetree hierarchy and describes how child device nodes should be addressed. The #address-cells property defines the number of cells used to encode the address field in a child node's reg property. The #size-cells property defines the number of cells used to encode the size field in a child node’s reg property. The #address-cells and #size-cells properties are not inherited from ancestors in the devicetree. They shall be explicitly defined. A DTSpec-compliant boot program shall supply #address-cells and #size-cells on all nodes that have children. If missing, a client program should assume a default value of 2 for We should 1. Retrieve #address-cells/#size-cells from memory's parent(aka root node) instead of it self. 2. Use a u32 instead of u64 to read value from memory->reg prop value. [1] Devicetree Specification 0.3 Signed-off-by: crazykev --- plat/common/bootinfo_fdt.c | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/plat/common/bootinfo_fdt.c b/plat/common/bootinfo_fdt.c index c00bddd1..64f75587 100644 --- a/plat/common/bootinfo_fdt.c +++ b/plat/common/bootinfo_fdt.c @@ -7,17 +7,15 @@ #include #include #include -#include +#include #define ukplat_bootinfo_crash(s) ukplat_crash() static void fdt_bootinfo_mem_mrd(struct ukplat_bootinfo *bi, void *fdtp) { struct ukplat_memregion_desc mrd = {0}; - int prop_len, prop_min_len; __u64 mem_base, mem_sz; - int naddr, nsz, nmem; - const __u64 *regs; + int nmem; int rc; nmem = fdt_node_offset_by_prop_value(fdtp, -1, "device_type", @@ -25,28 +23,17 @@ static void fdt_bootinfo_mem_mrd(struct ukplat_bootinfo *bi, void *fdtp) if (unlikely(nmem < 0)) ukplat_bootinfo_crash("No memory found in DTB"); - naddr = fdt_address_cells(fdtp, nmem); - if (unlikely(naddr < 0 || naddr >= FDT_MAX_NCELLS)) - ukplat_bootinfo_crash("Could not find proper address cells!"); - - nsz = fdt_size_cells(fdtp, nmem); - if (unlikely(nsz < 0 || nsz >= FDT_MAX_NCELLS)) - ukplat_bootinfo_crash("Could not find proper size cells!"); - /* * The property must contain at least the start address - * and size, each of which is 8-bytes. + * and size, each length of which is defined in + * #address-cells/#size-cells of root node. * For now, we only support one memory bank. * TODO: Support more than one memory@ node/regs/ranges properties. */ - prop_len = 0; - prop_min_len = (int)sizeof(fdt32_t) * (naddr + nsz); - regs = fdt_getprop(fdtp, nmem, "reg", &prop_len); - if (unlikely(!regs || prop_len < prop_min_len)) - ukplat_bootinfo_crash("Bad 'reg' property or more than one memory bank."); - - mem_sz = fdt64_to_cpu(regs[1]); - mem_base = fdt64_to_cpu(regs[0]); + rc = fdt_get_address(fdtp, nmem, 0, &mem_base, &mem_sz); + if (unlikely(rc)) + ukplat_bootinfo_crash("Get memory device address/size failed"); + if (unlikely(!RANGE_CONTAIN(mem_base, mem_sz, __BASE_ADDR, __END - __BASE_ADDR))) ukplat_bootinfo_crash("Image outside of RAM"); -- Gitee From 393149f7a71f9cbdd15a1e1f05c4331657239d23 Mon Sep 17 00:00:00 2001 From: crazykev Date: Wed, 15 Nov 2023 14:46:16 +0800 Subject: [PATCH 19/57] plat/common: [upstream][bugfix]Align free type memregion page boundary UKPLAT_MEMRT_FREE type memregion should align to a contracted page boundary while others should align to a extended page boundary Signed-off-by: crazykev --- plat/common/include/uk/plat/common/memory.h | 41 +++++++++++++++++++++ plat/common/memory.c | 33 +++++++---------- 2 files changed, 55 insertions(+), 19 deletions(-) diff --git a/plat/common/include/uk/plat/common/memory.h b/plat/common/include/uk/plat/common/memory.h index b39a9bb5..649606a4 100644 --- a/plat/common/include/uk/plat/common/memory.h +++ b/plat/common/include/uk/plat/common/memory.h @@ -43,6 +43,47 @@ #include #include + +/** + * Aligns a free memory region to a contracted page boundary and + * returns the aligned start address, length and end address. + * This is to avoid conflict with already mapped/reserved memory regions. + * + * @param mrd + * Pointer to the memory region descriptor. + * @param pstart + * Variable of the start address of the aligned memory region. + * @param plen + * Variable of the length of the aligned memory region. + * @param pend + * Variable of the end address of the aligned memory region. + */ +#define ALIGN_FREE_MEMREGION(mrd, pstart, plen, pend) do { \ + pstart = ALIGN_UP((mrd)->pbase, __PAGE_SIZE); \ + plen = ALIGN_DOWN((mrd)->len - (pstart - (mrd)->pbase), __PAGE_SIZE); \ + pend = pstart + plen; \ +} while (0) + +/** + * Aligns a mapped memory region to a extended page boundary and + * returns the aligned start address, length and end address. + * This is to avoid truncating already mapped/reserved memory regions. + * + * @param mrd + * Pointer to the memory region descriptor. + * @param pstart + * Variable of the start address of the aligned memory region. + * @param plen + * Variable of the length of the aligned memory region. + * @param pend + * Variable of the end address of the aligned memory region. + */ +#define ALIGN_MAPPED_MEMREGION(mrd, pstart, plen, pend) do { \ + pend = ALIGN_UP((mrd)->pbase + (mrd)->len, __PAGE_SIZE); \ + pstart = ALIGN_DOWN((mrd)->pbase, __PAGE_SIZE); \ + plen = pend - pstart; \ +} while (0) + struct ukplat_memregion_list { /** Maximum regions in the list */ __u32 capacity; diff --git a/plat/common/memory.c b/plat/common/memory.c index 10eb35bd..6b331d92 100644 --- a/plat/common/memory.c +++ b/plat/common/memory.c @@ -71,9 +71,7 @@ void *ukplat_memregion_alloc(__sz size, int type, __u16 flags) __paddr_t ostart, olen; int rc; - unmap_start = ALIGN_DOWN(bpt_unmap_mrd.vbase, __PAGE_SIZE); - unmap_end = unmap_start + ALIGN_DOWN(bpt_unmap_mrd.len, __PAGE_SIZE); - unmap_len = unmap_end - unmap_start; + ALIGN_FREE_MEMREGION(&bpt_unmap_mrd, unmap_start, unmap_len, unmap_end); /* Preserve desired size */ desired_sz = size; @@ -261,16 +259,10 @@ static void ukplat_memregion_align_mrd(struct ukplat_memregion_desc *mrd, *opbase = mrd->pbase; *olen = mrd->len; - /* Compute the page-aligned end address of the region */ - pend = ALIGN_UP(mrd->pbase + mrd->len, __PAGE_SIZE); - - /* Overwrite original pbase with its page-aligned value */ - mrd->pbase = ALIGN_DOWN(mrd->pbase, __PAGE_SIZE); - - /* Overwrite original len with the supposed size of end-to-end - * page-aligned memory region. - */ - mrd->len = pend - mrd->pbase; + if (mrd->type == UKPLAT_MEMRT_FREE) + ALIGN_FREE_MEMREGION(mrd, mrd->pbase, mrd->len, pend); + else + ALIGN_MAPPED_MEMREGION(mrd, mrd->pbase, mrd->len, pend); } /* Called at the end of ukplat_memregion_list_coalesce to undo what @@ -343,6 +335,10 @@ void ukplat_memregion_list_coalesce(struct ukplat_memregion_list *list) uk_pr_debug("Priority of right memory region: %d\n", mr_prio); UK_ASSERT(mr_prio >= 0); + /* Store original pbase */ + ml_opbase = ml->pbase; + mr_opbase = mr->pbase; + ukplat_memregion_align_mrd(ml, &ml_opbase, &ml_olen); ukplat_memregion_align_mrd(mr, &mr_opbase, &mr_olen); @@ -506,7 +502,7 @@ int ukplat_memregion_get(int i, struct ukplat_memregion_desc **mrd) static int ukplat_memregion_list_insert_unmaps(struct ukplat_bootinfo *bi) { - __vaddr_t unmap_start, unmap_end; + __vaddr_t unmap_start, unmap_end, unmap_len; int rc; if (!bpt_unmap_mrd.len) @@ -515,8 +511,8 @@ static int ukplat_memregion_list_insert_unmaps(struct ukplat_bootinfo *bi) /* Be PIE aware: split the unmap memory region so that we do no unmap * the Kernel image. */ - unmap_start = ALIGN_DOWN(bpt_unmap_mrd.vbase, __PAGE_SIZE); - unmap_end = unmap_start + ALIGN_DOWN(bpt_unmap_mrd.len, __PAGE_SIZE); + ALIGN_FREE_MEMREGION(&bpt_unmap_mrd, unmap_start, unmap_len, + unmap_end) /* After Kernel image */ rc = ukplat_memregion_list_insert(&bi->mrds, @@ -573,13 +569,12 @@ int ukplat_mem_init(void) { struct ukplat_bootinfo *bi = ukplat_bootinfo_get(); struct ukplat_memregion_desc *mrdp; - __vaddr_t unmap_end; + __vaddr_t unmap_start, unmap_end, unmap_len; int i; UK_ASSERT(bi); - unmap_end = ALIGN_DOWN(bpt_unmap_mrd.vbase + bpt_unmap_mrd.len, - __PAGE_SIZE); + ALIGN_FREE_MEMREGION(&bpt_unmap_mrd, unmap_start, unmap_len, unmap_end); for (i = (int)bi->mrds.count - 1; i >= 0; i--) { ukplat_memregion_get(i, &mrdp); if (mrdp->vbase >= unmap_end) { -- Gitee From ff4b92d9a7bf938e1e535c3d59f8778bcd403629 Mon Sep 17 00:00:00 2001 From: crazykev Date: Mon, 27 Nov 2023 15:16:50 +0800 Subject: [PATCH 20/57] plat/common: [upstream][bugfix]Remove memregion outside unmapped area Signed-off-by: crazykev --- plat/common/memory.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/plat/common/memory.c b/plat/common/memory.c index 6b331d92..dbc5216a 100644 --- a/plat/common/memory.c +++ b/plat/common/memory.c @@ -577,31 +577,34 @@ int ukplat_mem_init(void) ALIGN_FREE_MEMREGION(&bpt_unmap_mrd, unmap_start, unmap_len, unmap_end); for (i = (int)bi->mrds.count - 1; i >= 0; i--) { ukplat_memregion_get(i, &mrdp); - if (mrdp->vbase >= unmap_end) { - /* Region is outside the mapped area */ - uk_pr_info("Memory %012lx-%012lx outside mapped area\n", + if (mrdp->vbase >= unmap_end + || mrdp->vbase + mrdp->len <= unmap_start) { + /* Region is outside the unmapped area */ + uk_pr_info("Memory %012lx-%012lx outside unmapped area\n", mrdp->vbase, mrdp->vbase + mrdp->len); if (mrdp->type == UKPLAT_MEMRT_FREE) ukplat_memregion_list_delete(&bi->mrds, i); - } else if (mrdp->vbase + mrdp->len > unmap_end) { - /* Region overlaps with unmapped area */ - uk_pr_info("Memory %012lx-%012lx outside mapped area\n", + } else if (mrdp->vbase < unmap_start + && mrdp->vbase + mrdp->len <= unmap_end) { + /* Region overlaps with mapped area */ + uk_pr_info("Memory %012lx-%012lx outside unmapped area\n", + mrdp->vbase, unmap_start); + + if (mrdp->type == UKPLAT_MEMRT_FREE) { + mrdp->len -= unmap_start - mrdp->vbase; + mrdp->vbase = mrdp->pbase = unmap_start; + } + } else if (mrdp->vbase >= unmap_start + && mrdp->vbase + mrdp->len > unmap_end) { + /* Region overlaps with mapped area */ + uk_pr_info("Memory %012lx-%012lx outside unmapped area\n", unmap_end, mrdp->vbase + mrdp->len); if (mrdp->type == UKPLAT_MEMRT_FREE) mrdp->len -= (mrdp->vbase + mrdp->len) - unmap_end; - - /* Since regions are non-overlapping and ordered, we - * can stop here, as the next region would be fully - * mapped anyways - */ - break; - } else { - /* Region is fully mapped */ - break; } } -- Gitee From 74b21c5b27bbdc9ddff7d4ab1e8ce76996634f70 Mon Sep 17 00:00:00 2001 From: crazykev Date: Mon, 27 Nov 2023 23:18:55 +0800 Subject: [PATCH 21/57] ci: use plat/raspi v0.15 changes 1. Use target plat/raspi branch same as unikraft's 2. Use dtb introduced by plat/raspi 0.15 3. boost make stage by allow multiple threads Signed-off-by: crazykev --- ci/.jenkinsfile | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/ci/.jenkinsfile b/ci/.jenkinsfile index 1cd5fbab..fa0147a9 100644 --- a/ci/.jenkinsfile +++ b/ci/.jenkinsfile @@ -21,6 +21,7 @@ string gitAppHelloWorldURL = "git@gitee.com:yingyitech/app-helloworld.git" string gitPlatRaspiUrl = "https://gitee.com/yingyitech/plat-raspi.git" string gitLibMuslUrl = "git@gitee.com:yingyitech/lib-musl.git" string gitLibcTestUrl = "git@gitee.com:yingyitech/lib-libc-test.git" +string targetBranch = env.giteeTargetBranch /* XEN配置文件内容 */ string xenConfig = """ @@ -99,6 +100,16 @@ pipeline { addGiteeMRComment comment: "开始CI测试,任务编号:" + env.BUILD_NUMBER + "\n任务链接:" + env.JOB_DISPLAY_URL } } + stage('变量初始化') { + steps { + script { + // 获取 CPU 核心数 + cpuCores = sh(script: 'nproc', returnStdout: true).trim() + echo "Detected CPU Cores: ${cpuCores}" + nBuildThreads = Integer.parseInt(cpuCores) / 2 + } + } + } stage('初始化公共代码仓') { when { not { @@ -120,7 +131,9 @@ pipeline { cd - # 将unikraft拷贝至app-helloworld/.unikraft/unikraft中 cp -r `ls |grep -v 'app-helloworld'|xargs` app-helloworld/.unikraft/unikraft - git clone $gitPlatRaspiUrl app-helloworld/.unikraft/unikraft/plat/raspi + # 默认使用与unikraft相同的分支 + # TODO: 应该提供一个能够从外部传入的参数指定这个分支,两个库同步修改的情况下需要用到 + git clone -b $targetBranch $gitPlatRaspiUrl app-helloworld/.unikraft/unikraft/plat/raspi # 为每个测试项建立独立目录 mkdir ut_self-test ut_libc-test run_qemu-x86_64 run_qemu-arm64 run_xen-x86_64 run_fc-x86_64 run_linuxu-x86_64 run_linuxu-arm64 cp -r app-helloworld/. ut_libc-test @@ -257,8 +270,11 @@ pipeline { result = sh(script: ''' cd $WORKSPACE/ut_libc-test # 编译unikraft, make & run流程 - make - qemu-system-aarch64 -cpu cortex-a53 -machine raspi3b -nodefaults -display none -pidfile $WORKSPACE/libc-test$BUILD_NUMBER.pid -serial file:$WORKSPACE/libc-test$BUILD_NUMBER.out -kernel build/kernel8.img -append verbose & + make -j$nBuildThreads + raspiRoot=$PWD/.unikraft/unikraft/plat/raspi + qemu-system-aarch64 -cpu cortex-a53 -machine raspi3b -nodefaults -display none \ + -pidfile $WORKSPACE/libc-test$BUILD_NUMBER.pid -serial file:$WORKSPACE/libc-test$BUILD_NUMBER.out \ + -kernel build/kernel8.img -dtb ${raspiRoot}/bootfiles/bcm2710-rpi-3-b-plus.dtb -append verbose & # 后台运行,等待15s sleep 15s ''', returnStatus: true) @@ -305,8 +321,11 @@ pipeline { result = sh(script: ''' cd $WORKSPACE/ut_self-test # 编译unikraft, make & run流程 - make - qemu-system-aarch64 -cpu cortex-a53 -machine raspi3b -nodefaults -display none -pidfile $WORKSPACE/self-test$BUILD_NUMBER.pid -serial file:$WORKSPACE/self-test$BUILD_NUMBER.out -kernel build/kernel8.img -append verbose & + make -j$nBuildThreads + raspiRoot=$PWD/.unikraft/unikraft/plat/raspi + qemu-system-aarch64 -cpu cortex-a53 -machine raspi3b -nodefaults -display none \ + -pidfile $WORKSPACE/self-test$BUILD_NUMBER.pid -serial file:$WORKSPACE/self-test$BUILD_NUMBER.out \ + -kernel build/kernel8.img -dtb ${raspiRoot}/bootfiles/bcm2710-rpi-3-b-plus.dtb -append verbose & # 后台运行,等待15s sleep 15s ''', returnStatus: true) @@ -352,7 +371,7 @@ pipeline { result = sh(script:''' cd $WORKSPACE/run_qemu-x86_64 UK_DEFCONFIG=\$PWD/.config.helloworld-qemu-x86_64 make defconfig - make + make -j$nBuildThreads qemu-system-x86_64 -kernel build/helloworld_qemu-x86_64 -nographic ''', returnStatus: true) if (result == 0) { @@ -374,7 +393,7 @@ pipeline { result = sh(script:''' cd $WORKSPACE/run_qemu-arm64 UK_DEFCONFIG=\$PWD/.config.helloworld-qemu-aarch64 make defconfig - make + make -j$nBuildThreads qemu-system-aarch64 -kernel build/helloworld_qemu-arm64 -nographic -machine virt -cpu cortex-a57 ''', returnStatus: true) if (result == 0) { @@ -403,7 +422,7 @@ pipeline { #!/bin/bash cd $WORKSPACE/run_xen-x86_64 UK_DEFCONFIG=$PWD/.unikraft/unikraft/ci/defconfigs/xen-x86_64 make defconfig - make + make -j$nBuildThreads xl create -c helloworld.cfg ''', returnStatus: true) if (result == 0) { @@ -425,7 +444,7 @@ pipeline { result = sh(script:''' cd $WORKSPACE/run_fc-x86_64 UK_DEFCONFIG=\$PWD/.config.helloworld-fc-x86_64 make defconfig - make + make -j$nBuildThreads ''', returnStatus: true) result = sh(script:""" #!/bin/bash @@ -462,7 +481,7 @@ pipeline { #!/bin/bash cd $WORKSPACE/run_linuxu-x86_64 UK_DEFCONFIG=\$PWD/.unikraft/unikraft/ci/defconfigs/linuxu-x86_64 make defconfig - make + make -j$nBuildThreads ''', returnStatus: true) if (result == 0) { sucNum++ @@ -483,7 +502,7 @@ pipeline { result = sh(script:''' cd $WORKSPACE/run_linuxu-arm64 UK_DEFCONFIG=\$PWD/.unikraft/unikraft/ci/defconfigs/linuxu-arm64 make defconfig - make + make -j$nBuildThreads # 虚拟机目前是linux x86_64系统,暂时先不运行 # ./build/app-helloworld_linuxu-arm64 ''', returnStatus: true) -- Gitee From 939d57387fff3172c8b953cc82dc3cb23e0c7cda Mon Sep 17 00:00:00 2001 From: zhaohaidan Date: Tue, 5 Dec 2023 14:25:31 +0800 Subject: [PATCH 22/57] plat/common: add debug messages Signed-off-by: zhaohaidan --- include/uk/event.h | 1 + plat/common/arm/traps_arm64.c | 24 +++++++++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/include/uk/event.h b/include/uk/event.h index e408a2da..3b96d020 100644 --- a/include/uk/event.h +++ b/include/uk/event.h @@ -277,6 +277,7 @@ static inline int uk_raise_event_ptr(struct uk_event *e, void *data) uk_event_handler_foreach(itr, e) { __uk_event_assert(*itr); + uk_pr_debug("Call uk_event_handler: %p()...\n", *itr); rc = ((*itr)(data)); if (unlikely(rc < 0)) return rc; diff --git a/plat/common/arm/traps_arm64.c b/plat/common/arm/traps_arm64.c index e05bf63a..eb2c49d5 100644 --- a/plat/common/arm/traps_arm64.c +++ b/plat/common/arm/traps_arm64.c @@ -200,10 +200,28 @@ void trap_el1_sync(struct __regs *regs, __u64 far) if (trap < AARCH64_TRAP_MAX) { rc = uk_raise_event_ptr(_trap_table[trap].event, &ctx); - if (unlikely(rc < 0)) - uk_pr_crit("event handler returned error: %d\n", rc); - else if (rc) + switch (rc) { + case UK_EVENT_HANDLED_CONT: + // fixme: UK_EVENT_HANDLED_CONT means continue to call + // next handler, but unikraft doesn't do so, maybe we + // should handle this. + uk_pr_debug( + "Event %s handled, continue to call next handler", + _trap_table[trap].str); return; + case UK_EVENT_HANDLED: + uk_pr_debug("Event %s handled\n", + _trap_table[trap].str); + return; + case UK_EVENT_NOT_HANDLED: + uk_pr_debug("Event %s is not handled\n", + _trap_table[trap].str); + break; + default: + uk_pr_crit("Event handler for %s returned error: %d\n", + _trap_table[trap].str, rc); + break; + } } uk_pr_crit("EL1 sync trap caught\n"); -- Gitee From 5b82d605d7658a1a0ac5bc8fb507623401169376 Mon Sep 17 00:00:00 2001 From: zhaohaidan Date: Tue, 5 Dec 2023 14:27:55 +0800 Subject: [PATCH 23/57] lib/vfscore: add 'readlinkat' syscall Signed-off-by: zhaohaidan --- lib/vfscore/Makefile.uk | 1 + lib/vfscore/exportsyms.uk | 3 +++ lib/vfscore/main.c | 31 +++++++++++++++++++++++++++++++ lib/vfscore/syscalls.c | 2 +- 4 files changed, 36 insertions(+), 1 deletion(-) diff --git a/lib/vfscore/Makefile.uk b/lib/vfscore/Makefile.uk index 062edb2b..8a1e11d7 100644 --- a/lib/vfscore/Makefile.uk +++ b/lib/vfscore/Makefile.uk @@ -25,6 +25,7 @@ LIBVFSCORE_EINITRD_CDEPS += $(CONFIG_LIBVFSCORE_ROOTFS_EINITRD_PATH) endif UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += readlink-3 +UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += readlinkat-4 UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += link-2 UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += ftruncate-2 UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += truncate-2 diff --git a/lib/vfscore/exportsyms.uk b/lib/vfscore/exportsyms.uk index 38edab60..1f3e9375 100644 --- a/lib/vfscore/exportsyms.uk +++ b/lib/vfscore/exportsyms.uk @@ -174,6 +174,9 @@ uk_syscall_r_faccessat readlink uk_syscall_e_readlink uk_syscall_r_readlink +readlinkat +uk_syscall_e_readlinkat +uk_syscall_r_readlinkat fallocate fallocate64 uk_syscall_e_fallocate diff --git a/lib/vfscore/main.c b/lib/vfscore/main.c index efae6c92..9a061a7d 100644 --- a/lib/vfscore/main.c +++ b/lib/vfscore/main.c @@ -2211,6 +2211,37 @@ UK_SYSCALL_DEFINE(ssize_t, readlink, const char *, pathname, char *, buf, size_t return -1; } +UK_SYSCALL_R_DEFINE(ssize_t, readlinkat, int, dirfd, const char *, pathname, + char *, buf, size_t, bufsize) +{ + if (pathname[0] == '/' || dirfd == AT_FDCWD) { + return uk_syscall_r_readlink((long)pathname, (long)buf, + bufsize); + } + + struct vfscore_file *fp; + int error = fget(dirfd, &fp); + + if (error) + return -error; + + struct vnode *vp = fp->f_dentry->d_vnode; + + vn_lock(vp); + + char p[PATH_MAX]; + /* build absolute path */ + strlcpy(p, fp->f_dentry->d_mount->m_path, PATH_MAX); + strlcat(p, fp->f_dentry->d_path, PATH_MAX); + strlcat(p, "/", PATH_MAX); + strlcat(p, pathname, PATH_MAX); + + vn_unlock(vp); + fdrop(fp); + + return uk_syscall_r_readlink((long)p, (long)buf, bufsize); +} + UK_TRACEPOINT(trace_vfs_fallocate, "%d %d %#x %#x", int, int, loff_t, loff_t); UK_TRACEPOINT(trace_vfs_fallocate_ret, ""); UK_TRACEPOINT(trace_vfs_fallocate_err, "%d", int); diff --git a/lib/vfscore/syscalls.c b/lib/vfscore/syscalls.c index 2cd091d3..1ecea886 100644 --- a/lib/vfscore/syscalls.c +++ b/lib/vfscore/syscalls.c @@ -388,7 +388,7 @@ vfscore_ioctl(struct vfscore_file *fp, unsigned long request, void *buf) int error = 0; int oldf; - DPRINTF(VFSDB_SYSCALL, ("sys_ioctl: fp=%p request=%lux\n", fp, request)); + DPRINTF(VFSDB_SYSCALL, ("sys_ioctl: fp=%p request=%lx\n", fp, request)); if ((fp->f_flags & (UK_FREAD | UK_FWRITE)) == 0) return EBADF; -- Gitee From 007a53d3d93fac7066656ab4a03d871ab6b3a29d Mon Sep 17 00:00:00 2001 From: zhaohaidan Date: Tue, 5 Dec 2023 17:01:07 +0800 Subject: [PATCH 24/57] plat/common: some arm platform doesn't use gic, make it optional Signed-off-by: zhaohaidan --- plat/common/arm/traps_arm64.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/plat/common/arm/traps_arm64.c b/plat/common/arm/traps_arm64.c index eb2c49d5..dba35660 100644 --- a/plat/common/arm/traps_arm64.c +++ b/plat/common/arm/traps_arm64.c @@ -27,15 +27,17 @@ #include #include #include -#include #include #ifdef CONFIG_ARM64_FEAT_MTE #include #endif /* CONFIG_ARM64_FEAT_MTE */ +#ifdef CONFIG_LIBUKINTCTLR_GIC +#include /** GIC driver to call interrupt handler */ extern struct _gic_dev *gic; +#endif static const char * const exception_modes[] = { "Synchronous Abort", @@ -229,8 +231,14 @@ void trap_el1_sync(struct __regs *regs, __u64 far) ukplat_crash(); } +/* + * Fixme:some arm platforms don't use gic as irq driver, here we just drop the + * logic by micro config, while drivers should be encapsulated in the controller + * library so that the caller is not aware of the difference + */ void trap_el1_irq(struct __regs *regs) { +#ifdef CONFIG_LIBUKINTCTLR_GIC UK_ASSERT(gic); #ifdef CONFIG_ARM64_FEAT_MTE @@ -239,6 +247,7 @@ void trap_el1_irq(struct __regs *regs) #endif /* CONFIG_ARM64_FEAT_MTE */ gic->ops.handle_irq(regs); +#endif /* CONFIG_LIBUKINTCTLR_GIC */ } #ifdef CONFIG_LIBSYSCALL_SHIM_HANDLER -- Gitee From 3289655e2c32a23f0e3c7863ecc243a4a05c8d00 Mon Sep 17 00:00:00 2001 From: crazykev Date: Wed, 29 Nov 2023 20:37:47 +0800 Subject: [PATCH 25/57] plat/common: [upstream][bugfix] use inline instead of macro fix code style introduced by plat/common: [upstream][bugfix]Align free type memregion page boundary Should rebase into that commit when we upgrade to next release or upstream. Macro reference without ; may be broken in some compiler. Also use inline method to avoid optional pend parameter. Ref: PRE00-C. Prefer inline or static functions to function-like macros Signed-off-by: crazykev --- plat/common/include/uk/plat/common/memory.h | 39 ++++++++++++++------- plat/common/memory.c | 39 +++++++++++---------- 2 files changed, 47 insertions(+), 31 deletions(-) diff --git a/plat/common/include/uk/plat/common/memory.h b/plat/common/include/uk/plat/common/memory.h index 649606a4..f9da5d35 100644 --- a/plat/common/include/uk/plat/common/memory.h +++ b/plat/common/include/uk/plat/common/memory.h @@ -43,7 +43,6 @@ #include #include - /** * Aligns a free memory region to a contracted page boundary and * returns the aligned start address, length and end address. @@ -56,13 +55,21 @@ * @param plen * Variable of the length of the aligned memory region. * @param pend - * Variable of the end address of the aligned memory region. + * Variable of the end address of the aligned memory region, optional. */ -#define ALIGN_FREE_MEMREGION(mrd, pstart, plen, pend) do { \ - pstart = ALIGN_UP((mrd)->pbase, __PAGE_SIZE); \ - plen = ALIGN_DOWN((mrd)->len - (pstart - (mrd)->pbase), __PAGE_SIZE); \ - pend = pstart + plen; \ -} while (0) +static inline void align_free_memregion(struct ukplat_memregion_desc *mrd, + __paddr_t *pstart, __sz *plen, + __paddr_t *pend) +{ + UK_ASSERT(mrd != NULL); + UK_ASSERT(pstart != NULL); + UK_ASSERT(plen != NULL); + + *pstart = ALIGN_UP(mrd->pbase, __PAGE_SIZE); + *plen = ALIGN_DOWN(mrd->len - (*pstart - mrd->pbase), __PAGE_SIZE); + if (pend != NULL) + *pend = *pstart + *plen; +} /** * Aligns a mapped memory region to a extended page boundary and @@ -78,11 +85,19 @@ * @param pend * Variable of the end address of the aligned memory region. */ -#define ALIGN_MAPPED_MEMREGION(mrd, pstart, plen, pend) do { \ - pend = ALIGN_UP((mrd)->pbase + (mrd)->len, __PAGE_SIZE); \ - pstart = ALIGN_DOWN((mrd)->pbase, __PAGE_SIZE); \ - plen = pend - pstart; \ -} while (0) +static inline void align_mapped_memregion(struct ukplat_memregion_desc *mrd, + __paddr_t *pstart, __sz *plen, + __paddr_t *pend) +{ + UK_ASSERT(mrd != NULL); + UK_ASSERT(pstart != NULL); + UK_ASSERT(plen != NULL); + UK_ASSERT(pend != NULL); + + *pend = ALIGN_UP(mrd->pbase + mrd->len, __PAGE_SIZE); + *pstart = ALIGN_DOWN(mrd->pbase, __PAGE_SIZE); + *plen = *pend - *pstart; +} struct ukplat_memregion_list { /** Maximum regions in the list */ diff --git a/plat/common/memory.c b/plat/common/memory.c index dbc5216a..cf301afa 100644 --- a/plat/common/memory.c +++ b/plat/common/memory.c @@ -64,14 +64,14 @@ struct uk_alloc *ukplat_memallocator_get(void) void *ukplat_memregion_alloc(__sz size, int type, __u16 flags) { struct ukplat_memregion_desc *mrd, alloc_mrd = {0}; - __vaddr_t unmap_start, unmap_end; + __paddr_t unmap_start; __sz unmap_len, desired_sz; struct ukplat_bootinfo *bi; __paddr_t pstart, pend; __paddr_t ostart, olen; int rc; - ALIGN_FREE_MEMREGION(&bpt_unmap_mrd, unmap_start, unmap_len, unmap_end); + align_free_memregion(&bpt_unmap_mrd, &unmap_start, &unmap_len, NULL); /* Preserve desired size */ desired_sz = size; @@ -253,16 +253,16 @@ static inline void overlapping_mrd_fixup(struct ukplat_memregion_list *list, static void ukplat_memregion_align_mrd(struct ukplat_memregion_desc *mrd, __paddr_t *opbase, __sz *olen) { - __sz pend; + __paddr_t pend; /* Store the **original** physical base and length */ *opbase = mrd->pbase; *olen = mrd->len; if (mrd->type == UKPLAT_MEMRT_FREE) - ALIGN_FREE_MEMREGION(mrd, mrd->pbase, mrd->len, pend); + align_free_memregion(mrd, &mrd->pbase, &mrd->len, &pend); else - ALIGN_MAPPED_MEMREGION(mrd, mrd->pbase, mrd->len, pend); + align_mapped_memregion(mrd, &mrd->pbase, &mrd->len, &pend); } /* Called at the end of ukplat_memregion_list_coalesce to undo what @@ -502,7 +502,7 @@ int ukplat_memregion_get(int i, struct ukplat_memregion_desc **mrd) static int ukplat_memregion_list_insert_unmaps(struct ukplat_bootinfo *bi) { - __vaddr_t unmap_start, unmap_end, unmap_len; + __paddr_t unmap_start, unmap_end, unmap_len; int rc; if (!bpt_unmap_mrd.len) @@ -511,8 +511,8 @@ static int ukplat_memregion_list_insert_unmaps(struct ukplat_bootinfo *bi) /* Be PIE aware: split the unmap memory region so that we do no unmap * the Kernel image. */ - ALIGN_FREE_MEMREGION(&bpt_unmap_mrd, unmap_start, unmap_len, - unmap_end) + align_free_memregion(&bpt_unmap_mrd, &unmap_start, &unmap_len, + &unmap_end); /* After Kernel image */ rc = ukplat_memregion_list_insert(&bi->mrds, @@ -528,15 +528,15 @@ static int ukplat_memregion_list_insert_unmaps(struct ukplat_bootinfo *bi) return rc; /* Before Kernel image */ - return ukplat_memregion_list_insert(&bi->mrds, - &(struct ukplat_memregion_desc){ - .vbase = unmap_start, - .pbase = 0, - .len = ALIGN_DOWN(__BASE_ADDR, __PAGE_SIZE) - - unmap_start, - .type = 0, - .flags = UKPLAT_MEMRF_UNMAP, - }); + return ukplat_memregion_list_insert( + &bi->mrds, + &(struct ukplat_memregion_desc){ + .vbase = (__vaddr_t)unmap_start, + .pbase = 0, + .len = ALIGN_DOWN(__BASE_ADDR, __PAGE_SIZE) - unmap_start, + .type = 0, + .flags = UKPLAT_MEMRF_UNMAP, + }); } int ukplat_mem_init(void) @@ -569,12 +569,13 @@ int ukplat_mem_init(void) { struct ukplat_bootinfo *bi = ukplat_bootinfo_get(); struct ukplat_memregion_desc *mrdp; - __vaddr_t unmap_start, unmap_end, unmap_len; + __paddr_t unmap_start, unmap_end, unmap_len; int i; UK_ASSERT(bi); - ALIGN_FREE_MEMREGION(&bpt_unmap_mrd, unmap_start, unmap_len, unmap_end); + align_free_memregion(&bpt_unmap_mrd, &unmap_start, &unmap_len, + &unmap_end); for (i = (int)bi->mrds.count - 1; i >= 0; i--) { ukplat_memregion_get(i, &mrdp); if (mrdp->vbase >= unmap_end -- Gitee From fc505c79dddd3de465a2dff22155e4c7a6832c3c Mon Sep 17 00:00:00 2001 From: liu__sai Date: Tue, 2 Jan 2024 11:23:12 +0800 Subject: [PATCH 26/57] ci:update to helloworld 0.15 Signed-off-by: liu__sai --- ci/.jenkinsfile | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/ci/.jenkinsfile b/ci/.jenkinsfile index fa0147a9..d55ef44b 100644 --- a/ci/.jenkinsfile +++ b/ci/.jenkinsfile @@ -28,7 +28,7 @@ string xenConfig = """ name = 'helloworld' vcpus = '1' memory = '4' -kernel = 'build/run_xen-x86_64_xen-x86_64.dbg' +kernel = 'workdir/build/run_xen-x86_64_xen-x86_64.dbg' """ /* fc配置文件内容 */ @@ -125,15 +125,13 @@ pipeline { cd $WORKSPACE git clone $gitAppHelloWorldURL cd app-helloworld - # 获取以下两次commit的中defconfig文件 - git cherry-pick -n 06ee0b7 438ca02 - mkdir .unikraft .unikraft/unikraft + mkdir workdir workdir/unikraft cd - - # 将unikraft拷贝至app-helloworld/.unikraft/unikraft中 - cp -r `ls |grep -v 'app-helloworld'|xargs` app-helloworld/.unikraft/unikraft + # 将unikraft拷贝至app-helloworld/workdir/unikraft中 + cp -r `ls |grep -v 'app-helloworld'|xargs` app-helloworld/workdir/unikraft # 默认使用与unikraft相同的分支 # TODO: 应该提供一个能够从外部传入的参数指定这个分支,两个库同步修改的情况下需要用到 - git clone -b $targetBranch $gitPlatRaspiUrl app-helloworld/.unikraft/unikraft/plat/raspi + git clone -b $targetBranch $gitPlatRaspiUrl app-helloworld/workdir/unikraft/plat/raspi # 为每个测试项建立独立目录 mkdir ut_self-test ut_libc-test run_qemu-x86_64 run_qemu-arm64 run_xen-x86_64 run_fc-x86_64 run_linuxu-x86_64 run_linuxu-arm64 cp -r app-helloworld/. ut_libc-test @@ -220,12 +218,12 @@ pipeline { #!/bin/bash cd $WORKSPACE/ut_libc-test git clone $gitAppHelloWorldURL - git clone $gitLibMuslUrl .unikraft/libs/musl - git clone $gitLibcTestUrl .unikraft/libs/libc-test + git clone $gitLibMuslUrl workdir/libs/musl + git clone $gitLibcTestUrl workdir/libs/libc-test # 将musl库与libc-test库编入Makefile sed -i '/^LIBS/{s/\$/\$(UK_LIBS)\\/musl:\$(UK_LIBS)\\/libc-test/}' Makefile # 将libc-test库依赖的源码URL改为官网URL,源码URL下载不稳定 - sed -i '/LIBLIBCTEST_URL/s/git:\\/\\/nsz.repo.hu:49100\\/repo\\/libc-test/git:\\/\\/repo.or.cz\\/libc-test/g' .unikraft/libs/libc-test/Makefile.uk + sed -i '/LIBLIBCTEST_URL/s/git:\\/\\/nsz.repo.hu:49100\\/repo\\/libc-test/git:\\/\\/repo.or.cz\\/libc-test/g' workdir/libs/libc-test/Makefile.uk # uktest测试库也需要musl编入 cd .. cp -r ut_libc-test/. ut_self-test @@ -257,7 +255,7 @@ pipeline { result = sh(script: ''' #!/bin/bash cd $WORKSPACE/ut_libc-test - make defconfig UK_DEFCONFIG=$PWD/.unikraft/unikraft/ci/defconfigs/raspi-arm64-libc-test + make defconfig UK_DEFCONFIG=$PWD/workdir/unikraft/ci/defconfigs/raspi-arm64-libc-test ''', returnStatus: true) if (result != 0) { failNum++ @@ -271,10 +269,10 @@ pipeline { cd $WORKSPACE/ut_libc-test # 编译unikraft, make & run流程 make -j$nBuildThreads - raspiRoot=$PWD/.unikraft/unikraft/plat/raspi + raspiRoot=$PWD/workdir/unikraft/plat/raspi qemu-system-aarch64 -cpu cortex-a53 -machine raspi3b -nodefaults -display none \ -pidfile $WORKSPACE/libc-test$BUILD_NUMBER.pid -serial file:$WORKSPACE/libc-test$BUILD_NUMBER.out \ - -kernel build/kernel8.img -dtb ${raspiRoot}/bootfiles/bcm2710-rpi-3-b-plus.dtb -append verbose & + -kernel workdir/build/kernel8.img -dtb ${raspiRoot}/bootfiles/bcm2710-rpi-3-b-plus.dtb -append verbose & # 后台运行,等待15s sleep 15s ''', returnStatus: true) @@ -308,7 +306,7 @@ pipeline { exeNum++ result = sh(script: ''' cd $WORKSPACE/ut_self-test - make defconfig UK_DEFCONFIG=$PWD/.unikraft/unikraft/ci/defconfigs/raspi-arm64-uktest + make defconfig UK_DEFCONFIG=$PWD/workdir/unikraft/ci/defconfigs/raspi-arm64-uktest ''', returnStatus: true) if (result != 0) { failNum++ @@ -322,10 +320,10 @@ pipeline { cd $WORKSPACE/ut_self-test # 编译unikraft, make & run流程 make -j$nBuildThreads - raspiRoot=$PWD/.unikraft/unikraft/plat/raspi + raspiRoot=$PWD/workdir/unikraft/plat/raspi qemu-system-aarch64 -cpu cortex-a53 -machine raspi3b -nodefaults -display none \ -pidfile $WORKSPACE/self-test$BUILD_NUMBER.pid -serial file:$WORKSPACE/self-test$BUILD_NUMBER.out \ - -kernel build/kernel8.img -dtb ${raspiRoot}/bootfiles/bcm2710-rpi-3-b-plus.dtb -append verbose & + -kernel workdir/build/kernel8.img -dtb ${raspiRoot}/bootfiles/bcm2710-rpi-3-b-plus.dtb -append verbose & # 后台运行,等待15s sleep 15s ''', returnStatus: true) @@ -370,9 +368,9 @@ pipeline { exeNum++ result = sh(script:''' cd $WORKSPACE/run_qemu-x86_64 - UK_DEFCONFIG=\$PWD/.config.helloworld-qemu-x86_64 make defconfig + UK_DEFCONFIG=\$PWD/defconfigs/qemu-x86_64 make defconfig make -j$nBuildThreads - qemu-system-x86_64 -kernel build/helloworld_qemu-x86_64 -nographic + qemu-system-x86_64 -kernel workdir/build/helloworld_qemu-x86_64 -nographic ''', returnStatus: true) if (result == 0) { sucNum++ @@ -392,9 +390,9 @@ pipeline { exeNum++ result = sh(script:''' cd $WORKSPACE/run_qemu-arm64 - UK_DEFCONFIG=\$PWD/.config.helloworld-qemu-aarch64 make defconfig + UK_DEFCONFIG=\$PWD/defconfigs/qemu-arm64 make defconfig make -j$nBuildThreads - qemu-system-aarch64 -kernel build/helloworld_qemu-arm64 -nographic -machine virt -cpu cortex-a57 + qemu-system-aarch64 -kernel workdir/build/helloworld_qemu-arm64 -nographic -machine virt -cpu cortex-a57 ''', returnStatus: true) if (result == 0) { sucNum++ @@ -421,7 +419,7 @@ pipeline { result = sh(script:''' #!/bin/bash cd $WORKSPACE/run_xen-x86_64 - UK_DEFCONFIG=$PWD/.unikraft/unikraft/ci/defconfigs/xen-x86_64 make defconfig + UK_DEFCONFIG=$PWD/workdir/unikraft/ci/defconfigs/xen-x86_64 make defconfig make -j$nBuildThreads xl create -c helloworld.cfg ''', returnStatus: true) @@ -480,7 +478,7 @@ pipeline { result = sh(script:''' #!/bin/bash cd $WORKSPACE/run_linuxu-x86_64 - UK_DEFCONFIG=\$PWD/.unikraft/unikraft/ci/defconfigs/linuxu-x86_64 make defconfig + UK_DEFCONFIG=\$PWD/workdir/unikraft/ci/defconfigs/linuxu-x86_64 make defconfig make -j$nBuildThreads ''', returnStatus: true) if (result == 0) { @@ -501,7 +499,7 @@ pipeline { exeNum++ result = sh(script:''' cd $WORKSPACE/run_linuxu-arm64 - UK_DEFCONFIG=\$PWD/.unikraft/unikraft/ci/defconfigs/linuxu-arm64 make defconfig + UK_DEFCONFIG=\$PWD/workdir/unikraft/ci/defconfigs/linuxu-arm64 make defconfig make -j$nBuildThreads # 虚拟机目前是linux x86_64系统,暂时先不运行 # ./build/app-helloworld_linuxu-arm64 -- Gitee From 335ac4a708f579a68cd9d43534e4f26ae69bc20c Mon Sep 17 00:00:00 2001 From: liu__sai Date: Wed, 20 Dec 2023 10:54:07 +0800 Subject: [PATCH 27/57] plat/drivers:make pl011.c a unified framework Signed-off-by: liu__sai --- drivers/uktty/pl011/include/uk/tty/pl011.h | 49 +++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/drivers/uktty/pl011/include/uk/tty/pl011.h b/drivers/uktty/pl011/include/uk/tty/pl011.h index a468d6e0..554cedd5 100644 --- a/drivers/uktty/pl011/include/uk/tty/pl011.h +++ b/drivers/uktty/pl011/include/uk/tty/pl011.h @@ -34,10 +34,57 @@ extern "C" { #endif +/* PL011 UART registers and masks*/ +/* Data register */ +#define REG_UARTDR_OFFSET 0x00 + +/* Receive status register/error clear register */ +#define REG_UARTRSR_OFFSET 0x04 +#define REG_UARTECR_OFFSET 0x04 + +/* Flag register */ +#define REG_UARTFR_OFFSET 0x18 +#define FR_TXFF (1 << 5) /* Transmit FIFO/reg full */ +#define FR_RXFE (1 << 4) /* Receive FIFO/reg empty */ + +/* Integer baud rate register */ +#define REG_UARTIBRD_OFFSET 0x24 +/* Fractional baud rate register */ +#define REG_UARTFBRD_OFFSET 0x28 + +/* Line control register */ +#define REG_UARTLCR_H_OFFSET 0x2C +#define LCR_H_WLEN8 (0x3 << 5) /* Data width is 8-bits */ + +/* Control register */ +#define REG_UARTCR_OFFSET 0x30 +#define CR_RXE (1 << 9) /* Receive enable */ +#define CR_TXE (1 << 8) /* Transmit enable */ +#define CR_UARTEN (1 << 0) /* UART enable */ + +/* Interrupt FIFO level select register */ +#define REG_UARTIFLS_OFFSET 0x34 +/* Interrupt mask set/clear register */ +#define REG_UARTIMSC_OFFSET 0x38 +/* Raw interrupt status register */ +#define REG_UARTRIS_OFFSET 0x3C +/* Masked interrupt status register */ +#define REG_UARTMIS_OFFSET 0x40 +/* Interrupt clear register */ +#define REG_UARTICR_OFFSET 0x44 + +extern uint8_t pl011_uart_initialized; +extern uint64_t pl011_uart_bas; + +/* Macros to access PL011 Registers with base address */ +#define PL011_REG(r) ((uint16_t *)(pl011_uart_bas + (r))) +#define PL011_REG_READ(r) ioreg_read16(PL011_REG(r)) +#define PL011_REG_WRITE(r, v) ioreg_write16(PL011_REG(r), v) + /** * Initialize the pl011 console driver */ -void pl011_console_init(void *dtb); +void pl011_console_init(const void *dtb); #ifdef __cplusplus } -- Gitee From 99ccf0c849f692f0b299c1e1e0abe196d9fe26a7 Mon Sep 17 00:00:00 2001 From: liu__sai Date: Tue, 2 Jan 2024 11:23:12 +0800 Subject: [PATCH 28/57] ci: rebuild the structure of ci Signed-off-by: liu__sai --- ci/.jenkinsfile | 583 +++++++++++++++++----------- ci/defconfigs/raspi-arm64-libc-test | 10 +- ci/defconfigs/raspi-arm64-uktest | 3 - 3 files changed, 357 insertions(+), 239 deletions(-) diff --git a/ci/.jenkinsfile b/ci/.jenkinsfile index d55ef44b..560b176a 100644 --- a/ci/.jenkinsfile +++ b/ci/.jenkinsfile @@ -17,18 +17,65 @@ string ret = "" /* 库相关 */ -string gitAppHelloWorldURL = "git@gitee.com:yingyitech/app-helloworld.git" -string gitPlatRaspiUrl = "https://gitee.com/yingyitech/plat-raspi.git" -string gitLibMuslUrl = "git@gitee.com:yingyitech/lib-musl.git" -string gitLibcTestUrl = "git@gitee.com:yingyitech/lib-libc-test.git" -string targetBranch = env.giteeTargetBranch +def UnikraftRepoInfo = [ +] + +def AppsRepoInfo = [ + [ + name:"app-helloworld", + url:"git@gitee.com:yingyitech/app-helloworld.git", + branch:'master', + /* 拉取代码后所做的一些统一的操作 */ + ops_after_clone:''' + # 为app-helloworld 建立工作目录结构 + cd app-helloworld + mkdir workdir + cd workdir + mkdir libs unikraft + ''' + ], +] + +def LibsRepoInfo = [ + [ + name:"lib-musl", + url:"git@gitee.com:yingyitech/lib-musl.git", + branch:'master', + ops_after_clone:''' + # 由于官网musl库获取tar包获取不稳定因此改为从fork的公司库获取 + cd lib-musl + sed -i 's|LIBMUSL_URL=https://www.musl-libc.org/releases/musl-\$(LIBMUSL_VERSION).tar.gz|LIBMUSL_URL=https://gitee.com/yingyitech/fork-musl/repository/archive/v\$(LIBMUSL_VERSION).zip|' Makefile.uk + sed -i 's|\$(eval \$(call patch,libmusl,\$(LIBMUSL_PATCHDIR),musl-\$(LIBMUSL_VERSION)))|\$(eval \$(call patch,libmusl,\$(LIBMUSL_PATCHDIR),fork-musl-v\$(LIBMUSL_VERSION)))|' Makefile.uk + sed -i 's|LIBMUSL_SUBDIR=musl-\$(LIBMUSL_VERSION)|LIBMUSL_SUBDIR=fork-musl-v\$(LIBMUSL_VERSION)|' Makefile.uk + ''' + ], + [ + name:"lib-libc-test", + url:"git@gitee.com:yingyitech/lib-libc-test.git", + branch:'master', + ops_after_clone:''' + # 将libc-test库依赖的源码URL改为官网URL,源码URL下载不稳定 + cd lib-libc-test + sed -i '/LIBLIBCTEST_URL/s/git:\\/\\/nsz.repo.hu:49100\\/repo\\/libc-test/git:\\/\\/repo.or.cz\\/libc-test/g' Makefile.uk + ''' + ], +] + +def PlatsRepoInfo = [ + [ + name:"plat-raspi", + url:"https://gitee.com/yingyitech/plat-raspi.git", + branch:'master', + ops_after_clone:'''''' + ], +] /* XEN配置文件内容 */ string xenConfig = """ name = 'helloworld' vcpus = '1' memory = '4' -kernel = 'workdir/build/run_xen-x86_64_xen-x86_64.dbg' +kernel = 'workdir/build/app-helloworld_xen-x86_64.dbg' """ /* fc配置文件内容 */ @@ -73,6 +120,51 @@ int failNum = 0 if (env.giteeActionType == "NOTE" && env.giteeTriggerPhrase.contains("skip_check")) { tolNum-- } +/* 存储依赖pr信息 */ +DpendedPRData = [ + "app-helloworld":[], + "plat-raspi":[], + "lib-musl":[], + "lib-libc-test":[], + "unikraft":[] +] +/* 根据仓库名去DepenedPRData里获取对应依赖pr信息,并根据路径进入到对应目录下 */ +def MergeDependedPR(def reponame, def path){ + if (!DpendedPRData[reponame].isEmpty()) { + DpendedPRData[reponame].each{ pr -> + result = sh(script: """ + #!/bin/bash + cd $WORKSPACE + cd $path + git fetch https://gitee.com/${pr.owner}/${pr.reponame}.git pull/${pr.prnumber}/head:pr_${pr.prnumber} + git merge pr_${pr.prnumber} + """, returnStatus: true) + if (result != 0) { + ret = ret + "\n|merge依赖PR|**失败**|具体规范要求见任务链接|" + error 'merge依赖PR失败' + } + } + } +} +/* @NonCPS指定本方法不被CPS转换,规定Jenkins不优化本方法内的非序列化变量matcher */ +@NonCPS +def GetDependedPRInfo() { + def prDesc = env.giteePullRequestDescription + /* 检测并获取依赖PR的信息 */ + if (prDesc.contains("相关PR:")) { + prDesc = prDesc.substring(prDesc.indexOf("相关PR:") + 5) + print(prDesc) + /* 获取相关PR的链接 */ + pattern = /\[(?:.*(?:\[.+\])*.*)\]\(.+\/([^\/]+)\/([^\/]+)\/pulls\/(\d+)\)/ + def matcher = (prDesc =~ pattern) + def prinfo = "" + while(matcher.find()){ + /* 分离链接中的信息 */ + prinfo = [owner:matcher.group(1),reponame:matcher.group(2),prnumber:matcher.group(3)] + DpendedPRData[prinfo.reponame].add(prinfo) + } + } +} /* pipeline 定义了整个测试流程中的工作 */ pipeline { @@ -85,7 +177,7 @@ pipeline { timestamps() } - /* stages 为pipeline需要的步骤集 */ + /* stages 为pipeline需要的步骤集 */ stages { /* stage 定义一个名为'***'的单个构建步骤 */ stage('开始CI测试,通知PR评论') { @@ -110,7 +202,7 @@ pipeline { } } } - stage('初始化公共代码仓') { + stage('初始化代码仓') { when { not { expression {env.giteeActionType == "NOTE" && (env.giteeTriggerPhrase[0..3] == "help")} @@ -119,32 +211,58 @@ pipeline { steps { /* script 块可以调用groovy方法 */ script { - /* 调用shell脚本,执行check测试。使用NAME = sh()形式可以防止shell脚本出错直接退出stage */ + /* 1.获得相关PR信息 */ + GetDependedPRInfo() + /* 2.初始化各类代码仓和目录结构 */ result = sh(script: """ - #!/bin/bash - cd $WORKSPACE - git clone $gitAppHelloWorldURL - cd app-helloworld - mkdir workdir workdir/unikraft - cd - - # 将unikraft拷贝至app-helloworld/workdir/unikraft中 - cp -r `ls |grep -v 'app-helloworld'|xargs` app-helloworld/workdir/unikraft - # 默认使用与unikraft相同的分支 - # TODO: 应该提供一个能够从外部传入的参数指定这个分支,两个库同步修改的情况下需要用到 - git clone -b $targetBranch $gitPlatRaspiUrl app-helloworld/workdir/unikraft/plat/raspi - # 为每个测试项建立独立目录 - mkdir ut_self-test ut_libc-test run_qemu-x86_64 run_qemu-arm64 run_xen-x86_64 run_fc-x86_64 run_linuxu-x86_64 run_linuxu-arm64 - cp -r app-helloworld/. ut_libc-test - cp -r app-helloworld/. run_qemu-x86_64 - cp -r app-helloworld/. run_qemu-arm64 - cp -r app-helloworld/. run_xen-x86_64 - cp -r app-helloworld/. run_fc-x86_64 - cp -r app-helloworld/. run_linuxu-x86_64 - cp -r app-helloworld/. run_linuxu-arm64 - """, returnStatus: true) - if (result != 0) { - ret = "初始化代码仓失败,详见任务链接" - error '初始化代码仓失败' + #!/bin/bash + cd $WORKSPACE + mkdir unikraft + cp -r `ls |grep -v 'unikraft'|xargs` unikraft + mkdir apps libs plats + """, returnStatus: true) + MergeDependedPR("unikraft", "unikraft") + for (item in AppsRepoInfo) { + result = sh(script: """ + cd $WORKSPACE + cd apps + git clone ${item.url} -b ${item.branch} + ${item.ops_after_clone} + """, returnStatus: true) + if (result != 0) { + failNum++ + ret = ret + "\n|初始化Apps|**失败**|具体规范要求见任务链接|" + error '初始化Apps失败' + } + MergeDependedPR(item.name, "apps/"+item.name) + } + for (item in LibsRepoInfo) { + result = sh(script: """ + cd $WORKSPACE + cd libs + git clone ${item.url} -b ${item.branch} + ${item.ops_after_clone} + """, returnStatus: true) + if (result != 0) { + failNum++ + ret = ret + "\n|初始化Libs|**失败**|具体规范要求见任务链接|" + error '初始化Libs失败' + } + MergeDependedPR(item.name, "libs/"+item.name) + } + for (item in PlatsRepoInfo) { + result = sh(script: """ + cd $WORKSPACE + cd plats + git clone ${item.url} -b ${item.branch} + ${item.ops_after_clone} + """, returnStatus: true) + if (result != 0) { + failNum++ + ret = ret + "\n|初始化Plats|**失败**|具体规范要求见任务链接|" + error '初始化Plats失败' + } + MergeDependedPR(item.name, "plats/"+item.name) } } } @@ -159,10 +277,10 @@ pipeline { script { exeNum++ result = sh(script: ''' - #!/bin/sh - cd $WORKSPACE - ./ci/scripts/check_pr_title.sh "$giteePullRequestTitle" - ''', returnStatus: true) + #!/bin/sh + cd $WORKSPACE + ./ci/scripts/check_pr_title.sh "$giteePullRequestTitle" + ''', returnStatus: true) /* 结果分支处理,将信息添加至ret中 */ if (result == 0) { sucNum++ @@ -175,126 +293,108 @@ pipeline { } } } - /* check测试步骤,进行commit信息规范与patch增量代码规范检查 */ - /* unikraft社区commit描述推荐格式 [selector]/[component name]: [Your short message] - * exp: lib/uktest: selftest - * 社区检查脚本只检查是否含有":",原则上commit信息需要符合社区规定 - */ stage('社区commit规范检查') { - /* when 块可以控制本stage执行条件,此处当PR评论内容不为test_skip_check时才执行 */ - when { - not { - expression {env.giteeActionType == "NOTE" && - ((env.giteeTriggerPhrase[0..3] == "help") || (env.giteeTriggerPhrase.contains("skip_check")))} - } - } - steps { - script { - exeNum++ - result = sh(script: ''' - #!/bin/sh - cd $WORKSPACE - git format-patch HEAD~1 - ./support/scripts/checkpatch.uk ./000* --no-signoff - ''', returnStatus: true) - if (result == 0) { - sucNum++ - ret = ret + "\n|社区commit信息与代码规范检查|成功||" - } else { - failNum++ - ret = ret + "\n|社区commit信息与代码规范检查|**失败**|具体规范要求见任务链接|" - error '社区commit信息与代码规范检查失败' - } - } - } - } - - stage('初始化libmusl代码仓') { + /* check测试步骤,进行commit信息规范与patch增量代码规范检查 */ + /* unikraft社区commit描述推荐格式 [selector]/[component name]: [Your short message] + * exp: lib/uktest: selftest + * 社区检查脚本只检查是否含有":",原则上commit信息需要符合社区规定 + */ + when { + not { + expression {env.giteeActionType == "NOTE" && + ((env.giteeTriggerPhrase[0..3] == "help") || (env.giteeTriggerPhrase.contains("skip_check")))} + } + } steps { - /* script 块可以调用groovy方法 */ script { - /* 调用shell脚本,执行check测试。使用NAME = sh()形式可以防止shell脚本出错直接退出stage */ - result = sh(script: """ - #!/bin/bash - cd $WORKSPACE/ut_libc-test - git clone $gitAppHelloWorldURL - git clone $gitLibMuslUrl workdir/libs/musl - git clone $gitLibcTestUrl workdir/libs/libc-test - # 将musl库与libc-test库编入Makefile - sed -i '/^LIBS/{s/\$/\$(UK_LIBS)\\/musl:\$(UK_LIBS)\\/libc-test/}' Makefile - # 将libc-test库依赖的源码URL改为官网URL,源码URL下载不稳定 - sed -i '/LIBLIBCTEST_URL/s/git:\\/\\/nsz.repo.hu:49100\\/repo\\/libc-test/git:\\/\\/repo.or.cz\\/libc-test/g' workdir/libs/libc-test/Makefile.uk - # uktest测试库也需要musl编入 - cd .. - cp -r ut_libc-test/. ut_self-test - """, returnStatus: true) - if (result != 0) { - ret = ret + "\n\n初始化libmusl失败,详见任务链接" - error '初始化libmusl失败' + exeNum++ + result = sh(script: ''' + #!/bin/sh + cd $WORKSPACE + git format-patch HEAD~1..HEAD + ./support/scripts/checkpatch.uk ./000* --no-signoff + ''', returnStatus: true) + if (result == 0) { + sucNum++ + ret = ret + "\n|社区commit信息与代码规范检查|成功||" + } else { + failNum++ + ret = ret + "\n|社区commit信息与代码规范检查|**失败**|具体规范要求见任务链接|" + error '社区commit信息与代码规范检查失败' } } } } - - /* UT测试步骤,打开uktest,测试是否可以通过libc测试与自验用例集 */ - stage('UT测试') { + stage('运行测试用例') { when { not { expression {env.giteeActionType == "NOTE" && (env.giteeTriggerPhrase[0..3] == "help")} } } - /* failFast 设置是否其中一个stage失败则立即停止此parallel所有任务 */ failFast false - /* parallel 并行开始stage */ parallel { + /* 1.UT测试步骤,打开uktest,测试是否可以通过libc测试与自验用例集 */ stage('libc-test') { steps { /* 初始化make config配置 */ script { exeNum++ result = sh(script: ''' - #!/bin/bash - cd $WORKSPACE/ut_libc-test - make defconfig UK_DEFCONFIG=$PWD/workdir/unikraft/ci/defconfigs/raspi-arm64-libc-test - ''', returnStatus: true) + #!/bin/bash + cd $WORKSPACE + mkdir ut_libc-test + cp -r apps/app-helloworld ut_libc-test/ + cp -r unikraft/* ut_libc-test/app-helloworld/workdir/unikraft + ln -s $WORKSPACE/plats/plat-raspi ut_libc-test/app-helloworld/workdir/unikraft/plat/raspi + ln -s $WORKSPACE/libs/lib-musl ut_libc-test/app-helloworld/workdir/libs/musl + ln -s $WORKSPACE/libs/lib-libc-test ut_libc-test/app-helloworld/workdir/libs/libc-test + cd ut_libc-test/app-helloworld + sed -i '/^LIBS/{s/\$/\$(UK_LIBS)\\/musl:\$(UK_LIBS)\\/libc-test/}' Makefile + make defconfig UK_DEFCONFIG=$PWD/workdir/unikraft/ci/defconfigs/raspi-arm64-libc-test + ''', returnStatus: true) if (result != 0) { failNum++ - ret = ret + "\n|UT测试|**libc-test失败**|初始化make config配置失败|" + ret = ret + "\n|测试用例|**libc-test失败**|初始化make config配置失败|" error '初始化make config配置失败!' } } /* make & run*/ script { result = sh(script: ''' - cd $WORKSPACE/ut_libc-test - # 编译unikraft, make & run流程 - make -j$nBuildThreads - raspiRoot=$PWD/workdir/unikraft/plat/raspi - qemu-system-aarch64 -cpu cortex-a53 -machine raspi3b -nodefaults -display none \ - -pidfile $WORKSPACE/libc-test$BUILD_NUMBER.pid -serial file:$WORKSPACE/libc-test$BUILD_NUMBER.out \ - -kernel workdir/build/kernel8.img -dtb ${raspiRoot}/bootfiles/bcm2710-rpi-3-b-plus.dtb -append verbose & - # 后台运行,等待15s - sleep 15s - ''', returnStatus: true) + cd $WORKSPACE/ut_libc-test/app-helloworld + # 编译unikraft, make & run流程 + make -j$nBuildThreads + raspiRoot=$PWD/workdir/unikraft/plat/raspi + qemu-system-aarch64 -cpu cortex-a53 -machine raspi3b -nodefaults -display none \ + -pidfile $WORKSPACE/libc-test$BUILD_NUMBER.pid -serial file:$WORKSPACE/libc-test$BUILD_NUMBER.out \ + -kernel workdir/build/kernel8.img -dtb ${raspiRoot}/bootfiles/bcm2710-rpi-3-b-plus.dtb -append verbose & + # 后台运行,等待15s + sleep 15s + ''', returnStatus: true) if (result == 0) { - resultCheck = sh(script: ''' - cd $WORKSPACE/ - # 如果输出文件中包含Hello world!则判断运行成功 - cat $WORKSPACE/libc-test$BUILD_NUMBER.out - grep -q "Hello" $WORKSPACE/libc-test$BUILD_NUMBER.out - ''', returnStatus: true) - if (resultCheck == 0) { + /* 校验是否成功打印hello world! */ + resultCheck_helloworld = sh(script: ''' + cd $WORKSPACE/ + cat $WORKSPACE/libc-test$BUILD_NUMBER.out + grep -q "Hello" $WORKSPACE/libc-test$BUILD_NUMBER.out + ''', returnStatus: true) + /* 校验uktest用例是否失败 */ + resultCheck_libc_test = sh(script: ''' + cd $WORKSPACE/ + grep "\\[ FAILED ]" $WORKSPACE/libc-test$BUILD_NUMBER.out + ''', returnStatus: true) + if (resultCheck_helloworld == 0 && resultCheck_libc_test != 0) { sucNum++ - ret = ret + "\n|UT测试|libc-test成功||" + ret = ret + "\n|测试用例|libc-test成功||" } else { failNum++ - ret = ret + "\n|UT测试|**libc-test失败**|运行失败,详见任务链接|" - error 'UT测试运行libc-test失败!' + ret = ret + "\n|测试用例|**uktest用例(libc-test)失败**|运行失败,详见任务链接|" + error '运行uktest用例失败!' } } else { failNum++ - ret = ret + "\n|UT测试|**libc-test失败**|make命令失败,详见任务链接|" - error 'UT测试libc-test make失败!' + ret = ret + "\n|测试用例|**libc-test失败**|make命令失败,详见任务链接|" + error '运行测试用例libc-test make失败!' } } } @@ -305,80 +405,78 @@ pipeline { script { exeNum++ result = sh(script: ''' - cd $WORKSPACE/ut_self-test - make defconfig UK_DEFCONFIG=$PWD/workdir/unikraft/ci/defconfigs/raspi-arm64-uktest - ''', returnStatus: true) + cd $WORKSPACE + mkdir -p ut_self-test/unikraft + cp -r unikraft/* ut_self-test/unikraft + ln -s $WORKSPACE/plats/plat-raspi ut_self-test/unikraft/plat/raspi + cd ut_self-test/unikraft + make defconfig UK_DEFCONFIG=$PWD/ci/defconfigs/raspi-arm64-uktest + ''', returnStatus: true) if (result != 0) { failNum++ - ret = ret + "\n|UT测试|**self-test失败**|初始化make config配置失败|" + ret = ret + "\n|测试用例|**self-test失败**|初始化make config配置失败|" error '初始化make config配置失败!' } } - /* make & run*/ + /* make & run */ script { result = sh(script: ''' - cd $WORKSPACE/ut_self-test - # 编译unikraft, make & run流程 - make -j$nBuildThreads - raspiRoot=$PWD/workdir/unikraft/plat/raspi - qemu-system-aarch64 -cpu cortex-a53 -machine raspi3b -nodefaults -display none \ - -pidfile $WORKSPACE/self-test$BUILD_NUMBER.pid -serial file:$WORKSPACE/self-test$BUILD_NUMBER.out \ - -kernel workdir/build/kernel8.img -dtb ${raspiRoot}/bootfiles/bcm2710-rpi-3-b-plus.dtb -append verbose & - # 后台运行,等待15s - sleep 15s - ''', returnStatus: true) + cd $WORKSPACE/ut_self-test/unikraft + # 编译unikraft, make & run流程 + make -j$nBuildThreads + raspiRoot=$PWD/unikraft/plat/raspi + qemu-system-aarch64 -cpu cortex-a53 -machine raspi3b -nodefaults -display none \ + -pidfile $WORKSPACE/self-test$BUILD_NUMBER.pid -serial file:$WORKSPACE/self-test$BUILD_NUMBER.out \ + -kernel build/kernel8.img -dtb ${raspiRoot}/bootfiles/bcm2710-rpi-3-b-plus.dtb -append verbose & + # 后台运行,等待15s + sleep 15s + ''', returnStatus: true) if (result == 0) { + /* 校验uktest用例是否失败 */ resultCheck = sh(script: ''' - cd $WORKSPACE/ - # 如果输出文件中包含Hello world!则判断运行成功 - cat $WORKSPACE/self-test$BUILD_NUMBER.out - grep -q "Hello" $WORKSPACE/self-test$BUILD_NUMBER.out - ''', returnStatus: true) - if (resultCheck == 0) { + cd $WORKSPACE/ + grep "\\[ FAILED ]" $WORKSPACE/self-test$BUILD_NUMBER.out + ''', returnStatus: true) + if (resultCheck != 0) { sucNum++ - ret = ret + "\n|UT测试|self-test成功||" + ret = ret + "\n|测试用例|self-test成功||" } else { failNum++ - ret = ret + "\n|UT测试|**self-test失败**|运行失败,详见任务链接|" - error 'UT测试self-test运行失败!' + ret = ret + "\n|测试用例|**uktest用例(self-test)失败**|运行失败,详见任务链接|" + error '运行uktest用例失败!' } } else { failNum++ - ret = ret + "\n|UT测试|**self-test失败**|make命令失败,详见任务链接|" - error 'UT测试self-test make失败!' + ret = ret + "\n|测试用例|**self-test失败**|make命令失败,详见任务链接|" + error '测试用例self-test make失败!' } } } } - } - } - /* 兼容性测试步骤,测试是否影响到支持的其他平台与架构 */ - stage('兼容性测试') { - when { - not { - expression {env.giteeActionType == "NOTE" && (env.giteeTriggerPhrase[0..3] == "help")} - } - } - failFast false - parallel { + /* 2.兼容性测试步骤,测试是否影响到支持的其他平台与架构 */ stage('helloworld (qemu, x86_64)') { steps { script { exeNum++ result = sh(script:''' - cd $WORKSPACE/run_qemu-x86_64 - UK_DEFCONFIG=\$PWD/defconfigs/qemu-x86_64 make defconfig - make -j$nBuildThreads - qemu-system-x86_64 -kernel workdir/build/helloworld_qemu-x86_64 -nographic - ''', returnStatus: true) + cd $WORKSPACE + mkdir run_qemu-x86_64 + cp -r apps/app-helloworld run_qemu-x86_64/ + cp -r unikraft/* run_qemu-x86_64/app-helloworld/workdir/unikraft + ln -s $WORKSPACE/plats/plat-raspi run_qemu-x86_64/app-helloworld/workdir/unikraft/plat/raspi + cd run_qemu-x86_64/app-helloworld + UK_DEFCONFIG=\$PWD/defconfigs/qemu-x86_64 make defconfig + make -j$nBuildThreads + qemu-system-x86_64 -kernel workdir/build/helloworld_qemu-x86_64 -nographic + ''', returnStatus: true) if (result == 0) { sucNum++ - ret = ret + "\n|兼容性测试|helloworld (qemu, x86_64)成功||" + ret = ret + "\n|测试用例|helloworld (qemu, x86_64)成功||" } else { failNum++ - ret = ret + "\n|兼容性测试|**helloworld (qemu, x86_64)失败**|运行失败,详见任务链接|" - error '兼容性测试 helloworld (qemu, x86_64) 失败!' + ret = ret + "\n|测试用例|**helloworld (qemu, x86_64)失败**|运行失败,详见任务链接|" + error '测试用例 helloworld (qemu, x86_64) 失败!' } } } @@ -389,18 +487,23 @@ pipeline { script { exeNum++ result = sh(script:''' - cd $WORKSPACE/run_qemu-arm64 - UK_DEFCONFIG=\$PWD/defconfigs/qemu-arm64 make defconfig - make -j$nBuildThreads - qemu-system-aarch64 -kernel workdir/build/helloworld_qemu-arm64 -nographic -machine virt -cpu cortex-a57 - ''', returnStatus: true) + cd $WORKSPACE + mkdir run_qemu-arm64 + cp -r apps/app-helloworld run_qemu-arm64/ + cp -r unikraft/* run_qemu-arm64/app-helloworld/workdir/unikraft + ln -s $WORKSPACE/plats/plat-raspi run_qemu-arm64/app-helloworld/workdir/unikraft/plat/raspi + cd run_qemu-arm64/app-helloworld + UK_DEFCONFIG=\$PWD/defconfigs/qemu-arm64 make defconfig + make -j$nBuildThreads + qemu-system-aarch64 -kernel workdir/build/helloworld_qemu-arm64 -nographic -machine virt -cpu cortex-a57 + ''', returnStatus: true) if (result == 0) { sucNum++ - ret = ret + "\n|兼容性测试|helloworld (qemu, arm64)成功||" + ret = ret + "\n|测试用例|helloworld (qemu, arm64)成功||" } else { failNum++ - ret = ret + "\n|兼容性测试|**helloworld (qemu, arm64)失败**|运行失败,详见任务链接|" - error '兼容性测试 helloworld (qemu, arm64) 失败!' + ret = ret + "\n|测试用例|**helloworld (qemu, arm64)失败**|运行失败,详见任务链接|" + error '测试用例 helloworld (qemu, arm64) 失败!' } } } @@ -411,25 +514,30 @@ pipeline { script { exeNum++ result = sh(script:""" - #!/bin/bash - cd $WORKSPACE/run_xen-x86_64 - cat>helloworld.cfg<helloworld.cfg<fc-x86_64.json<fc-x86_64.json< Date: Fri, 22 Dec 2023 09:57:57 +0800 Subject: [PATCH 29/57] lib/ukintctlr: support interrupt-controller driver of raspi Signed-off-by: 1788594346 --- drivers/ukintctlr/Makefile.uk | 1 + drivers/ukintctlr/bcm_intc/Config.uk | 16 + drivers/ukintctlr/bcm_intc/Makefile.uk | 12 + drivers/ukintctlr/bcm_intc/bcm2835_intc.c | 249 ++++++++++++++ drivers/ukintctlr/bcm_intc/bcm2836_intc.c | 310 ++++++++++++++++++ .../ukintctlr/bcm_intc/bcm_intc_initialize.c | 117 +++++++ drivers/ukintctlr/bcm_intc/exportsyms.uk | 1 + .../include/uk/intctlr/bcm2835_intc.h | 85 +++++ .../include/uk/intctlr/bcm2836_intc.h | 58 ++++ .../bcm_intc/include/uk/intctlr/bcm_intc.h | 53 +++ .../bcm_intc/include/uk/intctlr/limits.h | 27 ++ drivers/ukintctlr/gic/exportsyms.uk | 1 - drivers/ukintctlr/gic/ukintctlr.c | 5 +- drivers/ukintctlr/xpic/ukintctlr.c | 5 + lib/ukintctlr/exportsyms.uk | 3 + lib/ukintctlr/include/uk/intctlr.h | 30 ++ lib/ukintctlr/ukintctlr.c | 35 +- plat/common/arm/lcpu.c | 12 +- plat/common/arm/traps_arm64.c | 13 +- 19 files changed, 1006 insertions(+), 27 deletions(-) create mode 100644 drivers/ukintctlr/bcm_intc/Config.uk create mode 100644 drivers/ukintctlr/bcm_intc/Makefile.uk create mode 100644 drivers/ukintctlr/bcm_intc/bcm2835_intc.c create mode 100644 drivers/ukintctlr/bcm_intc/bcm2836_intc.c create mode 100644 drivers/ukintctlr/bcm_intc/bcm_intc_initialize.c create mode 100644 drivers/ukintctlr/bcm_intc/exportsyms.uk create mode 100644 drivers/ukintctlr/bcm_intc/include/uk/intctlr/bcm2835_intc.h create mode 100644 drivers/ukintctlr/bcm_intc/include/uk/intctlr/bcm2836_intc.h create mode 100644 drivers/ukintctlr/bcm_intc/include/uk/intctlr/bcm_intc.h create mode 100644 drivers/ukintctlr/bcm_intc/include/uk/intctlr/limits.h diff --git a/drivers/ukintctlr/Makefile.uk b/drivers/ukintctlr/Makefile.uk index 940c3d1a..296246d0 100644 --- a/drivers/ukintctlr/Makefile.uk +++ b/drivers/ukintctlr/Makefile.uk @@ -8,3 +8,4 @@ UK_DRIV_INTCTLR_BASE := $(UK_DRIV_BASE)/ukintctlr $(eval $(call import_lib,$(UK_DRIV_INTCTLR_BASE)/xpic)) $(eval $(call import_lib,$(UK_DRIV_INTCTLR_BASE)/gic)) +$(eval $(call import_lib,$(UK_DRIV_INTCTLR_BASE)/bcm_intc)) diff --git a/drivers/ukintctlr/bcm_intc/Config.uk b/drivers/ukintctlr/bcm_intc/Config.uk new file mode 100644 index 00000000..60fea952 --- /dev/null +++ b/drivers/ukintctlr/bcm_intc/Config.uk @@ -0,0 +1,16 @@ +config LIBUKINTCTLR_BCM_INTC + bool "bcm interrupt controller" + depends on (HAVE_INTCTLR && ARCH_ARM_64) + select LIBUKINTCTLR + default n + +config LIBUKINTCTLR_BCM2835_INTC + bool "bcm2835 interrupt controller" + depends on (LIBUKINTCTLR_BCM_INTC) + default n + +config LIBUKINTCTLR_BCM2836_INTC + bool "bcm2836/bcm2837 interrupt controller" + depends on (LIBUKINTCTLR_BCM_INTC) + select LIBUKINTCTLR_BCM2835_INTC + default y diff --git a/drivers/ukintctlr/bcm_intc/Makefile.uk b/drivers/ukintctlr/bcm_intc/Makefile.uk new file mode 100644 index 00000000..45a83e6c --- /dev/null +++ b/drivers/ukintctlr/bcm_intc/Makefile.uk @@ -0,0 +1,12 @@ +$(eval $(call addlib_s,libukintctlr_bcm_intc,$(CONFIG_LIBUKINTCTLR_BCM_INTC))) + +ASINCLUDES-$(CONFIG_LIBUKINTCTLR_BCM_INTC) += -I$(LIBUKINTCTLR_BCM_INTC_BASE)/include +CINCLUDES-$(CONFIG_LIBUKINTCTLR_BCM_INTC) += -I$(LIBUKINTCTLR_BCM_INTC_BASE)/include +CXXINCLUDES-$(CONFIG_LIBUKINTCTLR_BCM_INTC) += -I$(LIBUKINTCTLR_BCM_INTC_BASE)/include + +LIBUKINTCTLR_BCM_INTC_CINCLUDES-y += -I$(CONFIG_UK_BASE)/plat/common/include + +LIBUKINTCTLR_BCM_INTC_SRCS-y += $(LIBUKINTCTLR_BCM_INTC_BASE)/bcm_intc_initialize.c + +LIBUKINTCTLR_BCM_INTC_SRCS-$(CONFIG_LIBUKINTCTLR_BCM2835_INTC) += $(LIBUKINTCTLR_BCM_INTC_BASE)/bcm2835_intc.c +LIBUKINTCTLR_BCM_INTC_SRCS-$(CONFIG_LIBUKINTCTLR_BCM2836_INTC) += $(LIBUKINTCTLR_BCM_INTC_BASE)/bcm2836_intc.c diff --git a/drivers/ukintctlr/bcm_intc/bcm2835_intc.c b/drivers/ukintctlr/bcm_intc/bcm2835_intc.c new file mode 100644 index 00000000..0580e424 --- /dev/null +++ b/drivers/ukintctlr/bcm_intc/bcm2835_intc.c @@ -0,0 +1,249 @@ +/* Copyright 2023 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static const char *const bcm2835_intc_device_list[] __maybe_unused = { + /* 此处bcm2836-armctrl-ic沿用2835的中断控制器设计 */ + "brcm,bcm2836-armctrl-ic", + "brcm,bcm2835-armctrl-ic", + NULL +}; + +int fdt_bcm2835_intc_offset; + +/** bcm2835 interrupt driver */ +struct bcm_intc_dev bcm2835_intc_drv = { + .mem_addr = 0, + .mem_size = 0, +}; + +int fdt_xlat_bcm2835(const void *fdt, int nodeoffset, __u32 index, + struct uk_intctlr_irq *irq) +{ + int ret, size; + fdt32_t *prop; + __u32 bank_type, bank_irq_id; + + ret = fdt_get_interrupt(fdt, nodeoffset, index, &size, &prop); + if (unlikely(ret < 0)) + return ret; + + /* bcm中断控制器interrupt-cells为2 */ + UK_ASSERT(size == 2); + + bank_type = fdt32_to_cpu(prop[0]); + bank_irq_id = fdt32_to_cpu(prop[1]); + + switch (bank_type) { + case IRQ_BANK_BASIC: + if (bank_irq_id >= IRQ_BANK_BASIC_IRQ_MAX) + goto err; + irq->id = bank_irq_id + IRQ_BANK_BASIC_IRQ_OFFSET; + break; + case IRQ_BANK_1: + if (bank_irq_id >= IRQ_BANK_1_IRQ_MAX) + goto err; + irq->id = bank_irq_id + IRQ_BANK_1_IRQ_OFFSET; + break; + case IRQ_BANK_2: + if (bank_irq_id >= IRQ_BANK_2_IRQ_MAX) + goto err; + irq->id = bank_irq_id + IRQ_BANK_2_IRQ_OFFSET; + break; + default: + goto err; + } + + return 0; + +err: + uk_pr_err("DTB: bcm2835 interrupt irq bank err\n"); + uk_pr_err("bank_type: %x\n", bank_type); + uk_pr_err("bank_irq_id: %x\n", bank_irq_id); + return -FDT_ERR_BADNCELLS; +} + +static void bcm2835_intc_initialize(void) +{ + /* 初始化阶段先mask所有中断 */ + ioreg_write32((void *) + (ARM_SIDE_INTC_BASE + DISABLE_BASIC_IRQS_OFFSET), + IRQ_REG_MASK); + ioreg_write32((void *) + (ARM_SIDE_INTC_BASE + DISABLE_IRQS_1_OFFSET), + IRQ_REG_MASK); + ioreg_write32((void *) + (ARM_SIDE_INTC_BASE + DISABLE_IRQS_2_OFFSET), + IRQ_REG_MASK); +} + +static void bcm2835_intc_enable_irq(uint32_t irq) +{ + if ((irq >= IRQ_BANK_BASIC_IRQ_OFFSET) && + (irq < IRQ_BANK_BASIC_IRQ_OFFSET + IRQ_BANK_1_IRQ_OFFSET)) { + ioreg_write32((void *) + (ARM_SIDE_INTC_BASE + ENABLE_BASIC_IRQS_OFFSET), + 1 << (irq - IRQ_BANK_BASIC_IRQ_OFFSET)); + } else if ((irq >= IRQ_BANK_1_IRQ_OFFSET) && + (irq < IRQ_BANK_2_IRQ_OFFSET)) { + ioreg_write32((void *) + (ARM_SIDE_INTC_BASE + ENABLE_IRQS_1_OFFSET), + 1 << (irq - IRQ_BANK_1_IRQ_OFFSET)); + } else if (irq >= IRQ_BANK_2_IRQ_OFFSET) { + ioreg_write32((void *) + (ARM_SIDE_INTC_BASE + ENABLE_IRQS_2_OFFSET), + 1 << (irq - IRQ_BANK_2_IRQ_OFFSET)); + } +} + +static void bcm2835_intc_disable_irq(uint32_t irq) +{ + if ((irq >= IRQ_BANK_BASIC_IRQ_OFFSET) && + (irq < IRQ_BANK_BASIC_IRQ_OFFSET + IRQ_BANK_1_IRQ_OFFSET)) { + ioreg_write32((void *) + (ARM_SIDE_INTC_BASE + DISABLE_IRQS_1_OFFSET), + 1 << (irq - IRQ_BANK_BASIC_IRQ_OFFSET)); + } else if ((irq >= IRQ_BANK_1_IRQ_OFFSET) && + (irq < IRQ_BANK_2_IRQ_OFFSET)) { + ioreg_write32((void *) + (ARM_SIDE_INTC_BASE + DISABLE_IRQS_2_OFFSET), + 1 << (irq - IRQ_BANK_1_IRQ_OFFSET)); + } else if (irq >= IRQ_BANK_2_IRQ_OFFSET) { + ioreg_write32((void *) + (ARM_SIDE_INTC_BASE + ENABLE_IRQS_2_OFFSET), + 1 << (irq - IRQ_BANK_2_IRQ_OFFSET)); + } +} + +static +void bcm2835_intc_set_irq_trigger(uint32_t irq __unused, + enum uk_intctlr_irq_trigger trigger __unused) +{ + /* unused */ +} + +static void bcm2835_intc_handle_irq(struct __regs *regs) +{ + __u32 intc_source_val, intc_pending_val; + + intc_source_val = ioreg_read32( + (void *)(ARM_SIDE_INTC_BASE + IRQ_BASIC_PENDING_OFFSET)); + + for (int cnt = 0; cnt < IRQ_BANK_BASIC_IRQ_MAX; cnt++) { + if (((intc_source_val >> cnt) & 1) == 1) { + uk_intctlr_irq_handle(regs, + IRQ_BANK_BASIC_IRQ_OFFSET + cnt); + goto end; + } + } + + if ((intc_source_val & IRQ_PENDING_1_SET) == IRQ_PENDING_1_SET) { + intc_pending_val = ioreg_read32( + (void *)(ARM_SIDE_INTC_BASE + + IRQ_PENDING_1_OFFSET)); + for (int cnt = 0; cnt < IRQ_BANK_1_IRQ_MAX; cnt++) { + if (((intc_pending_val >> cnt) & 1) == 1) { + uk_intctlr_irq_handle(regs, + IRQ_BANK_1_IRQ_OFFSET + cnt); + goto end; + } + } + } + + if ((intc_source_val & IRQ_PENDING_2_SET) == IRQ_PENDING_2_SET) { + intc_pending_val = ioreg_read32( + (void *)(ARM_SIDE_INTC_BASE + + IRQ_PENDING_2_OFFSET)); + for (int cnt = 0; cnt < IRQ_BANK_2_IRQ_MAX; cnt++) { + if (((intc_pending_val >> cnt) & 1) == 1) { + uk_intctlr_irq_handle(regs, + IRQ_BANK_2_IRQ_OFFSET + cnt); + goto end; + } + } + } +end: + uk_pr_info("finished handling irq\n"); +} + +static inline void bcm2835_intc_set_ops(void) +{ + struct bcm_operations drv_ops = { + .initialize = bcm2835_intc_initialize, + .enable_irq = bcm2835_intc_enable_irq, + .disable_irq = bcm2835_intc_disable_irq, + .set_irq_trigger = bcm2835_intc_set_irq_trigger, + .handle_irq = bcm2835_intc_handle_irq, + }; + + bcm2835_intc_drv.ops = drv_ops; +} + +/* bcm2835中断控制器初始化函数 */ +int bcm2835_intc_set_info(void *fdt) +{ + int ret; + + /* 从设备树获取中断控制器节点信息 */ + fdt_bcm2835_intc_offset = fdt_node_offset_by_compatible_list( + fdt, -1, bcm2835_intc_device_list); + if (fdt_bcm2835_intc_offset < 0) + /* 节点不存在 */ + return -FDT_ERR_NOTFOUND; + + /* 获取中断控制器的内存区域地址和大小 */ + ret = fdt_get_address(fdt, fdt_bcm2835_intc_offset, 0, + &bcm2835_intc_drv.mem_addr, + &bcm2835_intc_drv.mem_size); + if (unlikely(ret < 0)) { + uk_pr_err("Could not find bcm2835_intc memory region!\n"); + return ret; + } + + bcm2835_intc_set_ops(); + + uk_pr_info("Found bcm2835_intc on:\n"); + uk_pr_info("\tDistributor : 0x%lx - 0x%lx\n", + bcm2835_intc_drv.mem_addr, + bcm2835_intc_drv.mem_addr + + bcm2835_intc_drv.mem_size - 1); + + return 0; +} + +/* bcm2835中断控制器注册函数 */ +int bcm2835_intc_do_probe(struct bcm_intc_dev **dev) +{ + struct ukplat_bootinfo *bi = ukplat_bootinfo_get(); + int ret; + void *fdt; + + UK_ASSERT(bi); + fdt = (void *)bi->dtb; + ret = bcm2835_intc_set_info(fdt); + if (unlikely(ret < 0)) + return ret; + *dev = &bcm2835_intc_drv; + + return 0; +} diff --git a/drivers/ukintctlr/bcm_intc/bcm2836_intc.c b/drivers/ukintctlr/bcm_intc/bcm2836_intc.c new file mode 100644 index 00000000..690ed95d --- /dev/null +++ b/drivers/ukintctlr/bcm_intc/bcm2836_intc.c @@ -0,0 +1,310 @@ +/* Copyright 2023 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int fdt_bcm2836_intc_offset; + +static const char *const bcm2836_intc_device_list[] __maybe_unused = { + "brcm,bcm2836-l1-intc", + NULL +}; + +struct bcm_intc_dev bcm2836_intc_drv = { + .mem_addr = 0, + .mem_size = 0, +}; + +int fdt_xlat_bcm2836(const void *fdt, int nodeoffset, __u32 index, + struct uk_intctlr_irq *irq) +{ + int ret, size; + fdt32_t *prop; + __u32 type, flags; + + UK_ASSERT(irq); + + ret = fdt_get_interrupt(fdt, nodeoffset, index, &size, &prop); + if (unlikely(ret < 0)) + return ret; + + /* bcm中断控制器interrupt-cells为2 */ + UK_ASSERT(size == 2); + + type = fdt32_to_cpu(prop[0]); + flags = fdt32_to_cpu(prop[1]); + + switch (type) { + case IRQ_TYPE_CNTPS: + case IRQ_TYPE_CNTPNS: + case IRQ_TYPE_CNTHP: + case IRQ_TYPE_CNTV: + irq->id = IRQ_ID_CNTV; + break; + case IRQ_TYPE_MAILBOX0: + irq->id = IRQ_BASE + IRQ_TYPE_MAILBOX0; + break; + case IRQ_TYPE_MAILBOX1: + irq->id = IRQ_BASE + IRQ_TYPE_MAILBOX1; + break; + case IRQ_TYPE_MAILBOX2: + irq->id = IRQ_BASE + IRQ_TYPE_MAILBOX2; + break; + case IRQ_TYPE_MAILBOX3: + irq->id = IRQ_BASE + IRQ_TYPE_MAILBOX3; + break; + case IRQ_TYPE_GPU_FAST: + irq->id = IRQ_BASE + IRQ_TYPE_GPU_FAST; + break; + case IRQ_TYPE_PMU_FAST: + irq->id = IRQ_BASE + IRQ_TYPE_PMU_FAST; + break; + default: + irq->id = IRQ_ID_INVALID; + } + + switch (flags & FDT_BCM_INTC_IRQ_FLAGS_TL_MASK) { + case FDT_BCM_INTC_IRQ_FLAGS_TL_EDGE_HI: + case FDT_BCM_INTC_IRQ_FLAGS_TL_EDGE_LO: + irq->trigger = UK_INTCTLR_IRQ_TRIGGER_EDGE; + break; + case FDT_BCM_INTC_IRQ_FLAGS_TL_LEVEL_LO: + case FDT_BCM_INTC_IRQ_FLAGS_TL_LEVEL_HI: + irq->trigger = UK_INTCTLR_IRQ_TRIGGER_LEVEL; + break; + default: + return -FDT_ERR_BADVALUE; + } + + return 0; +} + +static void bcm2836_enable_timer_irq(void) +{ + ioreg_write32((void *) + (ARM_TIMER_BASE + ARM_C0_TIMER_IRQ_CTL), + ARM_C0_TIMER_IRQ_CTL_CNTVIRQ_ENABLE); +} + +static void bcm2836_enable_mailbox0(void) +{ + /* unused */ +} + +static void bcm2836_enable_gpu_irq(void) +{ + /* unused */ +} + +static void bcm2836_enable_pmu_irq(void) +{ + /* unused */ +} + +static void bcm2836_intc_enable_irq(uint32_t irq __maybe_unused) +{ + BCM2835_OPS_ENABLE_IRQ(irq); + + switch (irq) { + case IRQ_TYPE_CNTPS: + case IRQ_TYPE_CNTPNS: + case IRQ_TYPE_CNTHP: + case IRQ_TYPE_CNTV: + bcm2836_enable_timer_irq(); + break; + case IRQ_TYPE_MAILBOX0: + bcm2836_enable_mailbox0(); + break; + case IRQ_TYPE_MAILBOX1: + /* unused */ + break; + case IRQ_TYPE_MAILBOX2: + /* unused */ + break; + case IRQ_TYPE_MAILBOX3: + /* unused */ + break; + case IRQ_TYPE_GPU_FAST: + bcm2836_enable_gpu_irq(); + break; + case IRQ_TYPE_PMU_FAST: + bcm2836_enable_pmu_irq(); + break; + default: + uk_pr_err("unsurpported bcm2836irq id:%d\n", irq); + } +} + +static void bcm2836_disable_timer_irq(void) +{ + ioreg_write32((void *) + (ARM_TIMER_BASE + ARM_C0_TIMER_IRQ_CTL), + ARM_C0_TIMER_IRQ_CTL_CNTVIRQ_DISABLE); +} + +static void bcm2836_disable_mailbox0(void) +{ + /* unused */ +} + +static void bcm2836_disable_gpu_irq(void) +{ + /* unused */ +} + +static void bcm2836_disable_pmu_irq(void) +{ + /* unused */ +} + +static void bcm2836_intc_disable_irq(uint32_t irq __maybe_unused) +{ + BCM2835_OPS_DISABLE_IRQ(irq); + + switch (irq) { + case IRQ_TYPE_CNTPS: + case IRQ_TYPE_CNTPNS: + case IRQ_TYPE_CNTHP: + case IRQ_TYPE_CNTV: + bcm2836_disable_timer_irq(); + break; + case IRQ_TYPE_MAILBOX0: + bcm2836_disable_mailbox0(); + break; + case IRQ_TYPE_MAILBOX1: + /* unused */ + break; + case IRQ_TYPE_MAILBOX2: + /* unused */ + break; + case IRQ_TYPE_MAILBOX3: + /* unused */ + break; + case IRQ_TYPE_GPU_FAST: + bcm2836_disable_gpu_irq(); + break; + case IRQ_TYPE_PMU_FAST: + bcm2836_disable_pmu_irq(); + break; + default: + uk_pr_err("unsurpported bcm2836irq id:%d\n", irq); + } +} + +static +void bcm2836_intc_set_irq_trigger(uint32_t irq __maybe_unused, + enum uk_intctlr_irq_trigger trigger + __maybe_unused) +{ + /* unused */ + BCM2835_OPS_SET_IRQ_TRIGGER(irq, trigger); +} + +static void bcm2836_intc_initialize(void) +{ + BCM2835_OPS_INITIALIZE; +} + +static void bcm2836_intc_handle_irq(struct __regs *regs) +{ + __u32 intc_source_val; + + intc_source_val = ioreg_read32( + (void *)(ARM_TIMER_BASE + ARM_C0_TIMER_IRQ_CTL)); + switch (intc_source_val) { + case IRQ_SOURCE_CNTPS: + case IRQ_SOURCE_CNTPNS: + case IRQ_SOURCE_CNTHP: + case IRQ_SOURCE_CNTV: + uk_intctlr_irq_handle(regs, IRQ_ID_CNTV); + break; + case IRQ_SOURCE_MAILBOX0: + uk_intctlr_irq_handle(regs, IRQ_BASE + IRQ_TYPE_MAILBOX0); + break; + case IRQ_SOURCE_MAILBOX1: + uk_intctlr_irq_handle(regs, IRQ_BASE + IRQ_TYPE_MAILBOX1); + break; + case IRQ_SOURCE_MAILBOX2: + uk_intctlr_irq_handle(regs, IRQ_BASE + IRQ_TYPE_MAILBOX2); + break; + case IRQ_SOURCE_MAILBOX3: + uk_intctlr_irq_handle(regs, IRQ_BASE + IRQ_TYPE_MAILBOX3); + break; + case IRQ_SOURCE_GPU_FAST: + uk_intctlr_irq_handle(regs, IRQ_BASE + IRQ_TYPE_GPU_FAST); + break; + case IRQ_SOURCE_PMU_FAST: + uk_intctlr_irq_handle(regs, IRQ_BASE + IRQ_TYPE_PMU_FAST); + break; + default: + break; + } +} + +static inline void bcm2836_intc_set_ops(void) +{ + struct bcm_operations drv_ops = { + .initialize = bcm2836_intc_initialize, + .enable_irq = bcm2836_intc_enable_irq, + .disable_irq = bcm2836_intc_disable_irq, + .set_irq_trigger = bcm2836_intc_set_irq_trigger, + .handle_irq = bcm2836_intc_handle_irq, + }; + + bcm2836_intc_drv.ops = drv_ops; +} + +int bcm2836_intc_do_probe(struct bcm_intc_dev **dev) +{ + struct ukplat_bootinfo *bi = ukplat_bootinfo_get(); + int ret; + void *fdt; + + UK_ASSERT(bi); + fdt = (void *)bi->dtb; + if (bcm2835_intc_set_info(fdt) < 0) + /* bcm2835_intc 初始化失败 */ + return -FDT_ERR_NOTFOUND; + + fdt_bcm2836_intc_offset = fdt_node_offset_by_compatible_list( + fdt, -1, bcm2836_intc_device_list); + if (fdt_bcm2836_intc_offset < 0) + /* bcm2836_intc 在设备树中未找到 */ + return -FDT_ERR_NOTFOUND; + + /* 从设备树获取中断控制器内存地址与长度 */ + ret = fdt_get_address(fdt, fdt_bcm2836_intc_offset, 0, + &bcm2836_intc_drv.mem_addr, + &bcm2836_intc_drv.mem_size); + if (unlikely(ret < 0)) { + uk_pr_err("Could not find bcm2836_intc memory region!\n"); + return ret; + } + + bcm2836_intc_set_ops(); + *dev = &bcm2836_intc_drv; + + return 0; +} diff --git a/drivers/ukintctlr/bcm_intc/bcm_intc_initialize.c b/drivers/ukintctlr/bcm_intc/bcm_intc_initialize.c new file mode 100644 index 00000000..4ed040cd --- /dev/null +++ b/drivers/ukintctlr/bcm_intc/bcm_intc_initialize.c @@ -0,0 +1,117 @@ +/* Copyright 2023 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#ifdef CONFIG_LIBUKINTCTLR_BCM2836_INTC +#include +#endif +#ifdef CONFIG_LIBUKINTCTLR_BCM2835_INTC +#include +#endif + +struct bcm_intc_dev *bcm_intc; +struct uk_intctlr_desc intctlr; +struct uk_intctlr_driver_ops ops; + +#if CONFIG_LIBUKOFW + +#include +#include + +static int fdt_xlat(const void *fdt, int nodeoffset, __u32 index, + struct uk_intctlr_irq *irq) +{ + int ret, irq_parent_offset, is_done; + + UK_ASSERT(irq); + + irq_parent_offset = fdt_find_irq_parent_offset(fdt, nodeoffset); + is_done = 0; +#ifdef CONFIG_LIBUKINTCTLR_BCM2836_INTC + if ((fdt_bcm2836_intc_offset > 0) && + (irq_parent_offset == fdt_bcm2836_intc_offset)) { + ret = fdt_xlat_bcm2836(fdt, nodeoffset, index, irq); + is_done = 1; + if (unlikely(ret < 0)) + return ret; + } +#endif /* CONFIG_LIBUKINTCTLR_BCM2836_INTC */ + +#ifdef CONFIG_LIBUKINTCTLR_BCM2835_INTC + if ((fdt_bcm2835_intc_offset > 0) && + (irq_parent_offset == fdt_bcm2835_intc_offset)) { + ret = fdt_xlat_bcm2835(fdt, nodeoffset, index, irq); + is_done = 1; + if (unlikely(ret < 0)) + return ret; + } +#endif /* CONFIG_LIBUKINTCTLR_BCM2835_INTC */ + if (is_done == 0) + return -FDT_ERR_NOTFOUND; + return 0; +} +#endif /* CONFIG_LIBUKOFW */ + +/* 根据设备树参数来设置中断属性 */ +static int configure_irq(struct uk_intctlr_irq *irq) +{ + if (irq->trigger != UK_INTCTLR_IRQ_TRIGGER_NONE) + /* 调用函数配置irq_trigger */ + bcm_intc->ops.set_irq_trigger(irq->id, irq->trigger); + + return 0; +} + +/* 注册中断API */ +int uk_intctlr_probe(void) +{ + int ret = -ENODEV; + +#ifdef CONFIG_LIBUKINTCTLR_BCM2836_INTC + ret = bcm2836_intc_do_probe(&bcm_intc); + if (ret == 0) + goto init; +#endif /* CONFIG_LIBUKINTCTLR_BCM2836_INTC */ + +#ifdef CONFIG_LIBUKINTCTLR_BCM2835_INTC + ret = bcm2835_intc_do_probe(&bcm_intc); + if (ret == 0) + goto init; +#endif /* CONFIG_LIBUKINTCTLR_BCM2835_INTC */ + if (unlikely(ret)) + return ret; + +init: + intctlr.name = "BCM-INTC"; + ops.initialize = bcm_intc->ops.initialize; + ops.percpu_init = __NULL; + ops.configure_irq = configure_irq; + ops.mask_irq = bcm_intc->ops.disable_irq; + ops.unmask_irq = bcm_intc->ops.enable_irq; + ops.handle = bcm_intc->ops.handle_irq; + /* reserved for software general interrupt to specified core */ + ops.sgi_op = __NULL; +#if CONFIG_LIBUKOFW + ops.fdt_xlat = fdt_xlat; +#endif /* CONFIG_LIBUKOFW */ + + intctlr.ops = &ops; + + return uk_intctlr_register(&intctlr); +} diff --git a/drivers/ukintctlr/bcm_intc/exportsyms.uk b/drivers/ukintctlr/bcm_intc/exportsyms.uk new file mode 100644 index 00000000..90d464ef --- /dev/null +++ b/drivers/ukintctlr/bcm_intc/exportsyms.uk @@ -0,0 +1 @@ +uk_intctlr_probe diff --git a/drivers/ukintctlr/bcm_intc/include/uk/intctlr/bcm2835_intc.h b/drivers/ukintctlr/bcm_intc/include/uk/intctlr/bcm2835_intc.h new file mode 100644 index 00000000..d6f1abd1 --- /dev/null +++ b/drivers/ukintctlr/bcm_intc/include/uk/intctlr/bcm2835_intc.h @@ -0,0 +1,85 @@ +/* Copyright 2023 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BCM2835_INTC_H +#define BCM2835_INTC_H + +#include + +#ifdef CONFIG_LIBUKINTCTLR_BCM2835_INTC +#define BCM2835_OPS_INITIALIZE bcm2835_intc_drv.ops.initialize() +#define BCM2835_OPS_ENABLE_IRQ(irq) bcm2835_intc_drv.ops.enable_irq(irq) +#define BCM2835_OPS_DISABLE_IRQ(irq) bcm2835_intc_drv.ops.disable_irq(irq) +#define BCM2835_OPS_SET_IRQ_TRIGGER(irq, trigger) \ + bcm2835_intc_drv.ops.set_irq_trigger(irq, trigger) +#define BCM2835_OPS_HANDLE_TRQ(regs) bcm2835_intc_drv.ops.handle_irq(regs) +#else +#define BCM2835_OPS_INITIALIZE +#define BCM2835_OPS_ENABLE_IRQ(irq) +#define BCM2835_OPS_DISABLE_IRQ(irq) +#define BCM2835_OPS_SET_IRQ_TRIGGER(irq, trigger) +#define BCM2835_OPS_HANDLE_TRQ(regs) +#endif + +#define IRQ_BANK_BASIC 0 +#define IRQ_BANK_1 1 +#define IRQ_BANK_2 2 +#define IRQ_BANK_BASIC_IRQ_MAX 8 +#define IRQ_BANK_1_IRQ_MAX 32 +#define IRQ_BANK_2_IRQ_MAX 32 +#ifdef CONFIG_LIBUKINTCTLR_BCM2836_INTC +#define ARM_SIDE_IRQ_ID_BASE 32 +#else +#define ARM_SIDE_IRQ_ID_BASE 0 +#endif + +#define IRQ_BANK_BASIC_IRQ_OFFSET ARM_SIDE_IRQ_ID_BASE +#define IRQ_BANK_1_IRQ_OFFSET (IRQ_BANK_BASIC_IRQ_OFFSET + \ + IRQ_BANK_BASIC_IRQ_MAX) +#define IRQ_BANK_2_IRQ_OFFSET (IRQ_BANK_1_IRQ_OFFSET + IRQ_BANK_1_IRQ_MAX) + +/* Macros to access Interrupt Controller Registers with base address */ +#define ARM_SIDE_INTC_BASE bcm2835_intc_drv.mem_addr + +#define IRQ_BASIC_PENDING_OFFSET 0x00 +#define IRQ_PENDING_1_OFFSET 0x04 +#define IRQ_PENDING_2_OFFSET 0x08 +#define FIQ_CONTROL_OFFSET 0x0C +#define ENABLE_IRQS_1_OFFSET 0x10 +#define ENABLE_IRQS_2_OFFSET 0x14 +#define ENABLE_BASIC_IRQS_OFFSET 0x18 +#define DISABLE_IRQS_1_OFFSET 0x1C +#define DISABLE_IRQS_2_OFFSET 0x20 +#define DISABLE_BASIC_IRQS_OFFSET 0x24 + +#define IRQ_PENDING_1_SET (1 << 8) +#define IRQ_PENDING_2_SET (1 << 9) + +#define IRQS_1_SYSTEM_TIMER_IRQ_0 (1 << 0) +#define IRQS_1_SYSTEM_TIMER_IRQ_1 (1 << 1) +#define IRQS_1_SYSTEM_TIMER_IRQ_2 (1 << 2) +#define IRQS_1_SYSTEM_TIMER_IRQ_3 (1 << 3) +#define IRQS_1_USB_IRQ (1 << 9) + +#define IRQ_REG_MASK 0xFFFFFFFF + +int bcm2835_intc_set_info(void *fdt); +int bcm2835_intc_do_probe(struct bcm_intc_dev **dev); +int fdt_xlat_bcm2835(const void *fdt, int nodeoffset, __u32 index, + struct uk_intctlr_irq *irq); +extern struct bcm_intc_dev bcm2835_intc_drv; +extern int fdt_bcm2835_intc_offset; + +#endif diff --git a/drivers/ukintctlr/bcm_intc/include/uk/intctlr/bcm2836_intc.h b/drivers/ukintctlr/bcm_intc/include/uk/intctlr/bcm2836_intc.h new file mode 100644 index 00000000..6e8e89a9 --- /dev/null +++ b/drivers/ukintctlr/bcm_intc/include/uk/intctlr/bcm2836_intc.h @@ -0,0 +1,58 @@ +/* Copyright 2023 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BCM2836_INTC_H +#define BCM2836_INTC_H + +#include + +/* bcm2836 registers*/ +#define ARM_TIMER_BASE bcm2836_intc_drv.mem_addr +#define ARM_C0_TIMER_IRQ_CTL 0x40 +#define ARM_C0_TIMER_IRQ_CTL_CNTVIRQ_ENABLE (1 << 3) +#define ARM_C0_TIMER_IRQ_CTL_CNTVIRQ_DISABLE 0 + +#define IRQ_BASE 20 +#define IRQ_TYPE_CNTPS 0 +#define IRQ_TYPE_CNTPNS 1 +#define IRQ_TYPE_CNTHP 2 +#define IRQ_TYPE_CNTV 3 +#define IRQ_TYPE_MAILBOX0 4 +#define IRQ_TYPE_MAILBOX1 5 +#define IRQ_TYPE_MAILBOX2 6 +#define IRQ_TYPE_MAILBOX3 7 +#define IRQ_TYPE_GPU_FAST 8 +#define IRQ_TYPE_PMU_FAST 9 +#define IRQ_ID_CNTV 0 +#define IRQ_ID_INVALID 0xFFFF + +#define IRQ_SOURCE_CNTPS 0 +#define IRQ_SOURCE_CNTPNS (1 << 1) +#define IRQ_SOURCE_CNTHP (1 << 2) +#define IRQ_SOURCE_CNTV (1 << 3) +#define IRQ_SOURCE_MAILBOX0 (1 << 4) +#define IRQ_SOURCE_MAILBOX1 (1 << 5) +#define IRQ_SOURCE_MAILBOX2 (1 << 6) +#define IRQ_SOURCE_MAILBOX3 (1 << 7) +#define IRQ_SOURCE_GPU_FAST (1 << 8) +#define IRQ_SOURCE_PMU_FAST (1 << 9) + +extern struct bcm_intc_dev bcm2836_intc_drv; +extern int fdt_bcm2836_intc_offset; +int bcm2836_intc_do_probe(struct bcm_intc_dev **dev); +int fdt_xlat_bcm2836(const void *fdt, int nodeoffset, __u32 index, + struct uk_intctlr_irq *irq); + +#endif diff --git a/drivers/ukintctlr/bcm_intc/include/uk/intctlr/bcm_intc.h b/drivers/ukintctlr/bcm_intc/include/uk/intctlr/bcm_intc.h new file mode 100644 index 00000000..076ffe48 --- /dev/null +++ b/drivers/ukintctlr/bcm_intc/include/uk/intctlr/bcm_intc.h @@ -0,0 +1,53 @@ +/* Copyright 2023 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BCM_INTC_H +#define BCM_INTC_H + +#include +#include + +#define FDT_BCM_INTC_IRQ_FLAGS_TL_MASK 0xf /* trigger - level */ +#define FDT_BCM_INTC_IRQ_FLAGS_TL_EDGE_HI 1 /* 上升沿使能 */ +#define FDT_BCM_INTC_IRQ_FLAGS_TL_EDGE_LO 2 /* 下降沿使能 */ +#define FDT_BCM_INTC_IRQ_FLAGS_TL_LEVEL_LO 4 /* 低电平使能 */ +#define FDT_BCM_INTC_IRQ_FLAGS_TL_LEVEL_HI 8 /* 高电平使能 */ + +/** BCM driver operations */ +struct bcm_operations { + /** Initialize BCM controller */ + void (*initialize)(void); + /** Enable IRQ */ + void (*enable_irq)(uint32_t irq); + /** Disable IRQ */ + void (*disable_irq)(uint32_t irq); + /** Set IRQ trigger type */ + void (*set_irq_trigger)(uint32_t irq, + enum uk_intctlr_irq_trigger trigger); + /** Handle IRQ */ + void (*handle_irq)(struct __regs *regs); +}; + +/** bcm controller structure */ +struct bcm_intc_dev { + /** Base address */ + uint64_t mem_addr; + /** Memory size */ + uint64_t mem_size; + /** Driver operations */ + struct bcm_operations ops; +}; + +#endif diff --git a/drivers/ukintctlr/bcm_intc/include/uk/intctlr/limits.h b/drivers/ukintctlr/bcm_intc/include/uk/intctlr/limits.h new file mode 100644 index 00000000..f1ce885b --- /dev/null +++ b/drivers/ukintctlr/bcm_intc/include/uk/intctlr/limits.h @@ -0,0 +1,27 @@ +/* Copyright 2023 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIMITS_H +#define LIMITS_H + +/* currently bcm_intctlr support irq number */ +#define UK_INTCTLR_FIRST_ALLOCABLE_IRQ 0 +#define UK_INTCTLR_LAST_ALLOCABLE_IRQ 99 +#define UK_INTCTLR_MAX_IRQ 100 + +#define UK_INTCTLR_ALLOCABLE_IRQ_COUNT \ + (UK_INTCTLR_LAST_ALLOCABLE_IRQ - UK_INTCTLR_FIRST_ALLOCABLE_IRQ) + +#endif diff --git a/drivers/ukintctlr/gic/exportsyms.uk b/drivers/ukintctlr/gic/exportsyms.uk index 1d12da5a..acf71bee 100644 --- a/drivers/ukintctlr/gic/exportsyms.uk +++ b/drivers/ukintctlr/gic/exportsyms.uk @@ -1,3 +1,2 @@ uk_intctlr_probe acpi_get_gicd -gic diff --git a/drivers/ukintctlr/gic/ukintctlr.c b/drivers/ukintctlr/gic/ukintctlr.c index 9675799d..4b50c337 100644 --- a/drivers/ukintctlr/gic/ukintctlr.c +++ b/drivers/ukintctlr/gic/ukintctlr.c @@ -117,7 +117,10 @@ init: #if CONFIG_LIBUKOFW ops.fdt_xlat = fdt_xlat; #endif /* CONFIG_LIBUKOFW */ - + ops.initialize = __NULL; + ops.handle = gic->ops.handle_irq; + ops.sgi_op = gic->ops.gic_sgi_gen; + ops.percpu_init = gic->ops.initialize; intctlr.ops = &ops; return uk_intctlr_register(&intctlr); diff --git a/drivers/ukintctlr/xpic/ukintctlr.c b/drivers/ukintctlr/xpic/ukintctlr.c index 93f153a8..5581aa9d 100644 --- a/drivers/ukintctlr/xpic/ukintctlr.c +++ b/drivers/ukintctlr/xpic/ukintctlr.c @@ -57,6 +57,11 @@ int uk_intctlr_probe(void) intctlr.ops = ops; intctlr.ops->configure_irq = configure_irq; + intctlr.ops->initialize = __NULL; + intctlr.ops->handle = uk_intctlr_xpic_handle_irq; + intctlr.ops->fdt_xlat = __NULL; + intctlr.ops->sgi_op = __NULL; + intctlr.ops->percpu_init = __NULL; return uk_intctlr_register(&intctlr); } diff --git a/lib/ukintctlr/exportsyms.uk b/lib/ukintctlr/exportsyms.uk index 632f038d..80ce0e8b 100644 --- a/lib/ukintctlr/exportsyms.uk +++ b/lib/ukintctlr/exportsyms.uk @@ -5,6 +5,9 @@ uk_intctlr_irq_fdt_xlat uk_intctlr_irq_alloc uk_intctlr_irq_free uk_intctlr_irq_handle +uk_intctlr_handle +uk_intctlr_sgi_op +uk_intctlr_percpu_init uk_intctlr_irq_register uk_intctlr_irq_unregister uk_intctlr_register diff --git a/lib/ukintctlr/include/uk/intctlr.h b/lib/ukintctlr/include/uk/intctlr.h index 0c9c4617..7ae83256 100644 --- a/lib/ukintctlr/include/uk/intctlr.h +++ b/lib/ukintctlr/include/uk/intctlr.h @@ -16,6 +16,7 @@ export "C" { #include #include #include +#include /** * This event is raised before the platform code handles an IRQ. The normal @@ -39,6 +40,8 @@ enum uk_intctlr_irq_trigger { UK_INTCTLR_IRQ_TRIGGER_LEVEL, }; +extern struct uk_intctlr_desc *uk_intctlr; + /** IRQ descriptor */ struct uk_intctlr_irq { unsigned int id; @@ -56,6 +59,10 @@ struct uk_intctlr_driver_ops { struct uk_intctlr_irq *irq); void (*mask_irq)(unsigned int irq); void (*unmask_irq)(unsigned int irq); + void (*initialize)(void); + void (*handle)(struct __regs *regs); + void (*sgi_op)(uint8_t sgintid, uint32_t cpuid); + int (*percpu_init)(uint64_t cpuid __maybe_unused); }; /** Interrupt controller descriptor */ @@ -183,6 +190,29 @@ int uk_intctlr_irq_free(unsigned int *irqs, __sz count); int uk_intctlr_irq_fdt_xlat(const void *fdt, int nodeoffset, __u32 index, struct uk_intctlr_irq *irq); +/** + * Handle function for interrupt controller + * + * @param regs Resgisters which the interrupt controller needs to handle + */ +void uk_intctlr_handle(struct __regs *regs); + +/** + * Handle function for interrupt controller + * + * @param sgintid the software generated interrupt id + * @param cpuid the id of the targeted cpu + * @return zero on success , error code on failure + */ +int uk_intctlr_sgi_op(uint8_t sgintid, uint32_t cpuid); + +/** + * extra initialize function for each cpu core + * + * @param cpuid the id of the targeted cpu + * @return zero on success , error code on failure + */ +int uk_intctlr_percpu_init(uint64_t cpuid __maybe_unused); #endif /* __ASSEMBLY__ */ #ifdef __cplusplus diff --git a/lib/ukintctlr/ukintctlr.c b/lib/ukintctlr/ukintctlr.c index 401f1459..88aa1cfd 100644 --- a/lib/ukintctlr/ukintctlr.c +++ b/lib/ukintctlr/ukintctlr.c @@ -220,21 +220,21 @@ exit: void uk_intctlr_irq_mask(unsigned int irq) { - UK_ASSERT(uk_intctlr && uk_intctlr->ops); + UK_ASSERT(uk_intctlr && uk_intctlr->ops->mask_irq); return uk_intctlr->ops->mask_irq(irq); } void uk_intctlr_irq_unmask(unsigned int irq) { - UK_ASSERT(uk_intctlr && uk_intctlr->ops); + UK_ASSERT(uk_intctlr && uk_intctlr->ops->unmask_irq); return uk_intctlr->ops->unmask_irq(irq); } int uk_intctlr_irq_configure(struct uk_intctlr_irq *irq) { - UK_ASSERT(uk_intctlr && uk_intctlr->ops); + UK_ASSERT(uk_intctlr && uk_intctlr->ops->configure_irq); UK_ASSERT(irq); return uk_intctlr->ops->configure_irq(irq); @@ -243,7 +243,7 @@ int uk_intctlr_irq_configure(struct uk_intctlr_irq *irq) int uk_intctlr_irq_fdt_xlat(const void *fdt, int nodeoffset, __u32 index, struct uk_intctlr_irq *irq) { - UK_ASSERT(uk_intctlr && uk_intctlr->ops); + UK_ASSERT(uk_intctlr && uk_intctlr->ops->fdt_xlat); UK_ASSERT(fdt); UK_ASSERT(irq); @@ -294,12 +294,11 @@ int uk_intctlr_irq_free(unsigned int *irqs, __sz count) return !rc; } -int uk_intctlr_init(struct uk_alloc *a __unused) +int uk_intctlr_init(struct uk_alloc *a __maybe_unused) { UK_ASSERT(uk_intctlr); UK_ASSERT(ukplat_lcpu_irqs_disabled()); - /* Nothing for now */ return 0; } @@ -311,3 +310,27 @@ int uk_intctlr_register(struct uk_intctlr_desc *intctlr) return 0; } + +void uk_intctlr_handle(struct __regs *regs) +{ + UK_ASSERT(uk_intctlr->ops->handle); + + return uk_intctlr->ops->handle(regs); +} + +int uk_intctlr_sgi_op(uint8_t sgintid, uint32_t cpuid) +{ + UK_ASSERT(uk_intctlr->ops->sgi_op); + + uk_intctlr->ops->sgi_op(sgintid, cpuid); + + return 0; +} + +int uk_intctlr_percpu_init(uint64_t cpuid __maybe_unused) +{ + UK_ASSERT(uk_intctlr->ops->percpu_init); + + /* initialize interrupt controller of specified cpu core */ + return uk_intctlr->ops->percpu_init(cpuid); +} diff --git a/plat/common/arm/lcpu.c b/plat/common/arm/lcpu.c index 9b994cc0..6439c2ad 100644 --- a/plat/common/arm/lcpu.c +++ b/plat/common/arm/lcpu.c @@ -38,9 +38,9 @@ #include #include #include +#include #include #include -#include #include #define CPU_ID_MASK 0xff00ffffffUL @@ -108,7 +108,6 @@ void __noreturn lcpu_arch_jump_to(void *sp, ukplat_lcpu_entry_t entry) #define FDT_ADDR_CELLS_DEFAULT 2 void lcpu_start(struct lcpu *cpu); -extern struct _gic_dev *gic; int lcpu_arch_init(struct lcpu *this_lcpu) { @@ -117,7 +116,7 @@ int lcpu_arch_init(struct lcpu *this_lcpu) /* Initialize the interrupt controller for non-bsp cores */ if (!lcpu_is_bsp(this_lcpu)) { - ret = gic->ops.initialize(); + ret = uk_intctlr_percpu_init(this_lcpu.id); if (unlikely(ret)) return ret; } @@ -209,9 +208,6 @@ static int do_arch_mp_init(void *arg) struct lcpu *lcpu; void *dtb; - /* MP support is dependent on an initialized GIC */ - UK_ASSERT(gic); - dtb = arg; bsp_cpu_id = lcpu_arch_id(); @@ -345,7 +341,7 @@ int lcpu_arch_run(struct lcpu *lcpu, const struct ukplat_lcpu_func *fn, if (unlikely(rc)) return rc; - gic->ops.gic_sgi_gen(*lcpu_run_irqv, lcpu->id); + uk_intctlr_sgi_op(*lcpu_run_irqv, lcpu->id); return 0; } @@ -354,7 +350,7 @@ int lcpu_arch_wakeup(struct lcpu *lcpu) { UK_ASSERT(lcpu->id != lcpu_arch_id()); - gic->ops.gic_sgi_gen(*lcpu_wakeup_irqv, lcpu->id); + uk_intctlr_sgi_op(*lcpu_wakeup_irqv, lcpu->id); return 0; } diff --git a/plat/common/arm/traps_arm64.c b/plat/common/arm/traps_arm64.c index dba35660..c5e6301b 100644 --- a/plat/common/arm/traps_arm64.c +++ b/plat/common/arm/traps_arm64.c @@ -28,17 +28,12 @@ #include #include #include +#include #ifdef CONFIG_ARM64_FEAT_MTE #include #endif /* CONFIG_ARM64_FEAT_MTE */ -#ifdef CONFIG_LIBUKINTCTLR_GIC -#include -/** GIC driver to call interrupt handler */ -extern struct _gic_dev *gic; -#endif - static const char * const exception_modes[] = { "Synchronous Abort", "IRQ", @@ -238,16 +233,12 @@ void trap_el1_sync(struct __regs *regs, __u64 far) */ void trap_el1_irq(struct __regs *regs) { -#ifdef CONFIG_LIBUKINTCTLR_GIC - UK_ASSERT(gic); - #ifdef CONFIG_ARM64_FEAT_MTE if (unlikely(mte_async_fault())) UK_CRASH("EL1 async tag check fault\n"); #endif /* CONFIG_ARM64_FEAT_MTE */ - gic->ops.handle_irq(regs); -#endif /* CONFIG_LIBUKINTCTLR_GIC */ + uk_intctlr_handle(regs); } #ifdef CONFIG_LIBSYSCALL_SHIM_HANDLER -- Gitee From 417c8979ad0346a9d338cbfb78e258ec926d3678 Mon Sep 17 00:00:00 2001 From: 1788594346 Date: Tue, 12 Dec 2023 09:21:12 +0800 Subject: [PATCH 30/57] lib/ukintctlr: add test cases for driver/ukintctlr and lib/ukintctlr Signed-off-by: 1788594346 --- drivers/ukintctlr/bcm_intc/Config.uk | 7 +- drivers/ukintctlr/bcm_intc/Makefile.uk | 4 + .../ukintctlr/bcm_intc/tests/test_bcm_intc.c | 187 +++++++++++++++ lib/ukintctlr/Config.uk | 7 +- lib/ukintctlr/Makefile.uk | 5 + lib/ukintctlr/tests/test_intctlr.c | 224 ++++++++++++++++++ 6 files changed, 432 insertions(+), 2 deletions(-) create mode 100644 drivers/ukintctlr/bcm_intc/tests/test_bcm_intc.c create mode 100644 lib/ukintctlr/tests/test_intctlr.c diff --git a/drivers/ukintctlr/bcm_intc/Config.uk b/drivers/ukintctlr/bcm_intc/Config.uk index 60fea952..17511262 100644 --- a/drivers/ukintctlr/bcm_intc/Config.uk +++ b/drivers/ukintctlr/bcm_intc/Config.uk @@ -1,4 +1,4 @@ -config LIBUKINTCTLR_BCM_INTC +menuconfig LIBUKINTCTLR_BCM_INTC bool "bcm interrupt controller" depends on (HAVE_INTCTLR && ARCH_ARM_64) select LIBUKINTCTLR @@ -14,3 +14,8 @@ config LIBUKINTCTLR_BCM2836_INTC depends on (LIBUKINTCTLR_BCM_INTC) select LIBUKINTCTLR_BCM2835_INTC default y + +config LIBUKINTCTLR_BCM_INTC_TEST + bool "Enable unit tests" + depends on (LIBUKINTCTLR_BCM_INTC && LIBUKTEST) + default n diff --git a/drivers/ukintctlr/bcm_intc/Makefile.uk b/drivers/ukintctlr/bcm_intc/Makefile.uk index 45a83e6c..3b0fa78b 100644 --- a/drivers/ukintctlr/bcm_intc/Makefile.uk +++ b/drivers/ukintctlr/bcm_intc/Makefile.uk @@ -10,3 +10,7 @@ LIBUKINTCTLR_BCM_INTC_SRCS-y += $(LIBUKINTCTLR_BCM_INTC_BASE)/bcm_intc_initializ LIBUKINTCTLR_BCM_INTC_SRCS-$(CONFIG_LIBUKINTCTLR_BCM2835_INTC) += $(LIBUKINTCTLR_BCM_INTC_BASE)/bcm2835_intc.c LIBUKINTCTLR_BCM_INTC_SRCS-$(CONFIG_LIBUKINTCTLR_BCM2836_INTC) += $(LIBUKINTCTLR_BCM_INTC_BASE)/bcm2836_intc.c + +ifneq ($(filter y,$(CONFIG_LIBUKINTCTLR_BCM_INTC_TEST) $(CONFIG_LIBUKTEST_ALL)),) +LIBUKINTCTLR_BCM_INTC_SRCS-y += $(LIBUKINTCTLR_BCM_INTC_BASE)/tests/test_bcm_intc.c +endif diff --git a/drivers/ukintctlr/bcm_intc/tests/test_bcm_intc.c b/drivers/ukintctlr/bcm_intc/tests/test_bcm_intc.c new file mode 100644 index 00000000..ae29db96 --- /dev/null +++ b/drivers/ukintctlr/bcm_intc/tests/test_bcm_intc.c @@ -0,0 +1,187 @@ +/* Copyright 2023 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* bcm中断控制器Time中断测试用例 */ +/* timer irq使能寄存器 */ +#define GENEREL_TIMER0_IRQ_REGISTER_ADDRESS 0x40000040 +#define GENEREL_TIMER0_IRQ_ENABLE 8 + +/* 系统时间相关宏 */ +/* 测试用例延时,单位ns,两倍于最小线程时间片 */ +#define GENEREL_TIME_DELAY 0x80000000 +/* ns粒度转换为16ms,便于断言检测 */ +#define GENEREL_TIME_DELAY_NS_TO_16MS 0x1000000 +#define GENEREL_TIME_EXPECTED_DELAY \ + (GENEREL_TIME_DELAY / GENEREL_TIME_DELAY_NS_TO_16MS) + +/* 设备树测试相关宏 */ +#define TEST_DTB_SIZE 1000 + +static __nsec nsec; +static int delay; + +/* 线程注册函数 */ +static void entry_fn(void *arg) +{ + /* 系统时钟中断未使能异常入口 */ + uk_pr_crit("ERR: System time interrupt err\n"); + ukplat_terminate(UKPLAT_CRASH); +} + +/* 测试timer irq disable场景 */ +UK_TESTCASE(uk_driver_bcm_intc, test_timer_disable_irq) +{ + struct uk_alloc *a = uk_alloc_get_default(); + struct uk_thread *current_thread = uk_thread_current(); + struct uk_sched *s = current_thread->sched; + + delay = 0; + nsec = 0; + /* 1.初始化测试场景 */ + /* 将timer irq寄存器值赋为disable */ + ioreg_write32((void *)(GENEREL_TIMER0_IRQ_REGISTER_ADDRESS), 0); + + /* 判断timer irq寄存器是否被更改为预期值0 */ + UK_TEST_EXPECT_ZERO(ioreg_read32( + (void *)(GENEREL_TIMER0_IRQ_REGISTER_ADDRESS))); + + /* 新建线程,供调度器调度 */ + struct uk_thread *t0 = uk_thread_create_container(a, + s->a_stack, 0x0, s->a_uktls, 0, + ("intc"), ((void *)0), ((void *)0)); + uk_thread_container_init_fn0(t0, entry_fn); + + /* 2.设置2s延时 */ + nsec = ukplat_monotonic_clock(); + /* 若无时间中断,系统线程超时,调度器退出本线程 */ + do; + while ((ukplat_monotonic_clock() - nsec) < GENEREL_TIME_DELAY); + /* 记录本线程执行时间 */ + delay = (ukplat_monotonic_clock() - nsec) / + GENEREL_TIME_DELAY_NS_TO_16MS; + + /* 3.检验测试结果 */ + /* 线程超时被调度器强制退出,时间戳被重置 */ + /* delay预期不等于预设延时 */ + UK_TEST_EXPECT_SNUM_NQ(delay, GENEREL_TIME_EXPECTED_DELAY); + + /* 4.恢复环境 */ + // uk_sched_dumpk_threads(3, uk_sched_head); + ioreg_write32((void *)(GENEREL_TIMER0_IRQ_REGISTER_ADDRESS), + GENEREL_TIMER0_IRQ_ENABLE); + uk_thread_release(t0); +} + +/* 测试timer irq enable场景 */ +UK_TESTCASE(uk_driver_bcm_intc, test_timer_enable_irq) +{ + struct uk_alloc *a = uk_alloc_get_default(); + struct uk_thread *current_thread = uk_thread_current(); + struct uk_sched *s = current_thread->sched; + + delay = 0; + nsec = 0; + /* 1.初始化测试场景 */ + /* 将timer irq寄存器值赋为enable */ + ioreg_write32((void *)(GENEREL_TIMER0_IRQ_REGISTER_ADDRESS), + GENEREL_TIMER0_IRQ_ENABLE); + + /* 判断timer irq寄存器是否被更改为预期值 */ + UK_TEST_EXPECT_PTR_EQ(ioreg_read32( + (void *)(GENEREL_TIMER0_IRQ_REGISTER_ADDRESS)), + GENEREL_TIMER0_IRQ_ENABLE); + + /* 新建线程,供调度器调度 */ + struct uk_thread *t1 = uk_thread_create_container(a, + s->a_stack, 0x0, s->a_uktls, 0, + ("intc"), ((void *)0), ((void *)0)); + uk_thread_container_init_fn0(t1, entry_fn); + + /* 2.设置2s延时 */ + nsec = ukplat_monotonic_clock(); + /* 若无时间中断,系统线程超时,调度器退出本线程 */ + do; + while ((ukplat_monotonic_clock() - nsec) < GENEREL_TIME_DELAY); + /* 记录本线程执行时间 */ + delay = (ukplat_monotonic_clock() - nsec) / + GENEREL_TIME_DELAY_NS_TO_16MS; + + /* 3.检验测试结果 */ + /* 中断使能,线程正常运行,delay预期等于预设延时 */ + UK_TEST_EXPECT_SNUM_EQ(delay, GENEREL_TIME_EXPECTED_DELAY); + + /* 4.恢复环境 */ + uk_thread_release(t1); +} + +/* 测试设备树中中断控制器读取异常场景 */ +UK_TESTCASE(uk_driver_bcm_intc, test_driver_dtb_bcm_intc_info_err) +{ + int ret, bufsize, fdt_bcm_intc, test_timer; + __u32 address_val, size_val; + __u64 fdt_address_val, fdt_size_val; + const char *const bcm_intc_device_list[] __maybe_unused = { + "brcm,bcm2836-l1-intc", + NULL, + }; + + /* 1.初始化测试场景 */ + bufsize = TEST_DTB_SIZE; + void *test_fdt = malloc(bufsize); + + ret = fdt_create_empty_tree(test_fdt, bufsize); + if (ret) + uk_pr_err("create a dtb failed\n"); + + /* 2.设备树读取中断控制器异常场景 */ + /* 2.1根据compatible读取中断控制器异常场景 */ + fdt_bcm_intc = fdt_node_offset_by_compatible_list( + test_fdt, -1, bcm_intc_device_list); + UK_TEST_EXPECT_SNUM_EQ(fdt_bcm_intc, -FDT_ERR_NOTFOUND); + + /* 2.2读取中断控制器地址与长度异常场景 */ + /* 向临时设备树中添加测试节点 */ + test_timer = fdt_add_subnode(test_fdt, 0, "intc"); + ret = fdt_setprop(test_fdt, test_timer, "compatible", + "brcm,bcm2836-l1-intc", + strlen(bcm_intc_device_list[0])); + if (ret) + uk_pr_err("set compatible failed\n"); + + /* 校验设备树中已注册测试节点 */ + fdt_bcm_intc = fdt_node_offset_by_compatible_list( + test_fdt, -1, bcm_intc_device_list); + UK_TEST_EXPECT_SNUM_EQ(fdt_bcm_intc, test_timer); + + /* 尝试读取地址,预期失败 */ + ret = fdt_get_address(test_fdt, 0, 0, + &fdt_address_val, + &fdt_size_val); + UK_TEST_EXPECT_SNUM_EQ(ret, -FDT_ERR_NOTFOUND); + + /* 3.恢复环境 */ + free(test_fdt); +} + +uk_testsuite_register(uk_driver_bcm_intc, NULL); diff --git a/lib/ukintctlr/Config.uk b/lib/ukintctlr/Config.uk index ca170ff7..05edee73 100644 --- a/lib/ukintctlr/Config.uk +++ b/lib/ukintctlr/Config.uk @@ -1,7 +1,7 @@ config HAVE_INTCTLR bool -config LIBUKINTCTLR +menuconfig LIBUKINTCTLR bool "ukintctlr: Interrupt Controller API" depends on HAVE_INTCTLR @@ -15,4 +15,9 @@ config LIBUKINTCTLR_ISR_ECTX_ASSERTIONS bool "Check for unmodified ECTX in interrupt handlers" depends on ARCH_X86_64 +config LIBUKINTCTLR_TEST + bool "Enable unit tests" + default n + select LIBUKTEST + endif diff --git a/lib/ukintctlr/Makefile.uk b/lib/ukintctlr/Makefile.uk index 9c4e3a20..543e1520 100644 --- a/lib/ukintctlr/Makefile.uk +++ b/lib/ukintctlr/Makefile.uk @@ -5,3 +5,8 @@ CINCLUDES-$(CONFIG_LIBUKINTCTLR) += -I$(LIBUKINTCTLR_BASE)/include CXXINCLUDES-$(CONFIG_LIBUKINTCTLR) += -I$(LIBUKINTCTLR_BASE)/include LIBUKINTCTLR_SRCS-y += $(LIBUKINTCTLR_BASE)/ukintctlr.c + +ifneq ($(filter y,$(CONFIG_LIBUKINTCTLR_TEST) $(CONFIG_LIBUKTEST_ALL)),) +LIBUKINTCTLR_CINCLUDES-y += -I$(CONFIG_UK_BASE)/plat/common/include +LIBUKINTCTLR_SRCS-y += $(LIBUKINTCTLR_BASE)/tests/test_intctlr.c +endif diff --git a/lib/ukintctlr/tests/test_intctlr.c b/lib/ukintctlr/tests/test_intctlr.c new file mode 100644 index 00000000..25e4a7cf --- /dev/null +++ b/lib/ukintctlr/tests/test_intctlr.c @@ -0,0 +1,224 @@ +/* Copyright 2023 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +static struct uk_intctlr_desc *ori_intctlr; +static struct uk_intctlr_desc test_intctlr; +struct uk_intctlr_driver_ops test_ops; +static int ret; + +enum ukintctlr_test_ret { + TEST_DEFAULT, + TEST_CONFIGURE_IRQ_SUCCESS, + TEST_FDT_XLAT_SUCCESS, + TEST_MASK_IRQ_SUCCESS, + TEST_UNMASK_IRQ_SUCCESS, + TEST_INITIALIZE_SUCCESS, + TEST_HANDLE_SUCCESS, + TEST_SGI_OP_SUCCESS, + TEST_PERCPU_INIT_SUCCESS, +}; + +static int test_configure_irq(struct uk_intctlr_irq *irq) +{ + (void)*irq; + ret = TEST_CONFIGURE_IRQ_SUCCESS; + return 0; +} + +static int test_fdt_xlat(const void *fdt __unused, int nodeoffset, __u32 index, + struct uk_intctlr_irq *irq) +{ + (void)nodeoffset; + (void)index; + (void)*irq; + ret = TEST_FDT_XLAT_SUCCESS; + return 0; +} + +static void test_mask_irq(unsigned int irq) +{ + (void)irq; + ret = TEST_MASK_IRQ_SUCCESS; +} + +static void test_unmask_irq(unsigned int irq) +{ + (void)irq; + ret = TEST_UNMASK_IRQ_SUCCESS; +} + +static void test_handle(struct __regs *regs) +{ + (void)*regs; + ret = TEST_HANDLE_SUCCESS; +} + +static void test_sgi_op(uint8_t sgintid, uint32_t cpuid) +{ + (void)sgintid; + (void)cpuid; + ret = TEST_SGI_OP_SUCCESS; +} + +static int test_percpu_init(uint64_t cpuid) +{ + (void)cpuid; + ret = TEST_SGI_OP_SUCCESS; + + return 0; +} + +static inline void test_intctlr_init(void) +{ + ori_intctlr = uk_intctlr; + ret = 0; + + test_intctlr.name = "TEST_INTCTLR"; + test_ops.configure_irq = test_configure_irq; + test_ops.fdt_xlat = test_fdt_xlat; + test_ops.mask_irq = test_mask_irq; + test_ops.unmask_irq = test_unmask_irq; + test_ops.handle = test_handle; + test_ops.sgi_op = test_sgi_op; + test_ops.percpu_init = test_percpu_init; + test_intctlr.ops = &test_ops; + + uk_intctlr_register(&test_intctlr); +} + +/* 测试configure_irq接口 */ +UK_TESTCASE(ukintctlr, call_intctlr_configure_irq) +{ + struct uk_intctlr_irq irq = {0}; + struct uk_intctlr_irq *p_irq = &irq; + + /* 1.备份原有uk_intctlr,初始化测试环境 */ + test_intctlr_init(); + + /* 2.通过统一接口调用configure_irq,并校验调用结果 */ + (void)uk_intctlr_irq_configure(p_irq); + UK_TEST_EXPECT_SNUM_EQ(ret, TEST_CONFIGURE_IRQ_SUCCESS); + + /* 3.恢复环境 */ + uk_intctlr_register(ori_intctlr); +} + +/* 测试fdt_xlat接口 */ +UK_TESTCASE(ukintctlr, call_fdt_xlat) +{ + struct uk_intctlr_irq irq = {0}; + struct uk_intctlr_irq *p_irq = &irq; + const char *fdt = "FDT"; + int nodeoffset = 0; + __u32 index = 0; + + /* 1.备份原有uk_intctlr,初始化测试环境 */ + test_intctlr_init(); + + /* 2.通过统一接口调用fdt_xlat,并校验调用结果 */ + (void)uk_intctlr_irq_fdt_xlat(fdt, nodeoffset, index, p_irq); + UK_TEST_EXPECT_SNUM_EQ(ret, TEST_FDT_XLAT_SUCCESS); + + /* 3.恢复环境 */ + uk_intctlr_register(ori_intctlr); +} + +/* 测试mask_irq接口 */ +UK_TESTCASE(ukintctlr, call_mask_irq) +{ + int irq = 0; + + /* 1.备份原有uk_intctlr,初始化测试环境 */ + test_intctlr_init(); + + /* 2.通过统一接口调用mask_irq,并校验调用结果 */ + uk_intctlr_irq_mask(irq); + UK_TEST_EXPECT_SNUM_EQ(ret, TEST_MASK_IRQ_SUCCESS); + + /* 3.恢复环境 */ + uk_intctlr_register(ori_intctlr); +} + +/* 测试unmask_irq接口 */ +UK_TESTCASE(ukintctlr, call_unmask_irq) +{ + int irq = 0; + + /* 1.备份原有uk_intctlr,初始化测试环境 */ + test_intctlr_init(); + + /* 2.通过统一接口调用unmask_irq,并校验调用结果 */ + uk_intctlr_irq_unmask(irq); + UK_TEST_EXPECT_SNUM_EQ(ret, TEST_UNMASK_IRQ_SUCCESS); + + /* 3.恢复环境 */ + uk_intctlr_register(ori_intctlr); +} + +/* 测试handle接口 */ +UK_TESTCASE(ukintctlr, call_handler) +{ + struct __regs *regs = NULL; + + /* 1.备份原有uk_intctlr,初始化测试环境 */ + test_intctlr_init(); + + /* 2.通过统一接口调用handle,并校验调用结果 */ + uk_intctlr_handle(regs); + UK_TEST_EXPECT_SNUM_EQ(ret, TEST_HANDLE_SUCCESS); + + /* 3.恢复环境 */ + uk_intctlr_register(ori_intctlr); +} + +/* 测试sgi_op接口 */ +UK_TESTCASE(ukintctlr, call_sgi_op) +{ + uint8_t sgintid = 0; + uint32_t cpuid = 0; + + /* 1.备份原有uk_intctlr,初始化测试环境 */ + test_intctlr_init(); + + /* 2.通过统一接口调用sgi_op,并校验调用结果 */ + (void)uk_intctlr_sgi_op(sgintid, cpuid); + UK_TEST_EXPECT_SNUM_EQ(ret, TEST_SGI_OP_SUCCESS); + + /* 3.恢复环境 */ + uk_intctlr_register(ori_intctlr); +} + +/* 测试percpu_init接口 */ +UK_TESTCASE(ukintctlr, call_percpu_init) +{ + uint64_t sgintid = 0; + int r; + + /* 1.备份原有uk_intctlr,初始化测试环境 */ + test_intctlr_init(); + + /* 2.通过统一接口调用percpu_init,并校验调用结果 */ + r = uk_intctlr_percpu_init(sgintid); + UK_TEST_EXPECT_SNUM_EQ(ret, TEST_SGI_OP_SUCCESS); + + /* 3.恢复环境 */ + uk_intctlr_register(ori_intctlr); +} + +uk_testsuite_register(ukintctlr, NULL); -- Gitee From f20b2430655eb59ab1578356ad9da2869bd6d970 Mon Sep 17 00:00:00 2001 From: liu__sai Date: Tue, 9 Jan 2024 16:21:15 +0800 Subject: [PATCH 31/57] ci: solve a problem when merging a pr belongs to the current repo Signed-off-by: liu__sai --- ci/.jenkinsfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ci/.jenkinsfile b/ci/.jenkinsfile index 560b176a..bd9a2e9f 100644 --- a/ci/.jenkinsfile +++ b/ci/.jenkinsfile @@ -214,6 +214,7 @@ pipeline { /* 1.获得相关PR信息 */ GetDependedPRInfo() /* 2.初始化各类代码仓和目录结构 */ + MergeDependedPR("unikraft", "./") result = sh(script: """ #!/bin/bash cd $WORKSPACE @@ -221,7 +222,6 @@ pipeline { cp -r `ls |grep -v 'unikraft'|xargs` unikraft mkdir apps libs plats """, returnStatus: true) - MergeDependedPR("unikraft", "unikraft") for (item in AppsRepoInfo) { result = sh(script: """ cd $WORKSPACE @@ -435,6 +435,7 @@ pipeline { /* 校验uktest用例是否失败 */ resultCheck = sh(script: ''' cd $WORKSPACE/ + cat $WORKSPACE/libc-test$BUILD_NUMBER.out grep "\\[ FAILED ]" $WORKSPACE/self-test$BUILD_NUMBER.out ''', returnStatus: true) if (resultCheck != 0) { -- Gitee From b2251a989ac6f672ebed3ac097c8416a8c6a8d3a Mon Sep 17 00:00:00 2001 From: Li Haode Date: Tue, 9 Jan 2024 16:52:05 +0800 Subject: [PATCH 32/57] lib/posix-mmap:[upstream][test]add mmap munmap mprotect test Signed-off-by: Li Haode --- lib/posix-mmap/tests/test_posix_mmap.c | 133 +++++++++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/lib/posix-mmap/tests/test_posix_mmap.c b/lib/posix-mmap/tests/test_posix_mmap.c index 12057c4b..f1469f2c 100644 --- a/lib/posix-mmap/tests/test_posix_mmap.c +++ b/lib/posix-mmap/tests/test_posix_mmap.c @@ -24,6 +24,57 @@ STRINGIFY(cond)); \ } while (0) +struct vma_entry { + __vaddr_t start; + __vaddr_t end; + unsigned long attr; +}; + +static void vmem_print(struct uk_vas *vas) +{ + struct uk_vma *vma; + int i = 0; + + pr_info(" VAS layout:\n"); + uk_list_for_each_entry(vma, &vas->vma_list, vma_list) { + if (vma->name && strcmp("heap", vma->name) == 0) + continue; + + pr_info(" [%d] 0x%lx-0x%lx %c%c%c %s\n", i++, + vma->start, vma->end, + (vma->attr & PAGE_ATTR_PROT_READ) ? 'r' : '-', + (vma->attr & PAGE_ATTR_PROT_WRITE) ? 'w' : '-', + (vma->attr & PAGE_ATTR_PROT_EXEC) ? 'x' : '-', + (vma->name) ? vma->name : ""); + } +} + +static int chk_vas(struct uk_vas *vas, struct vma_entry *vmas, int num) +{ + struct uk_vma *vma; + int i = 0; + + vmem_print(vas); + + uk_list_for_each_entry(vma, &vas->vma_list, vma_list) { + if (vma->name && strcmp("heap", vma->name) == 0) + continue; + + if (i >= num) + return -1; + + if (vma->start != vmas[i].start || + vma->end != vmas[i].end || + vma->attr != vmas[i].attr || + vma->vas != vas) + return -1; + + i++; + } + + return (i == num) ? 0 : -1; +} + static struct uk_vas *vas_init(void) { struct uk_vas *vas = uk_vas_get_active(); @@ -69,4 +120,86 @@ UK_TESTCASE(posix_mmap, test_mmap) vas_clean(vas); } +#ifdef CONFIG_LIBVFSCORE +#include +#include +#include +#include +#include + +UK_TESTCASE(posix_mmap, test_munmap) +{ + struct uk_vas *vas = vas_init(); + void *addr1, *addr2; + int fd, i, rc; + __ssz len; + + fd = creat("/test_munmap", 0700); + + addr1 = mmap(NULL, 2 * PAGE_SIZE, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + UK_TEST_EXPECT(addr1 != MAP_FAILED); + + addr2 = mmap(addr1 + 2 * PAGE_SIZE, 2 * PAGE_SIZE, PROT_READ, + MAP_PRIVATE, fd, 0); + UK_TEST_EXPECT(addr2 != MAP_FAILED); + + rc = munmap(addr1 + PAGE_SIZE, 2 * PAGE_SIZE); + UK_TEST_EXPECT_ZERO(rc); + + UK_TEST_EXPECT_ZERO(chk_vas(vas, (struct vma_entry[]){ + {(__vaddr_t)addr1, (__vaddr_t)addr1 + PAGE_SIZE, PROT_READ}, + {(__vaddr_t)addr2 + PAGE_SIZE, (__vaddr_t)addr2 + 2 * PAGE_SIZE, + PROT_READ}, + }, 2)); + + /* Clean up */ + close(fd); + unlink("/test_munmap"); + + vas_clean(vas); +} + +UK_TESTCASE(posix_mmap, test_mprotect) +{ + struct uk_vas *vas = vas_init(); + void *addr1, *addr2; + int fd, rc; + + fd = creat("/test_mprotect", 0700); + + addr1 = mmap(NULL, 2 * PAGE_SIZE, PROT_READ, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + UK_TEST_EXPECT(addr1 != MAP_FAILED); + + addr2 = mmap(addr1 + 2 * PAGE_SIZE, 2 * PAGE_SIZE, PROT_READ, + MAP_PRIVATE, fd, 0); + UK_TEST_EXPECT(addr2 != MAP_FAILED); + + UK_TEST_EXPECT_ZERO(chk_vas(vas, (struct vma_entry[]){ + {(__vaddr_t)addr1, (__vaddr_t)addr1 + 2 * PAGE_SIZE, PROT_READ}, + {(__vaddr_t)addr2, (__vaddr_t)addr2 + 2 * PAGE_SIZE, PROT_READ}, + }, 2)); + + rc = mprotect(addr1 + PAGE_SIZE, 2 * PAGE_SIZE, PROT_READ | PROT_WRITE); + UK_TEST_EXPECT_ZERO(rc); + + UK_TEST_EXPECT_ZERO(chk_vas(vas, (struct vma_entry[]){ + {(__vaddr_t)addr1, (__vaddr_t)addr1 + PAGE_SIZE, PROT_READ}, + {(__vaddr_t)addr1 + PAGE_SIZE, (__vaddr_t)addr1 + 2 * PAGE_SIZE, + PROT_READ | PROT_WRITE}, + {(__vaddr_t)addr2, (__vaddr_t)addr2 + PAGE_SIZE, + PROT_READ | PROT_WRITE}, + {(__vaddr_t)addr2 + PAGE_SIZE, (__vaddr_t)addr2 + 2 * PAGE_SIZE, + PROT_READ}, + }, 4)); + + /* Clean up */ + close(fd); + unlink("/test_mprotect"); + + vas_clean(vas); +} +#endif + uk_testsuite_register(posix_mmap, NULL); -- Gitee From 2d263b2d13bb8df26b55dd75d3f4a817ead35640 Mon Sep 17 00:00:00 2001 From: Li Haode Date: Tue, 9 Jan 2024 16:55:10 +0800 Subject: [PATCH 33/57] lib/ukvmem: [upstream][test]add anon_vma and dma_vma ops method tests Signed-off-by: Li Haode --- lib/ukvmem/tests/test_vmem.c | 363 ++++++++++++++++++++++++++++++++++- 1 file changed, 360 insertions(+), 3 deletions(-) diff --git a/lib/ukvmem/tests/test_vmem.c b/lib/ukvmem/tests/test_vmem.c index a88cc29b..475bc844 100644 --- a/lib/ukvmem/tests/test_vmem.c +++ b/lib/ukvmem/tests/test_vmem.c @@ -678,7 +678,6 @@ UK_TESTCASE(ukvmem, test_vma_stack) /** * Tests file mappings */ -#define VMEM_TEST_FILENAME "/test_vma_file" UK_TESTCASE(ukvmem, test_vma_file) { struct uk_vas *vas = vas_init(); @@ -693,7 +692,7 @@ UK_TESTCASE(ukvmem, test_vma_file) * page of data at the end, to check if the mapping returns zeroed * memory for the remainder of the page. */ - fd = creat(VMEM_TEST_FILENAME, 0700); + fd = creat("/test_vma_file", 0700); vmem_bug_on(fd < 0); buf = malloc(PAGE_SIZE); @@ -762,7 +761,7 @@ UK_TESTCASE(ukvmem, test_vma_file) /* Clean up */ close(fd); - unlink(VMEM_TEST_FILENAME); + unlink("/test_vma_file"); vas_clean(vas); } @@ -839,4 +838,362 @@ UK_TESTCASE(ukvmem, test_vma_replace) vas_clean(vas); } +UK_TESTCASE(ukvmem, test_vma_map_anon) +{ + struct uk_vas *vas = vas_init(); + __vaddr_t va1; + int rc; + __sz len; + + /* 测试正常情况 */ + va1 = __VADDR_ANY; + rc = uk_vma_map_anon(vas, &va1, 4 * PAGE_SIZE, PROT_R, + UK_VMA_MAP_POPULATE, NULL); + UK_TEST_EXPECT_ZERO(rc); + len = probe_r(va1, 4 * PAGE_SIZE); + UK_TEST_EXPECT_SNUM_EQ(len, 4 * PAGE_SIZE); + + /* 测试申请内存重合场景 未指定 UK_VMA_MAP_REPLACE */ + rc = uk_vma_map_anon(vas, &va1, PAGE_SIZE, PROT_RW, + UK_VMA_MAP_POPULATE, NULL); + UK_TEST_EXPECT_SNUM_EQ(rc, -EEXIST); + + /* 测试申请内存重合场景 指定 UK_VMA_MAP_REPLACE + * 同种类型 vma 支持 + */ + rc = uk_vma_map_anon(vas, &va1, PAGE_SIZE, PROT_RW, + UK_VMA_MAP_REPLACE, NULL); + UK_TEST_EXPECT_ZERO(rc); + + vas_clean(vas); +} + +UK_TESTCASE(ukvmem, test_vma_anon_set_attr) +{ + struct uk_vas *vas = vas_init(); + __vaddr_t va1; + int rc; + __sz len; + + va1 = __VADDR_ANY; + rc = uk_vma_map_anon(vas, &va1, PAGE_SIZE, PROT_R, + UK_VMA_MAP_POPULATE, NULL); + UK_TEST_EXPECT_ZERO(rc); + + struct uk_vma *cur_vma = uk_vma_find(vas, va1); + + len = probe_r_nopage(va1, PAGE_SIZE); + UK_TEST_EXPECT_SNUM_EQ(len, PAGE_SIZE); + len = probe_rw_nopage(va1, PAGE_SIZE); + UK_TEST_EXPECT_ZERO(len); + + rc = cur_vma->ops->set_attr(cur_vma, PROT_RW); + UK_TEST_EXPECT_ZERO(rc); + + len = probe_r_nopage(va1, PAGE_SIZE); + UK_TEST_EXPECT_SNUM_EQ(len, PAGE_SIZE); + len = probe_rw_nopage(va1, PAGE_SIZE); + UK_TEST_EXPECT_SNUM_EQ(len, PAGE_SIZE); + + vas_clean(vas); +} + +UK_TESTCASE(ukvmem, test_vma_anon_unmap) +{ + struct uk_vas *vas = vas_init(); + __vaddr_t va1, va2, va3, va4; + int rc; + __sz len; + + va1 = __VADDR_ANY; + rc = uk_vma_map_anon(vas, &va1, PAGE_SIZE, PROT_R, + UK_VMA_MAP_POPULATE, NULL); + UK_TEST_EXPECT_ZERO(rc); + + va2 = __VADDR_ANY; + rc = uk_vma_map_anon(vas, &va2, PAGE_SIZE, PROT_R, + 0, NULL); + UK_TEST_EXPECT_ZERO(rc); + + va3 = __VADDR_ANY; + rc = uk_vma_map_anon(vas, &va3, 2 * PAGE_SIZE, PROT_R, + UK_VMA_MAP_POPULATE, NULL); + UK_TEST_EXPECT_ZERO(rc); + + va4 = __VADDR_ANY; + rc = uk_vma_map_anon(vas, &va4, 2 * PAGE_SIZE, PROT_R, + 0, NULL); + UK_TEST_EXPECT_ZERO(rc); + + /* 分配底层帧且释放全部 */ + struct uk_vma *vma1 = uk_vma_find(vas, va1); + + rc = vma1->ops->unmap(vma1, va1, PAGE_SIZE); + UK_TEST_EXPECT_ZERO(rc); + len = probe_r_nopage(va1, PAGE_SIZE); + UK_TEST_EXPECT_ZERO(len); + + /* 未分配底层帧且释放全部 */ + struct uk_vma *vma2 = uk_vma_find(vas, va2); + + rc = vma2->ops->unmap(vma2, va2, PAGE_SIZE); + UK_TEST_EXPECT_ZERO(rc); + len = probe_r_nopage(va2, PAGE_SIZE); + UK_TEST_EXPECT_ZERO(len); + + /* 分配底层帧,释放部分 */ + struct uk_vma *vma3 = uk_vma_find(vas, va3); + + rc = vma3->ops->unmap(vma3, va3, PAGE_SIZE); + UK_TEST_EXPECT_ZERO(rc); + len = probe_r_nopage(va3, 2 * PAGE_SIZE); + UK_TEST_EXPECT_SNUM_EQ(len, PAGE_SIZE); + + /* 未分配底层帧,释放部分 */ + struct uk_vma *vma4 = uk_vma_find(vas, va4); + + rc = vma4->ops->unmap(vma4, va4, PAGE_SIZE); + UK_TEST_EXPECT_ZERO(rc); + len = probe_r_nopage(va3, 2 * PAGE_SIZE); + UK_TEST_EXPECT_SNUM_EQ(len, PAGE_SIZE); + + vas_clean(vas); +} + +UK_TESTCASE(ukvmem, test_vma_anon_fault) +{ + struct uk_vas *vas = vas_init(); + __vaddr_t va1; + int rc; + __sz len; + + va1 = __VADDR_ANY; + rc = uk_vma_map_anon(vas, &va1, 3 * PAGE_SIZE, PROT_R, + 0, NULL); + UK_TEST_EXPECT_ZERO(rc); + + len = probe_r_nopage(va1, 3 * PAGE_SIZE); + UK_TEST_EXPECT_ZERO(len); + + len = probe_r(va1, 3 * PAGE_SIZE); + UK_TEST_EXPECT_SNUM_EQ(len, 3 * PAGE_SIZE); + + len = probe_r_nopage(va1, 3 * PAGE_SIZE); + UK_TEST_EXPECT_SNUM_EQ(len, 3 * PAGE_SIZE); + + vas_clean(vas); +} + +UK_TESTCASE(ukvmem, test_map_dma) +{ + struct uk_vas *vas = vas_init(); + __vaddr_t va1, va2, va3; + __paddr_t pa1, pa2, pa3; + int rc; + + /* 测试正常情况 */ + va1 = __VADDR_ANY; + pa1 = __PADDR_ANY; + rc = vas->pt->fa->falloc(vas->pt->fa, &pa1, 3, 0); + vmem_bug_on(rc != 0); + rc = uk_vma_map_dma(vas, &va1, 3 * PAGE_SIZE, PROT_R, 0, + NULL, pa1); + UK_TEST_EXPECT_ZERO(rc); + + UK_TEST_EXPECT_ZERO(chk_vas(vas, (struct vma_entry[]){ + {va1, va1 + 3 * PAGE_SIZE, PROT_R}, + }, 1)); + + /* 测试申请内存重合场景 未指定 UK_VMA_MAP_REPLACE */ + va2 = va1; + pa2 = __PADDR_ANY; + rc = vas->pt->fa->falloc(vas->pt->fa, &pa2, 1, 0); + vmem_bug_on(rc != 0); + rc = uk_vma_map_dma(vas, &va2, PAGE_SIZE, PROT_RW, 0, + NULL, pa2); + UK_TEST_EXPECT_SNUM_EQ(rc, -EEXIST); + + /* 测试申请内存重合场景 指定 UK_VMA_MAP_REPLACE */ + va3 = va1 + 2 * PAGE_SIZE; + pa3 = __PADDR_ANY; + rc = vas->pt->fa->falloc(vas->pt->fa, &pa3, 1, 0); + vmem_bug_on(rc != 0); + rc = uk_vma_map_dma(vas, &va3, PAGE_SIZE, PROT_RW, UK_VMA_MAP_REPLACE, + NULL, pa3); + UK_TEST_EXPECT_ZERO(rc); + + UK_TEST_EXPECT_ZERO(chk_vas(vas, (struct vma_entry[]){ + {va1, va1 + 2 * PAGE_SIZE, PROT_R}, + {va3, va3 + PAGE_SIZE, PROT_RW}, + }, 2)); + + vas_clean(vas); +} + +UK_TESTCASE(ukvmem, test_vma_dma_set_attr) +{ + struct uk_vas *vas = vas_init(); + __vaddr_t va1; + __paddr_t pa1; + int rc; + __sz len; + + va1 = __VADDR_ANY; + pa1 = __PADDR_ANY; + rc = vas->pt->fa->falloc(vas->pt->fa, &pa1, 3, 0); + vmem_bug_on(rc != 0); + rc = uk_vma_map_dma(vas, &va1, 3 * PAGE_SIZE, PROT_R, + UK_VMA_MAP_POPULATE, NULL, pa1); + UK_TEST_EXPECT_ZERO(rc); + + struct uk_vma *cur_vma = uk_vma_find(vas, va1); + + len = probe_r_nopage(va1, 3 * PAGE_SIZE); + UK_TEST_EXPECT_SNUM_EQ(len, 3 * PAGE_SIZE); + len = probe_rw_nopage(va1, 3 * PAGE_SIZE); + UK_TEST_EXPECT_ZERO(len); + + cur_vma->ops->set_attr(cur_vma, PROT_RW); + + len = probe_r_nopage(va1, 3 * PAGE_SIZE); + UK_TEST_EXPECT_SNUM_EQ(len, 3 * PAGE_SIZE); + len = probe_rw_nopage(va1, 3 * PAGE_SIZE); + UK_TEST_EXPECT_SNUM_EQ(len, 3 * PAGE_SIZE); + + vas_clean(vas); +} + +UK_TESTCASE(ukvmem, test_vma_dma_unmap) +{ + struct uk_vas *vas = vas_init(); + __vaddr_t va1, va2; + __paddr_t pa1, pa2; + int rc; + __sz len; + + va1 = __VADDR_ANY; + pa1 = __PADDR_ANY; + rc = vas->pt->fa->falloc(vas->pt->fa, &pa1, 3, 0); + vmem_bug_on(rc != 0); + rc = uk_vma_map_dma(vas, &va1, 3 * PAGE_SIZE, PROT_R, + UK_VMA_MAP_POPULATE, NULL, pa1); + UK_TEST_EXPECT_ZERO(rc); + + va2 = __VADDR_ANY; + pa2 = __PADDR_ANY; + rc = vas->pt->fa->falloc(vas->pt->fa, &pa2, 3, 0); + vmem_bug_on(rc != 0); + rc = uk_vma_map_dma(vas, &va2, 3 * PAGE_SIZE, PROT_R, + UK_VMA_MAP_POPULATE, NULL, pa2); + UK_TEST_EXPECT_ZERO(rc); + + /* 分配物理帧且全部释放 */ + struct uk_vma *vma1 = uk_vma_find(vas, va1); + + rc = vma1->ops->unmap(vma1, va1, 3 * PAGE_SIZE); + UK_TEST_EXPECT_ZERO(rc); + len = probe_r_nopage(va1, 3 * PAGE_SIZE); + UK_TEST_EXPECT_ZERO(len); + + /* 分配物理帧且部分释放 */ + struct uk_vma *vma2 = uk_vma_find(vas, va2); + + rc = vma2->ops->unmap(vma2, va2 + PAGE_SIZE, PAGE_SIZE); + UK_TEST_EXPECT_ZERO(rc); + len = probe_r_nopage(va2, 3 * PAGE_SIZE); + UK_TEST_EXPECT_SNUM_EQ(len, 2 * PAGE_SIZE); + + vas_clean(vas); +} + +UK_TESTCASE(ukvmem, test_vma_dma_fault) +{ + struct uk_vas *vas = vas_init(); + __vaddr_t va1; + __paddr_t pa1; + int rc; + __sz len; + + va1 = __VADDR_ANY; + pa1 = __PADDR_ANY; + rc = vas->pt->fa->falloc(vas->pt->fa, &pa1, 5, 0); + vmem_bug_on(rc != 0); + rc = uk_vma_map_dma(vas, &va1, 5 * PAGE_SIZE, PROT_R, 0, + NULL, pa1); + UK_TEST_EXPECT_ZERO(rc); + + len = probe_r_nopage(va1, 5 * PAGE_SIZE); + UK_TEST_EXPECT_ZERO(len); + + len = probe_r(va1, 5 * PAGE_SIZE); + UK_TEST_EXPECT_SNUM_EQ(len, 5 * PAGE_SIZE); + + len = probe_r_nopage(va1, 5 * PAGE_SIZE); + UK_TEST_EXPECT_SNUM_EQ(len, 5 * PAGE_SIZE); + + vas_clean(vas); +} + +UK_TESTCASE(ukvmem, test_vma_dma_merge) +{ + struct uk_vas *vas = vas_init(); + __vaddr_t va1, va2; + __paddr_t pa1, pa2; + int rc; + + va1 = __VADDR_ANY; + pa1 = __PADDR_ANY; + rc = vas->pt->fa->falloc(vas->pt->fa, &pa1, 5, 0); + vmem_bug_on(rc != 0); + rc = uk_vma_map_dma(vas, &va1, 5 * PAGE_SIZE, PROT_R, 0, + NULL, pa1); + UK_TEST_EXPECT_ZERO(rc); + + va2 = va1 + 5 * PAGE_SIZE; + pa2 = __PADDR_ANY; + rc = vas->pt->fa->falloc(vas->pt->fa, &pa2, 1, 0); + vmem_bug_on(rc != 0); + rc = uk_vma_map_dma(vas, &va2, PAGE_SIZE, PROT_R, 0, + NULL, pa2); + UK_TEST_EXPECT_ZERO(rc); + + UK_TEST_EXPECT_ZERO(chk_vas(vas, (struct vma_entry[]){ + {va1, va1 + 6 * PAGE_SIZE, PROT_R} + }, 1)); + + vas_clean(vas); +} + +UK_TESTCASE(ukvmem, test_vma_dma_split) +{ + struct uk_vas *vas = vas_init(); + __vaddr_t va1, va2; + __paddr_t pa1, pa2; + int rc; + + va1 = __VADDR_ANY; + pa1 = __PADDR_ANY; + rc = vas->pt->fa->falloc(vas->pt->fa, &pa1, 5, 0); + vmem_bug_on(rc != 0); + rc = uk_vma_map_dma(vas, &va1, 5 * PAGE_SIZE, PROT_R, 0, + NULL, pa1); + UK_TEST_EXPECT_ZERO(rc); + + va2 = va1 + 2 * PAGE_SIZE; + pa2 = __PADDR_ANY; + rc = vas->pt->fa->falloc(vas->pt->fa, &pa2, 1, 0); + vmem_bug_on(rc != 0); + rc = uk_vma_map_dma(vas, &va2, PAGE_SIZE, PROT_RW, UK_VMA_MAP_REPLACE, + NULL, pa2); + UK_TEST_EXPECT_ZERO(rc); + + UK_TEST_EXPECT_ZERO(chk_vas(vas, (struct vma_entry[]){ + {va1, va1 + 2 * PAGE_SIZE, PROT_R}, + {va2, va2 + PAGE_SIZE, PROT_RW}, + {va2 + PAGE_SIZE, va1 + 5 * PAGE_SIZE, PROT_R}, + }, 3)); + + vas_clean(vas); +} + uk_testsuite_register(ukvmem, NULL); -- Gitee From 5ec9e384e06e4264f5e2ec1b6b636543f740a66d Mon Sep 17 00:00:00 2001 From: Li Haode Date: Tue, 9 Jan 2024 16:58:39 +0800 Subject: [PATCH 34/57] ci/defconfigs: add vmem config Signed-off-by: Li Haode --- ci/defconfigs/raspi-arm64-libc-test | 8 ++++++++ ci/defconfigs/raspi-arm64-uktest | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/ci/defconfigs/raspi-arm64-libc-test b/ci/defconfigs/raspi-arm64-libc-test index 88e70405..cde48fc4 100644 --- a/ci/defconfigs/raspi-arm64-libc-test +++ b/ci/defconfigs/raspi-arm64-libc-test @@ -38,3 +38,11 @@ CONFIG_LIBUKDEBUG_PRINTK_INFO=y # CONFIG_LIBUKDEBUG_PRINTK_CRIT is not set CONFIG_LIBLIBCTEST_ENV_TESTS=y CONFIG_LIBLIBCTEST_MALLOC_TESTS=y +# CONFIG_ENFORCE_W_XOR_X is not set +CONFIG_LIBUKNOFAULT=y +CONFIG_LIBUKVMEM=y +CONFIG_LIBPOSIX_MMAP=y +CONFIG_LIBVFSCORE=y +CONFIG_LIBVFSCORE_NONLARGEFILE=y +CONFIG_LIBVFSCORE_AUTOMOUNT_ROOTFS=y +CONFIG_LIBVFSCORE_FSTAB=y diff --git a/ci/defconfigs/raspi-arm64-uktest b/ci/defconfigs/raspi-arm64-uktest index ffbd87a5..550591f6 100644 --- a/ci/defconfigs/raspi-arm64-uktest +++ b/ci/defconfigs/raspi-arm64-uktest @@ -17,3 +17,11 @@ CONFIG_MCPU_ARM64_GENERIC=y # CONFIG_ARM64_ERRATUM_858921 is not set CONFIG_PLAT_RASPI=y CONFIG_LIBUKTEST=y +# CONFIG_ENFORCE_W_XOR_X is not set +CONFIG_LIBUKNOFAULT=y +CONFIG_LIBUKVMEM=y +CONFIG_LIBPOSIX_MMAP=y +CONFIG_LIBVFSCORE=y +CONFIG_LIBVFSCORE_NONLARGEFILE=y +CONFIG_LIBVFSCORE_AUTOMOUNT_ROOTFS=y +CONFIG_LIBVFSCORE_FSTAB=y \ No newline at end of file -- Gitee From 05841af79752a4800094fe9f16d559d8babb4534 Mon Sep 17 00:00:00 2001 From: liu__sai Date: Tue, 2 Jan 2024 09:45:22 +0800 Subject: [PATCH 35/57] lib/vfscore:support mkdir -m and chmod Signed-off-by: liu__sai --- lib/vfscore/Makefile.uk | 1 + lib/vfscore/exportsyms.uk | 3 +++ lib/vfscore/main.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/lib/vfscore/Makefile.uk b/lib/vfscore/Makefile.uk index 8a1e11d7..f15eda14 100644 --- a/lib/vfscore/Makefile.uk +++ b/lib/vfscore/Makefile.uk @@ -36,6 +36,7 @@ UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += chdir-1 UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += fchdir-1 UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += chmod-2 UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += fchmod-2 +UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += fchmodat-3 UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += utime-2 UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += utimes-2 UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += mknod-3 diff --git a/lib/vfscore/exportsyms.uk b/lib/vfscore/exportsyms.uk index 1f3e9375..3a28d0c2 100644 --- a/lib/vfscore/exportsyms.uk +++ b/lib/vfscore/exportsyms.uk @@ -58,6 +58,9 @@ uk_syscall_r_chmod fchmod uk_syscall_e_fchmod uk_syscall_r_fchmod +fchmodat +uk_syscall_e_fchmodat +uk_syscall_r_fchmodat fchown uk_syscall_e_fchown uk_syscall_r_fchown diff --git a/lib/vfscore/main.c b/lib/vfscore/main.c index 9a061a7d..75a9dff4 100644 --- a/lib/vfscore/main.c +++ b/lib/vfscore/main.c @@ -2477,6 +2477,39 @@ UK_SYSCALL_R_DEFINE(int, fchmod, int, fd, mode_t, mode) return 0; } +UK_SYSCALL_R_DEFINE(int, fchmodat, int, dirfd, + const char*, pathname, mode_t, mode) +{ + struct vfscore_file *fp; + int error; + + if (pathname[0] == '/' || dirfd == AT_FDCWD) + return uk_syscall_r_chmod((long) pathname, (long) mode); + + error = fget(dirfd, &fp); + if (error) + return error; + + struct vnode *vp = fp->f_dentry->d_vnode; + + vn_lock(vp); + + char p[PATH_MAX]; + + /* build absolute path */ + strlcpy(p, fp->f_dentry->d_mount->m_path, PATH_MAX); + strlcat(p, fp->f_dentry->d_path, PATH_MAX); + strlcat(p, "/", PATH_MAX); + strlcat(p, pathname, PATH_MAX); + + vn_unlock(vp); + fdrop(fp); + + error = uk_syscall_r_chmod((long) pathname, (long) mode); + + return error; +} + UK_TRACEPOINT(trace_vfs_fchown, "\"%d\" %d %d", int, uid_t, gid_t); UK_TRACEPOINT(trace_vfs_fchown_ret, ""); -- Gitee From 96f198a1718d39c6c9dcbe4775f15eb29498335a Mon Sep 17 00:00:00 2001 From: 1788594346 Date: Tue, 2 Jan 2024 09:57:48 +0800 Subject: [PATCH 36/57] lib/vfscore: supports paths for mkdir which end in '/' Signed-off-by: 1788594346 --- lib/vfscore/syscalls.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/vfscore/syscalls.c b/lib/vfscore/syscalls.c index 1ecea886..1d92dd26 100644 --- a/lib/vfscore/syscalls.c +++ b/lib/vfscore/syscalls.c @@ -580,10 +580,15 @@ sys_mkdir(char *path, mode_t mode) { char *name; struct dentry *dp, *ddp; - int error; + int error, len; DPRINTF(VFSDB_SYSCALL, ("sys_mkdir: path=%s mode=%d\n", path, mode)); + /* Supports paths ending in '/', such as "a/" */ + len = strlen(path); + if (len >= 1 && path[len - 1] == '/') + path[len - 1] = '\0'; + error = namei(path, &dp); if (!error) { /* File already exists */ -- Gitee From 4c06370ab19fba7db80b33636cee93de24a36d88 Mon Sep 17 00:00:00 2001 From: liu__sai Date: Thu, 11 Jan 2024 16:16:47 +0800 Subject: [PATCH 37/57] lib/vfscore: add test cases for vfscore Signed-off-by: liu__sai --- lib/vfscore/Config.uk | 4 ++ lib/vfscore/Makefile.uk | 6 ++ lib/vfscore/main.c | 2 +- lib/vfscore/tests/test_vfscore.c | 98 ++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 lib/vfscore/tests/test_vfscore.c diff --git a/lib/vfscore/Config.uk b/lib/vfscore/Config.uk index a51a9eae..5002fd82 100644 --- a/lib/vfscore/Config.uk +++ b/lib/vfscore/Config.uk @@ -12,6 +12,10 @@ menuconfig LIBVFSCORE select LIBPOSIX_PIPE if LIBVFSCORE +config LIBVFSCORE_TEST + bool "Enable unit tests" + default n + config LIBVFSCORE_NONLARGEFILE bool "Non-largefile system calls" default y if LIBSYSCALL_SHIM_HANDLER diff --git a/lib/vfscore/Makefile.uk b/lib/vfscore/Makefile.uk index f15eda14..f4d4886c 100644 --- a/lib/vfscore/Makefile.uk +++ b/lib/vfscore/Makefile.uk @@ -73,3 +73,9 @@ UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += newfstatat-4 UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += open-3 UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += openat-4 UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += creat-2 + +ifneq ($(filter y,$(CONFIG_LIBVFSCORE_TEST) $(CONFIG_LIBUKTEST_ALL)),) + +LIBVFSCORE_SRCS-y += $(LIBVFSCORE_BASE)/tests/test_vfscore.c + +endif diff --git a/lib/vfscore/main.c b/lib/vfscore/main.c index 75a9dff4..b570d1e3 100644 --- a/lib/vfscore/main.c +++ b/lib/vfscore/main.c @@ -2505,7 +2505,7 @@ UK_SYSCALL_R_DEFINE(int, fchmodat, int, dirfd, vn_unlock(vp); fdrop(fp); - error = uk_syscall_r_chmod((long) pathname, (long) mode); + error = uk_syscall_r_chmod((long) p, (long) mode); return error; } diff --git a/lib/vfscore/tests/test_vfscore.c b/lib/vfscore/tests/test_vfscore.c new file mode 100644 index 00000000..f449db22 --- /dev/null +++ b/lib/vfscore/tests/test_vfscore.c @@ -0,0 +1,98 @@ +/* Copyright 2023 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 测试mkdir的路径中包含"/",即递归创建 */ +UK_TESTCASE(vfscore, test_vfscore_mkdir_recursion) +{ + int rc; + struct stat st; + + /* 1.创建test/文件夹 */ + rc = uk_syscall_r_mkdirat(AT_FDCWD, "test/", (mode_t)0777); + UK_TEST_EXPECT_ZERO(rc); + + /* 2.创建test1/test2文件夹,预期创建失败 */ + rc = uk_syscall_r_mkdirat(AT_FDCWD, "test1/test2", (mode_t)0777); + UK_TEST_EXPECT_NOT_ZERO(rc); + + /* 3.读取test文件夹,判断是否存在 */ + rc = uk_syscall_r_fstatat(AT_FDCWD, "test", &st, 0); + UK_TEST_EXPECT_ZERO(rc); + + /* 4.删除test文件夹 */ + rc = uk_syscall_r_rmdir("test"); + UK_TEST_EXPECT_ZERO(rc); + + /* 5.删除test文件夹,判断是否删除成功 */ + rc = uk_syscall_r_fstatat(AT_FDCWD, "test", &st, 0); + UK_TEST_EXPECT_NOT_ZERO(rc); +} + +/* 测试能否赋予权限 */ +UK_TESTCASE(vfscore, test_vfscore_fchmodat) +{ + int rc; + struct stat st; + int dirfd; + + /* 1.创建test文件夹 */ + rc = uk_syscall_r_mkdirat(AT_FDCWD, "test", (mode_t)0777); + UK_TEST_EXPECT_ZERO(rc); + + /* 2.更改test文件夹权限为421,分别为rwx权限 */ + rc = uk_syscall_r_fchmodat(AT_FDCWD, "test", (mode_t)0421); + UK_TEST_EXPECT_ZERO(rc); + + /* 3.查看test文件夹权限是否为写入的权限 */ + rc = uk_syscall_r_fstatat(AT_FDCWD, "test", &st, 0); + UK_TEST_EXPECT_PTR_EQ(st.st_mode & 0777, 0421); + + /* 4.在test文件夹下创建test1文件夹 */ + rc = uk_syscall_r_mkdirat(AT_FDCWD, "test/test1", (mode_t)0777); + UK_TEST_EXPECT_ZERO(rc); + + /* 5.读取test文件夹的文件描述符 */ + dirfd = uk_syscall_r_openat(AT_FDCWD, "test", O_RDONLY, 0); + + /* 6.采用test的文件描述符作传参给test1文件夹写权限 */ + rc = uk_syscall_r_fchmodat(dirfd, "test1", (mode_t)0345); + UK_TEST_EXPECT_ZERO(rc); + + /* 7.查看test1文件夹权限是否为写入的权限 */ + rc = uk_syscall_r_fstatat(dirfd, "test1", &st, 0); + UK_TEST_EXPECT_PTR_EQ(st.st_mode & 0777, 0345); + + /* 8.删除test和test1文件夹 */ + rc = uk_syscall_r_rmdir("test/test1"); + rc = uk_syscall_r_rmdir("test"); + UK_TEST_EXPECT_ZERO(rc); + + /* 9.删除test文件夹,判断是否删除成功 */ + rc = uk_syscall_r_fstatat(AT_FDCWD, "test", &st, 0); + UK_TEST_EXPECT_NOT_ZERO(rc); +} + +uk_testsuite_register(vfscore, NULL); -- Gitee From d322d56f09369db82ea8db813edbba1e0419cb8d Mon Sep 17 00:00:00 2001 From: liu__sai Date: Fri, 12 Jan 2024 16:07:05 +0800 Subject: [PATCH 38/57] lib/vfscore: add 'flags' to syscall fchmodat Signed-off-by: liu__sai --- lib/vfscore/Makefile.uk | 2 +- lib/vfscore/main.c | 11 +++++++++-- lib/vfscore/tests/test_vfscore.c | 4 ++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/lib/vfscore/Makefile.uk b/lib/vfscore/Makefile.uk index f4d4886c..29a6aaac 100644 --- a/lib/vfscore/Makefile.uk +++ b/lib/vfscore/Makefile.uk @@ -36,7 +36,7 @@ UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += chdir-1 UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += fchdir-1 UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += chmod-2 UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += fchmod-2 -UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += fchmodat-3 +UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += fchmodat-4 UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += utime-2 UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += utimes-2 UK_PROVIDED_SYSCALLS-$(CONFIG_LIBVFSCORE) += mknod-3 diff --git a/lib/vfscore/main.c b/lib/vfscore/main.c index b570d1e3..0b3d949e 100644 --- a/lib/vfscore/main.c +++ b/lib/vfscore/main.c @@ -2477,9 +2477,16 @@ UK_SYSCALL_R_DEFINE(int, fchmod, int, fd, mode_t, mode) return 0; } -UK_SYSCALL_R_DEFINE(int, fchmodat, int, dirfd, - const char*, pathname, mode_t, mode) +UK_SYSCALL_R_DEFINE(int, fchmodat, int, dirfd, const char*, pathname, + mode_t, mode, int, flags) { + if (flags != 0) { + /* Only the AT_SYMLINK_NOFOLLOW is allowed */ + if (unlikely(flags & ~AT_SYMLINK_NOFOLLOW)) + return -EINVAL; + /* FIXME: Add support for AT_SYMLINK_NOFOLLOW */ + return -EOPNOTSUPP; + } struct vfscore_file *fp; int error; diff --git a/lib/vfscore/tests/test_vfscore.c b/lib/vfscore/tests/test_vfscore.c index f449db22..b945193b 100644 --- a/lib/vfscore/tests/test_vfscore.c +++ b/lib/vfscore/tests/test_vfscore.c @@ -63,7 +63,7 @@ UK_TESTCASE(vfscore, test_vfscore_fchmodat) UK_TEST_EXPECT_ZERO(rc); /* 2.更改test文件夹权限为421,分别为rwx权限 */ - rc = uk_syscall_r_fchmodat(AT_FDCWD, "test", (mode_t)0421); + rc = uk_syscall_r_fchmodat(AT_FDCWD, "test", (mode_t)0421, 0); UK_TEST_EXPECT_ZERO(rc); /* 3.查看test文件夹权限是否为写入的权限 */ @@ -78,7 +78,7 @@ UK_TESTCASE(vfscore, test_vfscore_fchmodat) dirfd = uk_syscall_r_openat(AT_FDCWD, "test", O_RDONLY, 0); /* 6.采用test的文件描述符作传参给test1文件夹写权限 */ - rc = uk_syscall_r_fchmodat(dirfd, "test1", (mode_t)0345); + rc = uk_syscall_r_fchmodat(dirfd, "test1", (mode_t)0345, 0); UK_TEST_EXPECT_ZERO(rc); /* 7.查看test1文件夹权限是否为写入的权限 */ -- Gitee From d383cdb38dce141b056c3e75eb774fa0c86d224f Mon Sep 17 00:00:00 2001 From: Yifan Zhang Date: Fri, 12 Jan 2024 17:50:18 +0800 Subject: [PATCH 39/57] lib/sched: [upstream][test]fix tests bugs for sched lib --- lib/uksched/tests/test_sched.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/lib/uksched/tests/test_sched.c b/lib/uksched/tests/test_sched.c index 9b390f7c..8108a974 100644 --- a/lib/uksched/tests/test_sched.c +++ b/lib/uksched/tests/test_sched.c @@ -25,6 +25,8 @@ #include #include #include +#include + UK_TESTCASE(uksched, test_sched_register) { @@ -49,8 +51,7 @@ UK_TESTCASE(uksched, test_sched_gc) { /*初始化返回值*/ int ret; - struct uk_alloc *a = uk_alloc_get_default(); - struct uk_sched *s = uk_schedcoop_create(a); + struct uk_sched *s = uk_sched_current(); uintptr_t tlsp; struct uk_thread *t, *tmp; @@ -75,7 +76,7 @@ UK_TESTCASE(uksched, test_sched_gc) UK_TESTCASE(uksched, test_thread_release) { struct uk_alloc *a = uk_alloc_get_default(); - struct uk_sched *s = uk_schedcoop_create(a); + struct uk_sched *s = uk_sched_current(); uintptr_t tlsp; tlsp = ukplat_tlsp_get(); @@ -92,7 +93,7 @@ UK_TESTCASE(uksched, test_thread_release) UK_TESTCASE(uksched, test_thread_block_no_timeout_then_wake) { struct uk_alloc *a = uk_alloc_get_default(); - struct uk_sched *s = uk_schedcoop_create(a); + struct uk_sched *s = uk_sched_current(); uintptr_t tlsp; tlsp = ukplat_tlsp_get(); @@ -110,7 +111,7 @@ UK_TESTCASE(uksched, test_thread_block_no_timeout_then_wake) UK_TESTCASE(uksched, test_thread_set_exited) { struct uk_alloc *a = uk_alloc_get_default(); - struct uk_sched *s = uk_schedcoop_create(a); + struct uk_sched *s = uk_sched_current(); uintptr_t tlsp; tlsp = ukplat_tlsp_get(); @@ -126,8 +127,7 @@ UK_TESTCASE(uksched, test_sched_thread_sleep) { /*初始化返回值*/ int ret; - struct uk_alloc *a = uk_alloc_get_default(); - struct uk_sched *s = uk_schedcoop_create(a); + struct uk_sched *s = uk_sched_current(); uintptr_t tlsp; tlsp = ukplat_tlsp_get(); @@ -138,11 +138,11 @@ UK_TESTCASE(uksched, test_sched_thread_sleep) time_t begin = ukplat_monotonic_clock(); - uk_sched_thread_sleep(1000000000); + uk_sched_thread_sleep(10000); time_t end = ukplat_monotonic_clock(); - UK_TEST_EXPECT_SNUM_EQ((end-begin)/1000000000, 1); + UK_TEST_EXPECT_SNUM_NQ(end-begin, 0); } static __noreturn void idle_thread_fn(void *argp) @@ -188,7 +188,7 @@ UK_TESTCASE(uksched, test_uk_sched_thread_create) struct uk_alloc *a = uk_alloc_get_default(); - struct uk_sched *s = uk_schedcoop_create(a); + struct uk_sched *s = uk_sched_current(); thread0 = uk_sched_thread_create_fn0((s), (entry_fn), @@ -224,7 +224,8 @@ UK_TESTCASE(uksched, test_uk_sched_thread_create) UK_TESTCASE(uksched, test_uk_thread_create_and_init) { struct uk_alloc *a = uk_alloc_get_default(); - struct uk_sched *s = uk_schedcoop_create(a); + struct uk_sched *s = uk_sched_current(); + struct uk_thread *t0 = uk_thread_create_container(a, s->a_stack, 0x0, s->a_uktls, 0, ("Waiter"), ((void *)0), ((void *)0)); struct uk_thread *t1 = uk_thread_create_container(a, s->a_stack, 0x0, -- Gitee From de9b7b20244bf316db261410705881550cd03ef4 Mon Sep 17 00:00:00 2001 From: liu__sai Date: Thu, 11 Jan 2024 16:32:13 +0800 Subject: [PATCH 40/57] ci: use make -j+cpu cores Signed-off-by: liu__sai --- ci/.jenkinsfile | 117 ++++++++++++++++--------------- ci/defconfigs/raspi-arm64-uktest | 3 +- 2 files changed, 64 insertions(+), 56 deletions(-) diff --git a/ci/.jenkinsfile b/ci/.jenkinsfile index bd9a2e9f..821b342c 100644 --- a/ci/.jenkinsfile +++ b/ci/.jenkinsfile @@ -82,8 +82,8 @@ kernel = 'workdir/build/app-helloworld_xen-x86_64.dbg' string fcJson = """ { "boot-source": { - "kernel_image_path": "build/helloworld_fc-x86_64", - "boot_args": "helloworld_fc-x86_64 " + "kernel_image_path": "workdir/build/helloworld_fc-x86_64", + "boot_args": "fc-x86_64 " }, "drives": [], "machine-config": { @@ -117,6 +117,8 @@ int tolNum = 10 int exeNum = 0 int sucNum = 0 int failNum = 0 +/* 记录cpu核心数,从而使用make -j */ +int nBuildThreads = 0 if (env.giteeActionType == "NOTE" && env.giteeTriggerPhrase.contains("skip_check")) { tolNum-- } @@ -360,17 +362,17 @@ pipeline { } /* make & run*/ script { - result = sh(script: ''' - cd $WORKSPACE/ut_libc-test/app-helloworld + result = sh(script: """ + cd \$WORKSPACE/ut_libc-test/app-helloworld # 编译unikraft, make & run流程 - make -j$nBuildThreads - raspiRoot=$PWD/workdir/unikraft/plat/raspi + make -j${nBuildThreads} + raspiRoot=\$PWD/workdir/unikraft/plat/raspi qemu-system-aarch64 -cpu cortex-a53 -machine raspi3b -nodefaults -display none \ - -pidfile $WORKSPACE/libc-test$BUILD_NUMBER.pid -serial file:$WORKSPACE/libc-test$BUILD_NUMBER.out \ - -kernel workdir/build/kernel8.img -dtb ${raspiRoot}/bootfiles/bcm2710-rpi-3-b-plus.dtb -append verbose & + -pidfile \$WORKSPACE/libc-test\$BUILD_NUMBER.pid -serial file:\$WORKSPACE/libc-test\$BUILD_NUMBER.out \ + -kernel workdir/build/kernel8.img -dtb \${raspiRoot}/bootfiles/bcm2710-rpi-3-b-plus.dtb -append verbose & # 后台运行,等待15s sleep 15s - ''', returnStatus: true) + """, returnStatus: true) if (result == 0) { /* 校验是否成功打印hello world! */ resultCheck_helloworld = sh(script: ''' @@ -420,25 +422,30 @@ pipeline { } /* make & run */ script { - result = sh(script: ''' - cd $WORKSPACE/ut_self-test/unikraft + result = sh(script: """ + cd \$WORKSPACE/ut_self-test/unikraft # 编译unikraft, make & run流程 - make -j$nBuildThreads - raspiRoot=$PWD/unikraft/plat/raspi + make -j${nBuildThreads} + raspiRoot=\$PWD/plat/raspi qemu-system-aarch64 -cpu cortex-a53 -machine raspi3b -nodefaults -display none \ - -pidfile $WORKSPACE/self-test$BUILD_NUMBER.pid -serial file:$WORKSPACE/self-test$BUILD_NUMBER.out \ - -kernel build/kernel8.img -dtb ${raspiRoot}/bootfiles/bcm2710-rpi-3-b-plus.dtb -append verbose & + -pidfile \$WORKSPACE/self-test\$BUILD_NUMBER.pid -serial file:\$WORKSPACE/self-test\$BUILD_NUMBER.out \ + -kernel build/kernel8.img -dtb \${raspiRoot}/bootfiles/bcm2710-rpi-3-b-plus.dtb -append verbose & # 后台运行,等待15s sleep 15s - ''', returnStatus: true) + """, returnStatus: true) if (result == 0) { + /* 校验是否成功打印Powered by */ + resultCheck_powered_by = sh(script: ''' + cd $WORKSPACE/ + cat $WORKSPACE/self-test$BUILD_NUMBER.out + grep -q "Powered by" $WORKSPACE/self-test$BUILD_NUMBER.out + ''', returnStatus: true) /* 校验uktest用例是否失败 */ resultCheck = sh(script: ''' cd $WORKSPACE/ - cat $WORKSPACE/libc-test$BUILD_NUMBER.out grep "\\[ FAILED ]" $WORKSPACE/self-test$BUILD_NUMBER.out ''', returnStatus: true) - if (resultCheck != 0) { + if (resultCheck_powered_by ==0 && resultCheck != 0) { sucNum++ ret = ret + "\n|测试用例|self-test成功||" } else { @@ -460,17 +467,17 @@ pipeline { steps { script { exeNum++ - result = sh(script:''' - cd $WORKSPACE + result = sh(script:""" + cd \$WORKSPACE mkdir run_qemu-x86_64 cp -r apps/app-helloworld run_qemu-x86_64/ cp -r unikraft/* run_qemu-x86_64/app-helloworld/workdir/unikraft - ln -s $WORKSPACE/plats/plat-raspi run_qemu-x86_64/app-helloworld/workdir/unikraft/plat/raspi + ln -s \$WORKSPACE/plats/plat-raspi run_qemu-x86_64/app-helloworld/workdir/unikraft/plat/raspi cd run_qemu-x86_64/app-helloworld UK_DEFCONFIG=\$PWD/defconfigs/qemu-x86_64 make defconfig - make -j$nBuildThreads + make -j${nBuildThreads} qemu-system-x86_64 -kernel workdir/build/helloworld_qemu-x86_64 -nographic - ''', returnStatus: true) + """, returnStatus: true) if (result == 0) { sucNum++ ret = ret + "\n|测试用例|helloworld (qemu, x86_64)成功||" @@ -487,17 +494,17 @@ pipeline { steps { script { exeNum++ - result = sh(script:''' - cd $WORKSPACE + result = sh(script:""" + cd \$WORKSPACE mkdir run_qemu-arm64 cp -r apps/app-helloworld run_qemu-arm64/ cp -r unikraft/* run_qemu-arm64/app-helloworld/workdir/unikraft - ln -s $WORKSPACE/plats/plat-raspi run_qemu-arm64/app-helloworld/workdir/unikraft/plat/raspi + ln -s \$WORKSPACE/plats/plat-raspi run_qemu-arm64/app-helloworld/workdir/unikraft/plat/raspi cd run_qemu-arm64/app-helloworld UK_DEFCONFIG=\$PWD/defconfigs/qemu-arm64 make defconfig - make -j$nBuildThreads + make -j${nBuildThreads} qemu-system-aarch64 -kernel workdir/build/helloworld_qemu-arm64 -nographic -machine virt -cpu cortex-a57 - ''', returnStatus: true) + """, returnStatus: true) if (result == 0) { sucNum++ ret = ret + "\n|测试用例|helloworld (qemu, arm64)成功||" @@ -516,22 +523,22 @@ pipeline { exeNum++ result = sh(script:""" #!/bin/bash - cd $WORKSPACE + cd \$WORKSPACE mkdir run_xen-x86_64 cp -r apps/app-helloworld run_xen-x86_64/ cp -r unikraft/* run_xen-x86_64/app-helloworld/workdir/unikraft - ln -s $WORKSPACE/plats/plat-raspi run_xen-x86_64/app-helloworld/workdir/unikraft/plat/raspi + ln -s \$WORKSPACE/plats/plat-raspi run_xen-x86_64/app-helloworld/workdir/unikraft/plat/raspi cd run_xen-x86_64/app-helloworld cat>helloworld.cfg<fc-x86_64.json< Date: Fri, 12 Jan 2024 18:26:30 +0800 Subject: [PATCH 41/57] lib/posix-mmap/tests: add mix vma type test --- lib/posix-mmap/tests/test_posix_mmap.c | 83 +++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/lib/posix-mmap/tests/test_posix_mmap.c b/lib/posix-mmap/tests/test_posix_mmap.c index f1469f2c..b508c9cd 100644 --- a/lib/posix-mmap/tests/test_posix_mmap.c +++ b/lib/posix-mmap/tests/test_posix_mmap.c @@ -13,6 +13,7 @@ #include #include #include +#include #define pr_info(fmt, ...) \ _uk_printk(KLVL_INFO, __NULL, __NULL, 0x0, fmt, ##__VA_ARGS__) @@ -104,6 +105,31 @@ static void vas_clean(struct uk_vas *vas) } while (restart); } + +static inline __sz probe_r(__vaddr_t vaddr, __sz len) +{ + return uk_nofault_probe_r(vaddr, len, UK_NOFAULTF_CONTINUE); +} + +static inline __sz probe_rw(__vaddr_t vaddr, __sz len) +{ + return uk_nofault_probe_rw(vaddr, len, UK_NOFAULTF_CONTINUE); +} + +static inline __sz probe_r_nopage(__vaddr_t vaddr, __sz len) +{ + unsigned long flags = UK_NOFAULTF_CONTINUE | UK_NOFAULTF_NOPAGING; + + return uk_nofault_probe_r(vaddr, len, flags); +} + +static inline __sz probe_rw_nopage(__vaddr_t vaddr, __sz len) +{ + unsigned long flags = UK_NOFAULTF_CONTINUE | UK_NOFAULTF_NOPAGING; + + return uk_nofault_probe_rw(vaddr, len, flags); +} + UK_TESTCASE(posix_mmap, test_mmap) { struct uk_vas *vas = vas_init(); @@ -200,6 +226,61 @@ UK_TESTCASE(posix_mmap, test_mprotect) vas_clean(vas); } -#endif + + + +UK_TESTCASE(posix_mmap, test_mix_mmap) +{ + struct uk_vas *vas = vas_init(); + void *addr1, *addr2; + int fd, i, rc, len2; + __ssz len; + + fd = creat("/test_vma_file_munmap", 0700); + + addr1 = mmap(NULL, 2 * PAGE_SIZE, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + UK_TEST_EXPECT(addr1 != MAP_FAILED); + len2 = probe_r_nopage(addr1, 2 * PAGE_SIZE); + UK_TEST_EXPECT_SNUM_EQ(len2, 0); + + addr2 = mmap(addr1 + 2 * PAGE_SIZE, 2 * PAGE_SIZE, + PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + UK_TEST_EXPECT(addr2 != MAP_FAILED); + + + UK_TEST_EXPECT_ZERO(chk_vas(vas, (struct vma_entry[]){ + {addr1, addr1 + 2 * PAGE_SIZE, PROT_READ | PROT_WRITE}, + {addr2, addr2 + 2 * PAGE_SIZE, PROT_READ | PROT_WRITE}, + }, 2)); + + // todo:unikraft has not impletement UK_VMA_ADV_WILLNEED yet + // should be modified when unikraft finish it + rc = madvise(addr1, PAGE_SIZE, UK_VMA_ADV_WILLNEED); + UK_TEST_EXPECT_ZERO(chk_vas(vas, (struct vma_entry[]){ + {addr1, addr1 + 2 * PAGE_SIZE, PROT_READ | PROT_WRITE}, + {addr2, addr2 + 2 * PAGE_SIZE, PROT_READ | PROT_WRITE}, + }, 2)); + len2 = probe_rw_nopage(addr1, 2 * PAGE_SIZE); + UK_TEST_EXPECT_SNUM_EQ(len2, 0); + + rc = madvise(addr1, 3 * PAGE_SIZE, MADV_DONTNEED); + UK_TEST_EXPECT_ZERO(chk_vas(vas, (struct vma_entry[]){ + {addr1, addr1 + 2 * PAGE_SIZE, PROT_READ | PROT_WRITE}, + {addr2, addr2 + 2 * PAGE_SIZE, PROT_READ | PROT_WRITE}, + }, 2)); + len2 = probe_rw_nopage(addr1, PAGE_SIZE); + UK_TEST_EXPECT_SNUM_EQ(len2, 0); + len2 = probe_rw_nopage(addr1+PAGE_SIZE, PAGE_SIZE); + UK_TEST_EXPECT_SNUM_EQ(len2, 0); + len2 = probe_rw_nopage(addr1+PAGE_SIZE*2, PAGE_SIZE); + UK_TEST_EXPECT_SNUM_EQ(len2, 0); + vas_clean(vas); + + /* Clean up */ + close(fd); + unlink("/test_vma_file_munmap"); +} +# endif uk_testsuite_register(posix_mmap, NULL); -- Gitee From 64d3e4e4564692b879caede1f769923659ef7191 Mon Sep 17 00:00:00 2001 From: Yifan Zhang Date: Fri, 12 Jan 2024 18:26:43 +0800 Subject: [PATCH 42/57] lib/ukvmem/tests/: append tests for file vma --- lib/ukvmem/tests/test_vmem.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/lib/ukvmem/tests/test_vmem.c b/lib/ukvmem/tests/test_vmem.c index 475bc844..e3b99011 100644 --- a/lib/ukvmem/tests/test_vmem.c +++ b/lib/ukvmem/tests/test_vmem.c @@ -722,6 +722,9 @@ UK_TESTCASE(ukvmem, test_vma_file) len = probe_r(va1, 3 * PAGE_SIZE); vmem_bug_on(len != 3 * PAGE_SIZE); + len = probe_rw(va1, 3 * PAGE_SIZE); + vmem_bug_on(len != 0); + UK_TEST_EXPECT_SNUM_EQ(*((unsigned char *)(va1)), 0); UK_TEST_EXPECT_SNUM_EQ(*((unsigned char *)(va1 + 1)), 0xdd); UK_TEST_EXPECT_SNUM_EQ(*((unsigned char *)(va1 + PAGE_SIZE)), 1); @@ -735,6 +738,9 @@ UK_TESTCASE(ukvmem, test_vma_file) {va1 + 2 * PAGE_SIZE, va1 + 3 * PAGE_SIZE, PROT_RW}, }, 2)); + len = probe_rw(va1, 3 * PAGE_SIZE); + UK_TEST_EXPECT_SNUM_EQ(len, 1 * PAGE_SIZE); + /* Unmap the first two pages of the file. Then map the last half page * of the file directly after the last VMA. They should merge. */ @@ -746,6 +752,13 @@ UK_TESTCASE(ukvmem, test_vma_file) 3 * PAGE_SIZE); UK_TEST_EXPECT_ZERO(rc); + + /* lib/ukvmem/vma_file.c:61 vma_file is forced to be attached + * with flag UK_VMA_MAP_POPULATE,so pagefault is handled while mapping + */ + len = probe_rw(va2, 3 * PAGE_SIZE); + UK_TEST_EXPECT_SNUM_EQ(len, 1 * PAGE_SIZE); + UK_TEST_EXPECT_ZERO(chk_vas(vas, (struct vma_entry[]){ {va1 + 2 * PAGE_SIZE, va1 + 4 * PAGE_SIZE, PROT_RW}, }, 1)); @@ -759,6 +772,13 @@ UK_TESTCASE(ukvmem, test_vma_file) UK_TEST_EXPECT_SNUM_EQ(*((unsigned char *)(va1)), 0xdd); UK_TEST_EXPECT_SNUM_EQ(*((unsigned char *)(va1 + 1)), 0x00); + rc = uk_vma_set_attr(vas, va1 + 2 * PAGE_SIZE, + 2 * PAGE_SIZE, PROT_R, 0); + UK_TEST_EXPECT_ZERO(rc); + + len = probe_rw(va1, 4 * PAGE_SIZE); + UK_TEST_EXPECT_SNUM_EQ(len, PAGE_SIZE/2 + 1); + /* Clean up */ close(fd); unlink("/test_vma_file"); -- Gitee From d4401c22e17bef9f89f7e9f1d2309a3fe092883e Mon Sep 17 00:00:00 2001 From: 1788594346 Date: Fri, 12 Jan 2024 15:44:05 +0800 Subject: [PATCH 43/57] lib/ukintctlr: fix warnings during compilation Signed-off-by: 1788594346 --- .../ukintctlr/bcm_intc/tests/test_bcm_intc.c | 136 ++---------------- lib/ukintctlr/tests/test_intctlr.c | 5 +- 2 files changed, 12 insertions(+), 129 deletions(-) diff --git a/drivers/ukintctlr/bcm_intc/tests/test_bcm_intc.c b/drivers/ukintctlr/bcm_intc/tests/test_bcm_intc.c index ae29db96..04b33cf3 100644 --- a/drivers/ukintctlr/bcm_intc/tests/test_bcm_intc.c +++ b/drivers/ukintctlr/bcm_intc/tests/test_bcm_intc.c @@ -13,137 +13,21 @@ * limitations under the License. */ -#include #include -#include -#include #include -#include -#include -#include - -/* bcm中断控制器Time中断测试用例 */ -/* timer irq使能寄存器 */ -#define GENEREL_TIMER0_IRQ_REGISTER_ADDRESS 0x40000040 -#define GENEREL_TIMER0_IRQ_ENABLE 8 - -/* 系统时间相关宏 */ -/* 测试用例延时,单位ns,两倍于最小线程时间片 */ -#define GENEREL_TIME_DELAY 0x80000000 -/* ns粒度转换为16ms,便于断言检测 */ -#define GENEREL_TIME_DELAY_NS_TO_16MS 0x1000000 -#define GENEREL_TIME_EXPECTED_DELAY \ - (GENEREL_TIME_DELAY / GENEREL_TIME_DELAY_NS_TO_16MS) +#include /* 设备树测试相关宏 */ -#define TEST_DTB_SIZE 1000 - -static __nsec nsec; -static int delay; - -/* 线程注册函数 */ -static void entry_fn(void *arg) -{ - /* 系统时钟中断未使能异常入口 */ - uk_pr_crit("ERR: System time interrupt err\n"); - ukplat_terminate(UKPLAT_CRASH); -} - -/* 测试timer irq disable场景 */ -UK_TESTCASE(uk_driver_bcm_intc, test_timer_disable_irq) -{ - struct uk_alloc *a = uk_alloc_get_default(); - struct uk_thread *current_thread = uk_thread_current(); - struct uk_sched *s = current_thread->sched; - - delay = 0; - nsec = 0; - /* 1.初始化测试场景 */ - /* 将timer irq寄存器值赋为disable */ - ioreg_write32((void *)(GENEREL_TIMER0_IRQ_REGISTER_ADDRESS), 0); - - /* 判断timer irq寄存器是否被更改为预期值0 */ - UK_TEST_EXPECT_ZERO(ioreg_read32( - (void *)(GENEREL_TIMER0_IRQ_REGISTER_ADDRESS))); - - /* 新建线程,供调度器调度 */ - struct uk_thread *t0 = uk_thread_create_container(a, - s->a_stack, 0x0, s->a_uktls, 0, - ("intc"), ((void *)0), ((void *)0)); - uk_thread_container_init_fn0(t0, entry_fn); - - /* 2.设置2s延时 */ - nsec = ukplat_monotonic_clock(); - /* 若无时间中断,系统线程超时,调度器退出本线程 */ - do; - while ((ukplat_monotonic_clock() - nsec) < GENEREL_TIME_DELAY); - /* 记录本线程执行时间 */ - delay = (ukplat_monotonic_clock() - nsec) / - GENEREL_TIME_DELAY_NS_TO_16MS; - - /* 3.检验测试结果 */ - /* 线程超时被调度器强制退出,时间戳被重置 */ - /* delay预期不等于预设延时 */ - UK_TEST_EXPECT_SNUM_NQ(delay, GENEREL_TIME_EXPECTED_DELAY); - - /* 4.恢复环境 */ - // uk_sched_dumpk_threads(3, uk_sched_head); - ioreg_write32((void *)(GENEREL_TIMER0_IRQ_REGISTER_ADDRESS), - GENEREL_TIMER0_IRQ_ENABLE); - uk_thread_release(t0); -} - -/* 测试timer irq enable场景 */ -UK_TESTCASE(uk_driver_bcm_intc, test_timer_enable_irq) -{ - struct uk_alloc *a = uk_alloc_get_default(); - struct uk_thread *current_thread = uk_thread_current(); - struct uk_sched *s = current_thread->sched; - - delay = 0; - nsec = 0; - /* 1.初始化测试场景 */ - /* 将timer irq寄存器值赋为enable */ - ioreg_write32((void *)(GENEREL_TIMER0_IRQ_REGISTER_ADDRESS), - GENEREL_TIMER0_IRQ_ENABLE); - - /* 判断timer irq寄存器是否被更改为预期值 */ - UK_TEST_EXPECT_PTR_EQ(ioreg_read32( - (void *)(GENEREL_TIMER0_IRQ_REGISTER_ADDRESS)), - GENEREL_TIMER0_IRQ_ENABLE); - - /* 新建线程,供调度器调度 */ - struct uk_thread *t1 = uk_thread_create_container(a, - s->a_stack, 0x0, s->a_uktls, 0, - ("intc"), ((void *)0), ((void *)0)); - uk_thread_container_init_fn0(t1, entry_fn); - - /* 2.设置2s延时 */ - nsec = ukplat_monotonic_clock(); - /* 若无时间中断,系统线程超时,调度器退出本线程 */ - do; - while ((ukplat_monotonic_clock() - nsec) < GENEREL_TIME_DELAY); - /* 记录本线程执行时间 */ - delay = (ukplat_monotonic_clock() - nsec) / - GENEREL_TIME_DELAY_NS_TO_16MS; - - /* 3.检验测试结果 */ - /* 中断使能,线程正常运行,delay预期等于预设延时 */ - UK_TEST_EXPECT_SNUM_EQ(delay, GENEREL_TIME_EXPECTED_DELAY); - - /* 4.恢复环境 */ - uk_thread_release(t1); -} +#define TEST_DTB_SIZE 1000 /* 测试设备树中中断控制器读取异常场景 */ UK_TESTCASE(uk_driver_bcm_intc, test_driver_dtb_bcm_intc_info_err) { int ret, bufsize, fdt_bcm_intc, test_timer; - __u32 address_val, size_val; __u64 fdt_address_val, fdt_size_val; const char *const bcm_intc_device_list[] __maybe_unused = { - "brcm,bcm2836-l1-intc", - NULL, + "brcm,bcm2836-l1-intc", + NULL, }; /* 1.初始化测试场景 */ @@ -156,8 +40,8 @@ UK_TESTCASE(uk_driver_bcm_intc, test_driver_dtb_bcm_intc_info_err) /* 2.设备树读取中断控制器异常场景 */ /* 2.1根据compatible读取中断控制器异常场景 */ - fdt_bcm_intc = fdt_node_offset_by_compatible_list( - test_fdt, -1, bcm_intc_device_list); + fdt_bcm_intc = fdt_node_offset_by_compatible_list(test_fdt, -1, + bcm_intc_device_list); UK_TEST_EXPECT_SNUM_EQ(fdt_bcm_intc, -FDT_ERR_NOTFOUND); /* 2.2读取中断控制器地址与长度异常场景 */ @@ -170,14 +54,12 @@ UK_TESTCASE(uk_driver_bcm_intc, test_driver_dtb_bcm_intc_info_err) uk_pr_err("set compatible failed\n"); /* 校验设备树中已注册测试节点 */ - fdt_bcm_intc = fdt_node_offset_by_compatible_list( - test_fdt, -1, bcm_intc_device_list); + fdt_bcm_intc = fdt_node_offset_by_compatible_list(test_fdt, -1, + bcm_intc_device_list); UK_TEST_EXPECT_SNUM_EQ(fdt_bcm_intc, test_timer); /* 尝试读取地址,预期失败 */ - ret = fdt_get_address(test_fdt, 0, 0, - &fdt_address_val, - &fdt_size_val); + ret = fdt_get_address(test_fdt, 0, 0, &fdt_address_val, &fdt_size_val); UK_TEST_EXPECT_SNUM_EQ(ret, -FDT_ERR_NOTFOUND); /* 3.恢复环境 */ diff --git a/lib/ukintctlr/tests/test_intctlr.c b/lib/ukintctlr/tests/test_intctlr.c index 25e4a7cf..f9a9906d 100644 --- a/lib/ukintctlr/tests/test_intctlr.c +++ b/lib/ukintctlr/tests/test_intctlr.c @@ -79,7 +79,7 @@ static void test_sgi_op(uint8_t sgintid, uint32_t cpuid) static int test_percpu_init(uint64_t cpuid) { (void)cpuid; - ret = TEST_SGI_OP_SUCCESS; + ret = TEST_PERCPU_INIT_SUCCESS; return 0; } @@ -215,7 +215,8 @@ UK_TESTCASE(ukintctlr, call_percpu_init) /* 2.通过统一接口调用percpu_init,并校验调用结果 */ r = uk_intctlr_percpu_init(sgintid); - UK_TEST_EXPECT_SNUM_EQ(ret, TEST_SGI_OP_SUCCESS); + UK_TEST_EXPECT_SNUM_EQ(ret, TEST_PERCPU_INIT_SUCCESS); + UK_TEST_EXPECT_ZERO(r); /* 3.恢复环境 */ uk_intctlr_register(ori_intctlr); -- Gitee From 4aa2cb05fb745bab46729c2c76618bbcbfc6a5ff Mon Sep 17 00:00:00 2001 From: Li Haode Date: Wed, 10 Jan 2024 15:34:17 +0800 Subject: [PATCH 44/57] kvm/exceptions.S: fix bug, restore x0 in syscall case Signed-off-by: Li Haode --- plat/kvm/arm/exceptions.S | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plat/kvm/arm/exceptions.S b/plat/kvm/arm/exceptions.S index 457b919d..0fa6e531 100644 --- a/plat/kvm/arm/exceptions.S +++ b/plat/kvm/arm/exceptions.S @@ -129,12 +129,12 @@ str x0, [sp, #__SP_OFFSET] /* Store old SP in auxiliary stack */ b 1f 0: - /* Restore x0 */ - mrs x0, tpidrro_el0 - sub sp, sp, #__TRAP_STACK_SIZE 1: + /* Restore x0 */ + mrs x0, tpidrro_el0 + /* Save general purpose registers */ stp x0, x1, [sp, #16 * 0] stp x2, x3, [sp, #16 * 1] -- Gitee From 3986506535cc296867d5a8fd221aaf7929ca94b0 Mon Sep 17 00:00:00 2001 From: Li Haode Date: Mon, 15 Jan 2024 15:08:04 +0800 Subject: [PATCH 45/57] drivers/uktty: modify pl011.c a unified framework Signed-off-by: Li Haode --- ci/defconfigs/raspi-arm64-libc-test | 1 + ci/defconfigs/raspi-arm64-uktest | 1 + drivers/uktty/pl011/exportsyms.uk | 1 + drivers/uktty/pl011/pl011.c | 91 ++++++----------------------- 4 files changed, 21 insertions(+), 73 deletions(-) diff --git a/ci/defconfigs/raspi-arm64-libc-test b/ci/defconfigs/raspi-arm64-libc-test index cde48fc4..f5d55760 100644 --- a/ci/defconfigs/raspi-arm64-libc-test +++ b/ci/defconfigs/raspi-arm64-libc-test @@ -46,3 +46,4 @@ CONFIG_LIBVFSCORE=y CONFIG_LIBVFSCORE_NONLARGEFILE=y CONFIG_LIBVFSCORE_AUTOMOUNT_ROOTFS=y CONFIG_LIBVFSCORE_FSTAB=y +CONFIG_LIBUKTTY_PL011=y diff --git a/ci/defconfigs/raspi-arm64-uktest b/ci/defconfigs/raspi-arm64-uktest index 717244db..8a0654d2 100644 --- a/ci/defconfigs/raspi-arm64-uktest +++ b/ci/defconfigs/raspi-arm64-uktest @@ -26,3 +26,4 @@ CONFIG_LIBVFSCORE_NONLARGEFILE=y CONFIG_LIBVFSCORE_AUTOMOUNT_ROOTFS=y CONFIG_LIBVFSCORE_FSTAB=y CONFIG_LIBUKBOOT_BANNER_POWEREDBY=y +CONFIG_LIBUKTTY_PL011=y diff --git a/drivers/uktty/pl011/exportsyms.uk b/drivers/uktty/pl011/exportsyms.uk index 35d49adb..323d9550 100644 --- a/drivers/uktty/pl011/exportsyms.uk +++ b/drivers/uktty/pl011/exportsyms.uk @@ -2,3 +2,4 @@ pl011_console_init ukplat_cink ukplat_coutd ukplat_coutk +pl011_uart_bas \ No newline at end of file diff --git a/drivers/uktty/pl011/pl011.c b/drivers/uktty/pl011/pl011.c index b26c9332..4ed34673 100644 --- a/drivers/uktty/pl011/pl011.c +++ b/drivers/uktty/pl011/pl011.c @@ -22,45 +22,8 @@ #include #include #include - -/* PL011 UART registers and masks*/ -/* Data register */ -#define REG_UARTDR_OFFSET 0x00 - -/* Receive status register/error clear register */ -#define REG_UARTRSR_OFFSET 0x04 -#define REG_UARTECR_OFFSET 0x04 - -/* Flag register */ -#define REG_UARTFR_OFFSET 0x18 -#define FR_TXFF UK_BIT(5) /* Transmit FIFO/reg full */ -#define FR_RXFE UK_BIT(4) /* Receive FIFO/reg empty */ - -/* Integer baud rate register */ -#define REG_UARTIBRD_OFFSET 0x24 -/* Fractional baud rate register */ -#define REG_UARTFBRD_OFFSET 0x28 - -/* Line control register */ -#define REG_UARTLCR_H_OFFSET 0x2C -#define LCR_H_WLEN8 (0x3 << 5) /* Data width is 8-bits */ - -/* Control register */ -#define REG_UARTCR_OFFSET 0x30 -#define CR_RXE UK_BIT(9) /* Receive enable */ -#define CR_TXE UK_BIT(8) /* Transmit enable */ -#define CR_UARTEN UK_BIT(0) /* UART enable */ - -/* Interrupt FIFO level select register */ -#define REG_UARTIFLS_OFFSET 0x34 -/* Interrupt mask set/clear register */ -#define REG_UARTIMSC_OFFSET 0x38 -/* Raw interrupt status register */ -#define REG_UARTRIS_OFFSET 0x3C -/* Masked interrupt status register */ -#define REG_UARTMIS_OFFSET 0x40 -/* Interrupt clear register */ -#define REG_UARTICR_OFFSET 0x44 +#include +#include /* * PL011 UART base address @@ -70,21 +33,15 @@ * use pl011_uart_initialized as an extra variable to check * whether the UART has been initialized. */ - #if defined(CONFIG_LIBUKTTY_PL011_EARLY_CONSOLE_BASE) -static __u8 pl011_uart_initialized = 1; -static __u64 pl011_uart_bas = CONFIG_LIBUKTTY_PL011_EARLY_CONSOLE_BASE; +uint8_t pl011_uart_initialized = 1; +uint64_t pl011_uart_bas = CONFIG_LIBUKTTY_PL011_EARLY_CONSOLE_BASE; #else /* !CONFIG_LIBUKTTY_PL011_EARLY_CONSOLE_BASE */ -static __u8 pl011_uart_initialized; -static __u64 pl011_uart_bas; +uint8_t pl011_uart_initialized; +uint64_t pl011_uart_bas; #endif /* !CONFIG_LIBUKTTY_PL011_EARLY_CONSOLE_BASE */ -/* Macros to access PL011 Registers with base address */ -#define PL011_REG(r) ((__u16 *)(pl011_uart_bas + (r))) -#define PL011_REG_READ(r) ioreg_read16(PL011_REG(r)) -#define PL011_REG_WRITE(r, v) ioreg_write16(PL011_REG(r), v) - -static void init_pl011(__u64 bas) +static void init_pl011(uint64_t bas) { pl011_uart_bas = bas; @@ -103,39 +60,27 @@ static void init_pl011(__u64 bas) (PL011_REG_READ(REG_UARTLCR_H_OFFSET) & 0xff00) | LCR_H_WLEN8); + /* Set baudrate for 115200 */ + PL011_REG_WRITE(REG_UARTIBRD_OFFSET, 2); // 115200 baud + PL011_REG_WRITE(REG_UARTFBRD_OFFSET, 0xB); + /* Just enable UART and data transmit/receive */ - PL011_REG_WRITE(REG_UARTCR_OFFSET, CR_TXE | CR_UARTEN); + PL011_REG_WRITE(REG_UARTCR_OFFSET, CR_TXE | CR_UARTEN | CR_RXE); } void pl011_console_init(const void *dtb) { - int offset, len, naddr, nsize; - const __u64 *regs; - __u64 reg_uart_bas; + int offset, val; + uint64_t naddr, nsize; uk_pr_info("Serial initializing\n"); - offset = fdt_node_offset_by_compatible(dtb, -1, "arm,pl011"); if (unlikely(offset < 0)) UK_CRASH("No console UART found!\n"); - - naddr = fdt_address_cells(dtb, offset); - if (unlikely(naddr < 0 || naddr >= FDT_MAX_NCELLS)) - UK_CRASH("Could not find proper address cells!\n"); - - nsize = fdt_size_cells(dtb, offset); - if (unlikely(nsize < 0 || nsize >= FDT_MAX_NCELLS)) - UK_CRASH("Could not find proper size cells!\n"); - - regs = fdt_getprop(dtb, offset, "reg", &len); - if (unlikely(!regs || (len < (int)sizeof(fdt32_t) * (naddr + nsize)))) - UK_CRASH("Bad 'reg' property: %p %d\n", regs, len); - - reg_uart_bas = fdt64_to_cpu(regs[0]); - uk_pr_info("Found PL011 UART on: 0x%lx\n", reg_uart_bas); - - init_pl011(reg_uart_bas); - + val = fdt_get_address(dtb, offset, 0, &naddr, &nsize); + if (val < 0) + UK_CRASH("Could not find proper address!\n"); + init_pl011((uint64_t)naddr); uk_pr_info("PL011 UART initialized\n"); pl011_uart_initialized = 1; } -- Gitee From 7460dbc7a997f3a3c2eb23c6d95c306b417e31e3 Mon Sep 17 00:00:00 2001 From: Li Haode Date: Wed, 10 Jan 2024 15:34:48 +0800 Subject: [PATCH 46/57] arm/lcpu.c: change the method to get this_lcpu id Signed-off-by: Li Haode --- plat/common/arm/lcpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plat/common/arm/lcpu.c b/plat/common/arm/lcpu.c index 6439c2ad..5bf79652 100644 --- a/plat/common/arm/lcpu.c +++ b/plat/common/arm/lcpu.c @@ -116,7 +116,7 @@ int lcpu_arch_init(struct lcpu *this_lcpu) /* Initialize the interrupt controller for non-bsp cores */ if (!lcpu_is_bsp(this_lcpu)) { - ret = uk_intctlr_percpu_init(this_lcpu.id); + ret = uk_intctlr_percpu_init(this_lcpu->id); if (unlikely(ret)) return ret; } -- Gitee From a20c966c95ec416f534b837219204c1cda73c609 Mon Sep 17 00:00:00 2001 From: Yifan Zhang Date: Fri, 12 Jan 2024 14:18:41 +0800 Subject: [PATCH 47/57] lib/uksched: update test case to meet auxiliary stack --- lib/uksched/tests/test_sched.c | 64 +++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/lib/uksched/tests/test_sched.c b/lib/uksched/tests/test_sched.c index 8108a974..cc469bdc 100644 --- a/lib/uksched/tests/test_sched.c +++ b/lib/uksched/tests/test_sched.c @@ -26,7 +26,22 @@ #include #include #include - +#if CONFIG_LIBUKBOOT_INITBBUDDY +#include +#define uk_alloc_init uk_allocbbuddy_init +#elif CONFIG_LIBUKBOOT_INITREGION +#include +#define uk_alloc_init uk_allocregion_init +#elif CONFIG_LIBUKBOOT_INITMIMALLOC +#include +#define uk_alloc_init uk_mimalloc_init +#elif CONFIG_LIBUKBOOT_INITTLSF +#include +#define uk_alloc_init uk_tlsf_init +#elif CONFIG_LIBUKBOOT_INITTINYALLOC +#include +#define uk_alloc_init uk_tinyalloc_init +#endif UK_TESTCASE(uksched, test_sched_register) { @@ -57,19 +72,19 @@ UK_TESTCASE(uksched, test_sched_gc) tlsp = ukplat_tlsp_get(); struct uk_thread *main_thread = uk_thread_create_bare( - s->a, 0x0, 0x0, tlsp, !(!tlsp), false, "init", NULL, NULL); + s->a, 0x0, 0x0, 0x0, tlsp, !(!tlsp), + false, "test", NULL, NULL); ret = uk_sched_thread_add(s, main_thread); //mock: a thread runs and exit uk_thread_set_exited(main_thread); - UK_TAILQ_INSERT_TAIL(&s->exited_threads, main_thread, queue); main_thread->sched = NULL; - ret = uk_sched_thread_gc(s); + uk_sched_thread_gc(s); + UK_TAILQ_REMOVE(&s->exited_threads, main_thread, thread_list); uk_sched_foreach_thread_safe(s, t, tmp) { UK_TEST_EXPECT_SNUM_NQ(t, main_thread); } - UK_TEST_EXPECT_SNUM_EQ(ret, 1); } @@ -81,7 +96,8 @@ UK_TESTCASE(uksched, test_thread_release) tlsp = ukplat_tlsp_get(); struct uk_thread *main_thread = uk_thread_create_bare( - s->a, 0x0, 0x0, tlsp, !(!tlsp), false, "init", NULL, NULL); + s->a, 0x0, 0x0, 0x0, tlsp, !(!tlsp), + false, "init", NULL, NULL); uk_thread_release(main_thread); UK_TEST_EXPECT_SNUM_EQ(uk_thread_is_exited(main_thread), UK_THREADF_EXITED); @@ -98,7 +114,8 @@ UK_TESTCASE(uksched, test_thread_block_no_timeout_then_wake) tlsp = ukplat_tlsp_get(); struct uk_thread *main_thread = uk_thread_create_bare( - s->a, 0x0, 0x0, tlsp, !(!tlsp), false, "init", NULL, NULL); + s->a, 0x0, 0x0, 0x0, tlsp, !(!tlsp), + false, "init", NULL, NULL); uk_thread_set_runnable(main_thread); uk_thread_block(main_thread); UK_TEST_EXPECT_SNUM_EQ(uk_thread_is_runnable(main_thread), 0); @@ -116,7 +133,8 @@ UK_TESTCASE(uksched, test_thread_set_exited) tlsp = ukplat_tlsp_get(); struct uk_thread *main_thread = uk_thread_create_bare( - s->a, 0x0, 0x0, tlsp, !(!tlsp), false, "init", NULL, NULL); + s->a, 0x0, 0x0, 0x0, tlsp, !(!tlsp), + false, "init", NULL, NULL); uk_thread_set_exited(main_thread); UK_TEST_EXPECT_SNUM_EQ(uk_thread_is_exited(main_thread), UK_THREADF_EXITED); @@ -133,7 +151,8 @@ UK_TESTCASE(uksched, test_sched_thread_sleep) tlsp = ukplat_tlsp_get(); struct uk_thread *main_thread = uk_thread_create_bare( - s->a, 0x0, 0x0, tlsp, !(!tlsp), false, "init", NULL, NULL); + s->a, 0x0, 0x0, 0x0, tlsp, !(!tlsp), + false, "test_sleep", NULL, NULL); ret = uk_sched_thread_add(s, main_thread); time_t begin = ukplat_monotonic_clock(); @@ -170,7 +189,8 @@ UK_TESTCASE(uksched, test_thread_init) /* Create idle thread */ rc = uk_thread_init_fn1(&c->idle, idle_thread_fn, (void *)c, a, - STACK_SIZE, a, false, NULL, "idle", NULL, NULL); + STACK_SIZE, a, STACK_SIZE, a, + false, NULL, "idle", NULL, NULL); UK_TEST_EXPECT_SNUM_EQ(rc, 0); } @@ -192,25 +212,25 @@ UK_TESTCASE(uksched, test_uk_sched_thread_create) thread0 = uk_sched_thread_create_fn0((s), (entry_fn), - 0x0, 0, 0, ("Waiter"), ((void *)0), ((void *)0)); + 0x0, 0x0, 0, 0, ("Waiter"), ((void *)0), ((void *)0)); thread1 = uk_sched_thread_create_fn1((s), (entry_fn), (void *)(((void *)0)), - 0x0, 0, 0, ("Waiter"), ((void *)0), ((void *)0)); + 0x0, 0x0, 0, 0, ("Waiter"), ((void *)0), ((void *)0)); thread2 = uk_sched_thread_create_fn2((s), (entry_fn), (void *)(((void *)0)), (void *)(((void *)0)), - 0x0, 0, 0, ("Waiter"), ((void *)0), ((void *)0)); + 0x0, 0x0, 0, 0, ("Waiter"), ((void *)0), ((void *)0)); thread3 = uk_thread_create_fn0(s->a, (entry_fn), - s->a_stack, 0x0, 0 ? NULL : s->a_uktls, 0, + s->a_stack, 0x0, s->a_stack, 0x0, 0 ? NULL : s->a_uktls, 0, ("Waiter"), ((void *)0), ((void *)0)); thread4 = uk_thread_create_fn1(s->a, (entry_fn), (void *)(((void *)0)), - s->a_stack, 0x0, 0 ? NULL : s->a_uktls, 0, + s->a_stack, 0x0, s->a_stack, 0x0, 0 ? NULL : s->a_uktls, 0, ("Waiter"), ((void *)0), ((void *)0)); thread5 = uk_thread_create_fn2(s->a, (entry_fn), (void *)(((void *)0)), (void *)(((void *)0)), - s->a_stack, 0x0, 0 ? NULL : s->a_uktls, 0, + s->a_stack, 0x0, s->a_stack, 0x0, 0 ? NULL : s->a_uktls, 0, ("Waiter"), ((void *)0), ((void *)0)); UK_TEST_EXPECT_NOT_NULL(thread0); @@ -225,14 +245,16 @@ UK_TESTCASE(uksched, test_uk_thread_create_and_init) { struct uk_alloc *a = uk_alloc_get_default(); struct uk_sched *s = uk_sched_current(); - struct uk_thread *t0 = uk_thread_create_container(a, s->a_stack, 0x0, - s->a_uktls, 0, ("Waiter"), ((void *)0), ((void *)0)); + s->a_stack, 0x0, s->a_uktls, 0, + ("Waiter"), ((void *)0), ((void *)0)); struct uk_thread *t1 = uk_thread_create_container(a, s->a_stack, 0x0, - s->a_uktls, 0, ("Waiter"), ((void *)0), ((void *)0)); + s->a_stack, 0x0, s->a_uktls, 0, + ("Waiter"), ((void *)0), ((void *)0)); struct uk_thread *t2 = uk_thread_create_container(a, s->a_stack, 0x0, - s->a_uktls, 0, ("Waiter"), ((void *)0), ((void *)0)); - struct uk_thread *t3 = uk_thread_create_container2(a, 1, 1, 0, 0, + s->a_stack, 0x0, s->a_uktls, 0, + ("Waiter"), ((void *)0), ((void *)0)); + struct uk_thread *t3 = uk_thread_create_container2(a, 1, 1, 1, 0, 0, ("Waiter"), ((void *)0), ((void *)0)); UK_TEST_EXPECT_NOT_NULL(t0); uk_thread_container_init_fn1(t1, entry_fn, (void *)(((void *)0))); -- Gitee From be666ddcacf95aaedf91a58ba05dc6ebb75333a4 Mon Sep 17 00:00:00 2001 From: Li Haode Date: Tue, 16 Jan 2024 11:01:23 +0800 Subject: [PATCH 48/57] plat/memory.h: name the auxiliary stack Signed-off-by: Li Haode --- include/uk/plat/memory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/uk/plat/memory.h b/include/uk/plat/memory.h index c438ea6f..ccd93eb3 100644 --- a/include/uk/plat/memory.h +++ b/include/uk/plat/memory.h @@ -313,7 +313,7 @@ static inline __uptr ukplat_auxsp_alloc(struct uk_alloc __maybe_unused *a, &auxsp, auxsp_len, UK_VMA_MAP_POPULATE, - NULL, + "auxiliary_stack", 0); if (unlikely(rc)) { uk_pr_err("Failed to map auxiliary stack\n"); -- Gitee From f6745b3d7b287b0e90c7e488f0dc033204b025b0 Mon Sep 17 00:00:00 2001 From: Li Haode Date: Tue, 16 Jan 2024 11:03:54 +0800 Subject: [PATCH 49/57] lib/posix_mmap: update test case to meet auxiliary stack Signed-off-by: Li Haode --- lib/posix-mmap/tests/test_posix_mmap.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/posix-mmap/tests/test_posix_mmap.c b/lib/posix-mmap/tests/test_posix_mmap.c index b508c9cd..94ba00f9 100644 --- a/lib/posix-mmap/tests/test_posix_mmap.c +++ b/lib/posix-mmap/tests/test_posix_mmap.c @@ -40,6 +40,8 @@ static void vmem_print(struct uk_vas *vas) uk_list_for_each_entry(vma, &vas->vma_list, vma_list) { if (vma->name && strcmp("heap", vma->name) == 0) continue; + if (vma->name && strcmp("auxiliary_stack", vma->name) == 0) + continue; pr_info(" [%d] 0x%lx-0x%lx %c%c%c %s\n", i++, vma->start, vma->end, @@ -60,6 +62,8 @@ static int chk_vas(struct uk_vas *vas, struct vma_entry *vmas, int num) uk_list_for_each_entry(vma, &vas->vma_list, vma_list) { if (vma->name && strcmp("heap", vma->name) == 0) continue; + if (vma->name && strcmp("auxiliary_stack", vma->name) == 0) + continue; if (i >= num) return -1; @@ -94,6 +98,9 @@ static void vas_clean(struct uk_vas *vas) uk_list_for_each_entry(vma, &vas->vma_list, vma_list) { if (vma->name && strcmp("heap", vma->name) == 0) continue; + if (vma->name && + strcmp("auxiliary_stack", vma->name) == 0) + continue; rc = uk_vma_unmap(vas, vma->start, vma->end - vma->start, 0); @@ -280,6 +287,8 @@ UK_TESTCASE(posix_mmap, test_mix_mmap) /* Clean up */ close(fd); unlink("/test_vma_file_munmap"); + + vas_clean(vas); } # endif -- Gitee From 50ce150290e523992c1b59a64975467425105e16 Mon Sep 17 00:00:00 2001 From: Li Haode Date: Tue, 16 Jan 2024 11:04:41 +0800 Subject: [PATCH 50/57] lib/ukvmem: update test case to meet auxiliary stack Signed-off-by: Li Haode --- lib/ukvmem/tests/test_vmem.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/lib/ukvmem/tests/test_vmem.c b/lib/ukvmem/tests/test_vmem.c index e3b99011..9b2af260 100644 --- a/lib/ukvmem/tests/test_vmem.c +++ b/lib/ukvmem/tests/test_vmem.c @@ -19,7 +19,8 @@ #include #include -#define MAPPING_BASE CONFIG_LIBUKVMEM_DEFAULT_BASE +__vaddr_t mapping_base; +#define MAPPING_BASE mapping_base /* Just define some shorter aliases */ #undef PROT_R @@ -56,6 +57,8 @@ static void vmem_print(struct uk_vas *vas) uk_list_for_each_entry(vma, &vas->vma_list, vma_list) { if (vma->name && strcmp("heap", vma->name) == 0) continue; + if (vma->name && strcmp("auxiliary_stack", vma->name) == 0) + continue; pr_info(" [%d] 0x%lx-0x%lx %c%c%c %s\n", i++, vma->start, vma->end, @@ -76,6 +79,8 @@ static int chk_vas(struct uk_vas *vas, struct vma_entry *vmas, int num) uk_list_for_each_entry(vma, &vas->vma_list, vma_list) { if (vma->name && strcmp("heap", vma->name) == 0) continue; + if (vma->name && strcmp("auxiliary_stack", vma->name) == 0) + continue; if (i >= num) return -1; @@ -110,6 +115,9 @@ static void vas_clean(struct uk_vas *vas) uk_list_for_each_entry(vma, &vas->vma_list, vma_list) { if (vma->name && strcmp("heap", vma->name) == 0) continue; + if (vma->name && + strcmp("auxiliary_stack", vma->name) == 0) + continue; rc = uk_vma_unmap(vas, vma->start, vma->end - vma->start, 0); @@ -121,6 +129,19 @@ static void vas_clean(struct uk_vas *vas) } while (restart); } +static void get_mappingbase(struct uk_vas *vas) +{ + struct uk_vma *vma; + __vaddr_t va = 0; + + uk_list_for_each_entry(vma, &vas->vma_list, vma_list) { + if (vma->name && strcmp("auxiliary_stack", vma->name) == 0 + && va < vma->end) + va = vma->end; + } + mapping_base = va; +} + /** * Tests if the virtual address space layout is as expected after creating and * removing address reservations. This includes tests if VMAs properly merge @@ -134,6 +155,7 @@ UK_TESTCASE(ukvmem, test_basic_vas_layout) __vaddr_t va; int rc; + get_mappingbase(vas); /* Create VMA at mapping base */ va = __VADDR_ANY; rc = uk_vma_reserve(vas, &va, 0x10000); @@ -214,7 +236,7 @@ UK_TESTCASE(ukvmem, test_basic_vas_layout) rc = uk_vma_unmap(vas, MAPPING_BASE + 0x100000, 0x100000, 0); UK_TEST_EXPECT_ZERO(rc); - rc = uk_vma_unmap(vas, MAPPING_BASE - 0x1000, 0x2000, 0); + rc = uk_vma_unmap(vas, MAPPING_BASE, 0x1000, 0); UK_TEST_EXPECT_ZERO(rc); UK_TEST_EXPECT_ZERO(chk_vas(vas, (struct vma_entry[]){ @@ -460,6 +482,7 @@ UK_TESTCASE(ukvmem, test_vma_anon_large) int rc; __sz len; + get_mappingbase(vas); /* First try with an invalid length and address */ va = __VADDR_ANY; rc = uk_vma_map_anon(vas, &va, PAGE_SIZE, PROT_RW, -- Gitee From 5ab6f6f281fd02798d7cb4f9fd590450091eb1c0 Mon Sep 17 00:00:00 2001 From: liu__sai Date: Wed, 17 Jan 2024 14:24:46 +0800 Subject: [PATCH 51/57] ci:add function to input branch for repo with version Signed-off-by: liu__sai --- ci/.jenkinsfile | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/ci/.jenkinsfile b/ci/.jenkinsfile index 821b342c..919a92cb 100644 --- a/ci/.jenkinsfile +++ b/ci/.jenkinsfile @@ -16,6 +16,13 @@ /* 返回给gitee PR评论信息字符串 */ string ret = "" +/* 获取提供的分支名 */ +def getBranch() { + if (env.giteeActionType == "NOTE") + return env.giteeTriggerPhrase.contains("branch:") ? env.giteeTriggerPhrase[env.giteeTriggerPhrase.indexOf(":")+1..-1] : "master" + else return "master" +} + /* 库相关 */ def UnikraftRepoInfo = [ ] @@ -24,7 +31,7 @@ def AppsRepoInfo = [ [ name:"app-helloworld", url:"git@gitee.com:yingyitech/app-helloworld.git", - branch:'master', + branch:getBranch(), /* 拉取代码后所做的一些统一的操作 */ ops_after_clone:''' # 为app-helloworld 建立工作目录结构 @@ -40,7 +47,7 @@ def LibsRepoInfo = [ [ name:"lib-musl", url:"git@gitee.com:yingyitech/lib-musl.git", - branch:'master', + branch:getBranch(), ops_after_clone:''' # 由于官网musl库获取tar包获取不稳定因此改为从fork的公司库获取 cd lib-musl @@ -52,7 +59,7 @@ def LibsRepoInfo = [ [ name:"lib-libc-test", url:"git@gitee.com:yingyitech/lib-libc-test.git", - branch:'master', + branch:getBranch(), ops_after_clone:''' # 将libc-test库依赖的源码URL改为官网URL,源码URL下载不稳定 cd lib-libc-test @@ -65,7 +72,7 @@ def PlatsRepoInfo = [ [ name:"plat-raspi", url:"https://gitee.com/yingyitech/plat-raspi.git", - branch:'master', + branch:"master", ops_after_clone:'''''' ], ] @@ -660,6 +667,7 @@ pipeline { "\n|\\|执行指定测试任务|(null) - - - - - - 执行默认测试任务" + "
skip_check - - 不运行代码规范检查" + "
save - - - - - - 保存本次测试工作区文件" + + "
branch:分支名字 - - - - - - 更改拉取仓库时的分支名,该参数需加到最后" + "|test后可跟零个或多个入参,用空格分隔
譬如```test skip_check save```|" + "\n|\\|回评本表所示帮助内容|无|输入```help```即可|" } else { -- Gitee From 9181ec867d7086d45beff1be9d861161bb1cbd40 Mon Sep 17 00:00:00 2001 From: 1788594346 Date: Tue, 16 Jan 2024 17:43:07 +0800 Subject: [PATCH 52/57] ci: remove COMMIT_SUBJECT_LONG_LINE rule during codecheck Signed-off-by: 1788594346 --- .checkpatch.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/.checkpatch.conf b/.checkpatch.conf index a19adfd2..fc749538 100644 --- a/.checkpatch.conf +++ b/.checkpatch.conf @@ -3,3 +3,4 @@ --ignore NEW_TYPEDEFS --ignore FILE_PATH_CHANGES --ignore OBSOLETE +--ignore COMMIT_SUBJECT_LONG_LINE -- Gitee From 91d50411863923a28321b0ec84e6e21d84141663 Mon Sep 17 00:00:00 2001 From: Li Haode Date: Thu, 18 Jan 2024 14:06:28 +0800 Subject: [PATCH 53/57] ci:use ssh to git fetch pr Signed-off-by: Li Haode --- ci/.jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/.jenkinsfile b/ci/.jenkinsfile index 919a92cb..cb64d634 100644 --- a/ci/.jenkinsfile +++ b/ci/.jenkinsfile @@ -145,7 +145,7 @@ def MergeDependedPR(def reponame, def path){ #!/bin/bash cd $WORKSPACE cd $path - git fetch https://gitee.com/${pr.owner}/${pr.reponame}.git pull/${pr.prnumber}/head:pr_${pr.prnumber} + git fetch git@gitee.com:${pr.owner}/${pr.reponame}.git pull/${pr.prnumber}/head:pr_${pr.prnumber} git merge pr_${pr.prnumber} """, returnStatus: true) if (result != 0) { -- Gitee From 94fe1c78e49f3d9326210e22a64cdf6b82622f28 Mon Sep 17 00:00:00 2001 From: Li Haode Date: Thu, 18 Jan 2024 14:09:55 +0800 Subject: [PATCH 54/57] ci:modify the form of string ret Signed-off-by: Li Haode --- ci/.jenkinsfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ci/.jenkinsfile b/ci/.jenkinsfile index cb64d634..2b0e682d 100644 --- a/ci/.jenkinsfile +++ b/ci/.jenkinsfile @@ -293,10 +293,10 @@ pipeline { /* 结果分支处理,将信息添加至ret中 */ if (result == 0) { sucNum++ - ret = ret + "|PR标题合法性检查|成功||" + ret = ret + "\n|PR标题合法性检查|成功||" } else { failNum++ - ret = ret + "|PR标题合法性检查|**失败**|PR标题详细要求见任务链接|" + ret = ret + "\n|PR标题合法性检查|**失败**|PR标题详细要求见任务链接|" error 'PR标题合法性检查失败' } } @@ -683,7 +683,7 @@ pipeline { int untestedNum = tolNum - exeNum addGiteeMRComment comment: "结束CI测试,计划测试" + "**$tolNum**" + "项-->已经测试" + "**$exeNum**" + "项:成功" + "**$sucNum**" + "项,失败" + "**$failNum**" + "项;未测试" + "**$untestedNum**项" + "\n|任务名|测试状态|备注|\n|-|-|-|" + - "\n" + ret + + ret + "\n\n任务链接:" + env.JOB_DISPLAY_URL } deleteDir() -- Gitee From 06919d827ddb3675ab456c357a60e569cc50a092 Mon Sep 17 00:00:00 2001 From: 1788594346 Date: Tue, 30 Jan 2024 09:35:53 +0800 Subject: [PATCH 55/57] lib/ukintctlr: remove param of percpu-init function and fix some warnings Signed-off-by: Wu Shifang --- lib/ukintctlr/include/uk/intctlr.h | 6 ++---- lib/ukintctlr/tests/test_intctlr.c | 30 ++++++++++-------------------- lib/ukintctlr/ukintctlr.c | 4 ++-- plat/common/arm/lcpu.c | 2 +- 4 files changed, 15 insertions(+), 27 deletions(-) diff --git a/lib/ukintctlr/include/uk/intctlr.h b/lib/ukintctlr/include/uk/intctlr.h index 7ae83256..c49eb62d 100644 --- a/lib/ukintctlr/include/uk/intctlr.h +++ b/lib/ukintctlr/include/uk/intctlr.h @@ -62,7 +62,7 @@ struct uk_intctlr_driver_ops { void (*initialize)(void); void (*handle)(struct __regs *regs); void (*sgi_op)(uint8_t sgintid, uint32_t cpuid); - int (*percpu_init)(uint64_t cpuid __maybe_unused); + int (*percpu_init)(void); }; /** Interrupt controller descriptor */ @@ -208,11 +208,9 @@ int uk_intctlr_sgi_op(uint8_t sgintid, uint32_t cpuid); /** * extra initialize function for each cpu core - * - * @param cpuid the id of the targeted cpu * @return zero on success , error code on failure */ -int uk_intctlr_percpu_init(uint64_t cpuid __maybe_unused); +int uk_intctlr_percpu_init(void); #endif /* __ASSEMBLY__ */ #ifdef __cplusplus diff --git a/lib/ukintctlr/tests/test_intctlr.c b/lib/ukintctlr/tests/test_intctlr.c index f9a9906d..c10e3c54 100644 --- a/lib/ukintctlr/tests/test_intctlr.c +++ b/lib/ukintctlr/tests/test_intctlr.c @@ -34,51 +34,42 @@ enum ukintctlr_test_ret { TEST_PERCPU_INIT_SUCCESS, }; -static int test_configure_irq(struct uk_intctlr_irq *irq) +static int test_configure_irq(struct uk_intctlr_irq *irq __unused) { - (void)*irq; ret = TEST_CONFIGURE_IRQ_SUCCESS; return 0; } -static int test_fdt_xlat(const void *fdt __unused, int nodeoffset, __u32 index, - struct uk_intctlr_irq *irq) +static int test_fdt_xlat(const void *fdt __unused, int nodeoffset __unused, + __u32 index __unused, + struct uk_intctlr_irq *irq __unused) { - (void)nodeoffset; - (void)index; - (void)*irq; ret = TEST_FDT_XLAT_SUCCESS; return 0; } -static void test_mask_irq(unsigned int irq) +static void test_mask_irq(unsigned int irq __unused) { - (void)irq; ret = TEST_MASK_IRQ_SUCCESS; } -static void test_unmask_irq(unsigned int irq) +static void test_unmask_irq(unsigned int irq __unused) { - (void)irq; ret = TEST_UNMASK_IRQ_SUCCESS; } -static void test_handle(struct __regs *regs) +static void test_handle(struct __regs *regs __unused) { - (void)*regs; ret = TEST_HANDLE_SUCCESS; } -static void test_sgi_op(uint8_t sgintid, uint32_t cpuid) +static void test_sgi_op(uint8_t sgintid __unused, uint32_t cpuid __unused) { - (void)sgintid; - (void)cpuid; ret = TEST_SGI_OP_SUCCESS; } -static int test_percpu_init(uint64_t cpuid) +static int test_percpu_init(void) { - (void)cpuid; ret = TEST_PERCPU_INIT_SUCCESS; return 0; @@ -207,14 +198,13 @@ UK_TESTCASE(ukintctlr, call_sgi_op) /* 测试percpu_init接口 */ UK_TESTCASE(ukintctlr, call_percpu_init) { - uint64_t sgintid = 0; int r; /* 1.备份原有uk_intctlr,初始化测试环境 */ test_intctlr_init(); /* 2.通过统一接口调用percpu_init,并校验调用结果 */ - r = uk_intctlr_percpu_init(sgintid); + r = uk_intctlr_percpu_init(); UK_TEST_EXPECT_SNUM_EQ(ret, TEST_PERCPU_INIT_SUCCESS); UK_TEST_EXPECT_ZERO(r); diff --git a/lib/ukintctlr/ukintctlr.c b/lib/ukintctlr/ukintctlr.c index 88aa1cfd..5b470587 100644 --- a/lib/ukintctlr/ukintctlr.c +++ b/lib/ukintctlr/ukintctlr.c @@ -327,10 +327,10 @@ int uk_intctlr_sgi_op(uint8_t sgintid, uint32_t cpuid) return 0; } -int uk_intctlr_percpu_init(uint64_t cpuid __maybe_unused) +int uk_intctlr_percpu_init(void) { UK_ASSERT(uk_intctlr->ops->percpu_init); /* initialize interrupt controller of specified cpu core */ - return uk_intctlr->ops->percpu_init(cpuid); + return uk_intctlr->ops->percpu_init(); } diff --git a/plat/common/arm/lcpu.c b/plat/common/arm/lcpu.c index 5bf79652..927989f4 100644 --- a/plat/common/arm/lcpu.c +++ b/plat/common/arm/lcpu.c @@ -116,7 +116,7 @@ int lcpu_arch_init(struct lcpu *this_lcpu) /* Initialize the interrupt controller for non-bsp cores */ if (!lcpu_is_bsp(this_lcpu)) { - ret = uk_intctlr_percpu_init(this_lcpu->id); + ret = uk_intctlr_percpu_init(); if (unlikely(ret)) return ret; } -- Gitee From 3fbf504492966372a6d1dc4e0c7c0c25cdf2d4ff Mon Sep 17 00:00:00 2001 From: crazykev Date: Tue, 19 Mar 2024 14:38:35 +0800 Subject: [PATCH 56/57] arch/*: [upstream][bugfix]should call uk_sched_thread_exit when thread exit Signed-off-by: crazykev --- arch/arm/arm64/ctx.S | 24 ++++++++++++-- arch/arm/ctx.c | 38 +++++++++++----------- arch/arm/ctx.h | 28 ++++++++++++++++ arch/x86/ctx.c | 39 +++++++++++------------ arch/x86/ctx.h | 28 ++++++++++++++++ arch/x86/x86_64/ctx.S | 21 +++++++++--- lib/syscall_shim/arch/arm64/syscall_ctx.S | 2 +- 7 files changed, 132 insertions(+), 48 deletions(-) create mode 100644 arch/arm/ctx.h create mode 100644 arch/x86/ctx.h diff --git a/arch/arm/arm64/ctx.S b/arch/arm/arm64/ctx.S index 68ce8993..5fefa6e9 100644 --- a/arch/arm/arm64/ctx.S +++ b/arch/arm/arm64/ctx.S @@ -78,7 +78,7 @@ ENTRY(_ctx_arm_clearregs) ldr x30, [sp], #16 ret -ENTRY(_ctx_arm_call0) +ENTRY(_ctx_arm_callip) #if !__OMIT_FRAMEPOINTER__ mov x29, xzr /* reset frame pointer */ #endif /* !__OMIT_FRAMEPOINTER__ */ @@ -86,13 +86,27 @@ ENTRY(_ctx_arm_call0) ldr x30, [sp], #16 ret +ENTRY(_ctx_arm_call0) +#if !__OMIT_FRAMEPOINTER__ + mov x29, xzr /* reset frame pointer */ +#endif /* !__OMIT_FRAMEPOINTER__ */ + ldr x0, [sp], #16 + /* pop cleanup func into x30 as return address */ + ldr x30, [sp], #16 + br x0 + ret + ENTRY(_ctx_arm_call1) #if !__OMIT_FRAMEPOINTER__ mov x29, xzr /* reset frame pointer */ #endif /* !__OMIT_FRAMEPOINTER__ */ ldr x0, [sp], #16 - /* jump to entrance function left on stack */ + /* Load entry function address as x1 */ + ldr x1, [sp], #16 + /* pop cleanup func into x30 as return address */ ldr x30, [sp], #16 + /* jump to entry func */ + br x1 ret ENTRY(_ctx_arm_call2) @@ -101,8 +115,12 @@ ENTRY(_ctx_arm_call2) #endif /* !__OMIT_FRAMEPOINTER__ */ ldr x1, [sp], #16 ldr x0, [sp], #16 - /* jump to entrance function left on stack */ + /* Load entry function address as x2 */ + ldr x2, [sp], #16 + /* pop cleanup func into x30 as return address */ ldr x30, [sp], #16 + /* jump to entry func */ + br x2 ret /* diff --git a/arch/arm/ctx.c b/arch/arm/ctx.c index 9dc48fa9..5c863785 100644 --- a/arch/arm/ctx.c +++ b/arch/arm/ctx.c @@ -41,12 +41,7 @@ #define UK_ASSERT(..) do {} while (0) #define uk_pr_debug(..) do {} while (0) #endif /* !CONFIG_LIBUKDEBUG */ - -/* Assembler functions */ -void _ctx_arm_clearregs(void); -void _ctx_arm_call0(void); -void _ctx_arm_call1(void); -void _ctx_arm_call2(void); +#include "ctx.h" void ukarch_ctx_init(struct ukarch_ctx *ctx, __uptr sp, int keep_regs, @@ -59,16 +54,16 @@ void ukarch_ctx_init(struct ukarch_ctx *ctx, UK_ASSERT(ip); /* IP == NULL would cause a crash */ UK_ASSERT(!keep_regs && sp); /* stack is needed for clearing regs */ - _sp = ukarch_rstack_push(sp, (long) ip); + _sp = ukarch_rstack_push(sp, (long)ip); if (keep_regs) { - ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_arm_call0); + ukarch_ctx_init_bare(ctx, _sp, (long)_ctx_arm_callip); } else { - _sp = ukarch_rstack_push(_sp, (long) _ctx_arm_call0); + _sp = ukarch_rstack_push(_sp, (long)_ctx_arm_callip); ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_arm_clearregs); } - uk_pr_debug("ukarch_ctx %p: start:%p sp:%p\n", - ctx, (void *) ip, (void *) sp); + uk_pr_debug("ukarch_ctx %p: start:%p sp:%p\n", ctx, (void *)ip, + (void *)_sp); } void ukarch_ctx_init_entry0(struct ukarch_ctx *ctx, @@ -82,7 +77,8 @@ void ukarch_ctx_init_entry0(struct ukarch_ctx *ctx, UK_ASSERT(entry); /* entry == NULL will cause a crash */ UK_ASSERT(!(sp & UKARCH_SP_ALIGN_MASK)); /* sp properly aligned? */ - _sp = ukarch_rstack_push(sp, (long) entry); + _sp = ukarch_rstack_push(sp, (long)uk_sched_thread_exit); + _sp = ukarch_rstack_push(_sp, (long)entry); if (keep_regs) { ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_arm_call0); } else { @@ -90,8 +86,8 @@ void ukarch_ctx_init_entry0(struct ukarch_ctx *ctx, ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_arm_clearregs); } - uk_pr_debug("ukarch_ctx %p: entry:%p(), sp:%p\n", - ctx, entry, (void *) sp); + uk_pr_debug("ukarch_ctx %p: entry:%p(), sp:%p\n", ctx, entry, + (void *)_sp); } void ukarch_ctx_init_entry1(struct ukarch_ctx *ctx, @@ -105,7 +101,8 @@ void ukarch_ctx_init_entry1(struct ukarch_ctx *ctx, UK_ASSERT(entry); /* NULL as func will cause a crash */ UK_ASSERT(!(sp & UKARCH_SP_ALIGN_MASK)); /* sp properly aligned? */ - _sp = ukarch_rstack_push(sp, (long) entry); + _sp = ukarch_rstack_push(sp, (long)uk_sched_thread_exit); + _sp = ukarch_rstack_push(_sp, (long)entry); _sp = ukarch_rstack_push(_sp, arg); if (keep_regs) { ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_arm_call1); @@ -114,8 +111,8 @@ void ukarch_ctx_init_entry1(struct ukarch_ctx *ctx, ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_arm_clearregs); } - uk_pr_debug("ukarch_ctx %p: entry:%p(%lx), sp:%p\n", - ctx, entry, arg, (void *) sp); + uk_pr_debug("ukarch_ctx %p: entry:%p(%lx), sp:%p\n", ctx, entry, arg, + (void *)_sp); } void ukarch_ctx_init_entry2(struct ukarch_ctx *ctx, @@ -129,7 +126,8 @@ void ukarch_ctx_init_entry2(struct ukarch_ctx *ctx, UK_ASSERT(entry); /* NULL as func will cause a crash */ UK_ASSERT(!(sp & UKARCH_SP_ALIGN_MASK)); /* sp properly aligned? */ - _sp = ukarch_rstack_push(sp, (long) entry); + _sp = ukarch_rstack_push(sp, (long)uk_sched_thread_exit); + _sp = ukarch_rstack_push(_sp, (long)entry); _sp = ukarch_rstack_push(_sp, arg0); _sp = ukarch_rstack_push(_sp, arg1); if (keep_regs) { @@ -139,6 +137,6 @@ void ukarch_ctx_init_entry2(struct ukarch_ctx *ctx, ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_arm_clearregs); } - uk_pr_debug("ukarch_ctx %p: entry:%p(%lx, %lx), sp:%p\n", - ctx, entry, arg0, arg1, (void *) sp); + uk_pr_debug("ukarch_ctx %p: entry:%p(%lx, %lx), sp:%p\n", ctx, entry, + arg0, arg1, (void *)_sp); } diff --git a/arch/arm/ctx.h b/arch/arm/ctx.h new file mode 100644 index 00000000..8b45208b --- /dev/null +++ b/arch/arm/ctx.h @@ -0,0 +1,28 @@ +/* Copyright 2023 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !__ASSEMBLY__ + +/* thread cleanup func */ +extern void uk_sched_thread_exit(void); + +/* Assembler functions */ +void _ctx_arm_clearregs(void); +void _ctx_arm_callip(void); +void _ctx_arm_call0(void); +void _ctx_arm_call1(void); +void _ctx_arm_call2(void); + +#endif /* !__ASSEMBLY__ */ diff --git a/arch/x86/ctx.c b/arch/x86/ctx.c index d850b233..e3aff828 100644 --- a/arch/x86/ctx.c +++ b/arch/x86/ctx.c @@ -40,12 +40,7 @@ #define UK_ASSERT(..) do {} while (0) #define uk_pr_debug(..) do {} while (0) #endif /* !CONFIG_LIBUKDEBUG */ - -/* Assembler functions */ -void _ctx_x86_clearregs(void); -void _ctx_x86_call0(void); -void _ctx_x86_call1(void); -void _ctx_x86_call2(void); +#include "ctx.h" void ukarch_ctx_init(struct ukarch_ctx *ctx, __uptr sp, int keep_regs, @@ -58,16 +53,17 @@ void ukarch_ctx_init(struct ukarch_ctx *ctx, UK_ASSERT(ip); /* NULL as IP will cause a crash */ UK_ASSERT(!keep_regs && sp); /* a stack is needed when clearing */ - _sp = ukarch_rstack_push(sp, (long) ip); + _sp = ukarch_rstack_push(sp, (long)ip); + if (keep_regs) { - ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_x86_call0); + ukarch_ctx_init_bare(ctx, _sp, (long)_ctx_x86_callip); } else { - _sp = ukarch_rstack_push(_sp, (long) _ctx_x86_call0); + _sp = ukarch_rstack_push(_sp, (long)_ctx_x86_callip); ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_x86_clearregs); } - uk_pr_debug("ukarch_ctx %p: start:%p sp:%p\n", - ctx, (void *) ip, (void *) sp); + uk_pr_debug("ukarch_ctx %p: start:%p sp:%p\n", ctx, (void *)ip, + (void *)_sp); } void ukarch_ctx_init_entry0(struct ukarch_ctx *ctx, @@ -97,7 +93,8 @@ void ukarch_ctx_init_entry0(struct ukarch_ctx *ctx, * through. */ sp = ukarch_rstack_push(sp, (__u64) 0x0); - _sp = ukarch_rstack_push(sp, (long) entry); + _sp = ukarch_rstack_push(sp, (long)uk_sched_thread_exit); + _sp = ukarch_rstack_push(_sp, (long)entry); if (keep_regs) { ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_x86_call0); } else { @@ -105,8 +102,8 @@ void ukarch_ctx_init_entry0(struct ukarch_ctx *ctx, ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_x86_clearregs); } - uk_pr_debug("ukarch_ctx %p: entry:%p(), sp:%p\n", - ctx, entry, (void *) sp); + uk_pr_debug("ukarch_ctx %p: entry:%p(), sp:%p\n", ctx, entry, + (void *)_sp); } void ukarch_ctx_init_entry1(struct ukarch_ctx *ctx, @@ -121,7 +118,8 @@ void ukarch_ctx_init_entry1(struct ukarch_ctx *ctx, UK_ASSERT(!(sp & UKARCH_SP_ALIGN_MASK)); /* sp properly aligned? */ sp = ukarch_rstack_push(sp, (__u64) 0x0); /* SystemV call convention */ - _sp = ukarch_rstack_push(sp, (long) entry); + _sp = ukarch_rstack_push(sp, (long)uk_sched_thread_exit); + _sp = ukarch_rstack_push(_sp, (long)entry); _sp = ukarch_rstack_push(_sp, arg); if (keep_regs) { ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_x86_call1); @@ -130,8 +128,8 @@ void ukarch_ctx_init_entry1(struct ukarch_ctx *ctx, ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_x86_clearregs); } - uk_pr_debug("ukarch_ctx %p: entry:%p(%lx), sp:%p\n", - ctx, entry, arg, (void *) sp); + uk_pr_debug("ukarch_ctx %p: entry:%p(%lx), sp:%p\n", ctx, entry, arg, + (void *)_sp); } void ukarch_ctx_init_entry2(struct ukarch_ctx *ctx, @@ -146,7 +144,8 @@ void ukarch_ctx_init_entry2(struct ukarch_ctx *ctx, UK_ASSERT(!(sp & UKARCH_SP_ALIGN_MASK)); /* sp properly aligned? */ sp = ukarch_rstack_push(sp, (__u64) 0x0); /* SystemV call convention */ - _sp = ukarch_rstack_push(sp, (long) entry); + _sp = ukarch_rstack_push(sp, (long)uk_sched_thread_exit); + _sp = ukarch_rstack_push(_sp, (long)entry); _sp = ukarch_rstack_push(_sp, arg0); _sp = ukarch_rstack_push(_sp, arg1); if (keep_regs) { @@ -156,6 +155,6 @@ void ukarch_ctx_init_entry2(struct ukarch_ctx *ctx, ukarch_ctx_init_bare(ctx, _sp, (long) _ctx_x86_clearregs); } - uk_pr_debug("ukarch_ctx %p: entry:%p(%lx, %lx), sp:%p\n", - ctx, entry, arg0, arg1, (void *) sp); + uk_pr_debug("ukarch_ctx %p: entry:%p(%lx, %lx), sp:%p\n", ctx, entry, + arg0, arg1, (void *)_sp); } diff --git a/arch/x86/ctx.h b/arch/x86/ctx.h new file mode 100644 index 00000000..a147c6c4 --- /dev/null +++ b/arch/x86/ctx.h @@ -0,0 +1,28 @@ +/* Copyright 2023 Hangzhou Yingyi Technology Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if !__ASSEMBLY__ + +/* thread cleanup func */ +extern void uk_sched_thread_exit(void); + +/* Assembler functions */ +void _ctx_x86_clearregs(void); +void _ctx_x86_callip(void); +void _ctx_x86_call0(void); +void _ctx_x86_call1(void); +void _ctx_x86_call2(void); + +#endif /* !__ASSEMBLY__ */ diff --git a/arch/x86/x86_64/ctx.S b/arch/x86/x86_64/ctx.S index 87e2d971..a7083060 100644 --- a/arch/x86/x86_64/ctx.S +++ b/arch/x86/x86_64/ctx.S @@ -54,18 +54,29 @@ ENTRY(_ctx_x86_clearregs) ret /* jump to entrance function left on stack */ -ENTRY(_ctx_x86_call0) +ENTRY(_ctx_x86_callip) #if !__OMIT_FRAMEPOINTER__ xorq %rbp, %rbp /* reset frame pointer */ #endif /* !__OMIT_FRAMEPOINTER__ */ ret /* jump to entrance function left on stack */ +ENTRY(_ctx_x86_call0) +#if !__OMIT_FRAMEPOINTER__ + xorq %rbp, %rbp /* reset frame pointer */ +#endif /* !__OMIT_FRAMEPOINTER__ */ + popq %rax /* Get the 'entry' function address */ + call *%rax /* Call 'entry' */ + ret /* jump to thread cleanup function left on stack */ + ENTRY(_ctx_x86_call1) #if !__OMIT_FRAMEPOINTER__ xorq %rbp, %rbp /* reset frame pointer */ #endif /* !__OMIT_FRAMEPOINTER__ */ - popq %rdi /* load first argument from stack */ - ret /* jump to entrance function left on stack */ + /* Retrieve and call the 'entry' function, argument already in place */ + popq %rdi /* Get the argument for 'entry' */ + popq %rax /* Get the 'entry' function address */ + call *%rax /* Call 'entry', it uses the argument from %rdi */ + ret /* jump to thread cleanup function left on stack */ ENTRY(_ctx_x86_call2) #if !__OMIT_FRAMEPOINTER__ @@ -73,7 +84,9 @@ ENTRY(_ctx_x86_call2) #endif /* !__OMIT_FRAMEPOINTER__ */ popq %rsi /* load second argument from stack */ popq %rdi /* load first argument from stack */ - ret /* jump to entrance function left on stack */ + popq %rax /* Get the 'entry' function address */ + call *%rax /* Call 'entry', it uses the argument from %rdi %rsi */ + ret /* jump to thread cleanup function left on stack */ /* * Do a local context switch diff --git a/lib/syscall_shim/arch/arm64/syscall_ctx.S b/lib/syscall_shim/arch/arm64/syscall_ctx.S index 10b7be8f..496e3996 100644 --- a/lib/syscall_shim/arch/arm64/syscall_ctx.S +++ b/lib/syscall_shim/arch/arm64/syscall_ctx.S @@ -14,7 +14,7 @@ ENTRY(uk_syscall_ctx_popall) mov x0, sp add x0, x0, #(__REGS_SIZEOF + UKARCH_SYSREGS_SIZE) - bl ukarch_ectx_store + bl ukarch_ectx_load mov x0, sp add x0, x0, #(__REGS_SIZEOF) -- Gitee From 405a4e6a6b388389a58a52760c2808dcab9540da Mon Sep 17 00:00:00 2001 From: sunhaoyi Date: Tue, 19 Mar 2024 17:22:33 +0800 Subject: [PATCH 57/57] plat/common: Unified maintenance of exception vector tables and link.lds.S link scripts Signed-off-by: sunhaoyi --- plat/common/arm/exceptions64.S | 249 ++++++++++++++++++ plat/common/arm/link64.lds.S | 87 ++++++ .../include/uk/plat/common/common.lds.h | 3 +- 3 files changed, 338 insertions(+), 1 deletion(-) create mode 100644 plat/common/arm/exceptions64.S create mode 100644 plat/common/arm/link64.lds.S diff --git a/plat/common/arm/exceptions64.S b/plat/common/arm/exceptions64.S new file mode 100644 index 00000000..70787ead --- /dev/null +++ b/plat/common/arm/exceptions64.S @@ -0,0 +1,249 @@ +/* + * MIT License + * + * Copyright (c) 2018, Sergey Matyukevich + * (c) 2020, Santiago Pagani + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#include +#include +#include +#include +#include +#include + +.macro EXCHANGE_SP_WITH_X0 + add sp, sp, x0 // new_sp = sp + x0 + sub x0, sp, x0 // new_x0 = new_sp - x0 = sp + x0 - x0 = sp + sub sp, sp, x0 // new_sp = new_sp - new_x0 = sp + x0 - sp = x0 +.endm + +.macro SAVE_REGS, is_irq + /* Use TPIDRRO_EL0 as scratch register. It is fine to do so because + * it will always hold a value the application can't modify and we will + * always be able to restore it to its desired known value anytime we + * want. Thus, temporarily store x0. + */ + msr tpidrro_el0, x0 + + /* Fetch middle of `lcpu_irqntrap_sp`: + * CPU_EXCEPT_STACK_SIZE CPU_EXCEPT_STACK_SIZE + * <---------------------><---------------------> + * |============================================| + * | | | + * | trap stack | IRQ stack | + * | | | + * |============================================= + * ^ + * SP_EL0 + */ + mrs x0, sp_el0 + + /* Make it so that SP contains SP_EL0 and x0 contains old SP */ + EXCHANGE_SP_WITH_X0 + +.if \is_irq != 0 + /* If we are an IRQ, use the IRQ stack instead. */ + add sp, sp, #CPU_EXCEPT_STACK_SIZE +.endif + + /* Store old SP previously saved into x0 */ + str x0, [sp, #-16] + + /* Is this trap a system call? */ + mrs x0, esr_el1 + and x0, x0, #ESR_EC_MASK + orr x0, xzr, x0, lsr #ESR_EC_SHIFT + cmp x0, #ESR_EL1_EC_SVC64 + bne 0f + + /* If we are in a system call trap then switch to auxiliary stack + * from the current lcpu pointer + */ + mrs x0, tpidr_el1 + ldr x0, [x0, #LCPU_AUXSP_OFFSET] + /* NOTE: We should normally align the stack before doing this + * subtraction because we must ensure that the `ectx` field + * is aligned to the corresponding ECTX alignment. + * However, this is guaranteed to already be the case for the + * auxiliary stack because it is allocated with this exact alignment + * in mind. + */ + sub x0, x0, #UK_SYSCALL_CTX_SIZE + + /* We now have in SP the trap stack and in x0 the auxiliary stack */ + EXCHANGE_SP_WITH_X0 /* Switch them */ + /* Restore old SP we stored before system call check */ + ldr x0, [x0, #-16] + str x0, [sp, #__SP_OFFSET] /* Store old SP in auxiliary stack */ + b 1f +0: + sub sp, sp, #__TRAP_STACK_SIZE +1: + /* Restore x0 */ + mrs x0, tpidrro_el0 + + /* Save general purpose registers */ + stp x0, x1, [sp, #16 * 0] + stp x2, x3, [sp, #16 * 1] + stp x4, x5, [sp, #16 * 2] + stp x6, x7, [sp, #16 * 3] + stp x8, x9, [sp, #16 * 4] + stp x10, x11, [sp, #16 * 5] + stp x12, x13, [sp, #16 * 6] + stp x14, x15, [sp, #16 * 7] + stp x16, x17, [sp, #16 * 8] + stp x18, x19, [sp, #16 * 9] + stp x20, x21, [sp, #16 * 10] + stp x22, x23, [sp, #16 * 11] + stp x24, x25, [sp, #16 * 12] + stp x26, x27, [sp, #16 * 13] + stp x28, x29, [sp, #16 * 14] + + /* Save LR and exception PC */ + mrs x21, elr_el1 + stp x30, x21, [sp, #16 * 15] + + /* Save pstate and exception status register */ + mrs x22, spsr_el1 + mrs x23, esr_el1 + stp x22, x23, [sp, #16 * 16] +.endm + +.macro RESTORE_REGS + /* Mask IRQ to make sure restore would not be interrupted by IRQ */ + msr daifset, #2 + + /* Restore pstate and exception status register */ + ldp x22, x23, [sp, #16 * 16] + msr spsr_el1, x22 + msr esr_el1, x23 + + /* Restore LR and exception PC */ + ldp x30, x21, [sp, #16 * 15] + msr elr_el1, x21 + + /* Restore general purpose registers */ + ldp x28, x29, [sp, #16 * 14] + ldp x26, x27, [sp, #16 * 13] + ldp x24, x25, [sp, #16 * 12] + ldp x22, x23, [sp, #16 * 11] + ldp x20, x21, [sp, #16 * 10] + /* Skip x18, x19 */ + ldp x16, x17, [sp, #16 * 8] + ldp x14, x15, [sp, #16 * 7] + ldp x12, x13, [sp, #16 * 6] + ldp x10, x11, [sp, #16 * 5] + ldp x8, x9, [sp, #16 * 4] + ldp x6, x7, [sp, #16 * 3] + ldp x4, x5, [sp, #16 * 2] + ldp x2, x3, [sp, #16 * 1] + ldp x0, x1, [sp, #16 * 0] + + /* Restore stack pointer for exception from EL1 */ + ldr x18, [sp, #__SP_OFFSET] + mov x19, sp + mov sp, x18 + + /* Restore x18, x19 */ + ldp x18, x19, [x19, #16 * 9] + + eret +.endm + +/* Bad Abort numbers */ +#define BAD_SYNC 0 +#define BAD_IRQ 1 +#define BAD_FIQ 2 +#define BAD_ERROR 3 + +#define el_invalid(name, reason, el) \ +.align 6; \ +name##_invalid: \ + SAVE_REGS 0; \ + mov x0, sp; \ + mov x1, el; \ + mov x2, #(reason); \ + mrs x3, far_el1; \ + b invalid_trap_handler; \ +ENDPROC(name##_invalid); \ + +el_invalid(el1_sync, BAD_SYNC, 1); +el_invalid(el0_sync, BAD_SYNC, 0); +el_invalid(el1_irq, BAD_IRQ, 1); +el_invalid(el0_irq, BAD_IRQ, 0); +el_invalid(el1_fiq, BAD_FIQ, 1); +el_invalid(el0_fiq, BAD_FIQ, 0); +el_invalid(el1_error, BAD_ERROR, 1); +el_invalid(el0_error, BAD_ERROR, 0); + +/* + * Macro for Exception vectors. + */ +.macro ventry label +.align 7 +b \label +.endm + +/* + * Exception vectors. + */ +.align 11 +.globl vectors_el1 +vectors_el1: + ventry el1_sync_invalid /* Synchronous EL1t */ + ventry el1_irq_invalid /* IRQ EL1t */ + ventry el1_fiq_invalid /* FIQ EL1t */ + ventry el1_error_invalid /* Error EL1t */ + + ventry el1_sync /* Synchronous EL1h */ + ventry el1_irq /* IRQ EL1h */ + ventry el1_fiq_invalid /* FIQ EL1h */ + ventry el1_error_invalid /* Error EL1h */ + + ventry el0_sync_invalid /* Synchronous 64-bit EL0 */ + ventry el0_irq_invalid /* IRQ 64-bit EL0 */ + ventry el0_fiq_invalid /* FIQ 64-bit EL0 */ + ventry el0_error_invalid /* Error 64-bit EL0 */ + + ventry el0_sync_invalid /* Synchronous 32-bit EL0 */ + ventry el0_irq_invalid /* IRQ 32-bit EL0 */ + ventry el0_fiq_invalid /* FIQ 32-bit EL0 */ + ventry el0_error_invalid /* Error 32-bit EL0 */ + +.align 6 +el1_sync: + SAVE_REGS 0 + mov x0, sp + mrs x1, FAR_EL1 + bl trap_el1_sync + RESTORE_REGS + +.align 6 +el1_irq: + SAVE_REGS 1 + msr daifclr, #(8 | 4 | 1) + mov x0, sp + bl trap_el1_irq + RESTORE_REGS diff --git a/plat/common/arm/link64.lds.S b/plat/common/arm/link64.lds.S new file mode 100644 index 00000000..7076503e --- /dev/null +++ b/plat/common/arm/link64.lds.S @@ -0,0 +1,87 @@ +#include +#include + +#define RAM_BASE_ADDR CONFIG_RAM_BASE_ADDR + +OUTPUT_FORMAT("elf64-littleaarch64") +OUTPUT_ARCH(aarch64) + +PHDRS +{ + text PT_LOAD FLAGS(PHDRS_PF_RX); + rodata PT_LOAD FLAGS(PHDRS_PF_R); + data PT_LOAD; + tls PT_TLS; + tls_load PT_LOAD; + stack PT_GNU_STACK FLAGS(PHDRS_PF_RW); +} + +SECTIONS +{ + . = RAM_BASE_ADDR; + + _base_addr = .; /* Symbol to represent the load base address */ + _start_ram_addr = .; + + /* Code */ + _text = .; + .text : + { + KEEP(*(.text.boot)) + *(.text) + *(.text.*) + } :text + . = ALIGN(__PAGE_SIZE); + _etext = .; + + /* Read-only data */ + . = ALIGN(__PAGE_SIZE); + _rodata = .; + .rodata : + { + *(.rodata) + *(.rodata.*) + } :rodata + + EXCEPTION_SECTIONS + + CTORTAB_SECTION + + INITTAB_SECTION + + EVENTTAB_SECTION + + _erodata = .; + + /* Constructor tables (read-only) */ + . = ALIGN(0x8); + _ctors = .; + .preinit_array : { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } + + . = ALIGN(0x8); + .init_array : { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) \ + SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } + _ectors = .; + . = ALIGN(__PAGE_SIZE); + + TLS_SECTIONS + + DATA_SECTIONS + + _end = .; + + .comment 0 : { *(.comment) } + DEBUG_SYMBOLS + + DISCARDS +} +__bss_size = (__bss_end - __bss_start)>>3; diff --git a/plat/common/include/uk/plat/common/common.lds.h b/plat/common/include/uk/plat/common/common.lds.h index 28dabf02..4ab9c958 100644 --- a/plat/common/include/uk/plat/common/common.lds.h +++ b/plat/common/include/uk/plat/common/common.lds.h @@ -187,7 +187,8 @@ *(.bss.*) \ *(COMMON) \ . = ALIGN(__PAGE_SIZE); \ - } + } \ + __bss_end = .; #define DISCARDS \ /DISCARD/ : \ -- Gitee