diff --git a/.clang-format b/.clang-format
index 0cda88089..363922fdb 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,136 +1,395 @@
+# This file is a part of Simple-XX/SimpleKernel
+# (https://github.com/Simple-XX/SimpleKernel).
+#
+# CMakeLists.txt for Simple-XX/SimpleKernel.
+
---
-Language: Cpp
+# @version clang-format version 15
+# @see https://clang.llvm.org/docs/ClangFormatStyleOptions.html
+
+# 访问说明符 public/private 的偏移,与类对齐
AccessModifierOffset: -4
+# ( 后的参数对齐,与 ( 对齐
AlignAfterOpenBracket: Align
-AlignConsecutiveMacros: false
-AlignConsecutiveAssignments: true
-AlignConsecutiveDeclarations: true
-AlignEscapedNewlines: Right
-AlignOperands: true
+# 结构体初始化对齐,右对齐
+AlignArrayOfStructures: Right
+# 连续赋值对齐
+AlignConsecutiveAssignments:
+ # 允许
+ Enabled: true
+ # 忽略空行
+ AcrossEmptyLines: true
+ # 忽略注释
+ AcrossComments: true
+ # 忽略混合运算符
+ AlignCompound: true
+ # 填充运算符
+ PadOperators: true
+# 位域对齐
+AlignConsecutiveBitFields:
+ # 允许
+ Enabled: true
+ # 忽略空行
+ AcrossEmptyLines: true
+ # 忽略注释
+ AcrossComments: true
+ # 忽略混合运算符
+ AlignCompound: true
+ # 填充运算符
+ PadOperators: true
+# 连续声明对齐,忽略空行/注释
+AlignConsecutiveDeclarations:
+ # 允许
+ Enabled: true
+ # 忽略空行
+ AcrossEmptyLines: true
+ # 忽略注释
+ AcrossComments: true
+ # 忽略混合运算符
+ AlignCompound: true
+ # 填充运算符
+ PadOperators: true
+# 连续宏定义对齐,忽略空行/注释
+AlignConsecutiveMacros:
+ # 允许
+ Enabled: true
+ # 忽略空行
+ AcrossEmptyLines: true
+ # 忽略注释
+ AcrossComments: true
+ # 忽略混合运算符
+ AlignCompound: true
+ # 填充运算符
+ PadOperators: true
+# 换行符号左对齐
+AlignEscapedNewlines: Left
+# 操作符对齐,与 BreakBeforeBinaryOperators 共同生效
+AlignOperands: AlignAfterOperator
+# 行后注释对齐
AlignTrailingComments: true
+# 尽量将函数调用/初始化的所有参数放在同一行,禁用
AllowAllArgumentsOnNextLine: false
-AllowAllConstructorInitializersOnNextLine: true
+# 尽量将函数声明的参数放在同一行
AllowAllParametersOfDeclarationOnNextLine: true
-AllowShortBlocksOnASingleLine: true
+# 将 while (true) {} 中的 {} 合并为一行,禁用
+AllowShortBlocksOnASingleLine: Never
+# 将 switch case: 中的 case: 合并为一行,禁用
AllowShortCaseLabelsOnASingleLine: false
-AllowShortFunctionsOnASingleLine: false
-AllowShortLambdasOnASingleLine: false
-AllowShortIfStatementsOnASingleLine: false
+# 将枚举类型合并为一行,禁用
+AllowShortEnumsOnASingleLine: false
+# 将短函数合并为一行,禁用
+AllowShortFunctionsOnASingleLine: None
+# 将短语句合并为一行,禁用
+AllowShortIfStatementsOnASingleLine: Never
+# 将 lambda 表达式合并为一行,禁用
+AllowShortLambdasOnASingleLine: None
+# 将短循环合并为一行,禁用
AllowShortLoopsOnASingleLine: false
-AlwaysBreakAfterDefinitionReturnType: None
+# 将在返回类型后换行,禁用
AlwaysBreakAfterReturnType: None
+# 将在多行字符串前换行,禁用
AlwaysBreakBeforeMultilineStrings: false
-AlwaysBreakTemplateDeclarations: true
+# 在模版声明后换行
+AlwaysBreakTemplateDeclarations: Yes
+# 编译器属性排除,不会参与格式化
+AttributeMacros: [ '__capability',
+ '__output',
+ '__ununsed',
+ '[[maybe_unused]]' ]
+
+# 尽量将函数调用的参数放在同一行
BinPackArguments: true
+# 尽量将函数声明的参数放在同一行
BinPackParameters: true
+# 在位域声明的 : 前后都加空格
+BitFieldColonSpacing: Both
+# 大括号换行设置
BraceWrapping:
- AfterCaseLabel: false
- AfterClass: false
- AfterControlStatement: false
- AfterEnum: false
- AfterFunction: false
- AfterNamespace: false
- AfterObjCDeclaration: false
- AfterStruct: false
- AfterUnion: false
+ # 在 case 后换行,禁用
+ AfterCaseLabel: false
+ # 在 class 后换行,禁用
+ AfterClass: false
+ # 在控制语句后换行,禁用
+ AfterControlStatement: Never
+ # 在 enum 后换行,禁用
+ AfterEnum: false
+ # 在函数定义后换行,禁用
+ AfterFunction: false
+ # 在 namespace 后换行,禁用
+ AfterNamespace: false
+ # 在结构体后换行,禁用
+ AfterStruct: false
+ # 在联合体后换行,禁用
+ AfterUnion: false
+ # 在 extern 后换行,禁用
AfterExternBlock: false
- BeforeCatch: false
- BeforeElse: true
- IndentBraces: false
+ # 在 catch 后换行,禁用
+ BeforeCatch: false
+ # 在 else 前换行
+ BeforeElse: true
+ # 在 lambda 后换行,禁用
+ BeforeLambdaBody: false
+ # 在 while 前换行,禁用
+ BeforeWhile: false
+ # 换行缩进括号,禁用
+ IndentBraces: false
+ # 空函数的大括号换行
SplitEmptyFunction: true
+ # 空 class/struct/union 的大括号换行
SplitEmptyRecord: true
+ # 空 namespace 的大括号换行
SplitEmptyNamespace: true
-BreakBeforeBinaryOperators: None
+# 在二元操作符前换行
+BreakBeforeBinaryOperators: All
+# 在大括号前换行,使用自定义规则,在 BraceWrapping 中规定
BreakBeforeBraces: Custom
-BreakBeforeInheritanceComma: false
-BreakInheritanceList: BeforeColon
+# 在 concept(c++20) 前换行
+BreakBeforeConceptDeclarations: Always
+# 在三元操作符前换行
BreakBeforeTernaryOperators: true
-BreakConstructorInitializersBeforeComma: false
+# 构造函数初始化列表在冒号 : 前,逗号 , 后换行
BreakConstructorInitializers: BeforeColon
-BreakAfterJavaFieldAnnotations: false
+# class 继承列表在冒号 : 前,逗号 , 后换行
+BreakInheritanceList: BeforeColon
+# 允许将字符串切割
BreakStringLiterals: true
-ColumnLimit: 80
-CommentPragmas: '^ IWYU pragma:'
+# 最大列数
+ColumnLimit: 80
+# 特殊注释的正则表达式,不会进行格式化
+CommentPragmas: '^ NO_STYLE:'
+# 将多个 namespace 合并为一行,禁用
CompactNamespaces: false
-ConstructorInitializerAllOnOneLineOrOnePerLine: false
+# 构造函数的初始化列表/继承列表的缩进宽度
ConstructorInitializerIndentWidth: 4
-ContinuationIndentWidth: 4
-Cpp11BracedListStyle: true
+# 续行的缩进宽度
+ContinuationIndentWidth: 2
+# 去除 C++11 的列表初始化的大括号 { 后和 } 前的空格,禁用
+Cpp11BracedListStyle: false
+# 分析文件使用最多的换行符并应用到整个文件,
+# 只有当无法得到结论时才会使用 UseCRLF,禁用
DeriveLineEnding: true
+# 分析文件使用最多的指针/引用的对齐方式并应用到整个文件,
+# 只有当无法得到结论时才会使用 PointerAlignment,禁用
DerivePointerAlignment: false
-DisableFormat: false
-ExperimentalAutoDetectBinPacking: false
+# 关闭格式化,禁用
+DisableFormat: false
+# 访问描述符后的空行,只保留 MaxEmptyLinesToKeep 指定的行数
+EmptyLineAfterAccessModifier: Leave
+# 访问描述符前的空行,始终保留,除非是 class/struct 的开始
+EmptyLineBeforeAccessModifier: Always
+# 在命名空间结束后添加注释,与 ShortNamespaceLines 共同生效
FixNamespaceComments: true
-ForEachMacros:
- - foreach
- - Q_FOREACH
- - BOOST_FOREACH
-IncludeBlocks: Preserve
+# for-each 宏,作为循环语句进行格式化
+ForEachMacros: [ 'RANGES_FOR', 'FOREACH' ]
+
+# if 宏,作为条件语句进行格式化
+IfMacros: [ 'IF' ]
+# 将 #include 分块,规则由 IncludeCategories 指定,暂未使用
+#IncludeBlocks: Regroup
+# 将 #include 分块,保留原有分块
+IncludeBlocks: Preserve
+# 对 #include 进行排序,匹配了某正则表达式的 #include 拥有对应的优先级,
+# 优先级越小排序越靠前,匹配不到的则默认优先级为 INT_MAX,暂未使用
IncludeCategories:
- - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
- Priority: 2
- SortPriority: 0
- - Regex: '^(<|"(gtest|gmock|isl|json)/)'
- Priority: 3
- SortPriority: 0
- - Regex: '.*'
- Priority: 1
- SortPriority: 0
-IncludeIsMainRegex: '(Test)?$'
-IncludeIsMainSourceRegex: ''
+ # 正则
+ - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
+ # 优先级
+ Priority: 2
+ # 排序优先级,默认与 Priority 相同
+ SortPriority: 2
+ # 大小写敏感
+ CaseSensitive: true
+ - Regex: '^((<|")(gtest|gmock|isl|json)/)'
+ Priority: 3
+ CaseSensitive: true
+ - Regex: '<[[:alnum:].]+>'
+ Priority: 4
+ CaseSensitive: true
+ - Regex: '.*'
+ Priority: 1
+ SortPriority: 0
+ CaseSensitive: true
+# 判断头文件是否为相关的头文件,用于排序
+# 如 a.cpp 与 a.h,设置为 a.cpp/a_test.cpp
+IncludeIsMainRegex: '(_test)?$'
+# 判断头文件是否包含实现,用于排序
+IncludeIsMainSourceRegex: '(*\.hpp)$'
+# 访问控制符缩进,禁用
+IndentAccessModifiers: false
+# case 块缩进,禁用
+IndentCaseBlocks: false
+# case 标签缩进
IndentCaseLabels: true
-IndentGotoLabels: true
-IndentPPDirectives: None
-IndentWidth: 4
+# extern 块缩进,与 BraceWrapping.AfterExternBlock 共同生效
+IndentExternBlock: AfterExternBlock
+# 缩进 goto 标签,禁用
+IndentGotoLabels: false
+# 缩进预处理,在 # 后缩进
+IndentPPDirectives: AfterHash
+# 缩进 requires
+IndentRequiresClause: true
+# 缩进宽度
+IndentWidth: 4
+# 函数返回类型换行时,缩进函数声明/函数定义的函数名,禁用
IndentWrappedFunctionNames: false
-JavaScriptQuotes: Leave
-JavaScriptWrapImports: true
-KeepEmptyLinesAtTheStartOfBlocks: true
-MacroBlockBegin: ''
-MacroBlockEnd: ''
+# 自动插入大括号
+InsertBraces: true
+# 保留在块开始处的空行,禁用
+KeepEmptyLinesAtTheStartOfBlocks: false
+# lambda 表达式函数体缩进
+LambdaBodyIndentation: OuterScope
+# 语言,设置语言为 c++
+Language: Cpp
+
+# 开始一个块的宏的正则表达式
+MacroBlockBegin: "^MACRO_BEGIN|NS_TABLE_HEAD$"
+# 结束一个块的宏的正则表达式
+MacroBlockEnd: "^MACRO_END|NS_TABLE_.*_END$"
+# 最大连续空行
MaxEmptyLinesToKeep: 1
+# namespace 缩进,禁用
NamespaceIndentation: None
-ObjCBinPackProtocolList: Auto
-ObjCBlockIndentWidth: 2
-ObjCSpaceAfterProperty: false
-ObjCSpaceBeforeProtocolList: true
+# namespace 宏
+NamespaceMacros: [ 'NAMESPACE' ]
+# 预处理缩进,-1 表示使用默认值 IndentWidth
+PPIndentWidth: -1
+# 如果构造函数的初始化列表超过一行则换行
+PackConstructorInitializers: NextLine
+
+# 有些情况下你会觉得怎么排版都达不到完美,
+# 只能各方面妥协一下(例如你限定了行宽,但注释想放宽松点允许超一些)。
+# penalty 简单来说就是給每一次“违规”设定一个罚分,
+# clang-format 帮你选择最终吃到的总罚分比较少的策略。
+# 在赋值前后换行时的罚分
+# @see https://www.zhihu.com/question/438473572/answer/1668773325
+# 在赋值前后打断的罚分
PenaltyBreakAssignment: 2
+# 在函数调用 fun( 后打断的罚分
PenaltyBreakBeforeFirstCallParameter: 19
+# 在注释中换行的罚分
PenaltyBreakComment: 300
+# 在第一个 << 点打断的罚分
PenaltyBreakFirstLessLess: 120
+# 在 ( 后打断的罚分
+PenaltyBreakOpenParenthesis: 100
+# 在字符串常量中换行的罚分
PenaltyBreakString: 1000
+# 在模版声明后打断的罚分
PenaltyBreakTemplateDeclaration: 10
+# 注释的每个字符超出 ColumnLimit 的罚分
PenaltyExcessCharacter: 1000000
-PenaltyReturnTypeOnItsOwnLine: 60
-PointerAlignment: Right
-ReflowComments: true
-SortIncludes: false
+# 每个空格缩进的罚分,
+# counted relative to leading non-whitespace column
+PenaltyIndentedWhitespace: 0
+# 函数返回类型单独成行的罚分
+PenaltyReturnTypeOnItsOwnLine: 0
+# 指针和引用对齐,左对齐
+PointerAlignment: Left
+# 修饰符对齐,由 QualifierOrder 指定
+QualifierAlignment: Custom
+# 修饰符顺序
+QualifierOrder: [ 'inline', 'static', 'const', 'volatile','type' ]
+# 将字符串格式化,与 ProtocolBuffers 配合使用,未使用
+RawStringFormats:
+ - Language: Cpp
+ BasedOnStyle: InheritParentConfig
+ Delimiters: [ pb ]
+# 引用对齐,与 PointerAlignment 相同
+ReferenceAlignment: Pointer
+# 重新排版注释
+ReflowComments: true
+# requires 位置,单独成行
+RequiresClausePosition: OwnLine
+# 在定义块之间添加空行,总是添加
+SeparateDefinitionBlocks: Always
+# 设置短 namespace 长度,0 表示将所有 namespace 视为 short namespace
+ShortNamespaceLines: 0
+# 排序 #include,按照字母序
+SortIncludes: CaseInsensitive
+# 排序 using 声明
SortUsingDeclarations: true
+# 在 C 风格类型转换后添加空格,禁用
SpaceAfterCStyleCast: false
+# 在逻辑非 ! 后添加空格,禁用
SpaceAfterLogicalNot: false
+# 在 template 后添加空格
SpaceAfterTemplateKeyword: true
+# 在指针修饰符周围添加空格,使用 PointerAlignment
+SpaceAroundPointerQualifiers: Default
+# 在赋值运算符之前添加空格
SpaceBeforeAssignmentOperators: true
-SpaceBeforeCpp11BracedList: false
+# 在 case 的 : 前添加空格,禁用
+SpaceBeforeCaseColon: false
+# 在 c++11 大括号初始化前添加空格
+SpaceBeforeCpp11BracedList: true
+# 在构造函数初始化列表 : 前添加空格
SpaceBeforeCtorInitializerColon: true
+# 在继承 : 前添加空格
SpaceBeforeInheritanceColon: true
-SpaceBeforeParens: ControlStatements
+# 在 ( 前添加空格,由 SpaceBeforeParensOptions 指定
+SpaceBeforeParens: Custom
+# 在 ( 前添加空格的规则
+SpaceBeforeParensOptions:
+ # 在控制语句后添加
+ AfterControlStatements: true
+ # 在 for-each 宏后添加,禁用
+ AfterForeachMacros: false
+ # 在函数声明后添加,禁用
+ AfterFunctionDeclarationName: false
+ # 在函数定义后添加,禁用
+ AfterFunctionDefinitionName: false
+ # 在 if 宏后添加,禁用
+ AfterIfMacros: false
+ # 在重载运算符后添加,禁用
+ AfterOverloadedOperator: false
+ # 在 requires 后添加
+ AfterRequiresInClause: true
+ # 在表达式中的 requires 后添加,禁用
+ AfterRequiresInExpression: false
+ # 在非空的 () 前添加,禁用
+ BeforeNonEmptyParentheses: false
+# 在范围 for 循环 : 前添加空格
SpaceBeforeRangeBasedForLoopColon: true
-SpaceInEmptyBlock: false
+# 在 [ 前添加空格,禁用
+SpaceBeforeSquareBrackets: false
+# 在空 {} 中添加空格
+SpaceInEmptyBlock: true
+# 在空的圆括号中添加空格,禁用
SpaceInEmptyParentheses: false
-SpacesBeforeTrailingComments: 1
-SpacesInAngles: false
+# 在行后注释前添加空格(只适用于 //)
+SpacesBeforeTrailingComments: 4
+# 在尖括号的 < 后和 > 前添加空格,禁用
+SpacesInAngles: Never
+# 在 C 风格类型转换的括号中添加空格,禁用
+SpacesInCStyleCastParentheses: false
+# 在条件判断中 ( 后 ) 前添加空格,禁用
SpacesInConditionalStatement: false
+# 在容器字面量中添加空格
SpacesInContainerLiterals: true
-SpacesInCStyleCastParentheses: false
+# 行注释前缀中的空格
+SpacesInLineCommentPrefix:
+ # 最大值
+ Maximum: 1
+ # 最小值
+ Minimum: 1
+# 在 ( 后和 ) 前添加空格,禁用
SpacesInParentheses: false
+# 在 [ 后和 ] 前添加空格,lamda 表达式和未指明大小的数组的声明不受影响,禁用
SpacesInSquareBrackets: false
-SpaceBeforeSquareBrackets: false
-Standard: Latest
-StatementMacros:
- - Q_UNUSED
- - QT_REQUIRE_VERSION
-TabWidth: 8
-UseCRLF: false
-UseTab: Never
+# cpp 标准,使用最新支持的
+Standard: Latest
+# 需要识别为宏的代码块前缀
+StatementAttributeLikeMacros: [ ]
+# 需要解释为完整代码段的宏
+StatementMacros: [ ]
+# tab 宽度,8 个空格
+TabWidth: 8
+# 需要识别为宏,而不是函数调用的宏
+TypenameMacros: [ ]
+# 使用 \r\n 换行符,与 DeriveLineEnding 共同生效,禁用
+UseCRLF: false
+# 使用 tab,禁用
+UseTab: Never
+# 对空格敏感的宏
+WhitespaceSensitiveMacros: [ ]
...
-
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 08eb5facb..644cf33b7 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -25,7 +25,7 @@ jobs:
shell: bash
run: |
brew install x86_64-elf-gcc
- brew tap riscv/riscv
+ brew tap riscv-software-src/riscv
brew install riscv-tools
- name: make build dir
diff --git a/.gitignore b/.gitignore
index fb7330002..6730d4eb5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,16 +1,14 @@
-# This file is a part of Simple-XX/SimpleKernel (https://github.com/Simple-XX/SimpleKernel).
+# This file is a part of Simple-XX/SimpleKernel
+# (https://github.com/Simple-XX/SimpleKernel).
#
# .gitinnore for Simple-XX/SimpleKernel.
-bochsout.txt
*.o
*.gch
*.tags*
.DS_Store
-build
-cmake-build-debug
-cmake-build-debug_simplekernel
+build*
grub-2.04.tar.xz
grub-2.04
tools/opensbi
@@ -20,3 +18,5 @@ iso
*.bin
null.d
tools/aarch64-unknown-linux-gnu*
+.gdbinit
+tools/opensbi/build
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index f45008db4..000000000
--- a/.gitmodules
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "tools/opensbi"]
- path = tools/opensbi
- url = https://github.com/riscv/opensbi.git
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 000000000..13566b81b
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/SimpleKernel.iml b/.idea/SimpleKernel.iml
new file mode 100644
index 000000000..f08604bb6
--- /dev/null
+++ b/.idea/SimpleKernel.iml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/.idea/cmake.xml b/.idea/cmake.xml
new file mode 100644
index 000000000..921664e6e
--- /dev/null
+++ b/.idea/cmake.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 000000000..249efa28a
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 000000000..79ee123c2
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/dictionaries/SimpleKernel_dir.xml b/.idea/dictionaries/SimpleKernel_dir.xml
new file mode 100644
index 000000000..2a7f9ade7
--- /dev/null
+++ b/.idea/dictionaries/SimpleKernel_dir.xml
@@ -0,0 +1,16 @@
+
+
+
+ bochsrc
+ corei
+ imafdc
+ lriscv
+ opensbi
+ readelf
+ simplekernel
+ syms
+ xlen
+ xorriso
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 000000000..97626ba45
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/git_toolbox_prj.xml b/.idea/git_toolbox_prj.xml
new file mode 100644
index 000000000..12ce1b3ad
--- /dev/null
+++ b/.idea/git_toolbox_prj.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 000000000..6b29ddf9f
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 000000000..79b3c9483
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 000000000..18309178f
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/kernel.xml b/.idea/runConfigurations/kernel.xml
new file mode 100644
index 000000000..66eb96783
--- /dev/null
+++ b/.idea/runConfigurations/kernel.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/make_i386_iso.xml b/.idea/runConfigurations/make_i386_iso.xml
new file mode 100644
index 000000000..d49cdd9f9
--- /dev/null
+++ b/.idea/runConfigurations/make_i386_iso.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/make_x86_64_iso.xml b/.idea/runConfigurations/make_x86_64_iso.xml
new file mode 100644
index 000000000..488560a44
--- /dev/null
+++ b/.idea/runConfigurations/make_x86_64_iso.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/qemu_i386_debug.xml b/.idea/runConfigurations/qemu_i386_debug.xml
new file mode 100644
index 000000000..aec032588
--- /dev/null
+++ b/.idea/runConfigurations/qemu_i386_debug.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/qemu_riscv64_debug.xml b/.idea/runConfigurations/qemu_riscv64_debug.xml
new file mode 100644
index 000000000..9ad3329d8
--- /dev/null
+++ b/.idea/runConfigurations/qemu_riscv64_debug.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/qemu_x86_64_debug.xml b/.idea/runConfigurations/qemu_x86_64_debug.xml
new file mode 100644
index 000000000..fcd6dcd30
--- /dev/null
+++ b/.idea/runConfigurations/qemu_x86_64_debug.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/scopes/src.xml b/.idea/scopes/src.xml
new file mode 100644
index 000000000..91d064d56
--- /dev/null
+++ b/.idea/scopes/src.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/.idea/tool_settings.zip b/.idea/tool_settings.zip
new file mode 100644
index 000000000..47ca8c075
Binary files /dev/null and b/.idea/tool_settings.zip differ
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 000000000..683e670e8
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 94577b97d..0afda3e62 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,12 +1,12 @@
# This file is a part of Simple-XX/SimpleKernel
# (https://github.com/Simple-XX/SimpleKernel).
-# Based on https://github.com/SynestiaOS/SynestiaOS
+#
# CMakeLists.txt for Simple-XX/SimpleKernel.
# CMake 入口
# 设置最小 cmake 版本
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.13)
# 跳过编译器检查
set(CMAKE_C_COMPILER_WORKS TRUE)
diff --git a/cmake/toolchain_linux_aarch64.cmake b/cmake/toolchain_linux_aarch64.cmake
index 5da6961f3..00c7c5885 100644
--- a/cmake/toolchain_linux_aarch64.cmake
+++ b/cmake/toolchain_linux_aarch64.cmake
@@ -1,5 +1,6 @@
-# This file is a part of Simple-XX/SimpleKernel (https://github.com/Simple-XX/SimpleKernel).
+# This file is a part of Simple-XX/SimpleKernel
+# (https://github.com/Simple-XX/SimpleKernel).
#
# toolchain_linux_aarch64.cmake for Simple-XX/SimpleKernel.
@@ -11,13 +12,13 @@ set(CMAKE_SYSTEM_PROCESSOR AARCH64)
# GCC
find_program(GCC aarch64-none-eabi-gcc)
if (NOT GCC)
- message(FATAL_ERROR "aarch64-none-eabi-gcc not found.\n"
- "Run `brew install aarch64-none-eabi-gcc` to install the toolchain")
+ message(FATAL_ERROR "gcc-aarch64-linux-gnu not found.\n"
+ "Run `sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu` to install.")
else ()
- message(STATUS "Found aarch64-none-eabi-gcc ${GCC}")
+ message(STATUS "Found gcc-aarch64-linux-gnu ${GCC}")
endif ()
-set(TOOLCHAIN_PREFIX aarch64-none-eabi-)
+set(TOOLCHAIN_PREFIX aarch64-linux-gnu-)
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++)
set(CMAKE_READELF ${TOOLCHAIN_PREFIX}readelf)
@@ -31,7 +32,7 @@ set(CMAKE_RANLIB ${TOOLCHAIN_PREFIX}ranlib)
find_program(QEMU qemu-system-aarch64)
if (NOT QEMU)
message(FATAL_ERROR "qemu not found.\n"
- "Please install qemu first.")
+ "Run `sudo apt-get install -y qemu-system` to install.")
else ()
message(STATUS "Found qemu ${QEMU}")
endif ()
diff --git a/cmake/toolchain_linux_riscv.cmake b/cmake/toolchain_linux_riscv.cmake
index cca928e3c..def485301 100644
--- a/cmake/toolchain_linux_riscv.cmake
+++ b/cmake/toolchain_linux_riscv.cmake
@@ -1,5 +1,6 @@
-# This file is a part of Simple-XX/SimpleKernel (https://github.com/Simple-XX/SimpleKernel).
+# This file is a part of Simple-XX/SimpleKernel
+# (https://github.com/Simple-XX/SimpleKernel).
#
# toolchain_linux_riscv.cmake for Simple-XX/SimpleKernel.
@@ -11,7 +12,7 @@ set(CMAKE_SYSTEM_PROCESSOR RISCV)
find_program(RISCV riscv64-linux-gnu-g++)
if (NOT RISCV)
message(FATAL_ERROR "riscv64-linux-gnu-gcc not found.\n"
- "Run `sudo apt-get install -y gcc-riscv64-linux-gnu g++-riscv64-linux-gnu` to install the toolchain. Then add the bin path to you PATH.")
+ "Run `sudo apt-get install -y gcc-riscv64-linux-gnu g++-riscv64-linux-gnu` to install.")
else ()
message(STATUS "Found riscv64-linux-gnu-gcc ${RISCV}.")
endif ()
@@ -30,7 +31,7 @@ set(CMAKE_RANLIB ${TOOLCHAIN_PREFIX}ranlib)
find_program(QEMU qemu-system-riscv64)
if (NOT QEMU)
message(FATAL_ERROR "qemu not found.\n"
- "Please install qemu-system-riscv64 first.")
+ "Run `sudo apt-get install -y qemu-system` to install.")
else ()
message(STATUS "Found qemu ${QEMU}")
endif ()
diff --git a/cmake/toolchain_linux_x86_64.cmake b/cmake/toolchain_linux_x86_64.cmake
index 30f61543d..67df794bf 100644
--- a/cmake/toolchain_linux_x86_64.cmake
+++ b/cmake/toolchain_linux_x86_64.cmake
@@ -1,5 +1,6 @@
-# This file is a part of Simple-XX/SimpleKernel (https://github.com/Simple-XX/SimpleKernel).
+# This file is a part of Simple-XX/SimpleKernel
+# (https://github.com/Simple-XX/SimpleKernel).
#
# toolchain_linux_x86_64.cmake for Simple-XX/SimpleKernel.
@@ -11,7 +12,7 @@ set(CMAKE_SYSTEM_PROCESSOR x86_64)
find_program(G++ g++)
if (NOT G++)
message(FATAL_ERROR "g++ not found.\n"
- "Run `sudo apt-get install -y gcc g++` to install the toolchain")
+ "Run `sudo apt-get install -y gcc g++` to install.")
else ()
message(STATUS "Found g++ ${G++}")
endif ()
@@ -20,7 +21,7 @@ endif ()
find_program(XORRISO xorriso)
if (NOT XORRISO)
message(FATAL_ERROR "xorriso not found.\n"
- "Run `sudo apt-get install -y xorriso` to install the toolchain")
+ "Run `sudo apt-get install -y xorriso` to install.")
else ()
message(STATUS "Found xorriso ${XORRISO}")
endif ()
@@ -29,25 +30,16 @@ endif ()
find_program(GRUB grub-file)
if (NOT GRUB)
message(FATAL_ERROR "grub-file not found.\n"
- "Please install grub2 common first.")
+ "Run `sudo apt-get install -y grub2` to install.")
else ()
message(STATUS "Found grub-file ${GRUB}")
endif ()
-# bochs
-find_program(BOCHS bochs)
-if (NOT BOCHS)
- message(FATAL_ERROR "bochs not found.\n"
- "Please install bochs and bochs-x first.")
-else ()
- message(STATUS "Found bochs ${BOCHS}")
-endif ()
-
# qemu
find_program(QEMU qemu-system-x86_64)
if (NOT QEMU)
message(FATAL_ERROR "qemu not found.\n"
- "Please install qemu first.")
+ "Run `sudo apt-get install -y qemu-system` to install.")
else ()
message(STATUS "Found qemu ${QEMU}")
endif ()
diff --git a/cmake/toolchain_mac_riscv.cmake b/cmake/toolchain_mac_riscv.cmake
index 1b4484a36..0f054bdac 100644
--- a/cmake/toolchain_mac_riscv.cmake
+++ b/cmake/toolchain_mac_riscv.cmake
@@ -19,7 +19,7 @@ endif ()
find_program(RISCV riscv64-unknown-elf-gcc)
if (NOT RISCV)
message(FATAL_ERROR "riscv64-unknown-elf-gcc not found.\n"
- "Run `brew tap riscv/riscv` and `brew install riscv-tools` to install the toolchain. Then add the bin path to you PATH.")
+ "Run `brew tap riscv-software-src/riscv` and `brew install riscv-tools` to install the toolchain. Then add the bin path to you PATH.")
else ()
message(STATUS "Found riscv64-unknown-elf-gcc ${RISCV}.")
endif ()
diff --git a/cmake/toolchain_mac_x86_64.cmake b/cmake/toolchain_mac_x86_64.cmake
index 70faec222..b9ff72f15 100644
--- a/cmake/toolchain_mac_x86_64.cmake
+++ b/cmake/toolchain_mac_x86_64.cmake
@@ -52,15 +52,6 @@ else ()
message(STATUS "Found grub-file ${GRUB}")
endif ()
-# bochs
-find_program(BOCHS bochs)
-if (NOT BOCHS)
- message(FATAL_ERROR "bochs not found.\n"
- "run `brew install bochs` to install the toolchain")
-else ()
- message(STATUS "Found bochs ${BOCHS}")
-endif ()
-
# qemu
find_program(QEMU qemu-system-x86_64)
if (NOT QEMU)
diff --git "a/docs/0_\345\267\245\345\205\267\351\223\276.md" "b/docs/0_\345\267\245\345\205\267\351\223\276.md"
index 7332179b4..3e1b3ed00 100644
--- "a/docs/0_\345\267\245\345\205\267\351\223\276.md"
+++ "b/docs/0_\345\267\245\345\205\267\351\223\276.md"
@@ -8,38 +8,19 @@ SimpleKernel 为了保证在各个平台上的可用性,选择了较为通用
2. 内核的编译
- 使用 g++, ld 进行编译与链接
+ 使用 GCC 工具链
-3. 虚拟机
+3. 模拟器
- 对于 x86/x86_64 架构,使用 bochs
+ 对于 x86/x86_64 架构,支持 bochs 与 qemu
- 对于其它架构,使用 qemu
+ arm/aarch64/riscv64 架构,使用 qemu
4. 辅助脚本
- 在根目录下的 run.sh/run.py 属于此类,此外还有 tools/ 目录下的 *.sh
-
-
-
-## GCC
-
-GCC 需要根据目标平台与宿主机进行配置,即 target 与 host。
-
-一般而言,网上有编译好的可以直接拿来用。
-
-以 target=riscv64,host=osx 为例,可以在 https://github.com/riscv/homebrew-riscv 找到现成的,只需要按照说明使用 brew 安装即可。
-
-对于特殊情况,可能需要自己手动编译 gcc,大致步骤如下[^1]:
-
-1. 安装依赖
-2. 下载源码
-3. 配置
-4. 编译
-
-其中比较重要的地方是第三步,需要根据需要进行配置,你可以参考 tools/x86_64-elf-gcc.sh 的内容进行编译。
-
+ 主要用于环境变量管理,如 `./run.sh` 是用来编译并运行内核,`./tools/env.sh` 则规定了需要的参数。
+ 此外还有模拟器配置,如 `./bochsrc_linux.txt`
## CMake
@@ -47,66 +28,86 @@ CMake 可以分为两个部分
1. 主要 cmake 规则
- 所有 CMakeLists.txt 文件,规定了内核的编译方式。其中
+ 所有 CMakeLists.txt 文件,规定了内核的编译方式。
- - /CMakeLists.txt
+ - ./CMakeLists.txt
- 设置了一些 CMake 选项,并在最后通过 `add_subdirectory(${SimpleKernel_SOURCE_CODE_DIR})` 将控制权转移到 src/CMakeLists.txt
+ 设置了一些 CMake 选项,并在最后通过 `add_subdirectory(${SimpleKernel_SOURCE_CODE_DIR})` 将控制权转移到 ./src/CMakeLists.txt
- - src/CMakeLists.txt
+ - ./src/CMakeLists.txt
规定了 gcc 的编译选项,指定生成的二进制文件名称,并规定生成二进制文件所需的模块
- - src/*/CMakeLists.txt
+ - ./src/*/CMakeLists.txt
各个模块的编译规则
2. 辅助 cmake 规则
- 用于辅助主要规则,保存在 /cmake 目录下
+ 用于辅助主要规则,保存在 ./cmake 目录下
- toolchain_*.cmake 用于判断依赖是否已安装
- header_files.cmake 用于添加头文件
- - find_asm_files.cmake 用于讲汇编文件添加到编译列表
+ - find_asm_files.cmake 用于将汇编文件添加到编译列表
- arch_detector.cmake 用于判断目标架构
更多细节请查看注释。
+项目地址:[CMake](https://cmake.org)
+## GCC
-## BOCHS
+GCC 需要根据目标平台与宿主机进行配置,即 target 与 host。
-bochs 是专门用于 x86/x86_64 的虚拟机。
+一般而言,网上有编译好的可以直接拿来用。
-tools/bochsrc_*.txt 规定了虚拟机的一些选项
+以 target=riscv64,host=osx 为例,可以在 `https://github.com/riscv/homebrew-riscv` 找到现成的,只需要按照说明安装即可。
-tools/bochsinit 规定在虚拟机启动后执行的命令
+对于特殊情况,可能需要自己手动编译 gcc,大致步骤如下[^1]:
-更多细节请查看注释
+1. 安装依赖
+2. 下载源码
+3. 配置
+4. 编译
+其中比较重要的地方是第三步,需要根据需要进行配置,你可以参考 ./tools/x86_64-elf-gcc.sh 的内容进行编译。
+项目地址:[GCC, the GNU Compiler Collection - GNU Project](https://gcc.gnu.org)
-## QEMU
+## bochs
+
+bochs 是专门用于 x86/x86_64 的虚拟机。
+
+./tools/bochsrc_*.txt 规定了虚拟机的配置选项
+
+./tools/bochsinit 规定在虚拟机启动后执行的命令
+
+项目地址:[bochs: The Open Source IA-32 Emulation Project (Home Page)](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwibsOK5v5b4AhUFD0QIHTX-BS4QFnoECBMQAQ&url=https%3A%2F%2Fbochs.sourceforge.io%2F&usg=AOvVaw22vn_4SPHPDYUk_NoYgyP2)
+
+更多细节请查看注释
+
+## qemu
qemu 是支持范围更大的虚拟机,支持多种架构。
+安装:
+项目地址:[QEMU](https://www.qemu.org)
## 辅助脚本
-- tools/env.sh
+- ./tools/env.sh
设置目标架构,并根据设置的目标架构初始化相关变量。
更多细节请查看注释。
-- run.sh
+- ./run.sh
根据 tools/env.sh 的设置在虚拟机中运行内核。
更多细节请查看注释。
-
## 相关文档
@@ -117,4 +118,3 @@ arm 工具链:https://developer.arm.com/tools-and-software/open-source-softwar
riscv 工具链:https://github.com/riscv/riscv-gnu-toolchain
[^1]: https://gcc.gnu.org/install/
-
diff --git "a/docs/1.5_cpp\347\232\204\345\210\235\345\247\213\345\214\226.md" "b/docs/1.5_cpp\347\232\204\345\210\235\345\247\213\345\214\226.md"
index e64acea6d..e5d984404 100644
--- "a/docs/1.5_cpp\347\232\204\345\210\235\345\247\213\345\214\226.md"
+++ "b/docs/1.5_cpp\347\232\204\345\210\235\345\247\213\345\214\226.md"
@@ -1,21 +1,19 @@
# SimpleKernel cpp 的初始化
-Simplekernel 主要是用 C++ 完成的,为了最大化 C++ 的优势,得对 C++ 的一些基础设施进行初始化。
+Simplekernel 主要是用 C++ 完成的,为了最大化 C++ 的优势,需要对 C++ 的一些基础设施进行初始化。
这一工作大致分为两部分。
## cxxabi
-cxxabi 是 C++ 特性的支持者,一些特性必须由 cxxabi 实现后才能使用。
+cxxabi 是 C++ 特性的基础,一些特性必须由 cxxabi 实现后才能使用。
-在 src/libcxx/include/cxxabi.h 与 src/libcxx/cxxabi.cpp 两个文件中定义了相关数据与函数。在链接阶段将这些定义链接上就可以正常使用相关特性了。
+在 ./src/libcxx/include/cxxabi.h 与 ./src/libcxx/cxxabi.cpp 两个文件中定义了相关数据与函数,链接阶段将这些定义链接上就可以正常使用相关特性了。
-这部分不进行深究,水太深了。
+这部分不进行深究,相关资料:[cxxabi-1.86](http://refspecs.linux-foundation.org/cxxabi-1.86.html)
## 全局对象的构造
-另一个重点是全局对象的构造。
-
在通常场景下,C++ 的全局对象会在进入 main 函数之前进行构造,在 main 返回后析构。在内核里也是一样,我们需要在进入 kernel_main 之前完成构造,不同的是我们不需要考虑析构问题,因为内核是不会返回的,当它结束的时候意味着关机了。
编译器在链接时,会将所有的全局对象的构造函数函数指针收集在一起,放在一个名为 `.init_array` 的段中,在 src/arch/*/link.ld 中,有这么一段规则:
@@ -40,9 +38,9 @@ cxxabi 是 C++ 特性的支持者,一些特性必须由 cxxabi 实现后才能
}
```
-这部分规定将构造函数放在 .rodata 段里,并将这段内存用 `ctors_start` 和 `ctors_end` 两个地址进行标识,以便在代码中访问。
+这部分规定将构造函数放在 `.rodata` 段里,并将这段内存用 `ctors_start` 和 `ctors_end` 两个地址进行标识,以便在代码中访问。
-初始化由 `cpp_init` 执行,定义在 src/libcxx/src/cxxabi.cpp 中
+初始化由 `cpp_init` 执行,定义在 ./src/libcxx/src/cxxabi.cpp 中
```c++
typedef void (*ctor_t)(void);
@@ -59,12 +57,8 @@ void cpp_init(void) {
遍历这一区域的所有函数并执行,这样就完成了全局对象的构造。
-
-
更多细节请查看注释。
-
-
## 相关文档
https://wiki.osdev.org/C++
diff --git "a/docs/1_\347\263\273\347\273\237\345\220\257\345\212\250.md" "b/docs/1_\347\263\273\347\273\237\345\220\257\345\212\250.md"
index ebfd17827..7c03a1c72 100644
--- "a/docs/1_\347\263\273\347\273\237\345\220\257\345\212\250.md"
+++ "b/docs/1_\347\263\273\347\273\237\345\220\257\345\212\250.md"
@@ -1,14 +1,12 @@
# SimpleKernel 启动
-内核实际上也是一个程序,它从链接脚本规定的入口点(`ENTRY(_start)`)开始执行,但在这一步之前,还得让硬件知道 `_start` 的位置,这一步骤 SImpleKernel 使用了一些开源的引导程序来辅助这一过程,你可以在 osdev 看看具体的流程[^1],这里就不再赘述。
-
-
+内核实际上也是一个程序,它从链接脚本规定的入口点(`ENTRY(_start)`)开始执行,但在这一步之前,还得让硬件知道 `_start` 的位置,这一步骤 SImpleKernel 使用了一些开源的引导程序来辅助这一过程,你可以在 osdev 看看具体的流程[^1],这里不再赘述。
## IA32
-IA32 包括 i386(或 x86) 与 x86_64,它们有着相似的结构,区别在于 i386 是 32 位,而 x86_64 是 64 位。
+IA32 包括 i386(或 x86) 与 x86_64,它们在细节上有部分区别。
-SimpleKernel 使用 Grub2 进行辅助,跳过与机器打交道的部分,由 grub2 进行最最开始的设置,我们只需要处理从 `_start` 开始的代码即可。
+SimpleKernel 使用 grub2 进行辅助,跳过与机器打交道的部分,由 grub2 进行最最开始的设置,我们只需要处理从 `_start` 开始的代码即可。
相比其它架构,IA32 有太多历史包袱,这导致它的启动过程比较麻烦,尤其是实模式(16bit),保护模式(32bit),以及长模式(64bit)的切换十分复杂。幸运的是,grub2 已经帮我们进入了保护模式,这使得我们可以暂时跳过相关模式的设置。
@@ -25,7 +23,7 @@ SimpleKernel 使用 Grub2 进行辅助,跳过与机器打交道的部分,由
```assembly
// 声明这一段代码以 32 位模式编译
.code32
-
+
// multiboot2 文件头
// 计算头长度
.SET HEADER_LENGTH, multiboot_header_end - multiboot_header
@@ -52,15 +50,15 @@ SimpleKernel 使用 Grub2 进行辅助,跳过与机器打交道的部分,由
multiboot_header_end:
```
- 只要在内核开始部分检测到符合这种布局的数据,就认为这是一个符合 multiboot2 规范的内核,引导程序会在对硬件进行初始化后将控制权交给 `_start`
+ 只要在内核开始部分检测到符合 multiboot2 规定的数据,就认为这是一个符合规范的内核,引导程序会在对硬件进行初始化后将控制权交给 `_start`
- x86
由于 grub 已经进入了保护模式,我们不需要做什么多余的事情,在设置栈指针后直接进入 C 函数 `kernel_main` 执行即可。
- - 运行逻辑
+ - 执行流
- 虚拟机-grub2-(_start)boot.S-kernel_main(kernel_main.cpp)
+ 模拟器 -> grub2 -> _start(boot.S ) -> kernel_main(kernel_main.cpp)
- x86_64
@@ -68,8 +66,6 @@ SimpleKernel 使用 Grub2 进行辅助,跳过与机器打交道的部分,由
更多细节请查看注释。
-
-
## RISCV
riscv 相较 IA32 非常新,其标准至今还在更新,它没有 IA32 那么多的遗留问题与设计冗余,所以简单不少。
@@ -82,18 +78,15 @@ riscv 相较 IA32 非常新,其标准至今还在更新,它没有 IA32 那
同样,在设置栈地址后跳转到 `kernel_main` 执行。
-- 运行逻辑
+- 执行流
- 虚拟机->opensbi->_start(boot.S)->kernel_main(kernel_main.cpp)
+ 模拟器 -> opensbi -> _start(boot.S) -> kernel_main(kernel_main.cpp)
更多细节请查看注释。
-
-
## 相关文档
[^1]: https://wiki.osdev.org/Bare_Bones
[^2]: https://www.gnu.org/software/grub/manual/grub/grub.html
[^3]: https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html
[^4]: https://github.com/riscv/opensbi
-
diff --git "a/docs/2_\345\237\272\346\234\254\350\276\223\345\207\272.md" "b/docs/2_\345\237\272\346\234\254\350\276\223\345\207\272.md"
index 3c62400f3..fc9a002fb 100644
--- "a/docs/2_\345\237\272\346\234\254\350\276\223\345\207\272.md"
+++ "b/docs/2_\345\237\272\346\234\254\350\276\223\345\207\272.md"
@@ -6,11 +6,15 @@
- 相关代码
- src/include/io.h
+ ./src/include/io.h
- src/kernel/io.cpp
+ ./src/kernel/io.cpp
+ ./src/drv/sbi_console,riscv 架构使用下基于 opensbi 的串口输出
+ ./src/drv/tui,IA32 下使用的 text user interface 输出
+
+ ./src/drv/uart,通用 uart 输出
## IA32
@@ -55,11 +59,45 @@ IA32 提供了一套名为 TUI(text user interface) 的东西,它允许我们
要在屏幕上输出字符,需要向地址 0xB8000 写入数据,数据格式为
```c++
- struct {
- uint8_t c;
+ /**
+ * @brief 颜色信息
+ */
+ class col_t {
+ public:
+ /**
+ * @brief 构造一个颜色对象
+ * @param _fore 前景色
+ * @param _back 背景色
+ */
+ col_t(const COLOR::color_t _fore, const COLOR::color_t _back);
+
+ ~col_t(void);
+ // 前景色
uint8_t fore : 4;
+ // 背景色
uint8_t back : 4;
};
+
+ /**
+ * @brief 内存中的字符对象
+ */
+ class char_t {
+ public:
+ char_t(void);
+
+ /**
+ * @brief 构造一个内存中的字符对象
+ * @param _c 字符
+ * @param _color 颜色
+ */
+ char_t(const uint8_t _c, const col_t _color);
+
+ ~char_t(void);
+ // 字符
+ uint8_t c;
+ // 颜色
+ col_t color;
+ };
```
共计 2 字节大小。
@@ -80,40 +118,121 @@ IA32 提供了一套名为 TUI(text user interface) 的东西,它允许我们
- 相关代码
- src/include/color.h
-
- src/drv/tui/include/tui.h
-
- src/drv/tui/tui.cpp
+ ./src/include/color.h
+ ./src/drv/tui/include/tui.h
+ ./src/drv/tui/tui.cpp
更多细节请查看注释。
-
-
## RISCV
-riscv 通过 UART 进行输出,但我们并不需要自己写 UART 驱动,opensbi 提供了线程的接口,直接调用即可。
+riscv 通过 uart 进行输出,但我们并不需要自己写 uart 驱动,opensbi 提供了现成的接口,直接调用即可。
+
+```c++
+void OPENSBI::put_char(const char _c) {
+ ecall(_c, 0, 0, 0, 0, 0, FID_CONSOLE_PUTCHAR, EID_CONSOLE_PUTCHAR);
+ return;
+}
+```
+
+- 颜色设置
+
+ 由于实际使用的是串口,所以可以通过控制字符来实现对颜色的控制
+ ```c++
+ void SBI_CONSOLE::set_color(const COLOR::color_t _color) const {
+ // 根据 _color 构造字符串
+ char *tmp = nullptr;
+ switch (_color) {
+ case COLOR::BLACK: {
+ tmp = (char *)"\033[30m";
+ break;
+ }
+ case COLOR::RED: {
+ tmp = (char *)"\033[31m";
+ break;
+ }
+ case COLOR::GREEN: {
+ tmp = (char *)"\033[32m";
+ break;
+ }
+ case COLOR::YELLOW: {
+ tmp = (char *)"\033[33m";
+ break;
+ }
+ case COLOR::BLUE: {
+ tmp = (char *)"\033[34m";
+ break;
+ }
+ case COLOR::PURPLE: {
+ tmp = (char *)"\033[35m";
+ break;
+ }
+ case COLOR::CYAN: {
+ tmp = (char *)"\033[36m";
+ break;
+ }
+ case COLOR::WHITE: {
+ tmp = (char *)"\033[37m";
+ break;
+ }
+ case COLOR::GREY: {
+ tmp = (char *)"\033[90m";
+ break;
+ }
+ case COLOR::LIGHT_RED: {
+ tmp = (char *)"\033[91m";
+ break;
+ }
+ case COLOR::LIGHT_GREEN: {
+ tmp = (char *)"\033[92m";
+ break;
+ }
+ case COLOR::LIGHT_YELLOW: {
+ tmp = (char *)"\033[93m";
+ break;
+ }
+ case COLOR::LIGHT_BLUE: {
+ tmp = (char *)"\033[94m";
+ break;
+ }
+ case COLOR::LIGHT_PURPLE: {
+ tmp = (char *)"\033[95m";
+ break;
+ }
+ case COLOR::LIGHT_CYAN: {
+ tmp = (char *)"\033[96m";
+ break;
+ }
+ case COLOR::LIGHT_WHITE: {
+ tmp = (char *)"\033[97m";
+ break;
+ }
+ }
+ // 写入
+ write_string(tmp);
+ color = _color;
+ return;
+ }
+ ```
+
+opensbi 接口文档:[riscv-sbi-doc](https://github.com/riscv-non-isa/riscv-sbi-doc/blob/master/riscv-sbi.adoc)
- 相关代码
- src/include/color.h
-
- src/drv/opensbi/include/opensbi.h
+ ./src/include/color.h
- src/drv/opensbi/opensbi.cpp
+ ./src/drv/opensbi/include/opensbi.h
- src/drv/sbi_console/include/sbi_console.h
-
- src/drv/sbi_console/sbi_console.cpp
+ ./src/drv/opensbi/opensbi.cpp
+ ./src/drv/sbi_console/include/sbi_console.h
+ ./src/drv/sbi_console/sbi_console.cpp
更多细节请查看注释。
-
-
## 相关文档
opensbi:https://github.com/riscv/opensbi
diff --git "a/docs/3_\350\247\243\346\236\220\345\220\257\345\212\250\344\277\241\346\201\257.md" "b/docs/3_\350\247\243\346\236\220\345\220\257\345\212\250\344\277\241\346\201\257.md"
index fe4202ea2..e5a9d2bd4 100644
--- "a/docs/3_\350\247\243\346\236\220\345\220\257\345\212\250\344\277\241\346\201\257.md"
+++ "b/docs/3_\350\247\243\346\236\220\345\220\257\345\212\250\344\277\241\346\201\257.md"
@@ -6,56 +6,222 @@
- 相关代码
- src/include/boot_info.h
-
- src/include/resource.h
-
+ ./src/include/boot_info.h
+ ./src/include/resource.h
## IA32
在启动时我们使用了 grub2+multiboot2 的方式进行引导,在同时还会为我们提供所需要的硬件信息。
-grub2 会通过 eax 和 ebx 两个寄存器将信息传递给我们,只需要在启动阶段保存它们,就能在后面进行解析,获取硬件信息。
+grub2 会通过 `eax` 和 `ebx` 两个寄存器将信息传递给我们,只需要在启动阶段保存它们,就能在后面进行解析,获取硬件信息。
multiboot2 使用迭代方法寻找所需信息,函数 `multiboot2_iter(bool (*_fun)(const iter_data_t *, void *), void *_data)` 提供了这一接口。
- 相关代码
- src/arch/ia32/i386/boot/boot.S
-
- src/drv/multiboot2/include/multiboot2.h
-
- src/drv/multiboot2/multiboot2.cpp
+ ./src/arch/ia32/i386/boot/boot.S
+ ./src/drv/multiboot2/include/multiboot2.h
+ ./src/drv/multiboot2/multiboot2.cpp
更多细节请查看注释。
-
-
## RISCV
-opensbi 会将 dtb 信息的地址传递给内核,原理与 multiboot2 相似,但能够提供更为丰富的信息,相应的,dtb 的解析也更为复杂。
-
-`void DTB::dtb_iter(uint8_t _cb_flags, bool (*_cb)(const iter_data_t *, void *), void * _data)` 函数提供了迭代功能。
+设备树(device tree)是嵌入式设备常用的硬件配置信息传递方式,在启动时,opensbi 会将设备树信息的地址传递给内核,
+
+```assembly
+.section .init
+.globl _start
+.type _start, @function
+.extern kernel_main
+.extern cpp_init
+.extern boot_info_addr
+.extern dtb_init_hart
+_start:
+ // 保存 sbi 传递的参数
+ // 将 a0 的值传递给 dtb_init_hart
+ sw a0, dtb_init_hart, t0
+ // 将 a1 的值传递给 boot_info_addr
+ sw a1, boot_info_addr, t0
+ // 设置栈地址
+ la sp, stack_top
+ // 初始化 C++
+ call cpp_init
+ // 跳转到 C 代码执行
+ call kernel_main
+```
+
+内核会在 `BOOT_INFO` 中进行初始化,解析其内容。
+
+```c++
+namespace BOOT_INFO {
+bool init(void) {
+ auto res = DTB::get_instance().dtb_init();
+ if (inited == false) {
+ inited = true;
+ info("BOOT_INFO init.\n");
+ }
+ else {
+ info("BOOT_INFO reinit.\n");
+ }
+ return res;
+}
+}; // namespace BOOT_INFO
+
+bool DTB::dtb_init(void) {
+ // 头信息
+ dtb_info.header = (fdt_header_t *)BOOT_INFO::boot_info_addr;
+ // 魔数
+ assert(be32toh(dtb_info.header->magic) == FDT_MAGIC);
+ // 版本
+ assert(be32toh(dtb_info.header->version) == FDT_VERSION);
+ // 设置大小
+ BOOT_INFO::boot_info_size = be32toh(dtb_info.header->totalsize);
+ // 内存保留区
+ dtb_info.reserved =
+ (fdt_reserve_entry_t *)(BOOT_INFO::boot_info_addr +
+ be32toh(dtb_info.header->off_mem_rsvmap));
+ // 数据区
+ dtb_info.data =
+ BOOT_INFO::boot_info_addr + be32toh(dtb_info.header->off_dt_struct);
+ // 字符区
+ dtb_info.str =
+ BOOT_INFO::boot_info_addr + be32toh(dtb_info.header->off_dt_strings);
+ // 检查保留内存
+ dtb_mem_reserved();
+ // 初始化 map
+ bzero(nodes, sizeof(nodes));
+ bzero(phandle_map, sizeof(phandle_map));
+ // 初始化节点的基本信息
+ dtb_iter(DT_ITER_BEGIN_NODE | DT_ITER_END_NODE | DT_ITER_PROP, dtb_init_cb,
+ nullptr);
+ // 中断信息初始化,因为需要查找 phandle,所以在基本信息初始化完成后进行
+ dtb_iter(DT_ITER_PROP, dtb_init_interrupt_cb, nullptr);
+// #define DEBUG
+#ifdef DEBUG
+ // 输出所有信息
+ for (size_t i = 0; i < nodes[0].count; i++) {
+ std::cout << nodes[i].path << ": " << std::endl;
+ for (size_t j = 0; j < nodes[i].prop_count; j++) {
+ printf("%s: ", nodes[i].props[j].name);
+ for (size_t k = 0; k < nodes[i].props[j].len / 4; k++) {
+ printf("0x%X ",
+ be32toh(((uint32_t *)nodes[i].props[j].addr)[k]));
+ }
+ printf("\n");
+ }
+ }
+#undef DEBUG
+#endif
+ return true;
+}
+```
+
+`void DTB::dtb_iter(uint8_t _cb_flags, bool (*_cb)(const iter_data_t *, void *), void * _data)` 是解析的核心函数
+
+```c++
+void DTB::dtb_iter(uint8_t _cb_flags, bool (*_cb)(const iter_data_t *, void *),
+ void *_data, uintptr_t _addr) {
+ // 迭代变量
+ iter_data_t iter;
+ // 路径深度
+ iter.path.len = 0;
+ // 数据地址
+ iter.addr = (uint32_t *)_addr;
+ // 节点索引
+ iter.nodes_idx = 0;
+ // 开始 flag
+ bool begin = true;
+
+ while (1) {
+ //
+ iter.type = be32toh(iter.addr[0]);
+ switch (iter.type) {
+ case FDT_NOP: {
+ // 跳过 type
+ iter.addr++;
+ break;
+ }
+ case FDT_BEGIN_NODE: {
+ // 第 len 深底的名称
+ iter.path.path[iter.path.len] = (char *)(iter.addr + 1);
+ // 深度+1
+ iter.path.len++;
+ iter.nodes_idx = begin ? 0 : (iter.nodes_idx + 1);
+ begin = false;
+ if (_cb_flags & DT_ITER_BEGIN_NODE) {
+ if (_cb(&iter, _data)) {
+ return;
+ }
+ }
+ // 跳过 type
+ iter.addr++;
+ // 跳过 name
+ iter.addr +=
+ COMMON::ALIGN(strlen((char *)iter.addr) + 1, 4) / 4;
+ break;
+ }
+ case FDT_END_NODE: {
+ if (_cb_flags & DT_ITER_END_NODE) {
+ if (_cb(&iter, _data)) {
+ return;
+ }
+ }
+ // 这一级结束了,所以 -1
+ iter.path.len--;
+ // 跳过 type
+ iter.addr++;
+ break;
+ }
+ case FDT_PROP: {
+ iter.prop_len = be32toh(iter.addr[1]);
+ iter.prop_name = (char *)(dtb_info.str + be32toh(iter.addr[2]));
+ iter.prop_addr = iter.addr + 3;
+ if (_cb_flags & DT_ITER_PROP) {
+ if (_cb(&iter, _data)) {
+ return;
+ }
+ }
+ iter.prop_name = nullptr;
+ iter.prop_addr = nullptr;
+ // 跳过 type
+ iter.addr++;
+ // 跳过 len
+ iter.addr++;
+ // 跳过 nameoff
+ iter.addr++;
+ // 跳过 data,并进行对齐
+ iter.addr += COMMON::ALIGN(iter.prop_len, 4) / 4;
+ iter.prop_len = 0;
+ break;
+ }
+ case FDT_END: {
+ return;
+ }
+ default: {
+ printf("unrecognized token 0x%X\n", iter.type);
+ return;
+ }
+ }
+ }
+ return;
+}
+```
- 相关代码
- src/arch/riscv64/boot/boot.S
-
- src/drv/dtb/include/dtb.h
-
- src/drv/dtb/dtb.cpp
-
+ ./src/arch/riscv64/boot/boot.S
+ ./src/drv/dtb/include/dtb.h
+ ./src/drv/dtb/dtb.cpp
更多细节请查看注释。
-
-
## 相关文档
multiboot2 规范:https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html
diff --git "a/docs/4_\347\211\251\347\220\206\345\206\205\345\255\230\347\256\241\347\220\206.md" "b/docs/4_\347\211\251\347\220\206\345\206\205\345\255\230\347\256\241\347\220\206.md"
index e2bc62d4e..6bd19127f 100644
--- "a/docs/4_\347\211\251\347\220\206\345\206\205\345\255\230\347\256\241\347\220\206.md"
+++ "b/docs/4_\347\211\251\347\220\206\345\206\205\345\255\230\347\256\241\347\220\206.md"
@@ -4,81 +4,143 @@
分配器的基类是 `ALLOCATOR` 类,这是一个抽象类,必须被继承后才能使用。
-由抽象类派生出的具体类是一个分配算法,使用了首次匹配算法。
+由抽象类派生出的具体类是一个分配算法,使用了首次匹配算法(First Fit)。
分配器以 4KB 为最小管理单位,每次分配或回收都是它的整数倍。
此外,为了区分内核权限的内存和用户权限的内存,在 PMM 类的实现中有两个指向 FIRSTFIT 类的 ALLOCATOR 类指针,这允许我们指定要操作的内存位置。
+```c++
+/**
+ * @brief 内存分配器抽象类
+ */
+class ALLOCATOR {
+private:
+protected:
+ /// 分配器名称
+ const char *name;
+ /// 当前管理的内存区域地址
+ uintptr_t allocator_start_addr;
+ /// 当前管理的内存区域长度
+ size_t allocator_length;
+ /// 当前管理的内存区域空闲长度
+ size_t allocator_free_count;
+ /// 当前管理的内存区域已使用长度
+ size_t allocator_used_count;
+
+public:
+ /**
+ * @brief 构造内存分配器
+ * @param _name 分配器名
+ * @param _addr 要管理的内存开始地址
+ * @param _len 要管理的内存长度,单位以具体实现为准
+ */
+ ALLOCATOR(const char *_name, uintptr_t _addr, size_t _len);
+
+ virtual ~ALLOCATOR(void) = 0;
+
+ /**
+ * @brief 分配 _len 页
+ * @param _len 页数
+ * @return uintptr_t 分配到的地址
+ */
+ virtual uintptr_t alloc(size_t _len) = 0;
+
+ /**
+ * @brief 在指定地址分配 _len 长度
+ * @param _addr 指定的地址
+ * @param _len 长度
+ * @return true 成功
+ * @return false 失败
+ */
+ virtual bool alloc(uintptr_t _addr, size_t _len) = 0;
+
+ /**
+ * @brief 释放 _len 长度
+ * @param _addr 地址
+ * @param _len 长度
+ */
+ virtual void free(uintptr_t _addr, size_t _len) = 0;
+
+ /**
+ * @brief 已使用数量
+ * @return size_t 数量
+ */
+ virtual size_t get_used_count(void) const = 0;
+
+ /**
+ * @brief 空闲数量
+ * @return size_t 数量
+ */
+ virtual size_t get_free_count(void) const = 0;
+};
+```
+
+具体到不同架构,物理内存管理会从 `BOOT_INFO` 获取信息进行初始化
+
+```c++
+bool PMM::init(void) {
+ // 获取物理内存信息
+ resource_t mem_info = BOOT_INFO::get_memory();
+ // 设置物理地址的起点与长度
+ start = mem_info.mem.addr;
+ length = mem_info.mem.len;
+ // 计算页数
+ total_pages = length / COMMON::PAGE_SIZE;
+ // 内核空间地址开始
+ kernel_space_start = COMMON::KERNEL_START_ADDR;
+ // 长度手动指定
+ kernel_space_length = COMMON::KERNEL_SPACE_SIZE;
+ // 非内核空间在内核空间结束后
+ non_kernel_space_start =
+ COMMON::KERNEL_START_ADDR + COMMON::KERNEL_SPACE_SIZE;
+ // 长度为总长度减去内核长度
+ non_kernel_space_length = length - kernel_space_length;
+
+ // 创建分配器
+ // 内核空间
+ static FIRSTFIT first_fit_allocator_kernel(
+ "First Fit Allocator(kernel space)", kernel_space_start,
+ kernel_space_length / COMMON::PAGE_SIZE);
+ kernel_space_allocator = (ALLOCATOR *)&first_fit_allocator_kernel;
+ // 非内核空间
+ static FIRSTFIT first_fit_allocator(
+ "First Fit Allocator", non_kernel_space_start,
+ non_kernel_space_length / COMMON::PAGE_SIZE);
+ allocator = (ALLOCATOR *)&first_fit_allocator;
+
+ // 内核实际占用页数 这里也算了 0~1M 的 reserved 内存
+ size_t kernel_pages =
+ (COMMON::ALIGN(COMMON::KERNEL_END_ADDR, COMMON::PAGE_SIZE) -
+ COMMON::ALIGN(COMMON::KERNEL_START_ADDR, COMMON::PAGE_SIZE)) /
+ COMMON::PAGE_SIZE;
+ // 将内核已使用部分划分出来
+ if (alloc_pages_kernel(COMMON::KERNEL_START_ADDR, kernel_pages) == true) {
+ // 将 multiboot2/dtb 信息移动到内核空间
+ move_boot_info();
+ info("pmm init.\n");
+ return true;
+ }
+ else {
+ assert(0);
+ return false;
+ }
+}
+```
+
- 相关代码
- src/include/mem/allocator.h
+ ./src/include/mem/allocator.h
- src/include/mem/firstfit.h
+ ./src/include/mem/firstfit.h
- src/include/mem/pmm.h
+ ./src/include/mem/pmm.h
- src/kernel/allocator.cpp
+ ./src/kernel/allocator.cpp
- src/kernel/firstfit.cpp
+ ./src/kernel/firstfit.cpp
- src/kernel/pmm.cpp
-
-
-
-## IA32
-
-
-
-
-- 相关代码
-
- src/arch/ia32/i386/boot/boot.S
-
- src/drv/multiboot2/include/multiboot2.h
-
- src/drv/multiboot2/multiboot2.cpp
-
+ ./src/kernel/pmm.cpp
更多细节请查看注释。
-
-
-
-## RISCV
-
-opensbi 会将 dtb 信息的地址传递给内核,原理与 multiboot2 相似,但能够提供更为丰富的信息,相应的,dtb 的解析也更为复杂。
-
-`void DTB::dtb_iter(uint8_t _cb_flags, bool (*_cb)(const iter_data_t *, void *), void * _data)` 函数提供了迭代功能。
-
-- 相关代码
-
- src/arch/riscv64/boot/boot.S
-
- src/drv/dtb/include/dtb.h
-
- src/drv/dtb/dtb.cpp
-
-
-
-
-更多细节请查看注释。
-
-
-
-## 相关文档
-
-multiboot2 规范:https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html
-
-opensbi:https://github.com/riscv/opensbi
-
-device-tree:https://github.com/devicetree-org/devicetree-specification
-
-dtb解析0: https://e-mailky.github.io/2016-12-06-dts-introduce
-
-dtb解析1: https://e-mailky.github.io/2019-01-14-dts-1
-
-dtb解析2: https://e-mailky.github.io/2019-01-14-dts-2
-
-dtb解析3: https://e-mailky.github.io/2019-01-14-dts-3
-
diff --git "a/docs/5_\350\231\232\346\213\237\345\206\205\345\255\230\347\256\241\347\220\206.md" "b/docs/5_\350\231\232\346\213\237\345\206\205\345\255\230\347\256\241\347\220\206.md"
new file mode 100644
index 000000000..d175c8feb
--- /dev/null
+++ "b/docs/5_\350\231\232\346\213\237\345\206\205\345\255\230\347\256\241\347\220\206.md"
@@ -0,0 +1,170 @@
+# SimpleKernel 虚拟内存管理
+
+虚拟内存与架构密切相关,但仍然能够找到它们的共同之处。
+
+在 `cpu.hpp` 中封装了它们的差异,使得可以获得一个近似一致的虚拟内存管理逻辑。
+
+
+## IA32
+
+TODO
+
+## RISCV
+
+页表结构可以抽象为以下数据
+
+```c++
+namespace CPU {
+/**
+ * @brief pte 结构
+ * @todo 使用 pte 结构重写 vmm
+ */
+struct pte_t {
+ enum {
+ VALID_OFFSET = 0,
+ READ_OFFSET = 1,
+ WRITE_OFFSET = 2,
+ EXEC_OFFSET = 3,
+ USER_OFFSET = 4,
+ GLOBAL_OFFSET = 5,
+ ACCESSED_OFFSET = 6,
+ DIRTY_OFFSET = 7,
+ VALID = 1 << VALID_OFFSET,
+ READ = 1 << READ_OFFSET,
+ WRITE = 1 << WRITE_OFFSET,
+ EXEC = 1 << EXEC_OFFSET,
+ USER = 1 << USER_OFFSET,
+ GLOBAL = 1 << GLOBAL_OFFSET,
+ ACCESSED = 1 << ACCESSED_OFFSET,
+ DIRTY = 1 << DIRTY_OFFSET,
+ };
+ union {
+ struct {
+ uint64_t flags : 8;
+ uint64_t rsw : 2;
+ uint64_t ppn : 44;
+ uint64_t reserved : 10;
+ };
+ uint64_t val;
+ };
+
+ pte_t(void) {
+ val = 0;
+ return;
+ }
+ pte_t(uint64_t _val) : val(_val) {
+ return;
+ }
+ friend std::ostream &operator<<(std::ostream &_os, const pte_t &_pte) {
+ printf("val: 0x%p, valid: %s, read: %s, write: %s, exec: %s, user: %s, "
+ "global: %s, accessed: %s, dirty: %s, rsw: 0x%p, ppn: 0x%p",
+ _pte.val, (_pte.flags & VALID) == VALID ? "true" : "false",
+ (_pte.flags & READ) == READ ? "true" : "false",
+ (_pte.flags & WRITE) == WRITE ? "true" : "false",
+ (_pte.flags & EXEC) == EXEC ? "true" : "false",
+ (_pte.flags & USER) == USER ? "true" : "false",
+ (_pte.flags & GLOBAL) == GLOBAL ? "true" : "false",
+ (_pte.flags & ACCESSED) == ACCESSED ? "true" : "false",
+ (_pte.flags & DIRTY) == DIRTY ? "true" : "false", _pte.rsw,
+ _pte.ppn);
+ return _os;
+ }
+};
+
+/**
+ * @brief satp 结构
+ */
+struct satp_t {
+ enum {
+ NONE = 0,
+ SV39 = 8,
+ SV48 = 9,
+ SV57 = 10,
+ SV64 = 11,
+ };
+ static constexpr const char *MODE_NAME[] = {
+ [NONE] = "NONE", "UNKNOWN", "UNKNOWN", "UNKNOWN",
+ "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN",
+ [SV39] = "SV39", [SV48] = "SV48", [SV57] = "SV57", [SV64] = "SV64",
+ };
+
+ union {
+ struct {
+ uint64_t ppn : 44;
+ uint64_t asid : 16;
+ uint64_t mode : 4;
+ };
+ uint64_t val;
+ };
+
+ static constexpr const uint64_t PPN_OFFSET = 12;
+
+ satp_t(void) {
+ val = 0;
+ return;
+ }
+ satp_t(uint64_t _val) : val(_val) {
+ return;
+ }
+ friend std::ostream &operator<<(std::ostream &_os, const satp_t &_satp) {
+ printf("val: 0x%p, ppn: 0x%p, asid: 0x%p, mode: %s", _satp.val,
+ _satp.ppn, _satp.asid, MODE_NAME[_satp.mode]);
+ return _os;
+ }
+};
+}; // namespace CPU
+```
+
+以下是在执行 mmap 映射内存时的逻辑。
+```c++
+// 在 _pgd 中查找 _va 对应的页表项
+// 如果未找到,_alloc 为真时会进行分配
+pte_t *VMM::find(const pt_t _pgd, uintptr_t _va, bool _alloc) {
+ pt_t pgd = _pgd;
+ // sv39 共有三级页表,一级一级查找
+ // -1 是因为最后一级是具体的某一页,在函数最后直接返回
+ for (size_t level = VMM_PT_LEVEL - 1; level > 0; level--) {
+ // 每次循环会找到 _va 的第 level 级页表 pgd
+ // 相当于 pgd_level[VPN_level],这样相当于得到了第 level 级页表的地址
+ pte_t *pte = (pte_t *)&pgd[PX(level, _va)];
+ // 解引用 pte,如果有效,获取 level+1 级页表,
+ if ((*pte & VMM_PAGE_VALID) == 1) {
+ // pgd 指向下一级页表
+ // *pte 保存的是页表项,需要转换为对应的物理地址
+ pgd = (pt_t)PTE2PA(*pte);
+ }
+ // 如果无效
+ else {
+ // 判断是否需要分配
+ // 如果需要
+ if (_alloc == true) {
+ // 申请新的物理页
+ pgd = (pt_t)PMM::get_instance().alloc_page_kernel();
+ bzero(pgd, COMMON::PAGE_SIZE);
+ // 申请失败则返回
+ if (pgd == nullptr) {
+ // 如果出现这种情况,说明物理内存不够,一般不会出现
+ assert(0);
+ return nullptr;
+ }
+ // 清零
+ bzero(pgd, COMMON::PAGE_SIZE);
+ // 填充页表项
+ *pte = PA2PTE((uintptr_t)pgd) | VMM_PAGE_VALID;
+ }
+ // 不分配的话直接返回
+ else {
+ return nullptr;
+ }
+ }
+ }
+ // 0 最低级 pt
+ return &pgd[PX(0, _va)];
+}
+```
+
+更多细节请查看注释。
+
+## 相关文档
+
+TODO
\ No newline at end of file
diff --git "a/docs/6_\345\240\206\347\256\241\347\220\206.md" "b/docs/6_\345\240\206\347\256\241\347\220\206.md"
new file mode 100644
index 000000000..cf8777280
--- /dev/null
+++ "b/docs/6_\345\240\206\347\256\241\347\220\206.md"
@@ -0,0 +1,59 @@
+# SimpleKernel 堆管理
+
+堆(heap)是内核使用动态内存的主要方式,`HEAP` 同样继承了 `ALLOCATOR`,这里使用了 slab 分配算法。
+
+
+堆的初始化,将内存分为内核/用户两部分
+```c++
+bool HEAP::init(void) {
+ // 内核空间
+ static SLAB slab_allocator_kernel(
+ "SLAB Allocator Kernel", PMM::get_instance().get_kernel_space_start(),
+ PMM::get_instance().get_kernel_space_length() * COMMON::PAGE_SIZE,
+ true);
+ allocator_kernel = (ALLOCATOR *)&slab_allocator_kernel;
+ // 非内核空间
+ static SLAB slab_allocator_non_kernel(
+ "SLAB Allocator", PMM::get_instance().get_non_kernel_space_start(),
+ PMM::get_instance().get_non_kernel_space_length() * COMMON::PAGE_SIZE,
+ false);
+ allocator_non_kernel = (ALLOCATOR *)&slab_allocator_non_kernel;
+ info("heap init.\n");
+ return 0;
+}
+```
+
+在堆管理实现后,动态内存就可以使用了,这允许我们用更多的语言特性。
+
+`malloc` 与 `free` 的实现
+```c++
+/**
+ * @brief malloc 定义
+ * @param _size 要申请的 bytes
+ * @return void* 申请到的地址
+ */
+extern "C" void *malloc(size_t _size) {
+ return (void *)HEAP::get_instance().malloc(_size);
+}
+
+/**
+ * @brief free 定义
+ * @param _p 要释放的内存地址
+ */
+extern "C" void free(void *_p) {
+ HEAP::get_instance().free(_p);
+ return;
+}
+```
+
+slab 部分较复杂,可以直接参考代码。
+
+- 相关代码
+
+ ./src/include/mem/heap.h
+
+ ./src/kernel/heap.cpp
+
+ ./src/include/mem/slab.h
+
+ ./src/kernel/slab.cpp
diff --git "a/docs/7_c++stl\347\232\204\346\224\257\346\214\201.md" "b/docs/7_c++stl\347\232\204\346\224\257\346\214\201.md"
new file mode 100644
index 000000000..2ba67e27f
--- /dev/null
+++ "b/docs/7_c++stl\347\232\204\346\224\257\346\214\201.md"
@@ -0,0 +1,7 @@
+# SimpleKernel c++ stl 的支持
+
+C++ 的标准模版库(STL) 非常强大,这里我们只使用了部分,使用了 [Alinshans/MyTinySTL](https://github.com/Alinshans/MyTinySTL) 的实现。
+
+- 相关代码
+
+ ./src/libcxx/include/*
diff --git "a/docs/8_\344\270\255\346\226\255.md" "b/docs/8_\344\270\255\346\226\255.md"
new file mode 100644
index 000000000..737054e09
--- /dev/null
+++ "b/docs/8_\344\270\255\346\226\255.md"
@@ -0,0 +1,595 @@
+# SimpleKernel 中断
+
+## IA32
+
+TODO
+
+## RISCV
+
+寄存结构及中断上下文
+```c++
+namespace CPU {
+/// 机器模式定义
+enum {
+ U_MODE = 0,
+ S_MODE = 1,
+ M_MODE = 3,
+};
+
+enum {
+ INTR_SOFT = 0,
+ /// U 态软中断
+ INTR_SOFT_U = INTR_SOFT + U_MODE,
+ /// S 态软中断
+ INTR_SOFT_S = INTR_SOFT + S_MODE,
+ /// M 态软中断
+ INTR_SOFT_M = INTR_SOFT + M_MODE,
+ INTR_TIMER = 4,
+ /// U 态时钟中断
+ INTR_TIMER_U = INTR_TIMER + U_MODE,
+ /// S 态时钟中断
+ INTR_TIMER_S = INTR_TIMER + S_MODE,
+ /// M 态时钟中断
+ INTR_TIMER_M = INTR_TIMER + M_MODE,
+ INTR_EXTERN = 8,
+ /// U 态外部中断
+ INTR_EXTERN_U = INTR_EXTERN + U_MODE,
+ /// S 态外部中断
+ INTR_EXTERN_S = INTR_EXTERN + S_MODE,
+ /// M 态外部中断
+ INTR_EXTERN_M = INTR_EXTERN + M_MODE,
+};
+
+enum {
+ EXCP_INSTRUCTION_ADDRESS_MISALIGNED = 0,
+ EXCP_INSTRUCTION_ACCESS_FAULT = 1,
+ EXCP_ILLEGAL_INSTRUCTION = 2,
+ EXCP_BREAKPOINT = 3,
+ EXCP_LOAD_ADDRESS_MISALIGNED = 4,
+ EXCP_LOAD_ACCESS_FAULT = 5,
+ EXCP_STORE_AMO_ADDRESS_MISALIGNED = 6,
+ EXCP_STORE_AMO_ACCESS_FAULT = 7,
+ EXCP_ECALL = 8,
+ EXCP_ECALL_U = EXCP_ECALL + U_MODE,
+ EXCP_ECALL_S = EXCP_ECALL + S_MODE,
+ EXCP_ECALL_M = EXCP_ECALL + M_MODE,
+ EXCP_INSTRUCTION_PAGE_FAULT = 12,
+ EXCP_LOAD_PAGE_FAULT = 13,
+ EXCP_STORE_AMO_PAGE_FAULT = 15,
+};
+
+// Supervisor Status Register, sstatus
+// User Interrupt Enable
+static constexpr const uint64_t SSTATUS_UIE = 1 << 0;
+// Supervisor Interrupt Enable
+static constexpr const uint64_t SSTATUS_SIE = 1 << 1;
+// User Previous Interrupt Enable
+static constexpr const uint64_t SSTATUS_UPIE = 1 << 4;
+// Supervisor Previous Interrupt Enable
+static constexpr const uint64_t SSTATUS_SPIE = 1 << 5;
+// Previous mode, 1=Supervisor, 0=User
+static constexpr const uint64_t SSTATUS_SPP = 1 << 8;
+
+/**
+ * @brief sstatus 寄存器定义
+ */
+struct sstatus_t {
+ union {
+ struct {
+ // Reserved Writes Preserve Values, Reads Ignore Values (WPRI)
+ uint64_t wpri1 : 1;
+ // interrupt enable
+ uint64_t sie : 1;
+ uint64_t wpri12 : 3;
+ // previous interrupt enable
+ uint64_t spie : 1;
+ uint64_t ube : 1;
+ uint64_t wpri3 : 1;
+ // previous mode (supervisor)
+ uint64_t spp : 1;
+ uint64_t wpri4 : 4;
+ // FPU status
+ uint64_t fs : 2;
+ // extensions status
+ uint64_t xs : 2;
+ uint64_t wpri5 : 1;
+ // permit supervisor user memory access
+ uint64_t sum : 1;
+ // make executable readable
+ uint64_t mxr : 1;
+ uint64_t wpri6 : 12;
+ // U-mode XLEN
+ uint64_t uxl : 2;
+ uint64_t wpri7 : 29;
+ // status dirty
+ uint64_t sd : 1;
+ };
+ uint64_t val;
+ };
+
+ sstatus_t(void) {
+ val = 0;
+ return;
+ }
+ sstatus_t(uint64_t _val) : val(_val) {
+ return;
+ }
+ friend std::ostream &operator<<(std::ostream &_os,
+ const sstatus_t &_sstatus) {
+ printf("val: 0x%p, sie: %s, spie: %s, spp: %s", _sstatus.val,
+ (_sstatus.sie == true ? "enable" : "disable"),
+ (_sstatus.spie == true ? "enable" : "disable"),
+ (_sstatus.spp == true ? "S mode" : "U mode"));
+ return _os;
+ }
+};
+
+// Supervisor Interrupt Enable
+// software
+static constexpr const uint64_t SIE_SSIE = 1 << 1;
+// timer
+static constexpr const uint64_t SIE_STIE = 1 << 5;
+// external
+static constexpr const uint64_t SIE_SEIE = 1 << 9;
+
+/// 中断模式 直接
+static constexpr const uint64_t TVEC_DIRECT = 0xFFFFFFFFFFFFFFFC;
+/// 中断模式 向量
+static constexpr const uint64_t TVEC_VECTORED = 0xFFFFFFFFFFFFFFFD;
+
+/**
+ * @brief 允许中断
+ */
+static inline void ENABLE_INTR(void) {
+ WRITE_SSTATUS(READ_SSTATUS().val | SSTATUS_SIE);
+ return;
+}
+
+/**
+ * @brief 允许中断
+ * @param _sstatus 要设置的 sstatus
+ */
+static inline void ENABLE_INTR(sstatus_t &_sstatus) {
+ _sstatus.sie = true;
+ return;
+}
+
+/**
+ * @brief 禁止中断
+ */
+static inline void DISABLE_INTR(void) {
+ WRITE_SSTATUS(READ_SSTATUS().val & ~SSTATUS_SIE);
+ return;
+}
+
+/**
+ * @brief 禁止中断
+ * @param _sstatus 要设置的原 sstatus 值
+ */
+static inline void DISABLE_INTR(sstatus_t &_sstatus) {
+ _sstatus.sie = false;
+ return;
+}
+
+/**
+ * @brief 读取中断状态
+ * @return true 允许
+ * @return false 禁止
+ */
+static inline bool STATUS_INTR(void) {
+ sstatus_t x = READ_SSTATUS();
+ return x.sie;
+}
+
+/**
+ * @brief 通用寄存器
+ */
+struct xregs_t {
+ uintptr_t zero;
+ uintptr_t ra;
+ uintptr_t sp;
+ uintptr_t gp;
+ uintptr_t tp;
+ uintptr_t t0;
+ uintptr_t t1;
+ uintptr_t t2;
+ uintptr_t s0;
+ uintptr_t s1;
+ uintptr_t a0;
+ uintptr_t a1;
+ uintptr_t a2;
+ uintptr_t a3;
+ uintptr_t a4;
+ uintptr_t a5;
+ uintptr_t a6;
+ uintptr_t a7;
+ uintptr_t s2;
+ uintptr_t s3;
+ uintptr_t s4;
+ uintptr_t s5;
+ uintptr_t s6;
+ uintptr_t s7;
+ uintptr_t s8;
+ uintptr_t s9;
+ uintptr_t s10;
+ uintptr_t s11;
+ uintptr_t t3;
+ uintptr_t t4;
+ uintptr_t t5;
+ uintptr_t t6;
+};
+
+/**
+ * @brief 浮点寄存器
+ */
+struct fregs_t {
+ uintptr_t ft0;
+ uintptr_t ft1;
+ uintptr_t ft2;
+ uintptr_t ft3;
+ uintptr_t ft4;
+ uintptr_t ft5;
+ uintptr_t ft6;
+ uintptr_t ft7;
+ uintptr_t fs0;
+ uintptr_t fs1;
+ uintptr_t fa0;
+ uintptr_t fa1;
+ uintptr_t fa2;
+ uintptr_t fa3;
+ uintptr_t fa4;
+ uintptr_t fa5;
+ uintptr_t fa6;
+ uintptr_t fa7;
+ uintptr_t fs2;
+ uintptr_t fs3;
+ uintptr_t fs4;
+ uintptr_t fs5;
+ uintptr_t fs6;
+ uintptr_t fs7;
+ uintptr_t fs8;
+ uintptr_t fs9;
+ uintptr_t fs10;
+ uintptr_t fs11;
+ uintptr_t ft8;
+ uintptr_t ft9;
+ uintptr_t ft10;
+ uintptr_t ft11;
+};
+
+/**
+ * @brief 所有寄存器,在中断时使用,共 32+32+7=71 个
+ */
+struct all_regs_t {
+ xregs_t xregs;
+ fregs_t fregs;
+ uintptr_t sepc;
+ uintptr_t stval;
+ uintptr_t scause;
+ uintptr_t sie;
+ sstatus_t sstatus;
+ satp_t satp;
+ uintptr_t sscratch;
+};
+
+}; // namespace CPU
+```
+
+现场保存与恢复
+
+```assembly
+
+// 寄存器长度,8 字节
+.equ REG_BYTES, 8
+// 所有寄存器数量
+.equ ALL_REGS, 71
+// 保存所有寄存器需要的大小
+.equ ALL_SIZE, (ALL_REGS * REG_BYTES)
+
+// 将寄存器 a 保存在 c 偏移 b 的位置
+.macro sd_base a, b, c
+sd \a, ((\b) * REG_BYTES)(\c)
+.endm
+
+// 从 c 的偏移 b 处获取数据并赋值给寄存器 a
+.macro ld_base a, b, c
+ld \a, ((\b) * REG_BYTES)(\c)
+.endm
+
+// 将 float 寄存器 a 保存在 c 偏移 b 的位置
+.macro fsd_base a, b, c
+fsd \a, ((\b) * REG_BYTES)(\c)
+.endm
+
+// 从 c 的偏移 b 处获取数据并赋值给 float 寄存器 a
+.macro fld_base a, b, c
+fld \a, ((\b) * REG_BYTES)(\c)
+.endm
+
+/**
+ * @brief 保存所有寄存器
+ * @param _base 要保存到的基地址
+ */
+.macro all_regs_save _base
+ sd_base zero, 0, \_base
+ sd_base ra, 1, \_base
+ sd_base sp, 2, \_base
+ sd_base gp, 3, \_base
+ sd_base tp, 4, \_base
+ sd_base t0, 5, \_base
+ sd_base t1, 6, \_base
+ sd_base t2, 7, \_base
+ sd_base s0, 8, \_base
+ sd_base s1, 9, \_base
+ sd_base a0, 10, \_base
+ sd_base a1, 11, \_base
+ sd_base a2, 12, \_base
+ sd_base a3, 13, \_base
+ sd_base a4, 14, \_base
+ sd_base a5, 15, \_base
+ sd_base a6, 16, \_base
+ sd_base a7, 17, \_base
+ sd_base s2, 18, \_base
+ sd_base s3, 19, \_base
+ sd_base s4, 20, \_base
+ sd_base s5, 21, \_base
+ sd_base s6, 22, \_base
+ sd_base s7, 23, \_base
+ sd_base s8, 24, \_base
+ sd_base s9, 25, \_base
+ sd_base s10, 26, \_base
+ sd_base s11, 27, \_base
+ sd_base t3, 28, \_base
+ sd_base t4, 29, \_base
+ sd_base t5, 30, \_base
+ sd_base t6, 31, \_base
+
+ fsd_base ft0, 32, \_base
+ fsd_base ft1, 33, \_base
+ fsd_base ft2, 34, \_base
+ fsd_base ft3, 35, \_base
+ fsd_base ft4, 36, \_base
+ fsd_base ft5, 37, \_base
+ fsd_base ft6, 38, \_base
+ fsd_base ft7, 39, \_base
+ fsd_base fs0, 40, \_base
+ fsd_base fs1, 41, \_base
+ fsd_base fa0, 42, \_base
+ fsd_base fa1, 43, \_base
+ fsd_base fa2, 44, \_base
+ fsd_base fa3, 45, \_base
+ fsd_base fa4, 46, \_base
+ fsd_base fa5, 47, \_base
+ fsd_base fa6, 48, \_base
+ fsd_base fa7, 49, \_base
+ fsd_base fs2, 50, \_base
+ fsd_base fs3, 51, \_base
+ fsd_base fs4, 52, \_base
+ fsd_base fs5, 53, \_base
+ fsd_base fs6, 54, \_base
+ fsd_base fs7, 55, \_base
+ fsd_base fs8, 56, \_base
+ fsd_base fs9, 57, \_base
+ fsd_base fs10, 58, \_base
+ fsd_base fs11, 59, \_base
+ fsd_base ft8, 60, \_base
+ fsd_base ft9, 61, \_base
+ fsd_base ft10, 62, \_base
+ fsd_base ft11, 63, \_base
+
+ csrr t0, sepc
+ sd_base t0, 64, \_base
+ csrr t0, stval
+ sd_base t0, 65, \_base
+ csrr t0, scause
+ sd_base t0, 66, \_base
+ csrr t0, sie
+ sd_base t0, 67, \_base
+ csrr t0, sstatus
+ sd_base t0, 68, \_base
+ csrr t0, satp
+ sd_base t0, 69, \_base
+ csrr t0, sscratch
+ sd_base t0, 70, \_base
+.endm
+
+/**
+ * @brief 恢复所有寄存器
+ * @param _base 要恢复数据的基地址
+ */
+.macro all_regs_load _base
+ ld_base t0, 64, \_base
+ csrw sepc, t0
+ ld_base t0, 65, \_base
+ csrw stval, t0
+ ld_base t0, 66, \_base
+ csrw scause, t0
+ ld_base t0, 67, \_base
+ csrw sie, t0
+ ld_base t0, 68, \_base
+ csrw sstatus, t0
+ ld_base t0, 69, \_base
+ csrw satp, t0
+ ld_base t0, 70, \_base
+ csrw sscratch, t0
+
+ ld_base zero, 0, \_base
+ ld_base ra, 1, \_base
+ ld_base sp, 2, \_base
+ ld_base gp, 3, \_base
+ ld_base tp, 4, \_base
+ ld_base t0, 5, \_base
+ ld_base t1, 6, \_base
+ ld_base t2, 7, \_base
+ ld_base s0, 8, \_base
+ ld_base s1, 9, \_base
+ ld_base a0, 10, \_base
+ ld_base a1, 11, \_base
+ ld_base a2, 12, \_base
+ ld_base a3, 13, \_base
+ ld_base a4, 14, \_base
+ ld_base a5, 15, \_base
+ ld_base a6, 16, \_base
+ ld_base a7, 17, \_base
+ ld_base s2, 18, \_base
+ ld_base s3, 19, \_base
+ ld_base s4, 20, \_base
+ ld_base s5, 21, \_base
+ ld_base s6, 22, \_base
+ ld_base s7, 23, \_base
+ ld_base s8, 24, \_base
+ ld_base s9, 25, \_base
+ ld_base s10, 26, \_base
+ ld_base s11, 27, \_base
+ ld_base t3, 28, \_base
+ ld_base t4, 29, \_base
+ ld_base t5, 30, \_base
+ ld_base t6, 31, \_base
+
+ fld_base ft0, 32, \_base
+ fld_base ft1, 33, \_base
+ fld_base ft2, 34, \_base
+ fld_base ft3, 35, \_base
+ fld_base ft4, 36, \_base
+ fld_base ft5, 37, \_base
+ fld_base ft6, 38, \_base
+ fld_base ft7, 39, \_base
+ fld_base fs0, 40, \_base
+ fld_base fs1, 41, \_base
+ fld_base fa0, 42, \_base
+ fld_base fa1, 43, \_base
+ fld_base fa2, 44, \_base
+ fld_base fa3, 45, \_base
+ fld_base fa4, 46, \_base
+ fld_base fa5, 47, \_base
+ fld_base fa6, 48, \_base
+ fld_base fa7, 49, \_base
+ fld_base fs2, 50, \_base
+ fld_base fs3, 51, \_base
+ fld_base fs4, 52, \_base
+ fld_base fs5, 53, \_base
+ fld_base fs6, 54, \_base
+ fld_base fs7, 55, \_base
+ fld_base fs8, 56, \_base
+ fld_base fs9, 57, \_base
+ fld_base fs10, 58, \_base
+ fld_base fs11, 59, \_base
+ fld_base ft8, 60, \_base
+ fld_base ft9, 61, \_base
+ fld_base ft10, 62, \_base
+ fld_base ft11, 63, \_base
+.endm
+
+.section .text
+// 保存所有寄存器
+.globl trap_entry
+.extern trap_handler
+.align 4
+trap_entry:
+ // 将所有寄存器保存到栈上
+ // 在栈上留出保存寄存器的空间
+ addi sp, sp, -ALL_SIZE
+ all_regs_save sp
+
+ // 调用 intr.cpp: trap_handler
+ // 传递参数
+ csrr a0, sepc
+ csrr a1, stval
+ csrr a2, scause
+ mv a3, sp
+ csrr a4, sie
+ csrr a5, sstatus
+ csrr a6, satp
+ csrr a7, sscratch
+ jal trap_handler
+
+ // 从栈上恢复所有寄存器
+ all_regs_load sp
+ // 释放栈上用于保存寄存器的空间
+ addi sp, sp, ALL_SIZE
+
+ // 跳转到 sepc 处执行
+ sret
+```
+
+中断初始化
+```c++
+int32_t INTR::init(void) {
+ // 设置 trap vector
+ CPU::WRITE_STVEC((uintptr_t)trap_entry);
+ // 直接跳转到处理函数
+ CPU::STVEC_DIRECT();
+ // 设置处理函数
+ for (auto &i : interrupt_handlers) {
+ i = handler_default;
+ }
+ for (auto &i : excp_handlers) {
+ i = handler_default;
+ }
+ // 内部中断初始化
+ CLINT::get_instance().init();
+ // 外部中断初始化
+ PLIC::get_instance().init();
+ // 注册缺页中断
+ register_excp_handler(CPU::EXCP_LOAD_PAGE_FAULT, pg_load_excp);
+ // 注册缺页中断
+ register_excp_handler(CPU::EXCP_STORE_AMO_PAGE_FAULT, pg_store_excp);
+ info("intr init.\n");
+ return 0;
+}
+```
+
+中断处理
+```c++
+/**
+ * @brief 中断处理函数
+ * @param _scause 原因
+ * @param _sepc 值
+ * @param _stval 值
+ * @param _scause 值
+ * @param _all_regs 保存在栈上的所有寄存器,实际上是 sp
+ * @param _sie 值
+ * @param _sstatus 值
+ * @param _sscratch 值
+ */
+extern "C" void trap_handler(uintptr_t _sepc, uintptr_t _stval,
+ uintptr_t _scause, CPU::all_regs_t *_all_regs,
+ uintptr_t _sie, CPU::sstatus_t _sstatus,
+ CPU::satp_t _satp, uintptr_t _sscratch) {
+ if (_scause & CPU::CAUSE_INTR_MASK) {
+// 中断
+ // 跳转到对应的处理函数
+ INTR::get_instance().do_interrupt(_scause & CPU::CAUSE_CODE_MASK, 0,
+ nullptr);
+ }
+ else {
+// 异常
+// 跳转到对应的处理函数
+ INTR::get_instance().do_excp(_scause & CPU::CAUSE_CODE_MASK, 0,
+ nullptr);
+ }
+ return;
+}
+```
+
+更多细节请查看注释。
+
+- 相关代码
+
+ ./src/arch/riscv64/context.S
+
+ ./src/arch/riscv64/intr/intr_s.S
+
+ ./src/arch/riscv64/intr/include/intr.h
+
+ ./src/arch/riscv64/intr/intr.cpp
+
+ ./src/arch/riscv64/intr/clint.cpp
+
+ ./src/arch/riscv64/intr/plic.cpp
+
+ ./src/arch/riscv64/intr/timer.cpp
+
+## 相关文档
+
+TODO
diff --git a/docs/UEFI_Spec_2_10_Aug29.pdf b/docs/UEFI_Spec_2_10_Aug29.pdf
new file mode 100644
index 000000000..b56b7b993
Binary files /dev/null and b/docs/UEFI_Spec_2_10_Aug29.pdf differ
diff --git a/run.py b/run.py
deleted file mode 100644
index b19a84e8b..000000000
--- a/run.py
+++ /dev/null
@@ -1,75 +0,0 @@
-
-# This file is a part of Simple-XX/SimpleKernel (https://github.com/Simple-XX/SimpleKernel).
-#
-# run.py for Simple-XX/SimpleKernel.
-
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-
-import os
-import argparse
-import subprocess
-
-# 通用依赖
-# cmake, make
-# i386/x86_64 需要的依赖
-# bochs, grub2, x86_64-elf-g++
-# arm 需要的依赖
-# qemu-system-aarch64, arm-none-eabi-g++
-# riscv64 需要的依赖
-# qemu-system-riscv64, riscv64-unknown-elf-g++
-# Depends = ["cmake", "make"]
-
-# 仅运行,默认所有依赖都可用
-
-
-# 清空旧目录
-def clean():
- proc = subprocess.call(
- "rm -rf ./build/*", shell=True)
- proc = subprocess.call(
- "mkdir -p ./build/", shell=True)
- return
-
-
-# 执行 CMake
-def cmake(arch):
- if arch == "riscv" or arch == "riscv64":
- proc = subprocess.call(
- ["cd ./build && cmake -DCMAKE_TOOLCHAIN_FILE=./cmake/toolchain_mac_riscv.cmake -DARCH=riscv64 -DCMAKE_BUILD_TYPE=DEBUG .."], shell=True)
- return
-
-
-def run(arch, simulator):
- if arch == "riscv" or arch == "riscv64":
- proc = subprocess.call(
- "qemu-system-riscv64 -machine virt -serial stdio -bios ./tools/opensbi/build/platform/generic/firmware/fw_jump.elf -kernel ./build/bin/kernel.elf", shell=True)
- return
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument(
- "-v", "--version", help="Print version.", action='version', version='dev')
- # 目标平台
- parser.add_argument("-a", "--arch", required=False, default="i386", type=str,
- help="i386, x86_64, arm, aarch64, riscv64")
- # 虚拟机
- parser.add_argument("-s", "--simulator", required=False, default="bochs", type=str,
- help="bochs, qemu")
- args = parser.parse_args()
- # i386/x86_64 暂不支持 qemu 模拟
- if (args.arch == "i386" or args.arch == "x86_64") and args.simulator == "qemu":
- print("Not Support yet.")
- exit(1)
- clean()
- cmake(args.arch)
- # 执行 make
- proc = subprocess.call(
- ["cd ./build && make"], shell=True)
- run(args.arch, args.simulator)
- return
-
-
-if __name__ == '__main__':
- main()
diff --git a/run.sh b/run.sh
index 930714d6e..c3f397fcc 100644
--- a/run.sh
+++ b/run.sh
@@ -1,23 +1,23 @@
+#!/bin/bash
-# This file is a part of Simple-XX/SimpleKernel
+# This file is a part of Simple-XX/SimpleKernel
# (https://github.com/Simple-XX/SimpleKernel).
#
# run.sh for Simple-XX/SimpleKernel.
# 在虚拟机中运行内核
-#!/bin/bash
# shell 执行出错时终止运行
set -e
# 输出实际执行内容
-# set -x
+#set -x
source ./tools/env.sh
export PATH="${GRUB_PATH}:$PATH"
# 重新编译
-mkdir -p ./build/
-rm -rf ./build/*
-cd ./build
+mkdir -p ./build_${ARCH}/
+rm -rf ./build_${ARCH}/*
+cd ./build_${ARCH}
cmake -DCMAKE_TOOLCHAIN_FILE=./cmake/${TOOLS} -DARCH=${ARCH} -DCMAKE_BUILD_TYPE=DEBUG ..
make
cd ../
@@ -37,12 +37,14 @@ if [ ${ARCH} == "riscv64" ]; then
# OPENSBI 不存在则编译
if [ ! -f ${OPENSBI} ]; then
echo build opensbi.
- git submodule init
- git submodule update
cd ./tools/opensbi
mkdir -p build
export CROSS_COMPILE=${TOOLCHAIN_PREFIX}
- make PLATFORM=generic FW_JUMP_ADDR=0x80200000
+ export FW_JUMP=y
+ export FW_JUMP_ADDR=0x80200000
+ export PLATFORM_RISCV_XLEN=64
+ export PLATFORM=generic
+ make
cd ../..
echo build opensbi done.
fi
@@ -56,31 +58,37 @@ else
rm -rf -f ${iso_boot}/*
fi
+# 初始化 gdb
+if [ ${DEBUG} == 1 ]; then
+ cp ./tools/gdbinit ./.gdbinit
+ echo "" >> ./.gdbinit
+ echo "file "${kernel} >> ./.gdbinit
+ if [ ${ARCH} == "riscv64" ]; then
+ echo "add-symbol-file "${OPENSBI} >> ./.gdbinit
+ fi
+ echo "target remote localhost:1234" >> ./.gdbinit
+ GDB_OPT='-S -gdb tcp::1234'
+ echo "Run gdb-multiarch in another shell"
+fi
+
# 设置 grub 相关数据
if [ ${ARCH} == "i386" ] || [ ${ARCH} == "x86_64" ]; then
+ mkdir -p ${iso_boot_grub}
cp ${kernel} ${iso_boot}
- mkdir ${iso_boot_grub}
- touch ${iso_boot_grub}/grub.cfg
- echo 'set timeout=15
- set default=0
- menuentry "SimpleKernel" {
- multiboot2 /boot/kernel.elf "KERNEL_ELF"
- }' >${iso_boot_grub}/grub.cfg
+ cp ./tools/grub.cfg ${iso_boot_grub}/
fi
# 运行虚拟机
if [ ${ARCH} == "i386" ] || [ ${ARCH} == "x86_64" ]; then
- if [ ${IA32_USE_QEMU} == 0 ]; then
- ${GRUB_PATH}/grub-mkrescue -o ${iso} ${iso_folder}
- bochs -q -f ${bochsrc} -rc ./tools/bochsinit
- else
- qemu-system-x86_64 -cdrom ${iso} -m 128M \
- -monitor telnet::2333,server,nowait -serial stdio
- fi
+ qemu-system-x86_64 -cdrom ${iso} -m 128M \
+ -monitor telnet::2333,server,nowait -serial stdio \
+ ${GDB_OPT}
elif [ ${ARCH} == "aarch64" ]; then
qemu-system-aarch64 -machine virt -cpu cortex-a72 -kernel ${kernel} \
- -monitor telnet::2333,server,nowait -serial stdio -nographic
+ -monitor telnet::2333,server,nowait -serial stdio -nographic \
+ ${GDB_OPT}
elif [ ${ARCH} == "riscv64" ]; then
qemu-system-riscv64 -machine virt -bios ${OPENSBI} -kernel ${kernel} \
- -monitor telnet::2333,server,nowait -serial stdio -nographic
+ -monitor telnet::2333,server,nowait -serial stdio -nographic \
+ ${GDB_OPT}
fi
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 65862d877..04256df16 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,7 +1,7 @@
# This file is a part of Simple-XX/SimpleKernel
# (https://github.com/Simple-XX/SimpleKernel).
-# Based on https://github.com/SynestiaOS/SynestiaOS
+#
# CMakeLists.txt for Simple-XX/SimpleKernel.
# 设置编译规则
@@ -36,9 +36,14 @@ else ()
set(CMAKE_BUILD_TYPE DEBUG)
endif ()
+# 代码优化级别
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0")
+set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}")
+
# 通用选项
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffreestanding -nostdlib -nostdinc -fexceptions -nostartfiles -fPIC -no-pie -O2 -Wall -Wextra -MMD")
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffreestanding -nostdlib -nostdinc -fexceptions -nostartfiles -fPIC -no-pie -O2 -Wall -Wextra -MMD")
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffreestanding -nostdlib -nostdinc -fexceptions -nostartfiles -fPIC -no-pie -Wall -Wextra -MMD")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffreestanding -nostdlib -nostdinc -fexceptions -nostartfiles -fPIC -no-pie -Wall -Wextra -MMD")
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}")
# 输出相关信息
@@ -58,11 +63,11 @@ add_subdirectory(${SimpleKernel_SOURCE_CODE_DIR}/libcxx)
# 将各个子对象链接为内核文件
add_executable(${KernelName}
- $
- $
- $
- $
- $)
+ $
+ $
+ $
+ $
+ $)
# 指定链接脚本
target_link_options(${KernelName} PRIVATE -T ${SimpleKernel_SOURCE_CODE_DIR}/arch/${SimpleKernelArch}/link.ld)
@@ -80,23 +85,40 @@ elseif (SimpleKernelArch STREQUAL riscv64)
target_link_options(${KernelName} PRIVATE -Wl,-melf64lriscv)
endif ()
-# readelf -a
+# objcopy --only-keep-debug foo foo.dbg 创建一个包含调试信息的文件
add_custom_command(TARGET ${KernelName}
- POST_BUILD
- WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
- COMMAND ${CMAKE_READELF} -a ${KernelName} >> ${KernelName}.readelf_a || (exit 0)
- COMMENT "readelf -a")
+ POST_BUILD
+ WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
+ COMMAND ${CMAKE_OBJCOPY} --only-keep-debug ${KernelName} ${KernelName}.debug
+ COMMENT "Generating kernel debug...")
-# objdump -D
+# objcopy --strip-debug foo 创建一个去掉调试信息的( strip 的)可执行文件
+# objcopy --add-gnu-debuglink=foo.dbg foo 为 strip 的文件添加调试信息链接
+add_custom_command(TARGET ${KernelName}
+ POST_BUILD
+ WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
+ COMMAND ${CMAKE_OBJCOPY} --strip-debug ${KernelName}
+ COMMAND ${CMAKE_OBJCOPY} --add-gnu-debuglink=${KernelName}.debug ${KernelName}
+ COMMENT "Generating raw kernel...")
+
+# nm
add_custom_command(TARGET ${KernelName}
- POST_BUILD
- WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
- COMMAND ${CMAKE_OBJDUMP} -D ${KernelName} >> ${KernelName}.disassembly
- COMMENT "Disassembling...")
+ POST_BUILD
+ WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
+ COMMAND ${CMAKE_NM} -a -A -C -l -n -s --special-syms --synthetic ${KernelName}
+ > ${KernelName}.nm
+ COMMENT "nm...")
-# objdump -t
+# readelf -a
+add_custom_command(TARGET ${KernelName}
+ POST_BUILD
+ WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
+ COMMAND ${CMAKE_READELF} -a ${KernelName} > ${KernelName}.readelf || (exit 0)
+ COMMENT "readelf...")
+
+# objdump -D
add_custom_command(TARGET ${KernelName}
- POST_BUILD
- WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
- COMMAND ${CMAKE_OBJDUMP} -t ${KernelName} >> ${KernelName}.symtlb
- COMMENT "Generating symbol table...")
+ POST_BUILD
+ WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
+ COMMAND ${CMAKE_OBJDUMP} -D ${KernelName} > ${KernelName}.disassembly
+ COMMENT "Disassembling...")
diff --git a/src/arch/CMakeLists.txt b/src/arch/CMakeLists.txt
index 4d1137946..e17ec2700 100644
--- a/src/arch/CMakeLists.txt
+++ b/src/arch/CMakeLists.txt
@@ -9,6 +9,6 @@
if (SimpleKernelArch STREQUAL "ia32/i386" OR SimpleKernelArch STREQUAL "ia32/x86_64")
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/ia32)
else ()
-# 其它情况跳转到与 SimpleKernelArch 同名目录即可
+ # 其它情况跳转到与 SimpleKernelArch 同名目录即可
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${SimpleKernelArch})
endif ()
diff --git a/src/arch/aarch64/CMakeLists.txt b/src/arch/aarch64/CMakeLists.txt
index 867f4091c..8cac90b45 100644
--- a/src/arch/aarch64/CMakeLists.txt
+++ b/src/arch/aarch64/CMakeLists.txt
@@ -1,5 +1,6 @@
-# This file is a part of Simple-XX/SimpleKernel (https://github.com/Simple-XX/SimpleKernel).
+# This file is a part of Simple-XX/SimpleKernel
+# (https://github.com/Simple-XX/SimpleKernel).
#
# CMakeLists.txt for Simple-XX/SimpleKernel.
diff --git a/src/arch/aarch64/boot/boot.S b/src/arch/aarch64/boot/boot.S
index 7d88fbad4..2504a4de0 100644
--- a/src/arch/aarch64/boot/boot.S
+++ b/src/arch/aarch64/boot/boot.S
@@ -4,6 +4,8 @@
// Based on https://wiki.osdev.org/Raspberry_Pi_Bare_Bones
// boot.S for Simple-XX/SimpleKernel.
+// clang-format off
+
.section .init
// Entry point for the kernel.
@@ -12,7 +14,7 @@
// r1 -> 0x00000C42 - machine id
// r2 -> 0x00000100 - start of ATAGS
// preserve these registers as argument for kernel_main
-.globl _start
+.global _start
.type _start, @function
.extern kernel_main
// 规定起始地址
diff --git a/src/arch/aarch64/hardware.h b/src/arch/aarch64/hardware.h
index 9ea08afbd..5a66f7338 100644
--- a/src/arch/aarch64/hardware.h
+++ b/src/arch/aarch64/hardware.h
@@ -1,87 +1,96 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-//
-// hardware.h for Simple-XX/SimpleKernel.
+/**
+ * @file hardware.h
+ * @brief 硬件定义
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
-#ifndef _HARDWARE_H_
-#define _HARDWARE_H_
+#ifndef SIMPLEKERNEL_HARDWARE_H
+#define SIMPLEKERNEL_HARDWARE_H
-#include "stdint.h"
+#include "cstdint"
namespace HARDWARE {
- // for raspi2 & 3
- static constexpr const uint32_t MMIO_BASE = 0x3F000000;
- // The offsets for reach register.
- static constexpr const uint32_t GPIO_BASE = MMIO_BASE + 0x200000;
- // Controls actuation of pull up/down to ALL GPIO pins.
- static constexpr const uint32_t GPPUD = GPIO_BASE + 0x94;
- // Controls actuation of pull up/down for specific GPIO pin.
- static constexpr const uint32_t GPPUDCLK0 = GPIO_BASE + 0x98;
+// for raspi2 & 3
+static constexpr const uint32_t MMIO_BASE = 0x3F000000;
+// The offsets for reach register.
+static constexpr const uint32_t GPIO_BASE = MMIO_BASE + 0x200000;
+// Controls actuation of pull up/down to ALL GPIO pins.
+static constexpr const uint32_t GPPUD = GPIO_BASE + 0x94;
+// Controls actuation of pull up/down for specific GPIO pin.
+static constexpr const uint32_t GPPUDCLK0 = GPIO_BASE + 0x98;
- // 设备 id
- static constexpr const uint32_t DEVICE_ID_SD_CARD = 0x00000000;
- static constexpr const uint32_t DEVICE_ID_UART0 = 0x00000001;
- static constexpr const uint32_t DEVICE_ID_UART1 = 0x00000002;
- static constexpr const uint32_t DEVICE_ID_USB_HCD = 0x00000003;
- static constexpr const uint32_t DEVICE_ID_I2C0 = 0x00000004;
- static constexpr const uint32_t DEVICE_ID_I2C1 = 0x00000005;
- static constexpr const uint32_t DEVICE_ID_I2C2 = 0x00000006;
- static constexpr const uint32_t DEVICE_ID_SPI = 0x00000007;
- static constexpr const uint32_t DEVICE_ID_CCP2TX = 0x00000008;
+// 设备 id
+static constexpr const uint32_t DEVICE_ID_SD_CARD = 0x00000000;
+static constexpr const uint32_t DEVICE_ID_UART0 = 0x00000001;
+static constexpr const uint32_t DEVICE_ID_UART1 = 0x00000002;
+static constexpr const uint32_t DEVICE_ID_USB_HCD = 0x00000003;
+static constexpr const uint32_t DEVICE_ID_I2C0 = 0x00000004;
+static constexpr const uint32_t DEVICE_ID_I2C1 = 0x00000005;
+static constexpr const uint32_t DEVICE_ID_I2C2 = 0x00000006;
+static constexpr const uint32_t DEVICE_ID_SPI = 0x00000007;
+static constexpr const uint32_t DEVICE_ID_CCP2TX = 0x00000008;
- // 时钟 id
- static constexpr const uint32_t CLOCK_ID_RESERVED = 0x000000000;
- static constexpr const uint32_t CLOCK_ID_EMMC = 0x000000001;
- static constexpr const uint32_t CLOCK_ID_UART = 0x000000002;
- static constexpr const uint32_t CLOCK_ID_ARM = 0x000000003;
- static constexpr const uint32_t CLOCK_ID_CORE = 0x000000004;
- static constexpr const uint32_t CLOCK_ID_V3D = 0x000000005;
- static constexpr const uint32_t CLOCK_ID_H264 = 0x000000006;
- static constexpr const uint32_t CLOCK_ID_ISP = 0x000000007;
- static constexpr const uint32_t CLOCK_ID_SDRAM = 0x000000008;
- static constexpr const uint32_t CLOCK_ID_PIXEL = 0x000000009;
- static constexpr const uint32_t CLOCK_ID_PWM = 0x00000000a;
- static constexpr const uint32_t CLOCK_ID_HEVC = 0x00000000b;
- static constexpr const uint32_t CLOCK_ID_EMMC2 = 0x00000000c;
- static constexpr const uint32_t CLOCK_ID_M2MC = 0x00000000d;
- static constexpr const uint32_t CLOCK_ID_PIXEL_BVB = 0x00000000e;
+// 时钟 id
+static constexpr const uint32_t CLOCK_ID_RESERVED = 0x000000000;
+static constexpr const uint32_t CLOCK_ID_EMMC = 0x000000001;
+static constexpr const uint32_t CLOCK_ID_UART = 0x000000002;
+static constexpr const uint32_t CLOCK_ID_ARM = 0x000000003;
+static constexpr const uint32_t CLOCK_ID_CORE = 0x000000004;
+static constexpr const uint32_t CLOCK_ID_V3D = 0x000000005;
+static constexpr const uint32_t CLOCK_ID_H264 = 0x000000006;
+static constexpr const uint32_t CLOCK_ID_ISP = 0x000000007;
+static constexpr const uint32_t CLOCK_ID_SDRAM = 0x000000008;
+static constexpr const uint32_t CLOCK_ID_PIXEL = 0x000000009;
+static constexpr const uint32_t CLOCK_ID_PWM = 0x00000000a;
+static constexpr const uint32_t CLOCK_ID_HEVC = 0x00000000b;
+static constexpr const uint32_t CLOCK_ID_EMMC2 = 0x00000000c;
+static constexpr const uint32_t CLOCK_ID_M2MC = 0x00000000d;
+static constexpr const uint32_t CLOCK_ID_PIXEL_BVB = 0x00000000e;
- // 电压 id
- static constexpr const uint32_t VOLTAGE_ID_RESERVED = 0x000000000;
- static constexpr const uint32_t VOLTAGE_ID_CORE = 0x000000001;
- static constexpr const uint32_t VOLTAGE_ID_SDRAM_C = 0x000000002;
- static constexpr const uint32_t VOLTAGE_ID_SDRAM_P = 0x000000003;
- static constexpr const uint32_t VOLTAGE_ID_SDRAM_I = 0x000000004;
+// 电压 id
+static constexpr const uint32_t VOLTAGE_ID_RESERVED = 0x000000000;
+static constexpr const uint32_t VOLTAGE_ID_CORE = 0x000000001;
+static constexpr const uint32_t VOLTAGE_ID_SDRAM_C = 0x000000002;
+static constexpr const uint32_t VOLTAGE_ID_SDRAM_P = 0x000000003;
+static constexpr const uint32_t VOLTAGE_ID_SDRAM_I = 0x000000004;
- // mailbox 地址
- static constexpr const uint32_t MAILBOX_OFFSET = 0x0000B880;
- static constexpr const uint32_t MAILBOX_READ_OFFSET = 0x0;
- static constexpr const uint32_t MAILBOX_POLL_OFFSET = 0x10;
- static constexpr const uint32_t MAILBOX_SENDER_OFFSET = 0x14;
- static constexpr const uint32_t MAILBOX_STATUS_OFFSET = 0x18;
- static constexpr const uint32_t MAILBOX_CONFIG_OFFSET = 0x1C;
- static constexpr const uint32_t MAILBOX_WRITE_OFFSET = 0x20;
- static constexpr const uint32_t MAILBOX_VIDEOCORE =
- MMIO_BASE + MAILBOX_OFFSET;
- static constexpr const uint32_t MAILBOX_READ =
- MAILBOX_VIDEOCORE + MAILBOX_READ_OFFSET;
- static constexpr const uint32_t MAILBOX_POLL =
- MAILBOX_VIDEOCORE + MAILBOX_POLL_OFFSET;
- static constexpr const uint32_t MAILBOX_SENDER =
- MAILBOX_VIDEOCORE + MAILBOX_SENDER_OFFSET;
- static constexpr const uint32_t MAILBOX_STATUS =
- MAILBOX_VIDEOCORE + MAILBOX_STATUS_OFFSET;
- static constexpr const uint32_t MAILBOX_CONFIG =
- MAILBOX_VIDEOCORE + MAILBOX_CONFIG_OFFSET;
- static constexpr const uint32_t MAILBOX_WRITE =
- MAILBOX_VIDEOCORE + MAILBOX_WRITE_OFFSET;
- static constexpr const uint32_t MAILBOX_RESPONSE_SUCCESSFUL = 0x80000000;
- static constexpr const uint32_t MAILBOX_RESPONSE_ERROR = 0x80000001;
- // 1<<31
- static constexpr const uint32_t MAILBOX_FULL = 0x80000000;
- // 1<<30
- static constexpr const uint32_t MAILBOX_EMPTY = 0x40000000;
-};
+// mailbox 地址
+static constexpr const uint32_t MAILBOX_OFFSET = 0x0000B880;
+static constexpr const uint32_t MAILBOX_READ_OFFSET = 0x0;
+static constexpr const uint32_t MAILBOX_POLL_OFFSET = 0x10;
+static constexpr const uint32_t MAILBOX_SENDER_OFFSET = 0x14;
+static constexpr const uint32_t MAILBOX_STATUS_OFFSET = 0x18;
+static constexpr const uint32_t MAILBOX_CONFIG_OFFSET = 0x1C;
+static constexpr const uint32_t MAILBOX_WRITE_OFFSET = 0x20;
+static constexpr const uint32_t MAILBOX_VIDEOCORE = MMIO_BASE + MAILBOX_OFFSET;
+static constexpr const uint32_t MAILBOX_READ
+ = MAILBOX_VIDEOCORE + MAILBOX_READ_OFFSET;
+static constexpr const uint32_t MAILBOX_POLL
+ = MAILBOX_VIDEOCORE + MAILBOX_POLL_OFFSET;
+static constexpr const uint32_t MAILBOX_SENDER
+ = MAILBOX_VIDEOCORE + MAILBOX_SENDER_OFFSET;
+static constexpr const uint32_t MAILBOX_STATUS
+ = MAILBOX_VIDEOCORE + MAILBOX_STATUS_OFFSET;
+static constexpr const uint32_t MAILBOX_CONFIG
+ = MAILBOX_VIDEOCORE + MAILBOX_CONFIG_OFFSET;
+static constexpr const uint32_t MAILBOX_WRITE
+ = MAILBOX_VIDEOCORE + MAILBOX_WRITE_OFFSET;
+static constexpr const uint32_t MAILBOX_RESPONSE_SUCCESSFUL = 0x80000000;
+static constexpr const uint32_t MAILBOX_RESPONSE_ERROR = 0x80000001;
+// 1<<31
+static constexpr const uint32_t MAILBOX_FULL = 0x80000000;
+// 1<<30
+static constexpr const uint32_t MAILBOX_EMPTY = 0x40000000;
+}; // namespace HARDWARE
-#endif /* _HARDWARE_H_ */
+#endif /* SIMPLEKERNEL_HARDWARE_H */
diff --git a/src/arch/aarch64/link.ld b/src/arch/aarch64/link.ld
index cbceed022..98c8d306a 100644
--- a/src/arch/aarch64/link.ld
+++ b/src/arch/aarch64/link.ld
@@ -1,7 +1,10 @@
-/* This file is a part of Simple-XX/SimpleKernel (https://github.com/Simple-XX/SimpleKernel).
+/* This file is a part of Simple-XX/SimpleKernel
+ * (https://github.com/Simple-XX/SimpleKernel).
*
- * link.ld for Simple-XX/SimpleKernel. */
+ * link.ld for Simple-XX/SimpleKernel.
+ * 链接脚本,指定生成的二进制文件的布局
+ */
OUTPUT_FORMAT(elf64-littleaarch64)
diff --git a/src/arch/aarch64/port/include/port.h b/src/arch/aarch64/port/include/port.h
index 37310d170..bd644de17 100644
--- a/src/arch/aarch64/port/include/port.h
+++ b/src/arch/aarch64/port/include/port.h
@@ -1,27 +1,37 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-//
-// port.h for Simple-XX/SimpleKernel.
+/**
+ * @file port.h
+ * @brief arm 端口驱动
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
-#ifndef _PORT_H_
-#define _PORT_H_
+#ifndef SIMPLEKERNEL_PORT_H
+#define SIMPLEKERNEL_PORT_H
-#include "stdint.h"
+#include "cstdint"
namespace PORT {
- // 端口读一个字节
- uint8_t inb(const uint32_t port);
- // 端口读一个字
- uint16_t inw(const uint32_t port);
- // 端口读一个双字
- uint32_t ind(const uint32_t port);
- // 端口写一个字节
- void outb(const uint32_t port, const uint8_t data);
- // 端口写一个字
- void outw(const uint32_t port, const uint16_t data);
- // 端口写一个双字
- void outd(const uint32_t port, const uint32_t data);
-};
+// 端口读一个字节
+uint8_t inb(const uint32_t port);
+// 端口读一个字
+uint16_t inw(const uint32_t port);
+// 端口读一个双字
+uint32_t ind(const uint32_t port);
+// 端口写一个字节
+void outb(const uint32_t port, const uint8_t data);
+// 端口写一个字
+void outw(const uint32_t port, const uint16_t data);
+// 端口写一个双字
+void outd(const uint32_t port, const uint32_t data);
+}; // namespace PORT
-#endif /* _PORT_H_ */
+#endif /* SIMPLEKERNEL_PORT_H */
diff --git a/src/arch/aarch64/port/port.cpp b/src/arch/aarch64/port/port.cpp
index 8a24cf5a8..a52701cf6 100644
--- a/src/arch/aarch64/port/port.cpp
+++ b/src/arch/aarch64/port/port.cpp
@@ -1,8 +1,18 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-//
-// port.cpp for Simple-XX/SimpleKernel.
+/**
+ * @file port.cpp
+ * @brief 串口驱动
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
#include "port.h"
@@ -15,7 +25,7 @@ uint16_t PORT::inw(const uint32_t port __attribute((unused))) {
}
uint32_t PORT::ind(const uint32_t port) {
- return *(volatile uint32_t *)port;
+ return *(volatile uint32_t*)port;
}
void PORT::outw(const uint32_t port __attribute((unused)),
@@ -29,6 +39,6 @@ void PORT::outb(const uint32_t port __attribute((unused)),
}
void PORT::outd(const uint32_t port, const uint32_t data) {
- *(volatile uint32_t *)port = data;
+ *(volatile uint32_t*)port = data;
return;
}
diff --git a/src/arch/ia32/CMakeLists.txt b/src/arch/ia32/CMakeLists.txt
index 50b05bb34..49e2c1707 100644
--- a/src/arch/ia32/CMakeLists.txt
+++ b/src/arch/ia32/CMakeLists.txt
@@ -22,10 +22,9 @@ if (${SimpleKernelArch} STREQUAL "ia32/i386")
find_asm_source_files(intr_asm_src ${arch_SOURCE_DIR}/i386/intr)
aux_source_directory(${arch_SOURCE_DIR}/i386/intr intr_cpp_src)
- set(intr_src ${intr_asm_src} ${intr_cpp_src})
+ set(intr_src ${intr_asm_src} ${intr_cpp_src})
-
-# 64 位
+ # 64 位
elseif (${SimpleKernelArch} STREQUAL "ia32/x86_64")
# 寻找汇编文件
find_asm_source_files(boot_asm_src ${arch_SOURCE_DIR}/x86_64/boot)
@@ -38,7 +37,7 @@ elseif (${SimpleKernelArch} STREQUAL "ia32/x86_64")
find_asm_source_files(intr_asm_src ${arch_SOURCE_DIR}/x86_64/intr)
aux_source_directory(${arch_SOURCE_DIR}/x86_64/intr intr_cpp_src)
- set(intr_src ${intr_asm_src} ${intr_cpp_src})
+ set(intr_src ${intr_asm_src} ${intr_cpp_src})
endif ()
# 寻找 CXX 文件
@@ -52,11 +51,12 @@ set(apic_src ${apic_cpp_src})
# 设置子模块所有的源码
set(arch_src ${boot_src} ${port_src} ${gdt_src} ${intr_src} ${apic_src})
-# 添加子模块
+# 添加子模块
add_library(${PROJECT_NAME} OBJECT ${arch_src})
# 添加头文件搜索路径
target_include_arch_header_files(${PROJECT_NAME})
target_include_libc_header_files(${PROJECT_NAME})
+target_include_libcxx_header_files(${PROJECT_NAME})
target_include_common_header_files(${PROJECT_NAME})
target_include_drv_header_files(${PROJECT_NAME})
diff --git a/src/arch/ia32/apic/apic.cpp b/src/arch/ia32/apic/apic.cpp
index f7eb2a840..41fbf84f9 100644
--- a/src/arch/ia32/apic/apic.cpp
+++ b/src/arch/ia32/apic/apic.cpp
@@ -14,11 +14,9 @@
*
*/
-#include "stdio.h"
-#include "assert.h"
-#include "intr.h"
-#include "cpu.hpp"
#include "apic.h"
+#include "cstdio"
+#include "intr.h"
// 64-ia-32-architectures-software-developer-vol-3a-manual#10
diff --git a/src/arch/ia32/apic/include/apic.h b/src/arch/ia32/apic/include/apic.h
index c4ba05d24..e5dc5e87c 100644
--- a/src/arch/ia32/apic/include/apic.h
+++ b/src/arch/ia32/apic/include/apic.h
@@ -17,14 +17,16 @@
#ifndef _APIC_H_
#define _APIC_H_
-#include "stdint.h"
+#include "cstdint"
/**
* @brief APIC 抽象
*/
class APIC {
private:
+
protected:
+
public:
APIC(void);
~APIC(void);
@@ -36,7 +38,9 @@ class APIC {
*/
class LOCAL_APIC {
private:
+
protected:
+
public:
LOCAL_APIC(void);
~LOCAL_APIC(void);
@@ -48,7 +52,9 @@ class LOCAL_APIC {
*/
class IO_APIC {
private:
+
protected:
+
public:
IO_APIC(void);
~IO_APIC(void);
diff --git a/src/arch/ia32/apic/io_apic.cpp b/src/arch/ia32/apic/io_apic.cpp
index 3259415e3..a96e5df37 100644
--- a/src/arch/ia32/apic/io_apic.cpp
+++ b/src/arch/ia32/apic/io_apic.cpp
@@ -14,10 +14,9 @@
*
*/
-#include "intr.h"
-#include "cpu.hpp"
-#include "io.h"
#include "apic.h"
+#include "cpu.hpp"
+#include "intr.h"
/// @todo
diff --git a/src/arch/ia32/apic/local_apic.cpp b/src/arch/ia32/apic/local_apic.cpp
index 12a60268f..5c8923409 100644
--- a/src/arch/ia32/apic/local_apic.cpp
+++ b/src/arch/ia32/apic/local_apic.cpp
@@ -14,11 +14,10 @@
*
*/
-#include "stdio.h"
-#include "assert.h"
-#include "intr.h"
-#include "cpu.hpp"
#include "apic.h"
+#include "cpu.hpp"
+#include "cstdio"
+#include "intr.h"
/// @see 64-ia-32-architectures-software-developer-vol-3a-manual#10
@@ -42,10 +41,10 @@ int32_t LOCAL_APIC::init(void) {
if (cpuid.x2apic() == false) {
warn("Not support x2APIC.\n");
}
- uint64_t msr = CPU::READ_MSR(CPU::IA32_APIC_BASE);
+ uint64_t msr = CPU::READ_MSR(CPU::IA32_APIC_BASE);
// 开启 xAPIC 与 x2APIC
- msr |= (CPU::IA32_APIC_BASE_GLOBAL_ENABLE_BIT |
- CPU::IA32_APIC_BASE_X2APIC_ENABLE_BIT);
+ msr |= (CPU::IA32_APIC_BASE_GLOBAL_ENABLE_BIT
+ | CPU::IA32_APIC_BASE_X2APIC_ENABLE_BIT);
CPU::WRITE_MSR(CPU::IA32_APIC_BASE, msr);
// 设置 SIVR
msr = CPU::READ_MSR(CPU::IA32_X2APIC_SIVR);
@@ -56,9 +55,9 @@ int32_t LOCAL_APIC::init(void) {
CPU::WRITE_MSR(CPU::IA32_X2APIC_SIVR, msr);
// 屏蔽所有 LVT
- msr = 0;
+ msr = 0;
msr |= CPU::IA32_X2APIC_LVT_MASK_BIT;
- msr = 0x10000;
+ msr = 0x10000;
CPU::WRITE_MSR(CPU::IA32_X2APIC_CMCI, msr);
CPU::WRITE_MSR(CPU::IA32_X2APIC_LVT_TIMER, msr);
CPU::WRITE_MSR(CPU::IA32_X2APIC_LVT_THERMAL, msr);
diff --git a/src/arch/ia32/cpu.hpp b/src/arch/ia32/cpu.hpp
index c366a8334..35efc55ae 100644
--- a/src/arch/ia32/cpu.hpp
+++ b/src/arch/ia32/cpu.hpp
@@ -14,535 +14,540 @@
*
*/
-#ifndef _CPU_HPP_
-#define _CPU_HPP_
+#ifndef SIMPLEKERNEL_CPU_HPP
+#define SIMPLEKERNEL_CPU_HPP
-#include "stdint.h"
-#include "stdbool.h"
-#include "assert.h"
-#include "string.h"
+#include "cstdbool"
+#include "cstdint"
+#include "cstdio"
+#include "cstring"
/**
* @brief cpu 相关
* @todo CPUID 相关操作,补全寄存器操作,数据地址等
*/
namespace CPU {
- // CR0:包含当前处理器运行的控制标志。
- // CR1:保留。
- // CR2:包含发生页面错误时的线性地址。
- // CR3:页面目录表(Page Directory Table)的物理地址。
- // 虚拟地址启用且CR0中PG位设置为1的情况下,CR3可以协助处理器将线性地址转换为物理地址。一般情况下为MMU提供页表的入口实现。
- // CR4:包含处理器扩展功能的标志位。
- // CR8:提供对任务优先级寄存器(Task Priority
- // Register)的读写(仅在64位模式下存在)。 对控制寄存器的读写是通过MOV
- // CRn指令来实现
-
- /// PE:CR0的位0是启用保护(Protection
- // Enable)标志。当设置该位时即开启了保护模式;
- // 当复位时即进入实地址模式。这个标志仅开启段级保护,而并没有启用分页机制。若要启用分页机制,那么PE和PG标志都要置位。
- static constexpr const uint32_t CR0_PE = 0x00000001;
- static constexpr const uint32_t CR0_MP = 0x00000002;
- static constexpr const uint32_t CR0_EM = 0x00000004;
- static constexpr const uint32_t CR0_TS = 0x00000008;
- static constexpr const uint32_t CR0_ET = 0x00000010;
-
- /// NE:对于 Intel 80486或以上的CPU,CR0 的位5是协处理器错误(Numeric
- // Error)标志。 当设置该标志时,就启用了 x87
- // 协处理器错误的内部报告机制;若复位该标志,那么就使用 PC 形式的 x87
- // 协处理器错误报告机制。 当NE为复位状态并且 CPU 的 IGNNE
- // 输入引脚有信号时,那么数学协处理器 x87 错误将被忽略。 当NE为复位状态并且
- // CPU 的 IGNNE 输入引脚无信号时,那么非屏蔽的数学协处理器 x87
- // 错误将导致处理器通过 FERR 引脚在外部产生一个中断,
- // 并且在执行下一个等待形式浮点指令或 WAIT/FWAIT 指令之前立刻停止指令执行。
- // CPU 的 FERR 引脚用于仿真外部协处理器 80387 的 ERROR 引脚,
- // 因此通常连接到中断控制器输入请求引脚上。NE 标志、IGNNE 引脚和 FERR
- // 引脚用于利用外部逻辑来实现 PC 形式的外部错误报告机制。
- static constexpr const uint32_t CR0_NE = 0x00000020;
-
- /// WP:对于Intel 80486或以上的CPU,CR0的位16是写保护(Write
- /// Proctect)标志。
- // 当设置该标志时,处理器会禁止超级用户程序(例如特权级0的程序)向用户级只读页面执行写操作;当该位复位时则反之。该标志有利于UNIX类操作系统在创建进程时实现写时复制(Copy
- // on Write)技术。
- static constexpr const uint32_t CR0_WP = 0x00010020;
- static constexpr const uint32_t CR0_AM = 0x00040020;
- static constexpr const uint32_t CR0_NW = 0x20000000;
- static constexpr const uint32_t CR0_CD = 0x40000000;
-
- /// PG:CR0的位31是分页(Paging)标志。当设置该位时即开启了分页机制;
- // 当复位时则禁止分页机制,此时所有线性地址等同于物理地址。在开启这个标志之前必须已经或者同时开启PE标志。即若要启用分页机制,那么PE和PG标志都要置位。
- static constexpr const uint32_t CR0_PG = 0x80000000;
-
- /// 启用保护模式PE(Protected
- // Enable)位(位0)和开启分页PG(Paging)位(位31)分别用于控制分段和分页机制。
- // PE用于控制分段机制。如果PE=1,处理器就工作在开启分段机制环境下,即运行在保护模式下。
- // 如果PE=0,则处理器关闭了分段机制,并如同8086工作于实地址模式下。PG用于控制分页机制。如果PG=1,则开启了分页机制。
- // 如果PG=0,分页机制被禁止,此时线性地址被直接作为物理地址使用。
- // 如果PE=0、PG=0,处理器工作在实地址模式下;如果PG=0、PE=1,处理器工作在没有开启分页机制的保护模式下;
- // 如果PG=1、PE=0,此时由于不在保护模式下不能启用分页机制,因此处理器会产生一个一般保护异常,即这种标志组合无效;
- // 如果PG=1、PE=1,则处理器工作在开启了分页机制的保护模式下。
-
- static constexpr const uint32_t CR3_PWT = 0x00000008;
- static constexpr const uint32_t CR3_PCD = 0x00000010;
-
- static constexpr const uint32_t CR4_VME = 0x00000001;
- static constexpr const uint32_t CR4_PVI = 0x00000002;
- static constexpr const uint32_t CR4_TSD = 0x00000004;
- static constexpr const uint32_t CR4_DE = 0x00000008;
- // PSE 为 1 时,32bits 的页面大小变为 4MB
- // 32bits 模式的分页模式支持物理地址宽度超过
- // 32bit,这种情况下的页面大小必须是 4MB,并且处理器必须支持 PSE-3
- static constexpr const uint32_t CR4_PSE = 0x00000010;
- // 物理地址拓展
- // 32bits 下寻址变为三级
- static constexpr const uint32_t CR4_PAE = 0x00000020;
- static constexpr const uint32_t CR4_MCE = 0x00000040;
- static constexpr const uint32_t CR4_PGE = 0x00000080;
- static constexpr const uint32_t CR4_PCE = 0x00000100;
- static constexpr const uint32_t CR4_OSFXSR = 0x00000200;
- static constexpr const uint32_t CR4_OSXMMEXCPT = 0x00000400;
- static constexpr const uint32_t CR4_VMXE = 0x00002000;
- static constexpr const uint32_t CR4_SMXE = 0x00004000;
- static constexpr const uint32_t CR4_PCIDE = 0x00020000;
- static constexpr const uint32_t CR4_OSXSAVE = 0x00040000;
- static constexpr const uint32_t CR4_SMEP = 0x00100000;
-
- static constexpr const uint32_t IA32_APIC_BASE = 0x1B;
- static constexpr const uint32_t IA32_APIC_BASE_BSP_BIT = 1 << 8;
- static constexpr const uint32_t IA32_APIC_BASE_X2APIC_ENABLE_BIT = 1 << 10;
- static constexpr const uint32_t IA32_APIC_BASE_GLOBAL_ENABLE_BIT = 1 << 11;
-
- // x2APIC ID Register (R/O)
- static constexpr const uint32_t IA32_X2APIC_APICID = 0x802;
- // x2APIC Version Register (R/O)
- static constexpr const uint32_t IA32_X2APIC_VERSION = 0x803;
- // Support for EOI-broadcast suppression
- static constexpr const uint32_t IA32_X2APIC_VERSION_EOI_SUPPORT_BIT = 1
- << 24;
- // x2APIC Task Priority Register (R/W)
- static constexpr const uint32_t IA32_X2APIC_TPR = 0x808;
- // x2APIC Processor Priority Register (R/O)
- static constexpr const uint32_t IA32_X2APIC_PPR = 0x80A;
- // x2APIC EOI Register (W/O)
- static constexpr const uint32_t IA32_X2APIC_EOI = 0x80B;
- // x2APIC Logical Destination Register (R/O)
- static constexpr const uint32_t IA32_X2APIC_LDR = 0x80D;
- // x2APIC Spurious Interrupt Vector Register (R/W)
- static constexpr const uint32_t IA32_X2APIC_SIVR = 0x80F;
- // 伪中断向量号
- static constexpr const uint32_t IA32_X2APIC_SIVR_NO_BIT = 0x0;
- // APIC 软件使能 1:enable
- static constexpr const uint32_t IA32_X2APIC_SIVR_APIC_ENABLE_BIT = 1 << 8;
- // 焦点处理器 0:disable
- static constexpr const uint32_t IA32_X2APIC_SIVR_FOCUS_ENABLE_BIT = 1 << 9;
- // 禁止广播 EOI 消息使能 1:enable
- static constexpr const uint32_t IA32_X2APIC_SIVR_EOI_ENABLE_BIT = 1 << 12;
- // x2APIC In-Service Register Bits 31:0 (R/O)
- static constexpr const uint32_t IA32_X2APIC_ISR0 = 0x810;
- static constexpr const uint32_t IA32_X2APIC_ISR1 = 0x811;
- static constexpr const uint32_t IA32_X2APIC_ISR2 = 0x812;
- static constexpr const uint32_t IA32_X2APIC_ISR3 = 0x813;
- static constexpr const uint32_t IA32_X2APIC_ISR4 = 0x814;
- static constexpr const uint32_t IA32_X2APIC_ISR5 = 0x815;
- static constexpr const uint32_t IA32_X2APIC_ISR6 = 0x816;
- // x2APIC In-Service Register Bits 255:224 (R/O)
- static constexpr const uint32_t IA32_X2APIC_ISR7 = 0x817;
- // x2APIC Trigger Mode Register Bits 31:0 (R/O)
- static constexpr const uint32_t IA32_X2APIC_TMR0 = 0x818;
- static constexpr const uint32_t IA32_X2APIC_TMR1 = 0x819;
- static constexpr const uint32_t IA32_X2APIC_TMR2 = 0x81A;
- static constexpr const uint32_t IA32_X2APIC_TMR3 = 0x81B;
- static constexpr const uint32_t IA32_X2APIC_TMR4 = 0x81C;
- static constexpr const uint32_t IA32_X2APIC_TMR5 = 0x81D;
- static constexpr const uint32_t IA32_X2APIC_TMR6 = 0x81E;
- // x2APIC Trigger Mode Register Bits 255:224 (R/O)
- static constexpr const uint32_t IA32_X2APIC_TMR7 = 0x81F;
- // x2APIC Interrupt Request Register Bits 31:0 (R/O)
- static constexpr const uint32_t IA32_X2APIC_IRR0 = 0x820;
- static constexpr const uint32_t IA32_X2APIC_IRR1 = 0x821;
- static constexpr const uint32_t IA32_X2APIC_IRR2 = 0x822;
- static constexpr const uint32_t IA32_X2APIC_IRR3 = 0x823;
- static constexpr const uint32_t IA32_X2APIC_IRR4 = 0x824;
- static constexpr const uint32_t IA32_X2APIC_IRR5 = 0x825;
- static constexpr const uint32_t IA32_X2APIC_IRR6 = 0x826;
- // x2APIC Interrupt Request Register Bits 255:224 (R/O)
- static constexpr const uint32_t IA32_X2APIC_IRR7 = 0x827;
- // x2APIC Error Status Register (R/W)
- static constexpr const uint32_t IA32_X2APIC_ESR = 0x828;
- // x2APIC LVT Corrected Machine Check Interrupt Register (R/W)
- static constexpr const uint32_t IA32_X2APIC_CMCI = 0x82F;
- // x2APIC Interrupt Command Register (R/W)
- static constexpr const uint32_t IA32_X2APIC_ICR = 0x830;
- // x2APIC LVT Timer Interrupt Register (R/W)
- static constexpr const uint32_t IA32_X2APIC_LVT_TIMER = 0x832;
- // x2APIC LVT Thermal Sensor Interrupt Register (R/W)
- static constexpr const uint32_t IA32_X2APIC_LVT_THERMAL = 0x833;
- // x2APIC LVT Performance Monitor Interrupt Register (R/W)
- static constexpr const uint32_t IA32_X2APIC_LVT_PMI = 0x834;
- // x2APIC LVT LINT0 Register (R/W)
- static constexpr const uint32_t IA32_X2APIC_LVT_LINT0 = 0x835;
- // x2APIC LVT LINT1 Register (R/W)
- static constexpr const uint32_t IA32_X2APIC_LVT_LINT1 = 0x836;
- // x2APIC LVT Error Register (R/W)
- static constexpr const uint32_t IA32_X2APIC_LVT_ERROR = 0x837;
- // Bits 0-7 The vector number
- static constexpr const uint32_t IA32_X2APIC_LVT_NO_BIT = 0x0;
- // Bits 8-11 (reserved for timer) 100b if NMI
- static constexpr const uint32_t IA32_X2APIC_LVT_NMI_BIT = 1 << 8;
- // Bit 12 Set if interrupt pending.
- static constexpr const uint32_t IA32_X2APIC_LVT_PENDING_BIT = 1 << 12;
- // Bit 13 (reserved for timer) Polarity, set is low triggered
- static constexpr const uint32_t IA32_X2APIC_LVT_POLAR_BIT = 1 << 13;
- // Bit 14 (reserved for timer) Remote IRR
- static constexpr const uint32_t IA32_X2APIC_LVT_REMOTE_IRR_BIT = 1 << 14;
- // Bit 15 (reserved for timer) trigger mode, set is level triggered
- static constexpr const uint32_t IA32_X2APIC_LVT_TRIGGER_BIT = 1 << 15;
- // Bit 16 Set to mask
- static constexpr const uint32_t IA32_X2APIC_LVT_MASK_BIT = 1 << 16;
- // Bits 17-31 Reserved
-
- // x2APIC Initial Count Register(R/W)
- static constexpr const uint32_t IA32_X2APIC_TIMER_INIT_COUNT = 0x838;
- // x2APIC Current Count Register (R/O)
- static constexpr const uint32_t IA32_X2APIC_TIMER_CUR_COUNT = 0x839;
- // x2APIC Divide Configuration Register (R/W)
- static constexpr const uint32_t IA32_X2APIC_DIV_CONF = 0x83E;
- // x2APIC Self IPI Register (W/O)
- static constexpr const uint32_t IA32_X2APIC_SELF_IPI = 0x83F;
-
- // 段描述符 DPL
- /// 内核级
- static constexpr const uint32_t DPL0 = 0x00;
- static constexpr const uint32_t DPL1 = 0x01;
- static constexpr const uint32_t DPL2 = 0x02;
- /// 用户级
- static constexpr const uint32_t DPL3 = 0x03;
-
- /**
- * @brief 执行CPU空操作
- */
- static inline void hlt(void) {
- __asm__ volatile("hlt");
- return;
- }
+// CR0:包含当前处理器运行的控制标志。
+// CR1:保留。
+// CR2:包含发生页面错误时的线性地址。
+// CR3:页面目录表(Page Directory Table)的物理地址。
+// 虚拟地址启用且CR0中PG位设置为1的情况下,CR3可以协助处理器将线性地址转换为物理地址。一般情况下为MMU提供页表的入口实现。
+// CR4:包含处理器扩展功能的标志位。
+// CR8:提供对任务优先级寄存器(Task Priority
+// Register)的读写(仅在64位模式下存在)。 对控制寄存器的读写是通过MOV
+// CRn指令来实现
+
+/// PE:CR0的位0是启用保护(Protection
+// Enable)标志。当设置该位时即开启了保护模式;
+// 当复位时即进入实地址模式。这个标志仅开启段级保护,而并没有启用分页机制。若要启用分页机制,那么PE和PG标志都要置位。
+static constexpr const uint32_t CR0_PE = 0x00000001;
+static constexpr const uint32_t CR0_MP = 0x00000002;
+static constexpr const uint32_t CR0_EM = 0x00000004;
+static constexpr const uint32_t CR0_TS = 0x00000008;
+static constexpr const uint32_t CR0_ET = 0x00000010;
+
+/// NE:对于 Intel 80486或以上的CPU,CR0 的位5是协处理器错误(Numeric
+// Error)标志。 当设置该标志时,就启用了 x87
+// 协处理器错误的内部报告机制;若复位该标志,那么就使用 PC 形式的 x87
+// 协处理器错误报告机制。 当NE为复位状态并且 CPU 的 IGNNE
+// 输入引脚有信号时,那么数学协处理器 x87 错误将被忽略。 当NE为复位状态并且
+// CPU 的 IGNNE 输入引脚无信号时,那么非屏蔽的数学协处理器 x87
+// 错误将导致处理器通过 FERR 引脚在外部产生一个中断,
+// 并且在执行下一个等待形式浮点指令或 WAIT/FWAIT 指令之前立刻停止指令执行。
+// CPU 的 FERR 引脚用于仿真外部协处理器 80387 的 ERROR 引脚,
+// 因此通常连接到中断控制器输入请求引脚上。NE 标志、IGNNE 引脚和 FERR
+// 引脚用于利用外部逻辑来实现 PC 形式的外部错误报告机制。
+static constexpr const uint32_t CR0_NE = 0x00000020;
+
+/// WP:对于Intel 80486或以上的CPU,CR0的位16是写保护(Write
+/// Proctect)标志。
+// 当设置该标志时,处理器会禁止超级用户程序(例如特权级0的程序)向用户级只读页面执行写操作;当该位复位时则反之。该标志有利于UNIX类操作系统在创建进程时实现写时复制(Copy
+// on Write)技术。
+static constexpr const uint32_t CR0_WP = 0x00010020;
+static constexpr const uint32_t CR0_AM = 0x00040020;
+static constexpr const uint32_t CR0_NW = 0x20000000;
+static constexpr const uint32_t CR0_CD = 0x40000000;
+
+/// PG:CR0的位31是分页(Paging)标志。当设置该位时即开启了分页机制;
+// 当复位时则禁止分页机制,此时所有线性地址等同于物理地址。在开启这个标志之前必须已经或者同时开启PE标志。即若要启用分页机制,那么PE和PG标志都要置位。
+static constexpr const uint32_t CR0_PG = 0x80000000;
+
+/// 启用保护模式PE(Protected
+// Enable)位(位0)和开启分页PG(Paging)位(位31)分别用于控制分段和分页机制。
+// PE用于控制分段机制。如果PE=1,处理器就工作在开启分段机制环境下,即运行在保护模式下。
+// 如果PE=0,则处理器关闭了分段机制,并如同8086工作于实地址模式下。PG用于控制分页机制。如果PG=1,则开启了分页机制。
+// 如果PG=0,分页机制被禁止,此时线性地址被直接作为物理地址使用。
+// 如果PE=0、PG=0,处理器工作在实地址模式下;如果PG=0、PE=1,处理器工作在没有开启分页机制的保护模式下;
+// 如果PG=1、PE=0,此时由于不在保护模式下不能启用分页机制,因此处理器会产生一个一般保护异常,即这种标志组合无效;
+// 如果PG=1、PE=1,则处理器工作在开启了分页机制的保护模式下。
+
+static constexpr const uint32_t CR3_PWT = 0x00000008;
+static constexpr const uint32_t CR3_PCD = 0x00000010;
+
+static constexpr const uint32_t CR4_VME = 0x00000001;
+static constexpr const uint32_t CR4_PVI = 0x00000002;
+static constexpr const uint32_t CR4_TSD = 0x00000004;
+static constexpr const uint32_t CR4_DE = 0x00000008;
+// PSE 为 1 时,32bits 的页面大小变为 4MB
+// 32bits 模式的分页模式支持物理地址宽度超过
+// 32bit,这种情况下的页面大小必须是 4MB,并且处理器必须支持 PSE-3
+static constexpr const uint32_t CR4_PSE = 0x00000010;
+// 物理地址拓展
+// 32bits 下寻址变为三级
+static constexpr const uint32_t CR4_PAE = 0x00000020;
+static constexpr const uint32_t CR4_MCE = 0x00000040;
+static constexpr const uint32_t CR4_PGE = 0x00000080;
+static constexpr const uint32_t CR4_PCE = 0x00000100;
+static constexpr const uint32_t CR4_OSFXSR = 0x00000200;
+static constexpr const uint32_t CR4_OSXMMEXCPT = 0x00000400;
+static constexpr const uint32_t CR4_VMXE = 0x00002000;
+static constexpr const uint32_t CR4_SMXE = 0x00004000;
+static constexpr const uint32_t CR4_PCIDE = 0x00020000;
+static constexpr const uint32_t CR4_OSXSAVE = 0x00040000;
+static constexpr const uint32_t CR4_SMEP = 0x00100000;
+
+static constexpr const uint32_t IA32_APIC_BASE = 0x1B;
+static constexpr const uint32_t IA32_APIC_BASE_BSP_BIT = 1 << 8;
+static constexpr const uint32_t IA32_APIC_BASE_X2APIC_ENABLE_BIT = 1 << 10;
+static constexpr const uint32_t IA32_APIC_BASE_GLOBAL_ENABLE_BIT = 1 << 11;
+
+// x2APIC ID Register (R/O)
+static constexpr const uint32_t IA32_X2APIC_APICID = 0x802;
+// x2APIC Version Register (R/O)
+static constexpr const uint32_t IA32_X2APIC_VERSION = 0x803;
+// Support for EOI-broadcast suppression
+static constexpr const uint32_t IA32_X2APIC_VERSION_EOI_SUPPORT_BIT = 1 << 24;
+// x2APIC Task Priority Register (R/W)
+static constexpr const uint32_t IA32_X2APIC_TPR = 0x808;
+// x2APIC Processor Priority Register (R/O)
+static constexpr const uint32_t IA32_X2APIC_PPR = 0x80A;
+// x2APIC EOI Register (W/O)
+static constexpr const uint32_t IA32_X2APIC_EOI = 0x80B;
+// x2APIC Logical Destination Register (R/O)
+static constexpr const uint32_t IA32_X2APIC_LDR = 0x80D;
+// x2APIC Spurious Interrupt Vector Register (R/W)
+static constexpr const uint32_t IA32_X2APIC_SIVR = 0x80F;
+// 伪中断向量号
+static constexpr const uint32_t IA32_X2APIC_SIVR_NO_BIT = 0x0;
+// APIC 软件使能 1:enable
+static constexpr const uint32_t IA32_X2APIC_SIVR_APIC_ENABLE_BIT = 1 << 8;
+// 焦点处理器 0:disable
+static constexpr const uint32_t IA32_X2APIC_SIVR_FOCUS_ENABLE_BIT = 1 << 9;
+// 禁止广播 EOI 消息使能 1:enable
+static constexpr const uint32_t IA32_X2APIC_SIVR_EOI_ENABLE_BIT = 1 << 12;
+// x2APIC In-Service Register Bits 31:0 (R/O)
+static constexpr const uint32_t IA32_X2APIC_ISR0 = 0x810;
+static constexpr const uint32_t IA32_X2APIC_ISR1 = 0x811;
+static constexpr const uint32_t IA32_X2APIC_ISR2 = 0x812;
+static constexpr const uint32_t IA32_X2APIC_ISR3 = 0x813;
+static constexpr const uint32_t IA32_X2APIC_ISR4 = 0x814;
+static constexpr const uint32_t IA32_X2APIC_ISR5 = 0x815;
+static constexpr const uint32_t IA32_X2APIC_ISR6 = 0x816;
+// x2APIC In-Service Register Bits 255:224 (R/O)
+static constexpr const uint32_t IA32_X2APIC_ISR7 = 0x817;
+// x2APIC Trigger Mode Register Bits 31:0 (R/O)
+static constexpr const uint32_t IA32_X2APIC_TMR0 = 0x818;
+static constexpr const uint32_t IA32_X2APIC_TMR1 = 0x819;
+static constexpr const uint32_t IA32_X2APIC_TMR2 = 0x81A;
+static constexpr const uint32_t IA32_X2APIC_TMR3 = 0x81B;
+static constexpr const uint32_t IA32_X2APIC_TMR4 = 0x81C;
+static constexpr const uint32_t IA32_X2APIC_TMR5 = 0x81D;
+static constexpr const uint32_t IA32_X2APIC_TMR6 = 0x81E;
+// x2APIC Trigger Mode Register Bits 255:224 (R/O)
+static constexpr const uint32_t IA32_X2APIC_TMR7 = 0x81F;
+// x2APIC Interrupt Request Register Bits 31:0 (R/O)
+static constexpr const uint32_t IA32_X2APIC_IRR0 = 0x820;
+static constexpr const uint32_t IA32_X2APIC_IRR1 = 0x821;
+static constexpr const uint32_t IA32_X2APIC_IRR2 = 0x822;
+static constexpr const uint32_t IA32_X2APIC_IRR3 = 0x823;
+static constexpr const uint32_t IA32_X2APIC_IRR4 = 0x824;
+static constexpr const uint32_t IA32_X2APIC_IRR5 = 0x825;
+static constexpr const uint32_t IA32_X2APIC_IRR6 = 0x826;
+// x2APIC Interrupt Request Register Bits 255:224 (R/O)
+static constexpr const uint32_t IA32_X2APIC_IRR7 = 0x827;
+// x2APIC Error Status Register (R/W)
+static constexpr const uint32_t IA32_X2APIC_ESR = 0x828;
+// x2APIC LVT Corrected Machine Check Interrupt Register (R/W)
+static constexpr const uint32_t IA32_X2APIC_CMCI = 0x82F;
+// x2APIC Interrupt Command Register (R/W)
+static constexpr const uint32_t IA32_X2APIC_ICR = 0x830;
+// x2APIC LVT Timer Interrupt Register (R/W)
+static constexpr const uint32_t IA32_X2APIC_LVT_TIMER = 0x832;
+// x2APIC LVT Thermal Sensor Interrupt Register (R/W)
+static constexpr const uint32_t IA32_X2APIC_LVT_THERMAL = 0x833;
+// x2APIC LVT Performance Monitor Interrupt Register (R/W)
+static constexpr const uint32_t IA32_X2APIC_LVT_PMI = 0x834;
+// x2APIC LVT LINT0 Register (R/W)
+static constexpr const uint32_t IA32_X2APIC_LVT_LINT0 = 0x835;
+// x2APIC LVT LINT1 Register (R/W)
+static constexpr const uint32_t IA32_X2APIC_LVT_LINT1 = 0x836;
+// x2APIC LVT Error Register (R/W)
+static constexpr const uint32_t IA32_X2APIC_LVT_ERROR = 0x837;
+// Bits 0-7 The vector number
+static constexpr const uint32_t IA32_X2APIC_LVT_NO_BIT = 0x0;
+// Bits 8-11 (reserved for timer) 100b if NMI
+static constexpr const uint32_t IA32_X2APIC_LVT_NMI_BIT = 1 << 8;
+// Bit 12 Set if interrupt pending.
+static constexpr const uint32_t IA32_X2APIC_LVT_PENDING_BIT = 1 << 12;
+// Bit 13 (reserved for timer) Polarity, set is low triggered
+static constexpr const uint32_t IA32_X2APIC_LVT_POLAR_BIT = 1 << 13;
+// Bit 14 (reserved for timer) Remote IRR
+static constexpr const uint32_t IA32_X2APIC_LVT_REMOTE_IRR_BIT = 1 << 14;
+// Bit 15 (reserved for timer) trigger mode, set is level triggered
+static constexpr const uint32_t IA32_X2APIC_LVT_TRIGGER_BIT = 1 << 15;
+// Bit 16 Set to mask
+static constexpr const uint32_t IA32_X2APIC_LVT_MASK_BIT = 1 << 16;
+// Bits 17-31 Reserved
+
+// x2APIC Initial Count Register(R/W)
+static constexpr const uint32_t IA32_X2APIC_TIMER_INIT_COUNT = 0x838;
+// x2APIC Current Count Register (R/O)
+static constexpr const uint32_t IA32_X2APIC_TIMER_CUR_COUNT = 0x839;
+// x2APIC Divide Configuration Register (R/W)
+static constexpr const uint32_t IA32_X2APIC_DIV_CONF = 0x83E;
+// x2APIC Self IPI Register (W/O)
+static constexpr const uint32_t IA32_X2APIC_SELF_IPI = 0x83F;
+
+// 段描述符 DPL
+/// 内核级
+static constexpr const uint32_t DPL0 = 0x00;
+static constexpr const uint32_t DPL1 = 0x01;
+static constexpr const uint32_t DPL2 = 0x02;
+/// 用户级
+static constexpr const uint32_t DPL3 = 0x03;
- /**
- * @brief 开启中断
- */
- static inline void ENABLE_INTR(void) {
- __asm__ volatile("sti" ::: "memory");
- return;
- }
+/**
+ * @brief 执行CPU空操作
+ */
+inline static void hlt(void) {
+ __asm__ volatile("hlt");
+ return;
+}
- /**
- * @brief 关闭中断
- */
- static inline void DISABLE_INTR(void) {
- __asm__ volatile("cli" ::: "memory");
- return;
- }
+/**
+ * @brief 开启中断
+ */
+inline static void ENABLE_INTR(void) {
+ __asm__ volatile("sti" ::: "memory");
+ return;
+}
- /**
- * @brief 触发 debug 中断
- */
- static inline void debug_intr(void) {
- __asm__ volatile("int $0x01");
- return;
- }
+/**
+ * @brief 关闭中断
+ */
+inline static void DISABLE_INTR(void) {
+ __asm__ volatile("cli" ::: "memory");
+ return;
+}
- /**
- * @brief 读取 EFLAGS
- * @return uint32_t eflags 值
- */
- static inline uint64_t READ_EFLAGS(void) {
- uint64_t eflags;
- __asm__ volatile("pushf\n\t"
- "pop %0\n\t"
- : "=r"(eflags));
- return eflags;
- }
+/**
+ * @brief 触发 debug 中断
+ */
+inline static void debug_intr(void) {
+ __asm__ volatile("int $0x01");
+ return;
+}
- /**
- * @brief 读取 CR0
- * @return uint32_t CR0 值
- */
- static inline uint32_t READ_CR0(void) {
- uint32_t cr0;
- __asm__ volatile("mov %%cr0, %0" : "=b"(cr0));
- return cr0;
- }
+/**
+ * @brief 读取 EFLAGS
+ * @return uint32_t eflags 值
+ */
+inline static uint32_t READ_EFLAGS(void) {
+ uint32_t eflags;
+ __asm__ volatile("pushf\n\t"
+ "pop %0\n\t"
+ : "=r"(eflags));
+ return eflags;
+}
- /**
- * @brief 读取 CR2
- * @return uint32_t CR2 值
- */
- static inline uint32_t READ_CR2(void) {
- uint32_t cr2;
- __asm__ volatile("mov %%cr2, %0" : "=b"(cr2));
- return cr2;
- }
+/**
+ * @brief 读取 CR0
+ * @return uint32_t CR0 值
+ */
+inline static uint32_t READ_CR0(void) {
+ uint32_t cr0;
+ __asm__ volatile("mov %%cr0, %0" : "=b"(cr0));
+ return cr0;
+}
- /**
- * @brief 获取页目录 CR3
- * @return uintptr_t CR3 值
- */
- static inline uintptr_t GET_PGD(void) {
- uintptr_t cr3;
- __asm__ volatile("mov %%cr3, %0" : "=b"(cr3));
- return cr3;
- }
+/**
+ * @brief 读取 CR2
+ * @return uint32_t CR2 值
+ */
+inline static uint32_t READ_CR2(void) {
+ uint32_t cr2;
+ __asm__ volatile("mov %%cr2, %0" : "=b"(cr2));
+ return cr2;
+}
- /**
- * @brief 切换内核栈
- * @param _stack_top 要切换的栈顶地址
- */
- static inline void switch_stack(void *_stack_top) {
- asm("mov %0, %%esp" : : "r"(_stack_top));
- asm("xor %%ebp, %%ebp" : :);
- return;
- }
+/**
+ * @brief 设置 页目录
+ * @param _pgd 要设置的页表
+ * @return true 成功
+ * @return false 失败
+ */
+inline static bool SET_PGD(uintptr_t _pgd) {
+ __asm__ volatile("mov %0, %%cr3" : : "r"(_pgd));
+ return true;
+}
- /**
- * @brief 读取 CR4
- * @return uint32_t CR4 值
- */
- static inline uint32_t READ_CR4(void) {
- uint32_t cr4;
- __asm__ volatile("mov %%cr4, %0" : "=b"(cr4));
- return cr4;
- }
+/**
+ * @brief 获取页目录 CR3
+ * @return uintptr_t CR3 值
+ */
+inline static uintptr_t GET_PGD(void) {
+ uintptr_t cr3;
+ __asm__ volatile("mov %%cr3, %0" : "=b"(cr3));
+ return cr3;
+}
- /**
- * @brief 刷新页表缓存
- * @param _addr 要刷新的地址
- */
- static inline void VMM_FLUSH(uintptr_t _addr) {
- __asm__ volatile("invlpg (%0)" : : "r"(_addr) : "memory");
- return;
- }
+/**
+ * @brief 切换内核栈
+ * @param _stack_top 要切换的栈顶地址
+ */
+inline static void switch_stack(void* _stack_top) {
+ asm("mov %0, %%esp" : : "r"(_stack_top));
+ asm("xor %%ebp, %%ebp" : :);
+ return;
+}
- // 开启 PG
- static inline bool ENABLE_PG(void) {
- uintptr_t cr0 = 0;
- __asm__ volatile("mov %%cr0, %0" : "=r"(cr0));
- // 最高位 PG 位置 1,分页开启
- cr0 |= (1u << 31);
- __asm__ volatile("mov %0, %%cr0" : : "r"(cr0));
- info("paging enabled.\n");
- return true;
- }
+/**
+ * @brief 读取 CR4
+ * @return uint32_t CR4 值
+ */
+inline static uint32_t READ_CR4(void) {
+ uint32_t cr4;
+ __asm__ volatile("mov %%cr4, %0" : "=b"(cr4));
+ return cr4;
+}
+
+/**
+ * @brief 刷新页表缓存
+ * @param _addr 要刷新的地址
+ */
+inline static void VMM_FLUSH(uintptr_t _addr) {
+ __asm__ volatile("invlpg (%0)" : : "r"(_addr) : "memory");
+ return;
+}
+
+// 开启 PG
+inline static bool ENABLE_PG(void) {
+ uintptr_t cr0 = 0;
+ __asm__ volatile("mov %%cr0, %0" : "=r"(cr0));
+ // 最高位 PG 位置 1,分页开启
+ cr0 |= (1u << 31);
+ __asm__ volatile("mov %0, %%cr0" : : "r"(cr0));
+ info("paging enabled.\n");
+ return true;
+}
+
+/**
+ * @brief 页表结构 32 位分页
+ * @note Use of CR3 with 32-Bit Paging
+ */
+class cr3_t {
+public:
+ // Ignored
+ uint32_t ignore1 : 3;
+ // Page-level write-through; indirectly determines the memory type used
+ // to access the page directory during linear-address translation
+ uint32_t pwt : 1;
+ // Page-level cache disable; indirectly determines the memory type used
+ // to access the page directory during linear-address translation
+ uint32_t pcd : 1;
+ // Ignored
+ uint32_t ignore2 : 7;
+ // Physical address of the 4-KByte aligned page directory used for
+ // linear-address translation
+ uint32_t addr : 20;
+};
+
+/**
+ * @brief 读 MSR
+ * @param _idx 要读的索引
+ * @return uint64_t 读取的值
+ */
+inline static uint64_t READ_MSR(uint32_t _idx) {
+ uint32_t low;
+ uint32_t high;
+ __asm__ volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(_idx));
+ return ((uint64_t)high << 32) | low;
+}
- /**
- * @brief 页表结构 32 位分页
- * @note Use of CR3 with 32-Bit Paging
- */
- class cr3_t {
- public:
- // Ignored
- uint32_t ignore1 : 3;
- // Page-level write-through; indirectly determines the memory type
- // used to access the page directory during linear-address
- // translation
- uint32_t pwt : 1;
- // Page-level cache disable; indirectly determines the memory type
- // used to access the page directory during linear-address
- // translation
- uint32_t pcd : 1;
- // Ignored
- uint32_t ignore2 : 7;
- // Physical address of the 4-KByte aligned page directory used for
- // linear-address translation
- uint32_t addr : 20;
+/**
+ * @brief 写 MSR
+ * @param _idx 要写的索引
+ * @param _msr 要写的值
+ */
+inline static void WRITE_MSR(uint32_t _idx, uint64_t _msr) {
+ uint32_t low = _msr;
+ uint32_t high = _msr >> 32;
+ __asm__ volatile("wrmsr" : : "a"(low), "d"(high), "c"(_idx));
+ return;
+}
+
+/// @todo 改为 static
+class CPUID {
+private:
+ static constexpr const uint32_t VENDOR_LEN = 16;
+ static constexpr const uint32_t BRAND_LEN = 50;
+ static constexpr const uint32_t FAMILY_LEN = 50;
+ static constexpr const uint32_t MODEL_LEN = 50;
+ // Vendor-strings.
+ static constexpr const char* VENDOR_OLDAMD = "AMDisbetter!";
+ // early engineering samples of AMD K5 processor
+ static constexpr const char* VENDOR_AMD = "AuthenticAMD";
+ static constexpr const char* VENDOR_INTEL = "GenuineIntel";
+ static constexpr const char* VENDOR_Centaur = "CentaurHauls";
+ static constexpr const char* VENDOR_OLDTRANSMETA = "TransmetaCPU";
+ static constexpr const char* VENDOR_TRANSMETA = "GenuineTMx86";
+ static constexpr const char* VENDOR_CYRIX = "CyrixInstead";
+ static constexpr const char* VENDOR_CENTAUR = "CentaurHauls";
+ static constexpr const char* VENDOR_NEXGEN = "NexGenDriven";
+ static constexpr const char* VENDOR_UMC = "UMC UMC UMC ";
+ static constexpr const char* VENDOR_SIS = "SiS SiS SiS ";
+ static constexpr const char* VENDOR_NSC = "Geode by NSC";
+ static constexpr const char* VENDOR_RISE = "RiseRiseRise";
+ static constexpr const char* VENDOR_VORTEX = "Vortex86 SoC";
+ static constexpr const char* VENDOR_VIA = "VIA VIA VIA ";
+ // Vendor-strings from Virtual Machines.
+ static constexpr const char* VENDOR_VMWARE = "VMwareVMware";
+ static constexpr const char* VENDOR_XENHVM = "XenVMMXenVMM";
+ static constexpr const char* VENDOR_MICROSOFT_HV = "Microsoft Hv";
+ static constexpr const char* VENDOR_PARALLELS = " lrpepyh vr";
+
+ static constexpr const uint32_t FEAT_ECX_SSE3 = 1 << 0;
+ static constexpr const uint32_t FEAT_ECX_PCLMUL = 1 << 1;
+ static constexpr const uint32_t FEAT_ECX_DTES64 = 1 << 2;
+ static constexpr const uint32_t FEAT_ECX_MONITOR = 1 << 3;
+ static constexpr const uint32_t FEAT_ECX_DS_CPL = 1 << 4;
+ static constexpr const uint32_t FEAT_ECX_VMX = 1 << 5;
+ static constexpr const uint32_t FEAT_ECX_SMX = 1 << 6;
+ static constexpr const uint32_t FEAT_ECX_EST = 1 << 7;
+ static constexpr const uint32_t FEAT_ECX_TM2 = 1 << 8;
+ static constexpr const uint32_t FEAT_ECX_SSSE3 = 1 << 9;
+ static constexpr const uint32_t FEAT_ECX_CID = 1 << 10;
+ static constexpr const uint32_t FEAT_ECX_FMA = 1 << 12;
+ static constexpr const uint32_t FEAT_ECX_CX16 = 1 << 13;
+ static constexpr const uint32_t FEAT_ECX_ETPRD = 1 << 14;
+ static constexpr const uint32_t FEAT_ECX_PDCM = 1 << 15;
+ static constexpr const uint32_t FEAT_ECX_PCIDE = 1 << 17;
+ static constexpr const uint32_t FEAT_ECX_DCA = 1 << 18;
+ static constexpr const uint32_t FEAT_ECX_SSE4_1 = 1 << 19;
+ static constexpr const uint32_t FEAT_ECX_SSE4_2 = 1 << 20;
+ static constexpr const uint32_t FEAT_ECX_x2APIC = 1 << 21;
+ static constexpr const uint32_t FEAT_ECX_MOVBE = 1 << 22;
+ static constexpr const uint32_t FEAT_ECX_POPCNT = 1 << 23;
+ static constexpr const uint32_t FEAT_ECX_AES = 1 << 25;
+ static constexpr const uint32_t FEAT_ECX_XSAVE = 1 << 26;
+ static constexpr const uint32_t FEAT_ECX_OSXSAVE = 1 << 27;
+ static constexpr const uint32_t FEAT_ECX_AVX = 1 << 28;
+ static constexpr const uint32_t FEAT_EDX_FPU = 1 << 0;
+ static constexpr const uint32_t FEAT_EDX_VME = 1 << 1;
+ static constexpr const uint32_t FEAT_EDX_DE = 1 << 2;
+ static constexpr const uint32_t FEAT_EDX_PSE = 1 << 3;
+ static constexpr const uint32_t FEAT_EDX_TSC = 1 << 4;
+ static constexpr const uint32_t FEAT_EDX_MSR = 1 << 5;
+ static constexpr const uint32_t FEAT_EDX_PAE = 1 << 6;
+ static constexpr const uint32_t FEAT_EDX_MCE = 1 << 7;
+ static constexpr const uint32_t FEAT_EDX_CX8 = 1 << 8;
+ static constexpr const uint32_t FEAT_EDX_APIC = 1 << 9;
+ static constexpr const uint32_t FEAT_EDX_SEP = 1 << 11;
+ static constexpr const uint32_t FEAT_EDX_MTRR = 1 << 12;
+ static constexpr const uint32_t FEAT_EDX_PGE = 1 << 13;
+ static constexpr const uint32_t FEAT_EDX_MCA = 1 << 14;
+ static constexpr const uint32_t FEAT_EDX_CMOV = 1 << 15;
+ static constexpr const uint32_t FEAT_EDX_PAT = 1 << 16;
+ static constexpr const uint32_t FEAT_EDX_PSE36 = 1 << 17;
+ static constexpr const uint32_t FEAT_EDX_PSN = 1 << 18;
+ static constexpr const uint32_t FEAT_EDX_CLF = 1 << 19;
+ static constexpr const uint32_t FEAT_EDX_DTES = 1 << 21;
+ static constexpr const uint32_t FEAT_EDX_ACPI = 1 << 22;
+ static constexpr const uint32_t FEAT_EDX_MMX = 1 << 23;
+ static constexpr const uint32_t FEAT_EDX_FXSR = 1 << 24;
+ static constexpr const uint32_t FEAT_EDX_SSE = 1 << 25;
+ static constexpr const uint32_t FEAT_EDX_SSE2 = 1 << 26;
+ static constexpr const uint32_t FEAT_EDX_SS = 1 << 27;
+ static constexpr const uint32_t FEAT_EDX_HTT = 1 << 28;
+ static constexpr const uint32_t FEAT_EDX_TM1 = 1 << 29;
+ static constexpr const uint32_t FEAT_EDX_IA64 = 1 << 30;
+ static constexpr const uint32_t FEAT_EDX_PBE = 1 << 31;
+
+ enum : uint32_t {
+ GET_VENDOR = 0x00,
+ GET_FEATURES,
+ GET_TLB,
+ GET_SERIAL,
+ INTEL_EXTENDED = 0x80000000,
+ INTEL_FEATURES,
+ INTEL_BRANDSTRING,
+ INTEL_BRANDSTRINGMORE,
+ INTEL_BRANDSTRINGEND,
};
- /**
- * @brief 设置 页目录
- * @param _pgd 要设置的页表
- * @return true 成功
- * @return false 失败
- */
- static inline bool SET_PGD(uintptr_t _pgd) {
- __asm__ volatile("mov %0, %%cr3" : : "r"(_pgd));
- return true;
+ // TODO: 获取字符串信息
+ char vendor[VENDOR_LEN];
+ char brand[BRAND_LEN];
+ char family_name[FAMILY_LEN];
+ char model_name[MODEL_LEN];
+ // 系列
+ uint32_t family;
+ // 型号
+ uint32_t model;
+ // 类型
+ uint32_t type;
+ // 频率
+ uint32_t stepping;
+ // cpu 基本信息
+ uint32_t max_cpuid;
+ // cpu 拓展信息
+ uint32_t max_cpuidex;
+
+ void cpuid(uint32_t Mop, uint32_t Sop, uint32_t* eax, uint32_t* ebx,
+ uint32_t* ecx, uint32_t* edx) {
+ __asm__ volatile("cpuid"
+ : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
+ : "0"(Mop), "2"(Sop));
}
- /**
- * @brief 读 MSR
- * @param _idx 要读的索引
- * @return uint64_t 读取的值
- */
- static inline uint64_t READ_MSR(uint32_t _idx) {
- uint32_t low;
- uint32_t high;
- __asm__ volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(_idx));
- return ((uint64_t)high << 32) | low;
+public:
+ CPUID(void) {
+ uint32_t eax, ebx, ecx, edx;
+ // 获取 vendor ID 与基本信息
+ cpuid(GET_VENDOR, 0, &eax, &ebx, &ecx, &edx);
+ max_cpuid = eax;
+ memcpy(vendor, &ebx, 4);
+ memcpy(vendor + 4, &edx, 4);
+ memcpy(vendor + 8, &ecx, 4);
+ vendor[12] = '\0';
+ // 获取拓展信息
+ cpuid(INTEL_EXTENDED, 0, &eax, &ebx, &ecx, &edx);
+ max_cpuidex = eax;
+ return;
}
- /**
- * @brief 写 MSR
- * @param _idx 要写的索引
- * @param _msr 要写的值
- */
- static inline void WRITE_MSR(uint32_t _idx, uint64_t _msr) {
- uint32_t low = _msr;
- uint32_t high = _msr >> 32;
- __asm__ volatile("wrmsr" : : "a"(low), "d"(high), "c"(_idx));
+ ~CPUID(void) {
return;
}
- /// @todo 改为 static
- class CPUID {
- private:
- static constexpr const uint32_t VENDOR_LEN = 16;
- static constexpr const uint32_t BRAND_LEN = 50;
- static constexpr const uint32_t FAMILY_LEN = 50;
- static constexpr const uint32_t MODEL_LEN = 50;
- // Vendor-strings.
- static constexpr const char *VENDOR_OLDAMD = "AMDisbetter!";
- // early engineering samples of AMD K5 processor
- static constexpr const char *VENDOR_AMD = "AuthenticAMD";
- static constexpr const char *VENDOR_INTEL = "GenuineIntel";
- static constexpr const char *VENDOR_Centaur = "CentaurHauls";
- static constexpr const char *VENDOR_OLDTRANSMETA = "TransmetaCPU";
- static constexpr const char *VENDOR_TRANSMETA = "GenuineTMx86";
- static constexpr const char *VENDOR_CYRIX = "CyrixInstead";
- static constexpr const char *VENDOR_CENTAUR = "CentaurHauls";
- static constexpr const char *VENDOR_NEXGEN = "NexGenDriven";
- static constexpr const char *VENDOR_UMC = "UMC UMC UMC ";
- static constexpr const char *VENDOR_SIS = "SiS SiS SiS ";
- static constexpr const char *VENDOR_NSC = "Geode by NSC";
- static constexpr const char *VENDOR_RISE = "RiseRiseRise";
- static constexpr const char *VENDOR_VORTEX = "Vortex86 SoC";
- static constexpr const char *VENDOR_VIA = "VIA VIA VIA ";
- // Vendor-strings from Virtual Machines.
- static constexpr const char *VENDOR_VMWARE = "VMwareVMware";
- static constexpr const char *VENDOR_XENHVM = "XenVMMXenVMM";
- static constexpr const char *VENDOR_MICROSOFT_HV = "Microsoft Hv";
- static constexpr const char *VENDOR_PARALLELS = " lrpepyh vr";
-
- static constexpr const uint32_t FEAT_ECX_SSE3 = 1 << 0;
- static constexpr const uint32_t FEAT_ECX_PCLMUL = 1 << 1;
- static constexpr const uint32_t FEAT_ECX_DTES64 = 1 << 2;
- static constexpr const uint32_t FEAT_ECX_MONITOR = 1 << 3;
- static constexpr const uint32_t FEAT_ECX_DS_CPL = 1 << 4;
- static constexpr const uint32_t FEAT_ECX_VMX = 1 << 5;
- static constexpr const uint32_t FEAT_ECX_SMX = 1 << 6;
- static constexpr const uint32_t FEAT_ECX_EST = 1 << 7;
- static constexpr const uint32_t FEAT_ECX_TM2 = 1 << 8;
- static constexpr const uint32_t FEAT_ECX_SSSE3 = 1 << 9;
- static constexpr const uint32_t FEAT_ECX_CID = 1 << 10;
- static constexpr const uint32_t FEAT_ECX_FMA = 1 << 12;
- static constexpr const uint32_t FEAT_ECX_CX16 = 1 << 13;
- static constexpr const uint32_t FEAT_ECX_ETPRD = 1 << 14;
- static constexpr const uint32_t FEAT_ECX_PDCM = 1 << 15;
- static constexpr const uint32_t FEAT_ECX_PCIDE = 1 << 17;
- static constexpr const uint32_t FEAT_ECX_DCA = 1 << 18;
- static constexpr const uint32_t FEAT_ECX_SSE4_1 = 1 << 19;
- static constexpr const uint32_t FEAT_ECX_SSE4_2 = 1 << 20;
- static constexpr const uint32_t FEAT_ECX_x2APIC = 1 << 21;
- static constexpr const uint32_t FEAT_ECX_MOVBE = 1 << 22;
- static constexpr const uint32_t FEAT_ECX_POPCNT = 1 << 23;
- static constexpr const uint32_t FEAT_ECX_AES = 1 << 25;
- static constexpr const uint32_t FEAT_ECX_XSAVE = 1 << 26;
- static constexpr const uint32_t FEAT_ECX_OSXSAVE = 1 << 27;
- static constexpr const uint32_t FEAT_ECX_AVX = 1 << 28;
- static constexpr const uint32_t FEAT_EDX_FPU = 1 << 0;
- static constexpr const uint32_t FEAT_EDX_VME = 1 << 1;
- static constexpr const uint32_t FEAT_EDX_DE = 1 << 2;
- static constexpr const uint32_t FEAT_EDX_PSE = 1 << 3;
- static constexpr const uint32_t FEAT_EDX_TSC = 1 << 4;
- static constexpr const uint32_t FEAT_EDX_MSR = 1 << 5;
- static constexpr const uint32_t FEAT_EDX_PAE = 1 << 6;
- static constexpr const uint32_t FEAT_EDX_MCE = 1 << 7;
- static constexpr const uint32_t FEAT_EDX_CX8 = 1 << 8;
- static constexpr const uint32_t FEAT_EDX_APIC = 1 << 9;
- static constexpr const uint32_t FEAT_EDX_SEP = 1 << 11;
- static constexpr const uint32_t FEAT_EDX_MTRR = 1 << 12;
- static constexpr const uint32_t FEAT_EDX_PGE = 1 << 13;
- static constexpr const uint32_t FEAT_EDX_MCA = 1 << 14;
- static constexpr const uint32_t FEAT_EDX_CMOV = 1 << 15;
- static constexpr const uint32_t FEAT_EDX_PAT = 1 << 16;
- static constexpr const uint32_t FEAT_EDX_PSE36 = 1 << 17;
- static constexpr const uint32_t FEAT_EDX_PSN = 1 << 18;
- static constexpr const uint32_t FEAT_EDX_CLF = 1 << 19;
- static constexpr const uint32_t FEAT_EDX_DTES = 1 << 21;
- static constexpr const uint32_t FEAT_EDX_ACPI = 1 << 22;
- static constexpr const uint32_t FEAT_EDX_MMX = 1 << 23;
- static constexpr const uint32_t FEAT_EDX_FXSR = 1 << 24;
- static constexpr const uint32_t FEAT_EDX_SSE = 1 << 25;
- static constexpr const uint32_t FEAT_EDX_SSE2 = 1 << 26;
- static constexpr const uint32_t FEAT_EDX_SS = 1 << 27;
- static constexpr const uint32_t FEAT_EDX_HTT = 1 << 28;
- static constexpr const uint32_t FEAT_EDX_TM1 = 1 << 29;
- static constexpr const uint32_t FEAT_EDX_IA64 = 1 << 30;
- static constexpr const uint32_t FEAT_EDX_PBE = 1 << 31;
- enum : uint32_t {
- GET_VENDOR = 0x00,
- GET_FEATURES,
- GET_TLB,
- GET_SERIAL,
- INTEL_EXTENDED = 0x80000000,
- INTEL_FEATURES,
- INTEL_BRANDSTRING,
- INTEL_BRANDSTRINGMORE,
- INTEL_BRANDSTRINGEND,
- };
- // TODO: 获取字符串信息
- char vendor[VENDOR_LEN];
- char brand[BRAND_LEN];
- char family_name[FAMILY_LEN];
- char model_name[MODEL_LEN];
- //系列
- uint32_t family;
- //型号
- uint32_t model;
- //类型
- uint32_t type;
- //频率
- uint32_t stepping;
- // cpu 基本信息
- uint32_t max_cpuid;
- // cpu 拓展信息
- uint32_t max_cpuidex;
- void cpuid(uint32_t Mop, uint32_t Sop, uint32_t *eax, uint32_t *ebx,
- uint32_t *ecx, uint32_t *edx) {
- __asm__ volatile("cpuid"
- : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
- : "0"(Mop), "2"(Sop));
- }
-
- public:
- CPUID(void) {
- uint32_t eax, ebx, ecx, edx;
- // 获取 vendor ID 与基本信息
- cpuid(GET_VENDOR, 0, &eax, &ebx, &ecx, &edx);
- max_cpuid = eax;
- memcpy(vendor, &ebx, 4);
- memcpy(vendor + 4, &edx, 4);
- memcpy(vendor + 8, &ecx, 4);
- vendor[12] = '\0';
- // 获取拓展信息
- cpuid(INTEL_EXTENDED, 0, &eax, &ebx, &ecx, &edx);
- max_cpuidex = eax;
- return;
- }
- ~CPUID(void) {
- return;
- }
- bool xapic(void) {
- uint32_t eax, ebx, ecx, edx;
- cpuid(GET_FEATURES, 0, &eax, &ebx, &ecx, &edx);
- return edx & FEAT_EDX_APIC;
- }
- bool x2apic(void) {
- uint32_t eax, ebx, ecx, edx;
- cpuid(GET_FEATURES, 0, &eax, &ebx, &ecx, &edx);
- return ecx & FEAT_ECX_x2APIC;
- }
- bool eoi(void) {
- uint64_t version = READ_MSR(IA32_X2APIC_VERSION);
- return version & IA32_X2APIC_SIVR_EOI_ENABLE_BIT;
- }
- };
+ bool xapic(void) {
+ uint32_t eax, ebx, ecx, edx;
+ cpuid(GET_FEATURES, 0, &eax, &ebx, &ecx, &edx);
+ return edx & FEAT_EDX_APIC;
+ }
+
+ bool x2apic(void) {
+ uint32_t eax, ebx, ecx, edx;
+ cpuid(GET_FEATURES, 0, &eax, &ebx, &ecx, &edx);
+ return ecx & FEAT_ECX_x2APIC;
+ }
+
+ bool eoi(void) {
+ uint64_t version = READ_MSR(IA32_X2APIC_VERSION);
+ return version & IA32_X2APIC_SIVR_EOI_ENABLE_BIT;
+ }
};
-#endif /* _CPU_HPP_ */
+}; // namespace CPU
+
+#endif /* SIMPLEKERNEL_CPU_HPP */
diff --git a/src/arch/ia32/e820.h b/src/arch/ia32/e820.h
index 829935e8f..50d6dc537 100644
--- a/src/arch/ia32/e820.h
+++ b/src/arch/ia32/e820.h
@@ -14,22 +14,22 @@
*
*/
-#ifndef _E820_H_
-#define _E820_H_
+#ifndef SIMPLEKERNEL_E820_H
+#define SIMPLEKERNEL_E820_H
-#include "stddef.h"
-#include "stdint.h"
+#include "cstddef"
+#include "cstdint"
/// 最大数量
-static constexpr const uint32_t E820_MAX = 8;
+static constexpr const uint32_t E820_MAX = 8;
/// RAM 标记
-static constexpr const uint32_t E820_RAM = 1;
+static constexpr const uint32_t E820_RAM = 1;
/// 保留 标记
static constexpr const uint32_t E820_RESERVED = 2;
/// ACPI 标记
-static constexpr const uint32_t E820_ACPI = 3;
+static constexpr const uint32_t E820_ACPI = 3;
/// NVS 标记
-static constexpr const uint32_t E820_NVS = 4;
+static constexpr const uint32_t E820_NVS = 4;
/// 不可用 标记
static constexpr const uint32_t E820_UNUSABLE = 5;
@@ -51,11 +51,13 @@ struct e820map_t {
nr_map = 0;
return;
}
+
~e820map_t(void) {
return;
}
+
uint32_t nr_map;
e820entry_t map[E820_MAX];
};
-#endif /* _E820_H_ */
+#endif /* SIMPLEKERNEL_E820_H */
diff --git a/src/arch/ia32/i386/boot/boot.S b/src/arch/ia32/i386/boot/boot.S
index 6ab33a518..c3397e50f 100644
--- a/src/arch/ia32/i386/boot/boot.S
+++ b/src/arch/ia32/i386/boot/boot.S
@@ -1,79 +1,89 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-//
-// boot.S for Simple-XX/SimpleKernel.
-// 启动代码,进行一些设置后跳转到 kernel_main
+/**
+ * @file boot.S
+ * @brief 启动代码,进行一些设置后跳转到 kernel_main
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2021-01-01
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2021-01-02 MRNIU 迁移到 doxygen
+ *
+ */
// 以下是来自 multiboot2 规范的定义
// How many bytes from the start of the file we search for the header.
-#define MULTIBOOT_SEARCH 32768
-#define MULTIBOOT_HEADER_ALIGN 8
-
-// The magic field should contain this.
-#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
-
-// This should be in %eax.
-#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
-
-// Alignment of multiboot modules.
-#define MULTIBOOT_MOD_ALIGN 0x00001000
-
-// Alignment of the multiboot info structure.
-#define MULTIBOOT_INFO_ALIGN 0x00000008
-
-// Flags set in the 'flags' member of the multiboot header.
-
-#define MULTIBOOT_TAG_ALIGN 8
-#define MULTIBOOT_TAG_TYPE_END 0
-#define MULTIBOOT_TAG_TYPE_CMDLINE 1
-#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
-#define MULTIBOOT_TAG_TYPE_MODULE 3
-#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
-#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
-#define MULTIBOOT_TAG_TYPE_MMAP 6
-#define MULTIBOOT_TAG_TYPE_VBE 7
-#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
-#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
-#define MULTIBOOT_TAG_TYPE_APM 10
-#define MULTIBOOT_TAG_TYPE_EFI32 11
-#define MULTIBOOT_TAG_TYPE_EFI64 12
-#define MULTIBOOT_TAG_TYPE_SMBIOS 13
-#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
-#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
-#define MULTIBOOT_TAG_TYPE_NETWORK 16
-#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
-#define MULTIBOOT_TAG_TYPE_EFI_BS 18
-#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
-#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
-#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
-
-#define MULTIBOOT_HEADER_TAG_END 0
-#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
-#define MULTIBOOT_HEADER_TAG_ADDRESS 2
-#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
-#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
-#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
-#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
-#define MULTIBOOT_HEADER_TAG_EFI_BS 7
-#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
-#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
-#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
-
-#define MULTIBOOT_ARCHITECTURE_I386 0
-#define MULTIBOOT_ARCHITECTURE_MIPS32 4
-#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
-
-#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
-#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
-#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
-
-#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
+#define MULTIBOOT_SEARCH 32768
+#define MULTIBOOT_HEADER_ALIGN 8
+
+// The magic field should contain this.
+#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
+
+// This should be in %eax.
+#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
+
+// Alignment of multiboot modules.
+#define MULTIBOOT_MOD_ALIGN 0x00001000
+
+// Alignment of the multiboot info structure.
+#define MULTIBOOT_INFO_ALIGN 0x00000008
+
+// Flags set in the 'flags' member of the multiboot header.
+
+#define MULTIBOOT_TAG_ALIGN 8
+#define MULTIBOOT_TAG_TYPE_END 0
+#define MULTIBOOT_TAG_TYPE_CMDLINE 1
+#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
+#define MULTIBOOT_TAG_TYPE_MODULE 3
+#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
+#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
+#define MULTIBOOT_TAG_TYPE_MMAP 6
+#define MULTIBOOT_TAG_TYPE_VBE 7
+#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
+#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
+#define MULTIBOOT_TAG_TYPE_APM 10
+#define MULTIBOOT_TAG_TYPE_EFI32 11
+#define MULTIBOOT_TAG_TYPE_EFI64 12
+#define MULTIBOOT_TAG_TYPE_SMBIOS 13
+#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
+#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
+#define MULTIBOOT_TAG_TYPE_NETWORK 16
+#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
+#define MULTIBOOT_TAG_TYPE_EFI_BS 18
+#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
+#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
+#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
+
+#define MULTIBOOT_HEADER_TAG_END 0
+#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
+#define MULTIBOOT_HEADER_TAG_ADDRESS 2
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
+#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
+#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
+#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
+#define MULTIBOOT_HEADER_TAG_EFI_BS 7
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
+#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
+
+#define MULTIBOOT_ARCHITECTURE_I386 0
+#define MULTIBOOT_ARCHITECTURE_MIPS32 4
+#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
+
+#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
+#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
+#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
+
+#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
+// clang-format off
+
// 声明这一段代码以 32 位模式编译
.code32
-
// multiboot2 文件头
// 计算头长度
.SET HEADER_LENGTH, multiboot_header_end - multiboot_header
@@ -82,7 +92,7 @@
// 8 字节对齐
.align MULTIBOOT_HEADER_ALIGN
// 声明所属段
-.section .multiboot_header
+.section .text.boot
multiboot_header:
// 魔数
.long MULTIBOOT2_HEADER_MAGIC
@@ -100,7 +110,7 @@ multiboot_header:
multiboot_header_end:
// 声明所属段
-.section .text
+.section .text.boot
// 全局可见
.global _start
// 声明类型
@@ -119,7 +129,7 @@ _start:
// 魔数
mov %eax, multiboot2_magic
// 设置栈地址
- mov $STACK_TOP, %esp
+ mov $stack_top, %esp
// 栈地址按照 16 字节对齐
and $0xFFFFFFF0, %esp
// 帧指针修改为 0
@@ -131,9 +141,11 @@ _start:
ret
// 声明所属段
-.section .bss
+.section .bss.boot
+// 16 字节对齐
+.align 16
+.global stack_top
// 栈
-STACK:
+stack_top:
// 跳过 16KB
- .skip 4096 * 4
-STACK_TOP:
+ .space 4096 * 4
diff --git a/src/arch/ia32/i386/gdt/gdt.cpp b/src/arch/ia32/i386/gdt/gdt.cpp
index 2db797029..e1be6b36d 100644
--- a/src/arch/ia32/i386/gdt/gdt.cpp
+++ b/src/arch/ia32/i386/gdt/gdt.cpp
@@ -14,63 +14,64 @@
*
*/
-#include "stdio.h"
#include "gdt.h"
+#include "cstdint"
+#include "cstdio"
namespace GDT {
- /// 加载 GDTR
- extern "C" void gdt_load(uint32_t);
- /// 全局 gdt 指针
- static gdt_ptr_t gdt_ptr;
- /// 全局描述符表定义
- static gdt_entry_t gdt_entries[GDT_LENGTH] __attribute__((aligned(8)));
+/// 加载 GDTR
+extern "C" void gdt_load(uint32_t);
+/// 全局 gdt 指针
+static gdt_ptr_t gdt_ptr;
+/// 全局描述符表定义
+static gdt_entry_t gdt_entries[GDT_LENGTH] __attribute__((aligned(8)));
- void set_gdt(const uint8_t idx, const uint32_t base, const uint32_t limit,
- const uint8_t type, const uint8_t s, const uint8_t dpl,
- const uint8_t p, const uint8_t avl, const uint8_t l,
- const uint8_t db, const uint8_t g) {
- gdt_entries[idx].limit1 = (limit & 0xFFFF);
- gdt_entries[idx].base_addr1 = (base & 0xFFFF);
- gdt_entries[idx].base_addr2 = (base >> 16) & 0xFF;
- gdt_entries[idx].type = type;
- gdt_entries[idx].s = s;
- gdt_entries[idx].dpl = dpl;
- gdt_entries[idx].p = p;
- gdt_entries[idx].limit2 = (limit >> 16) & 0x0F;
- gdt_entries[idx].avl = avl;
- gdt_entries[idx].l = l;
- gdt_entries[idx].db = db;
- gdt_entries[idx].g = g;
- gdt_entries[idx].base_addr3 = (base >> 24) & 0xFF;
- return;
- }
+void set_gdt(const uint8_t idx, const uint32_t base, const uint32_t limit,
+ const uint8_t type, const uint8_t s, const uint8_t dpl,
+ const uint8_t p, const uint8_t avl, const uint8_t l,
+ const uint8_t db, const uint8_t g) {
+ gdt_entries[idx].limit1 = (limit & 0xFFFF);
+ gdt_entries[idx].base_addr1 = (base & 0xFFFF);
+ gdt_entries[idx].base_addr2 = (base >> 16) & 0xFF;
+ gdt_entries[idx].type = type;
+ gdt_entries[idx].s = s;
+ gdt_entries[idx].dpl = dpl;
+ gdt_entries[idx].p = p;
+ gdt_entries[idx].limit2 = (limit >> 16) & 0x0F;
+ gdt_entries[idx].avl = avl;
+ gdt_entries[idx].l = l;
+ gdt_entries[idx].db = db;
+ gdt_entries[idx].g = g;
+ gdt_entries[idx].base_addr3 = (base >> 24) & 0xFF;
+ return;
+}
- int32_t init(void) {
- // 全局描述符表界限 从 0 开始,所以总长要 - 1
- gdt_ptr.limit = sizeof(gdt_entry_t) * GDT_LENGTH - 1;
- gdt_ptr.base = (uint32_t)&gdt_entries;
- // 采用 Intel 平坦模型
- // Intel 文档要求首个描述符全 0
- set_gdt(GDT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
- // 内核指令段
- set_gdt(GDT_KERNEL_CODE, BASE, LIMIT, TYPE_CODE_EXECUTE_READ,
- S_CODE_DATA, CPU::DPL0, SEGMENT_PRESENT, AVL_NOT_AVAILABLE,
- L_32BIT, DB_EXECUTABLE_CODE_SEGMENT_32, G_4KB);
- // 内核数据段
- set_gdt(GDT_KERNEL_DATA, BASE, LIMIT, TYPE_DATA_READ_WRITE, S_CODE_DATA,
- CPU::DPL0, SEGMENT_PRESENT, AVL_NOT_AVAILABLE, L_32BIT,
- DB_EXPAND_DOWN_DATA_SEGMENT_4GB, G_4KB);
- // 用户模式代码段
- set_gdt(GDT_USER_CODE, BASE, LIMIT, TYPE_CODE_EXECUTE_READ, S_CODE_DATA,
- CPU::DPL3, SEGMENT_PRESENT, AVL_NOT_AVAILABLE, L_32BIT,
- DB_EXECUTABLE_CODE_SEGMENT_32, G_4KB);
- // 用户模式数据段
- set_gdt(GDT_USER_DATA, BASE, LIMIT, TYPE_DATA_READ_WRITE, S_CODE_DATA,
- CPU::DPL3, SEGMENT_PRESENT, AVL_NOT_AVAILABLE, L_32BIT,
- DB_EXPAND_DOWN_DATA_SEGMENT_4GB, G_4KB);
- // 加载全局描述符表地址到 GDTR 寄存器
- gdt_load((uint32_t)&gdt_ptr);
- info("gdt init.\n");
- return 0;
- }
-};
+int32_t init(void) {
+ // 全局描述符表界限 从 0 开始,所以总长要 - 1
+ gdt_ptr.limit = sizeof(gdt_entry_t) * GDT_LENGTH - 1;
+ gdt_ptr.base = (uint32_t)&gdt_entries;
+ // 采用 Intel 平坦模型
+ // Intel 文档要求首个描述符全 0
+ set_gdt(GDT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
+ // 内核指令段
+ set_gdt(GDT_KERNEL_CODE, BASE, LIMIT, TYPE_CODE_EXECUTE_READ, S_CODE_DATA,
+ CPU::DPL0, SEGMENT_PRESENT, AVL_NOT_AVAILABLE, L_32BIT,
+ DB_EXECUTABLE_CODE_SEGMENT_32, G_4KB);
+ // 内核数据段
+ set_gdt(GDT_KERNEL_DATA, BASE, LIMIT, TYPE_DATA_READ_WRITE, S_CODE_DATA,
+ CPU::DPL0, SEGMENT_PRESENT, AVL_NOT_AVAILABLE, L_32BIT,
+ DB_EXPAND_DOWN_DATA_SEGMENT_4GB, G_4KB);
+ // 用户模式代码段
+ set_gdt(GDT_USER_CODE, BASE, LIMIT, TYPE_CODE_EXECUTE_READ, S_CODE_DATA,
+ CPU::DPL3, SEGMENT_PRESENT, AVL_NOT_AVAILABLE, L_32BIT,
+ DB_EXECUTABLE_CODE_SEGMENT_32, G_4KB);
+ // 用户模式数据段
+ set_gdt(GDT_USER_DATA, BASE, LIMIT, TYPE_DATA_READ_WRITE, S_CODE_DATA,
+ CPU::DPL3, SEGMENT_PRESENT, AVL_NOT_AVAILABLE, L_32BIT,
+ DB_EXPAND_DOWN_DATA_SEGMENT_4GB, G_4KB);
+ // 加载全局描述符表地址到 GDTR 寄存器
+ gdt_load((uint32_t)&gdt_ptr);
+ info("gdt init.\n");
+ return 0;
+}
+}; // namespace GDT
diff --git a/src/arch/ia32/i386/gdt/gdt_s.S b/src/arch/ia32/i386/gdt/gdt_s.S
index 9ff9c608f..94dfc85c4 100644
--- a/src/arch/ia32/i386/gdt/gdt_s.S
+++ b/src/arch/ia32/i386/gdt/gdt_s.S
@@ -4,6 +4,8 @@
//
// gdt_s.S for Simple-XX/SimpleKernel.
+// clang-format off
+
.code32
.section .text
diff --git a/src/arch/ia32/i386/gdt/include/gdt.h b/src/arch/ia32/i386/gdt/include/gdt.h
index d102c888b..e23ffe4f4 100644
--- a/src/arch/ia32/i386/gdt/include/gdt.h
+++ b/src/arch/ia32/i386/gdt/include/gdt.h
@@ -14,285 +14,284 @@
*
*/
-#ifndef _GDT_H_
-#define _GDT_H_
+#ifndef SIMPLEKERNEL_GDT_H
+#define SIMPLEKERNEL_GDT_H
-#include "stdint.h"
#include "cpu.hpp"
+#include "cstdint"
/**
* @brief GDT 接口
* @see 64-ia-32-architectures-software-developer-vol-3a-manual Chapter3
*/
namespace GDT {
- /// 全局描述符表长度
- static constexpr const uint32_t GDT_LENGTH = 5;
- /// 各个内存段所在全局描述符表下标
- static constexpr const uint32_t GDT_NULL = 0;
- /// 内核代码段
- static constexpr const uint32_t GDT_KERNEL_CODE = 1;
- /// 内核数据段
- static constexpr const uint32_t GDT_KERNEL_DATA = 2;
- /// 用户代码段
- static constexpr const uint32_t GDT_USER_CODE = 3;
- /// 用户数据段
- static constexpr const uint32_t GDT_USER_DATA = 4;
- /// 内核代码段选择子 0x08
- static constexpr const uint32_t SEG_KERNEL_CODE = GDT_KERNEL_CODE << 3;
- /// 内核数据段选择子
- static constexpr const uint32_t SEG_KERNEL_DATA = GDT_KERNEL_DATA << 3;
- /// 用户代码段选择子
- static constexpr const uint32_t SEG_USER_CODE = GDT_USER_CODE << 3;
- /// 用户数据段选择子
- static constexpr const uint32_t SEG_USER_DATA = GDT_USER_DATA << 3;
+/// 全局描述符表长度
+static constexpr const uint32_t GDT_LENGTH = 5;
+/// 各个内存段所在全局描述符表下标
+static constexpr const uint32_t GDT_NULL = 0;
+/// 内核代码段
+static constexpr const uint32_t GDT_KERNEL_CODE = 1;
+/// 内核数据段
+static constexpr const uint32_t GDT_KERNEL_DATA = 2;
+/// 用户代码段
+static constexpr const uint32_t GDT_USER_CODE = 3;
+/// 用户数据段
+static constexpr const uint32_t GDT_USER_DATA = 4;
+/// 内核代码段选择子 0x08
+static constexpr const uint32_t SEG_KERNEL_CODE = GDT_KERNEL_CODE << 3;
+/// 内核数据段选择子
+static constexpr const uint32_t SEG_KERNEL_DATA = GDT_KERNEL_DATA << 3;
+/// 用户代码段选择子
+static constexpr const uint32_t SEG_USER_CODE = GDT_USER_CODE << 3;
+/// 用户数据段选择子
+static constexpr const uint32_t SEG_USER_DATA = GDT_USER_DATA << 3;
- // type 类型
- // Code- and Data-Segment Types, S=1
- /// 数据段 只读
- static constexpr const uint32_t TYPE_DATA_READ_ONLY = 0x00;
- /// 数据段 只读,可访问
- static constexpr const uint32_t TYPE_DATA_READ_ONLY_ACCESSED = 0x01;
- /// 数据段 读写
- static constexpr const uint32_t TYPE_DATA_READ_WRITE = 0x02;
- /// 数据段,读写,可访问
- static constexpr const uint32_t TYPE_DATA_READ_WRITE_ACCESSED = 0x03;
- /// 数据段,只读,?
- static constexpr const uint32_t TYPE_DATA_READ_ONLY_EXPAND_DOWN = 0x04;
- /// 数据段,只读,?,可访问
- static constexpr const uint32_t TYPE_DATA_READ_ONLY_EXPAND_DOWN_ACCESSED =
- 0x05;
- /// 数据段,读写,?
- static constexpr const uint32_t TYPE_DATA_READ_WRITE_EXPAND_DOWN = 0x06;
- /// 数据段,读写,?可访问
- static constexpr const uint32_t TYPE_DATA_READ_WRITE_EXPAND_DOWN_ACCESSED =
- 0x07;
- /// 代码段,仅执行
- static constexpr const uint32_t TYPE_CODE_EXECUTE_ONLY = 0x08;
- /// 代码段,仅执行,可访问
- static constexpr const uint32_t TYPE_CODE_EXECUTE_ONLY_ACCESSED = 0x09;
- /// 代码段,可执行,可读
- static constexpr const uint32_t TYPE_CODE_EXECUTE_READ = 0x0A;
- /// 代码段,可执行,可读,可访问
- static constexpr const uint32_t TYPE_CODE_EXECUTE_READ_ACCESSED = 0x0B;
- /// 代码段,仅执行,?
- static constexpr const uint32_t TYPE_CODE_EXECUTE_ONLY_CONFORMING = 0x0C;
- /// 代码段,仅执行,?,可访问
- static constexpr const uint32_t TYPE_CODE_EXECUTE_ONLY_CONFORMING_ACCESSED =
- 0x0D;
- /// 代码段,可执行,可读,?
- static constexpr const uint32_t TYPE_CODE_EXECUTE_READ_CONFORMING = 0x0E;
- /// 代码段,可执行,可读,?,可访问
- static constexpr const uint32_t TYPE_CODE_EXECUTE_READ_CONFORMING_ACCESSED =
- 0x0F;
+// type 类型
+// Code- and Data-Segment Types, S=1
+/// 数据段 只读
+static constexpr const uint32_t TYPE_DATA_READ_ONLY = 0x00;
+/// 数据段 只读,可访问
+static constexpr const uint32_t TYPE_DATA_READ_ONLY_ACCESSED = 0x01;
+/// 数据段 读写
+static constexpr const uint32_t TYPE_DATA_READ_WRITE = 0x02;
+/// 数据段,读写,可访问
+static constexpr const uint32_t TYPE_DATA_READ_WRITE_ACCESSED = 0x03;
+/// 数据段,只读,?
+static constexpr const uint32_t TYPE_DATA_READ_ONLY_EXPAND_DOWN = 0x04;
+/// 数据段,只读,?,可访问
+static constexpr const uint32_t TYPE_DATA_READ_ONLY_EXPAND_DOWN_ACCESSED = 0x05;
+/// 数据段,读写,?
+static constexpr const uint32_t TYPE_DATA_READ_WRITE_EXPAND_DOWN = 0x06;
+/// 数据段,读写,?可访问
+static constexpr const uint32_t TYPE_DATA_READ_WRITE_EXPAND_DOWN_ACCESSED
+ = 0x07;
+/// 代码段,仅执行
+static constexpr const uint32_t TYPE_CODE_EXECUTE_ONLY = 0x08;
+/// 代码段,仅执行,可访问
+static constexpr const uint32_t TYPE_CODE_EXECUTE_ONLY_ACCESSED = 0x09;
+/// 代码段,可执行,可读
+static constexpr const uint32_t TYPE_CODE_EXECUTE_READ = 0x0A;
+/// 代码段,可执行,可读,可访问
+static constexpr const uint32_t TYPE_CODE_EXECUTE_READ_ACCESSED = 0x0B;
+/// 代码段,仅执行,?
+static constexpr const uint32_t TYPE_CODE_EXECUTE_ONLY_CONFORMING = 0x0C;
+/// 代码段,仅执行,?,可访问
+static constexpr const uint32_t TYPE_CODE_EXECUTE_ONLY_CONFORMING_ACCESSED
+ = 0x0D;
+/// 代码段,可执行,可读,?
+static constexpr const uint32_t TYPE_CODE_EXECUTE_READ_CONFORMING = 0x0E;
+/// 代码段,可执行,可读,?,可访问
+static constexpr const uint32_t TYPE_CODE_EXECUTE_READ_CONFORMING_ACCESSED
+ = 0x0F;
- // System-Segment and Gate-Descriptor Types, 32bit, when S=0
- /// 保留
- static constexpr const uint32_t TYPE_SYSTEM_16_RESERVESD1 = 0x00;
- /// 16 位 TSS
- static constexpr const uint32_t TYPE_SYSTEM_16_TSS_AVAILABLE = 0x01;
- /// LDT
- static constexpr const uint32_t TYPE_SYSTEM_LDT = 0x02;
- /// 16 位 TSS,在用
- static constexpr const uint32_t TYPE_SYSTEM_16_TSS_BUSY = 0x03;
- /// 16 位调用门
- static constexpr const uint32_t TYPE_SYSTEM_16_CALL_GATE = 0x04;
- /// 任务门
- static constexpr const uint32_t TYPE_SYSTEM_TASK_GATE = 0x05;
- /// 16 位 中断门
- static constexpr const uint32_t TYPE_SYSTEM_16_INTERRUPT_GATE = 0x06;
- /// 16 位 陷阱门
- static constexpr const uint32_t TYPE_SYSTEM_16_TRAP_GATE = 0x07;
- /// 保留
- static constexpr const uint32_t TYPE_SYSTEM_32_RESERVESD2 = 0x08;
- /// 32 位 TSS
- static constexpr const uint32_t TYPE_SYSTEM_32_TSS_AVAILABLE = 0x09;
- /// 保留
- static constexpr const uint32_t TYPE_SYSTEM_32_RESERVESD3 = 0x0A;
- /// 32 位,在用
- static constexpr const uint32_t TYPE_SYSTEM_32_TSS_BUSY = 0x0B;
- /// 32 位 调用门
- static constexpr const uint32_t TYPE_SYSTEM_32_CALL_GATE = 0x0C;
- /// 保留
- static constexpr const uint32_t TYPE_SYSTEM_RESERVESD4 = 0x0D;
- /// 32 位 中断门
- static constexpr const uint32_t TYPE_SYSTEM_32_INTERRUPT_GATE = 0x0E;
- /// 32 位 陷阱门
- static constexpr const uint32_t TYPE_SYSTEM_32_TRAP_GATE = 0x0F;
+// System-Segment and Gate-Descriptor Types, 32bit, when S=0
+/// 保留
+static constexpr const uint32_t TYPE_SYSTEM_16_RESERVESD1 = 0x00;
+/// 16 位 TSS
+static constexpr const uint32_t TYPE_SYSTEM_16_TSS_AVAILABLE = 0x01;
+/// LDT
+static constexpr const uint32_t TYPE_SYSTEM_LDT = 0x02;
+/// 16 位 TSS,在用
+static constexpr const uint32_t TYPE_SYSTEM_16_TSS_BUSY = 0x03;
+/// 16 位调用门
+static constexpr const uint32_t TYPE_SYSTEM_16_CALL_GATE = 0x04;
+/// 任务门
+static constexpr const uint32_t TYPE_SYSTEM_TASK_GATE = 0x05;
+/// 16 位 中断门
+static constexpr const uint32_t TYPE_SYSTEM_16_INTERRUPT_GATE = 0x06;
+/// 16 位 陷阱门
+static constexpr const uint32_t TYPE_SYSTEM_16_TRAP_GATE = 0x07;
+/// 保留
+static constexpr const uint32_t TYPE_SYSTEM_32_RESERVESD2 = 0x08;
+/// 32 位 TSS
+static constexpr const uint32_t TYPE_SYSTEM_32_TSS_AVAILABLE = 0x09;
+/// 保留
+static constexpr const uint32_t TYPE_SYSTEM_32_RESERVESD3 = 0x0A;
+/// 32 位,在用
+static constexpr const uint32_t TYPE_SYSTEM_32_TSS_BUSY = 0x0B;
+/// 32 位 调用门
+static constexpr const uint32_t TYPE_SYSTEM_32_CALL_GATE = 0x0C;
+/// 保留
+static constexpr const uint32_t TYPE_SYSTEM_RESERVESD4 = 0x0D;
+/// 32 位 中断门
+static constexpr const uint32_t TYPE_SYSTEM_32_INTERRUPT_GATE = 0x0E;
+/// 32 位 陷阱门
+static constexpr const uint32_t TYPE_SYSTEM_32_TRAP_GATE = 0x0F;
- // S 位
- /// 系统段
- static constexpr const uint32_t S_SYSTEM = 0x00;
- /// 代码/数据段
- static constexpr const uint32_t S_CODE_DATA = 0x01;
+// S 位
+/// 系统段
+static constexpr const uint32_t S_SYSTEM = 0x00;
+/// 代码/数据段
+static constexpr const uint32_t S_CODE_DATA = 0x01;
- // 各个段的全局描述符表的选择子
- /// 内核代码段
- static constexpr const uint32_t KERNEL_CS = SEG_KERNEL_CODE | CPU::DPL0;
- /// 内核数据段
- static constexpr const uint32_t KERNEL_DS = SEG_KERNEL_DATA | CPU::DPL0;
- /// 用户代码段
- static constexpr const uint32_t USER_CS = SEG_USER_CODE | CPU::DPL3;
- /// 用户数据段
- static constexpr const uint32_t USER_DS = SEG_USER_DATA | CPU::DPL3;
+// 各个段的全局描述符表的选择子
+/// 内核代码段
+static constexpr const uint32_t KERNEL_CS = SEG_KERNEL_CODE | CPU::DPL0;
+/// 内核数据段
+static constexpr const uint32_t KERNEL_DS = SEG_KERNEL_DATA | CPU::DPL0;
+/// 用户代码段
+static constexpr const uint32_t USER_CS = SEG_USER_CODE | CPU::DPL3;
+/// 用户数据段
+static constexpr const uint32_t USER_DS = SEG_USER_DATA | CPU::DPL3;
- // P 位
- /// 无效
- static constexpr const uint32_t SEGMENT_NOT_PRESENT = 0x00;
- /// 有效
- static constexpr const uint32_t SEGMENT_PRESENT = 0x01;
- // AVL
- /// 无效
- static constexpr const uint32_t AVL_NOT_AVAILABLE = 0x00;
- /// 有效
- static constexpr const uint32_t AVL_AVAILABLE = 0x01;
- // L 位
- /// 32 位
- static constexpr const uint32_t L_32BIT = 0x00;
- /// 64 位
- static constexpr const uint32_t L_64BIT = 0x01;
- // D/B
- /// @todo
- static constexpr const uint32_t DB_EXECUTABLE_CODE_SEGMENT_16 = 0x00;
- /// @todo
- static constexpr const uint32_t DB_EXECUTABLE_CODE_SEGMENT_32 = 0x01;
- /// @todo
- static constexpr const uint32_t DB_STACK_SEGMENT_STACK_POINTER_16 = 0x00;
- /// @todo
- static constexpr const uint32_t DB_STACK_SEGMENT_STACK_POINTER_32 = 0x01;
- /// @todo
- static constexpr const uint32_t DB_EXPAND_DOWN_DATA_SEGMENT_64KB = 0x00;
- /// @todo
- static constexpr const uint32_t DB_EXPAND_DOWN_DATA_SEGMENT_4GB = 0x01;
- // G
- /// 字节粒度
- static constexpr const uint32_t G_BYTE = 0x00;
- /// 4KB 粒度
- static constexpr const uint32_t G_4KB = 0x01;
+// P 位
+/// 无效
+static constexpr const uint32_t SEGMENT_NOT_PRESENT = 0x00;
+/// 有效
+static constexpr const uint32_t SEGMENT_PRESENT = 0x01;
+// AVL
+/// 无效
+static constexpr const uint32_t AVL_NOT_AVAILABLE = 0x00;
+/// 有效
+static constexpr const uint32_t AVL_AVAILABLE = 0x01;
+// L 位
+/// 32 位
+static constexpr const uint32_t L_32BIT = 0x00;
+/// 64 位
+static constexpr const uint32_t L_64BIT = 0x01;
+// D/B
+/// @todo
+static constexpr const uint32_t DB_EXECUTABLE_CODE_SEGMENT_16 = 0x00;
+/// @todo
+static constexpr const uint32_t DB_EXECUTABLE_CODE_SEGMENT_32 = 0x01;
+/// @todo
+static constexpr const uint32_t DB_STACK_SEGMENT_STACK_POINTER_16 = 0x00;
+/// @todo
+static constexpr const uint32_t DB_STACK_SEGMENT_STACK_POINTER_32 = 0x01;
+/// @todo
+static constexpr const uint32_t DB_EXPAND_DOWN_DATA_SEGMENT_64KB = 0x00;
+/// @todo
+static constexpr const uint32_t DB_EXPAND_DOWN_DATA_SEGMENT_4GB = 0x01;
+// G
+/// 字节粒度
+static constexpr const uint32_t G_BYTE = 0x00;
+/// 4KB 粒度
+static constexpr const uint32_t G_4KB = 0x01;
- // 访问权限
- /// 内核读,执行
- static constexpr const uint32_t KREAD_EXEC = 0x9A;
- /// 内核写
- static constexpr const uint32_t KREAD_WRITE = 0x92;
- /// 用户读,执行
- static constexpr const uint32_t UREAD_EXEC = 0xFA;
- /// 用户写
- static constexpr const uint32_t UREAD_WRITE = 0xF2;
+// 访问权限
+/// 内核读,执行
+static constexpr const uint32_t KREAD_EXEC = 0x9A;
+/// 内核写
+static constexpr const uint32_t KREAD_WRITE = 0x92;
+/// 用户读,执行
+static constexpr const uint32_t UREAD_EXEC = 0xFA;
+/// 用户写
+static constexpr const uint32_t UREAD_WRITE = 0xF2;
- /// 段基址
- static constexpr const uint32_t BASE = 0x00;
- /// 段长度
- static constexpr const uint32_t LIMIT = 0xFFFFFFFF;
+/// 段基址
+static constexpr const uint32_t BASE = 0x00;
+/// 段长度
+static constexpr const uint32_t LIMIT = 0xFFFFFFFF;
- /**
- * @brief 全局描述符
- */
- struct gdt_entry_t {
- /// 段界限 15:00
- uint64_t limit1 : 16;
- /// 基址 15:00
- uint64_t base_addr1 : 16;
- /// 基址 23:16
- uint64_t base_addr2 : 8;
- /// 类型
- uint64_t type : 4;
- /// Descriptor type (0 = system; 1 = code or data)
- uint64_t s : 1;
- /// Specifies the privilege level of the segment
- uint64_t dpl : 2;
- /// Indicates whether the segment is present in memory (set) or not
- /// present (clear).
- uint64_t p : 1;
- /// 段界限 19:16
- uint64_t limit2 : 4;
- /// Available for use by system software
- uint64_t avl : 1;
- /// 64-bit code segment (IA-32e mode only)
- uint64_t l : 1;
- /// Default operation size(0 = 16 - bit segment; 1 = 32 - bit segment)
- uint64_t db : 1;
- /// Determines the scaling of the segment limit field. When the
- /// granularity flag is clear, the segment limit is interpreted in
- /// byte units; when flag is set, the segment limit is interpreted in
- /// 4-KByte units.
- uint64_t g : 1;
- /// 基址 31:24
- uint64_t base_addr3 : 8;
- } __attribute__((packed));
+/**
+ * @brief 全局描述符
+ */
+struct gdt_entry_t {
+ /// 段界限 15:00
+ uint64_t limit1 : 16;
+ /// 基址 15:00
+ uint64_t base_addr1 : 16;
+ /// 基址 23:16
+ uint64_t base_addr2 : 8;
+ /// 类型
+ uint64_t type : 4;
+ /// Descriptor type (0 = system; 1 = code or data)
+ uint64_t s : 1;
+ /// Specifies the privilege level of the segment
+ uint64_t dpl : 2;
+ /// Indicates whether the segment is present in memory (set) or not
+ /// present (clear).
+ uint64_t p : 1;
+ /// 段界限 19:16
+ uint64_t limit2 : 4;
+ /// Available for use by system software
+ uint64_t avl : 1;
+ /// 64-bit code segment (IA-32e mode only)
+ uint64_t l : 1;
+ /// Default operation size(0 = 16 - bit segment; 1 = 32 - bit segment)
+ uint64_t db : 1;
+ /// Determines the scaling of the segment limit field. When the
+ /// granularity flag is clear, the segment limit is interpreted in
+ /// byte units; when flag is set, the segment limit is interpreted in
+ /// 4-KByte units.
+ uint64_t g : 1;
+ /// 基址 31:24
+ uint64_t base_addr3 : 8;
+} __attribute__((packed));
- /**
- * @brief 全剧描述符寄存器
- */
- struct gdt_ptr_t {
- /// 全局描述符表限长
- uint16_t limit;
- /// 全局描述符表 32位 基地址
- uint32_t base;
- } __attribute__((packed));
+/**
+ * @brief 全剧描述符寄存器
+ */
+struct gdt_ptr_t {
+ /// 全局描述符表限长
+ uint16_t limit;
+ /// 全局描述符表 32位 基地址
+ uint32_t base;
+} __attribute__((packed));
- /**
- * @brief 32 位 tss
- * @see 64-ia-32-architectures-software-developer-vol-3a-manual#7.2.1
- * @note 目前没有使用
- */
- struct tss32_t {
- uint16_t prev_task_link;
- uint16_t reserved0;
- uint32_t esp0;
- uint16_t ss0;
- uint32_t reserved1;
- uint32_t esp1;
- uint16_t ss1;
- uint32_t reserved2;
- uint32_t esp2;
- uint16_t ss2;
- uint32_t reserved3;
- uint32_t cr3;
- uint32_t eip;
- uint32_t eflags;
- uint32_t eax;
- uint32_t ecx;
- uint32_t edx;
- uint32_t ebx;
- uint32_t esp;
- uint32_t ebp;
- uint32_t esi;
- uint32_t edi;
- uint16_t es;
- uint16_t reserved4;
- uint16_t cs;
- uint16_t reserved5;
- uint16_t ss;
- uint16_t reserved6;
- uint16_t ds;
- uint16_t reserved7;
- uint16_t fs;
- uint16_t reserved8;
- uint16_t gs;
- uint16_t reserved9;
- uint16_t ldt_segment_selector;
- uint16_t reserved10;
- uint32_t t : 1;
- uint32_t reserved11 : 15;
- uint32_t io_map_base_addr : 16;
- } __attribute__((packed));
+/**
+ * @brief 32 位 tss
+ * @see 64-ia-32-architectures-software-developer-vol-3a-manual#7.2.1
+ * @note 目前没有使用
+ */
+struct tss32_t {
+ uint16_t prev_task_link;
+ uint16_t reserved0;
+ uint32_t esp0;
+ uint16_t ss0;
+ uint32_t reserved1;
+ uint32_t esp1;
+ uint16_t ss1;
+ uint32_t reserved2;
+ uint32_t esp2;
+ uint16_t ss2;
+ uint32_t reserved3;
+ uint32_t cr3;
+ uint32_t eip;
+ uint32_t eflags;
+ uint32_t eax;
+ uint32_t ecx;
+ uint32_t edx;
+ uint32_t ebx;
+ uint32_t esp;
+ uint32_t ebp;
+ uint32_t esi;
+ uint32_t edi;
+ uint16_t es;
+ uint16_t reserved4;
+ uint16_t cs;
+ uint16_t reserved5;
+ uint16_t ss;
+ uint16_t reserved6;
+ uint16_t ds;
+ uint16_t reserved7;
+ uint16_t fs;
+ uint16_t reserved8;
+ uint16_t gs;
+ uint16_t reserved9;
+ uint16_t ldt_segment_selector;
+ uint16_t reserved10;
+ uint32_t t : 1;
+ uint32_t reserved11 : 15;
+ uint32_t io_map_base_addr : 16;
+} __attribute__((packed));
- /**
- * @brief 全局描述符表构造函数
- * @param _num 描述符索引
- * @param _base 基地
- * @param _limit 长度
- * @param _access 访问权限
- * @param _gran 粒度
- */
- void set_gdt(int32_t _num, uint32_t _base, uint32_t _limit, uint8_t _access,
- uint8_t _gran);
+/**
+ * @brief 全局描述符表构造函数
+ * @param _num 描述符索引
+ * @param _base 基地
+ * @param _limit 长度
+ * @param _access 访问权限
+ * @param _gran 粒度
+ */
+void set_gdt(int32_t _num, uint32_t _base, uint32_t _limit, uint8_t _access,
+ uint8_t _gran);
- /**
- * @brief 初始化
- * @return int32_t 成功返回 0
- */
- int32_t init(void);
-};
+/**
+ * @brief 初始化
+ * @return int32_t 成功返回 0
+ */
+int32_t init(void);
+}; // namespace GDT
-#endif /* _GDT_H_ */
+#endif /* SIMPLEKERNEL_GDT_H */
diff --git a/src/arch/ia32/i386/intr/include/intr.h b/src/arch/ia32/i386/intr/include/intr.h
index b0b22a6a8..b48ba4bf1 100644
--- a/src/arch/ia32/i386/intr/include/intr.h
+++ b/src/arch/ia32/i386/intr/include/intr.h
@@ -14,10 +14,10 @@
*
*/
-#ifndef _INTR_H_
-#define _INTR_H_
+#ifndef SIMPLEKERNEL_INTR_H
+#define SIMPLEKERNEL_INTR_H
-#include "stdint.h"
+#include "cstdint"
/// @todo 升级为 APIC
class INTR {
@@ -26,9 +26,9 @@ class INTR {
* @brief 错误码结构
*/
struct error_code_t {
- uint32_t ext : 1;
- uint32_t idt : 1;
- uint32_t ti : 1;
+ uint32_t ext : 1;
+ uint32_t idt : 1;
+ uint32_t ti : 1;
uint32_t sec_idx : 28;
};
@@ -36,14 +36,14 @@ class INTR {
* @brief 缺页错误码结构
*/
struct page_fault_error_code_t {
- uint32_t p : 1;
- uint32_t wr : 1;
- uint32_t us : 1;
- uint32_t rsvd : 1;
- uint32_t id : 1;
- uint32_t pk : 1;
+ uint32_t p : 1;
+ uint32_t wr : 1;
+ uint32_t us : 1;
+ uint32_t rsvd : 1;
+ uint32_t id : 1;
+ uint32_t pk : 1;
uint32_t reserved1 : 9;
- uint32_t sgx : 1;
+ uint32_t sgx : 1;
uint32_t reserved2 : 16;
};
@@ -98,23 +98,23 @@ class INTR {
};
// 定义中断处理函数指针
- typedef void (*interrupt_handler_t)(intr_context_t *);
+ typedef void (*interrupt_handler_t)(intr_context_t*);
private:
/// 中断表最大值
- static constexpr const uint32_t INTERRUPT_MAX = 256;
+ static constexpr const uint32_t INTERRUPT_MAX = 256;
/// 8259A 相关定义
/// Master (IRQs 0-7)
- static constexpr const uint32_t IO_PIC1 = 0x20;
+ static constexpr const uint32_t IO_PIC1 = 0x20;
/// Slave (IRQs 8-15)
- static constexpr const uint32_t IO_PIC2 = 0xA0;
- static constexpr const uint32_t IO_PIC1C = IO_PIC1 + 1;
- static constexpr const uint32_t IO_PIC2C = IO_PIC2 + 1;
+ static constexpr const uint32_t IO_PIC2 = 0xA0;
+ static constexpr const uint32_t IO_PIC1C = IO_PIC1 + 1;
+ static constexpr const uint32_t IO_PIC2C = IO_PIC2 + 1;
/// End-of-interrupt command code
- static constexpr const uint32_t PIC_EOI = 0x20;
+ static constexpr const uint32_t PIC_EOI = 0x20;
/// 中断名数组
- static constexpr const char *const intrnames[] = {
+ static constexpr const char* const intrnames[] = {
"Divide Error",
"Debug Exception",
"NMI Interrupt",
@@ -144,21 +144,21 @@ class INTR {
*/
struct idt_entry32_t {
// 低位地址
- uint64_t offset0 : 16;
+ uint64_t offset0 : 16;
// 选择子
uint64_t selector : 16;
// 保留
uint64_t reserved : 4;
// 填充 0
- uint64_t zero : 4;
+ uint64_t zero : 4;
// 类型
- uint64_t type : 5;
+ uint64_t type : 5;
// 权限
- uint64_t dpl : 2;
+ uint64_t dpl : 2;
// 存在位
- uint64_t p : 1;
+ uint64_t p : 1;
// 中段地址
- uint64_t offset1 : 16;
+ uint64_t offset1 : 16;
} __attribute__((packed));
/**
@@ -174,10 +174,10 @@ class INTR {
/// 中断处理函数指针数组
static interrupt_handler_t interrupt_handlers[INTERRUPT_MAX]
- __attribute__((aligned(4)));
+ __attribute__((aligned(4)));
/// 中断描述符表
static idt_entry32_t idt_entry32[INTERRUPT_MAX]
- __attribute__((aligned(16)));
+ __attribute__((aligned(16)));
/// IDTR
static idt_ptr_t idt_ptr;
@@ -190,24 +190,24 @@ class INTR {
* @param _dpl ?
* @param _p ?
*/
- void set_idt(uint8_t _num, uint32_t _base, uint16_t _selector,
- uint8_t _type, uint8_t _dpl, uint8_t _p);
+ void set_idt(uint8_t _num, uint32_t _base, uint16_t _selector,
+ uint8_t _type, uint8_t _dpl, uint8_t _p);
/**
* @brief 8259A 芯片初始化
*/
- void init_interrupt_chip(void);
+ void init_interrupt_chip(void);
/**
* @brief 重设 8259A 芯片
* @param _no 要重设的中断号
*/
- void clear_interrupt_chip(uint8_t _no);
+ void clear_interrupt_chip(uint8_t _no);
/**
* @brief 关闭 8259A 芯片的所有中断,为启动 APIC 作准备
*/
- void disable_interrupt_chip(void);
+ void disable_interrupt_chip(void);
public:
// External(hardware generated) interrupts.
@@ -228,60 +228,60 @@ class INTR {
static constexpr const uint32_t INT_GENERAL_PROTECT = 13;
static constexpr const uint32_t INT_PAGE_FAULT = 14;
// 15 没有使用
- static constexpr const uint32_t INT_X87_FPU = 16;
- static constexpr const uint32_t INT_ALIGNMENT = 17;
- static constexpr const uint32_t INT_MACHINE_CHECK = 18;
- static constexpr const uint32_t INT_SIMD_FLOAT = 19;
- static constexpr const uint32_t INT_VIRTUAL_EXCE = 20;
+ static constexpr const uint32_t INT_X87_FPU = 16;
+ static constexpr const uint32_t INT_ALIGNMENT = 17;
+ static constexpr const uint32_t INT_MACHINE_CHECK = 18;
+ static constexpr const uint32_t INT_SIMD_FLOAT = 19;
+ static constexpr const uint32_t INT_VIRTUAL_EXCE = 20;
// 21~31 保留
// 定义IRQ
// 电脑系统计时器
- static constexpr const uint32_t IRQ0 = 32;
+ static constexpr const uint32_t IRQ0 = 32;
// 键盘
- static constexpr const uint32_t IRQ1 = 33;
+ static constexpr const uint32_t IRQ1 = 33;
// 与 IRQ9 相接,MPU-401 MD 使用
- static constexpr const uint32_t IRQ2 = 34;
+ static constexpr const uint32_t IRQ2 = 34;
// 串口设备
- static constexpr const uint32_t IRQ3 = 35;
+ static constexpr const uint32_t IRQ3 = 35;
// 串口设备
- static constexpr const uint32_t IRQ4 = 36;
+ static constexpr const uint32_t IRQ4 = 36;
// 建议声卡使用
- static constexpr const uint32_t IRQ5 = 37;
+ static constexpr const uint32_t IRQ5 = 37;
// 软驱传输控制使用
- static constexpr const uint32_t IRQ6 = 38;
+ static constexpr const uint32_t IRQ6 = 38;
// 打印机传输控制使用
- static constexpr const uint32_t IRQ7 = 39;
+ static constexpr const uint32_t IRQ7 = 39;
// 即时时钟
- static constexpr const uint32_t IRQ8 = 40;
+ static constexpr const uint32_t IRQ8 = 40;
// 与 IRQ2 相接,可设定给其他硬件
- static constexpr const uint32_t IRQ9 = 41;
+ static constexpr const uint32_t IRQ9 = 41;
// 建议网卡使用
- static constexpr const uint32_t IRQ10 = 42;
+ static constexpr const uint32_t IRQ10 = 42;
// 建议 AGP 显卡使用
- static constexpr const uint32_t IRQ11 = 43;
+ static constexpr const uint32_t IRQ11 = 43;
// 接 PS/2 鼠标,也可设定给其他硬件
- static constexpr const uint32_t IRQ12 = 44;
+ static constexpr const uint32_t IRQ12 = 44;
// 协处理器使用
- static constexpr const uint32_t IRQ13 = 45;
+ static constexpr const uint32_t IRQ13 = 45;
// SATA 主硬盘
- static constexpr const uint32_t IRQ14 = 46;
+ static constexpr const uint32_t IRQ14 = 46;
// SATA 从硬盘
- static constexpr const uint32_t IRQ15 = 47;
+ static constexpr const uint32_t IRQ15 = 47;
// 系统调用
- static constexpr const uint32_t IRQ128 = 128;
+ static constexpr const uint32_t IRQ128 = 128;
/**
* @brief 获取单例
* @return INTR& 静态对象
*/
- static INTR &get_instance(void);
+ static INTR& get_instance(void);
/**
* @brief 中断初始化
* @return int32_t desc
*/
- int32_t init(void);
+ int32_t init(void);
/**
* @brief 执行中断
@@ -289,9 +289,9 @@ class INTR {
* @param _intr_context 上下文
* @return int32_t 保存中断处理后的返回值
*/
- int32_t call_irq(uint8_t _no, intr_context_t *_intr_context);
+ int32_t call_irq(uint8_t _no, intr_context_t* _intr_context);
- int32_t call_isr(uint8_t _no, intr_context_t *_intr_context);
+ int32_t call_isr(uint8_t _no, intr_context_t* _intr_context);
/**
* @brief 注册一个中断处理函数
@@ -316,7 +316,7 @@ class INTR {
* @param _no 中断号
* @return const char* 对应的中断名
*/
- const char *get_intr_name(uint8_t _no);
+ const char* get_intr_name(uint8_t _no);
};
/**
@@ -328,12 +328,12 @@ class TIMER {
* @brief 获取单例
* @return TIMER& 静态对象
*/
- static TIMER &get_instance(void);
+ static TIMER& get_instance(void);
/**
* @brief 初始化
*/
- void init(void);
+ void init(void);
};
-#endif /* _INTR_H_ */
+#endif /* SIMPLEKERNEL_INTR_H */
diff --git a/src/arch/ia32/i386/intr/intr.cpp b/src/arch/ia32/i386/intr/intr.cpp
index 1a8238a9a..ae6c7d6bc 100644
--- a/src/arch/ia32/i386/intr/intr.cpp
+++ b/src/arch/ia32/i386/intr/intr.cpp
@@ -15,14 +15,13 @@
*
*/
-#include "io.h"
-#include "cpu.hpp"
-#include "stdio.h"
-#include "gdt.h"
#include "intr.h"
#include "apic.h"
+#include "cpu.hpp"
+#include "cstdio"
+#include "gdt.h"
+#include "io.h"
#include "keyboard.h"
-#include "vmm.h"
// 声明中断处理函数 0 ~ 19 属于 CPU 的异常中断
// ISR:中断服务程序(interrupt service routine)
@@ -110,7 +109,7 @@ extern "C" void idt_load(uint32_t);
/**
* @brief IRQ 处理函数
*/
-extern "C" void irq_handler(uint8_t _no, INTR::intr_context_t *_intr_context) {
+extern "C" void irq_handler(uint8_t _no, INTR::intr_context_t* _intr_context) {
INTR::get_instance().call_irq(_no, _intr_context);
return;
}
@@ -118,15 +117,15 @@ extern "C" void irq_handler(uint8_t _no, INTR::intr_context_t *_intr_context) {
/**
* @brief ISR 处理函数
*/
-extern "C" void isr_handler(uint8_t _no, INTR::intr_context_t *_intr_context,
- INTR::error_code_t *_err_code) {
+extern "C" void isr_handler(uint8_t _no, INTR::intr_context_t* _intr_context,
+ INTR::error_code_t* _err_code) {
(void)_err_code;
INTR::get_instance().call_isr(_no, _intr_context);
return;
}
// 默认处理函数
-static void handler_default(INTR::intr_context_t *) {
+static void handler_default(INTR::intr_context_t*) {
while (1) {
;
}
@@ -136,9 +135,9 @@ static void handler_default(INTR::intr_context_t *) {
// 中断处理函数指针数组
INTR::interrupt_handler_t INTR::interrupt_handlers[INTERRUPT_MAX];
// 中断描述符表
-INTR::idt_entry32_t INTR::idt_entry32[INTERRUPT_MAX];
+INTR::idt_entry32_t INTR::idt_entry32[INTERRUPT_MAX];
// IDTR
-INTR::idt_ptr_t INTR::idt_ptr;
+INTR::idt_ptr_t INTR::idt_ptr;
// 64-ia-32-architectures-software-developer-vol-3a-manual#6.11
void INTR::set_idt(uint8_t _num, uint32_t _base, uint16_t _selector,
@@ -207,7 +206,7 @@ void INTR::disable_interrupt_chip(void) {
return;
}
-INTR &INTR::get_instance(void) {
+INTR& INTR::get_instance(void) {
/// 定义全局 INTR 对象
static INTR intr;
return intr;
@@ -356,7 +355,7 @@ int32_t INTR::init(void) {
return 0;
}
-int32_t INTR::call_irq(uint8_t _no, intr_context_t *_intr_context) {
+int32_t INTR::call_irq(uint8_t _no, intr_context_t* _intr_context) {
// 重设PIC芯片
clear_interrupt_chip(_no);
if (interrupt_handlers[_no] != nullptr) {
@@ -365,7 +364,7 @@ int32_t INTR::call_irq(uint8_t _no, intr_context_t *_intr_context) {
return 0;
}
-int32_t INTR::call_isr(uint8_t _no, intr_context_t *_intr_context) {
+int32_t INTR::call_isr(uint8_t _no, intr_context_t* _intr_context) {
if (interrupt_handlers[_no] != nullptr) {
interrupt_handlers[_no](_intr_context);
}
@@ -410,8 +409,8 @@ void INTR::disable_irq(uint8_t _no) {
return;
}
-const char *INTR::get_intr_name(uint8_t _no) {
- if (_no < sizeof(intrnames) / sizeof(const char *const)) {
+const char* INTR::get_intr_name(uint8_t _no) {
+ if (_no < sizeof(intrnames) / sizeof(const char* const)) {
return intrnames[_no];
}
return "(unknown trap)";
diff --git a/src/arch/ia32/i386/intr/intr_s.S b/src/arch/ia32/i386/intr/intr_s.S
index db08dfb48..429ef3cf6 100644
--- a/src/arch/ia32/i386/intr/intr_s.S
+++ b/src/arch/ia32/i386/intr/intr_s.S
@@ -1,8 +1,11 @@
-// This file is a part of Simple-XX/SimpleKernel (https://github.com/Simple-XX/SimpleKernel).
+// This file is a part of Simple-XX/SimpleKernel
+// (https://github.com/Simple-XX/SimpleKernel).
#
// intr_s.s for Simple-XX/SimpleKernel.
+// clang-format off
+
.code32
// 加载 idt
diff --git a/src/arch/ia32/i386/intr/timer.cpp b/src/arch/ia32/i386/intr/timer.cpp
index 1fff2cc79..e5a0b8aa1 100644
--- a/src/arch/ia32/i386/intr/timer.cpp
+++ b/src/arch/ia32/i386/intr/timer.cpp
@@ -14,21 +14,18 @@
*
*/
-#include "stdint.h"
-#include "stdio.h"
-#include "cpu.hpp"
+#include "cstdio"
#include "intr.h"
-#include "io.h"
/**
* @brief 时钟中断
*/
-void timer_intr(INTR::intr_context_t *) {
+void timer_intr(INTR::intr_context_t*) {
printf("timer.\n");
return;
}
-TIMER &TIMER::get_instance(void) {
+TIMER& TIMER::get_instance(void) {
/// 定义全局 TIMER 对象
static TIMER timer;
return timer;
diff --git a/src/arch/ia32/i386/link.ld b/src/arch/ia32/i386/link.ld
index 7a2f50f47..24c1bd9ab 100644
--- a/src/arch/ia32/i386/link.ld
+++ b/src/arch/ia32/i386/link.ld
@@ -2,75 +2,244 @@
/* This file is a part of Simple-XX/SimpleKernel
* (https://github.com/Simple-XX/SimpleKernel).
*
- * link.ld for Simple-XX/SimpleKernel.
- * 链接脚本,指定生成的二进制文件的布局 */
+ * link.ld for Simple-XX/SimpleKernel.
+ * 链接脚本,指定生成的二进制文件的布局
+ */
+/* Script for -z combreloc -z separate-code */
+/* Copyright (C) 2014-2022 Free Software Foundation, Inc.
+ Copying and distribution of this script, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. */
/* 指定输出格式 */
-OUTPUT_FORMAT(elf32-i386)
-/* 执行输出架构 */
+OUTPUT_FORMAT(
+ "elf32-i386",
+ "elf32-i386",
+ "elf32-i386"
+)
+/* 指定输出架构 */
OUTPUT_ARCH(i386)
/* 设置入口点 */
ENTRY(_start)
/* 设置各个 section */
SECTIONS {
- /* VMA 为顺序排列,LMA 按照 AT(addr) 排列 */
- . = 0;
- PROVIDE(kernel_start = .);
- /* 指定内核从地址 1M 处开始 */
- /* 0~1M 的空间为 BIOS 保留区域 */
- /* TODO: 这里似乎可以修改为任意地址 */
- . = 1M;
-
- PROVIDE(kernel_text_start = .);
- /* 代码段 */
- .text : ALIGN(4K) {
- *(.multiboot_header)
- *(.text*)
+ PROVIDE (__executable_start = SEGMENT_START("text-segment", 1M));
+ . = SEGMENT_START("text-segment", 1M);
+ .boot : { *(.text.boot) *(.data.boot) *(.bss.boot) }
+ .interp : { *(.interp) }
+ .note.gnu.build-id : { *(.note.gnu.build-id) }
+ .hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rela.dyn : {
+ *(.rela.init)
+ *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+ *(.rela.fini)
+ *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+ *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+ *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+ *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+ *(.rela.ctors)
+ *(.rela.dtors)
+ *(.rela.got)
+ *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+ *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
+ *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
+ *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
+ *(.rela.ifunc)
}
- PROVIDE(kernel_text_end = .);
-
- PROVIDE(kernel_rodata_start = .);
- /* 只读数据段 */
- .rodata : ALIGN(4K) {
- /* 构造函数起点 */
- PROVIDE(ctors_start = .);
- *(SORT_BY_INIT_PRIORITY (.init_array.*))
- *(SORT_BY_INIT_PRIORITY (.ctors.*))
- *(.init_array .ctors)
- /* 构造函数终点 */
- PROVIDE(ctors_end = .);
- /* 析构函数起点 */
- PROVIDE(dtors_start = .);
- *(.dtor*)
- /* 析构函数终点 */
- PROVIDE(dtors_end = .);
- *(.rodata*)
- *(.gcc_except_table)
- }
- PROVIDE(kernel_rodata_end = .);
-
- PROVIDE(kernel_data_start = .);
- /* 数据段 */
- .data : ALIGN(4K) {
- *(.data*)
- *(.eh_frame)
- *(.got*)
- }
- PROVIDE(kernel_data_end = .);
-
- PROVIDE(kernel_bss_start = .);
- /* 未初始化数据段 */
- .bss : ALIGN(4K) {
- *(.bss)
+ .rela.plt : {
+ *(.rela.plt)
+ PROVIDE_HIDDEN (__rela_iplt_start = .);
+ *(.rela.iplt)
+ PROVIDE_HIDDEN (__rela_iplt_end = .);
}
- PROVIDE(kernel_bss_end = .);
-
- PROVIDE(kernel_debug_start = .);
- /* 调试信息 */
- .debug : ALIGN(4K) {
- *(.debug*)
+ .relr.dyn : { *(.relr.dyn) }
+ . = ALIGN(CONSTANT (MAXPAGESIZE));
+ .init : {
+ KEEP (*(SORT_NONE(.init)))
}
- PROVIDE(kernel_debug_end = .);
-
- PROVIDE(kernel_end = .);
+ .plt : { *(.plt) *(.iplt) }
+ .plt.got : { *(.plt.got) }
+ .plt.sec : { *(.plt.sec) }
+ .text : {
+ *(.text.unlikely .text.*_unlikely .text.unlikely.*)
+ *(.text.exit .text.exit.*)
+ *(.text.startup .text.startup.*)
+ *(.text.hot .text.hot.*)
+ *(SORT(.text.sorted.*))
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ /* .gnu.warning sections are handled specially by elf.em. */
+ *(.gnu.warning)
+ }
+ .fini : {
+ KEEP (*(SORT_NONE(.fini)))
+ }
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+ . = ALIGN(CONSTANT (MAXPAGESIZE));
+ /* Adjust the address for the rodata segment. We want to adjust up to
+ the same address within the page on the next page up. */
+ . = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)));
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+ .rodata1 : { *(.rodata1) }
+ .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
+ .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
+ .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
+ .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }
+ /* These sections are generated by the Sun/Oracle C++ compiler. */
+ .exception_ranges : ONLY_IF_RO { *(.exception_ranges*) }
+ /* Adjust the address for the data segment. We want to adjust up to
+ the same address within the page on the next page up. */
+ . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+ /* Exception handling */
+ .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
+ .gnu_extab : ONLY_IF_RW { *(.gnu_extab) }
+ .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
+ .exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
+ /* Thread Local Storage sections */
+ .tdata : {
+ PROVIDE_HIDDEN (__tdata_start = .);
+ *(.tdata .tdata.* .gnu.linkonce.td.*)
+ }
+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+ .preinit_array : {
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ }
+ .init_array : {
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
+ KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ }
+ .fini_array : {
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
+ KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ }
+ .ctors : {
+ /* gcc uses crtbegin.o to find the start of
+ the constructors, so we make sure it is
+ first. Because this is a wildcard, it
+ doesn't matter if the user does not
+ actually link against crtbegin.o; the
+ linker won't look for a file to match a
+ wildcard. The wildcard also means that it
+ doesn't matter which directory crtbegin.o
+ is in. */
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*crtbegin?.o(.ctors))
+ /* We don't want to include the .ctor section from
+ the crtend.o file until after the sorted ctors.
+ The .ctor section from the crtend file contains the
+ end of ctors marker and it must be last */
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ }
+ .dtors : {
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*crtbegin?.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ }
+ .jcr : { KEEP (*(.jcr)) }
+ .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
+ .dynamic : { *(.dynamic) }
+ .got : { *(.got) *(.igot) }
+ . = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
+ .got.plt : { *(.got.plt) *(.igot.plt) }
+ .data : {
+ *(.data .data.* .gnu.linkonce.d.*)
+ SORT(CONSTRUCTORS)
+ }
+ .data1 : { *(.data1) }
+ _edata = .; PROVIDE (edata = .);
+ . = .;
+ __bss_start = .;
+ .bss : {
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ /* Align here to ensure that the .bss section occupies space up to
+ _end. Align after .bss to ensure correct alignment even if the
+ .bss section disappears because there are no input sections.
+ FIXME: Why do we need it? When there is no .bss section, we do not
+ pad the .data section. */
+ . = ALIGN(. != 0 ? 64 / 8 : 1);
+ }
+ .lbss : {
+ *(.dynlbss)
+ *(.lbss .lbss.* .gnu.linkonce.lb.*)
+ *(LARGE_COMMON)
+ }
+ . = ALIGN(64 / 8);
+ . = SEGMENT_START("ldata-segment", .);
+ .lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : {
+ *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
+ }
+ .ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : {
+ *(.ldata .ldata.* .gnu.linkonce.l.*)
+ . = ALIGN(. != 0 ? 64 / 8 : 1);
+ }
+ . = ALIGN(64 / 8);
+ _end = .; PROVIDE (end = .);
+ . = DATA_SEGMENT_END (.);
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1. */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions. */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2. */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2. */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions. */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ /* DWARF 3. */
+ .debug_pubtypes 0 : { *(.debug_pubtypes) }
+ .debug_ranges 0 : { *(.debug_ranges) }
+ /* DWARF 5. */
+ .debug_addr 0 : { *(.debug_addr) }
+ .debug_line_str 0 : { *(.debug_line_str) }
+ .debug_loclists 0 : { *(.debug_loclists) }
+ .debug_macro 0 : { *(.debug_macro) }
+ .debug_names 0 : { *(.debug_names) }
+ .debug_rnglists 0 : { *(.debug_rnglists) }
+ .debug_str_offsets 0 : { *(.debug_str_offsets) }
+ .debug_sup 0 : { *(.debug_sup) }
+ .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+ /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
}
diff --git a/src/arch/ia32/port/include/port.h b/src/arch/ia32/port/include/port.h
index a877d60a5..24dd94fba 100644
--- a/src/arch/ia32/port/include/port.h
+++ b/src/arch/ia32/port/include/port.h
@@ -14,62 +14,62 @@
*
*/
-#ifndef _PORT_H_
-#define _PORT_H_
+#ifndef SIMPLEKERNEL_PORT_H
+#define SIMPLEKERNEL_PORT_H
-#include "stdint.h"
+#include "cstdint"
/**
* @brief 端口读写封装
*/
namespace PORT {
- /**
- * @brief 读一个字节
- * @param _port 要读的端口
- * @return uint8_t 读取到的数据
- * @warning 不处理执行失败的问题
- */
- uint8_t inb(const uint32_t _port);
+/**
+ * @brief 读一个字节
+ * @param _port 要读的端口
+ * @return uint8_t 读取到的数据
+ * @warning 不处理执行失败的问题
+ */
+uint8_t inb(const uint32_t _port);
- /**
- * @brief 读一个字
- * @param _port 要读的端口
- * @return uint16_t 读取到的数据
- * @warning 不处理执行失败的问题
- */
- uint16_t inw(const uint32_t _port);
+/**
+ * @brief 读一个字
+ * @param _port 要读的端口
+ * @return uint16_t 读取到的数据
+ * @warning 不处理执行失败的问题
+ */
+uint16_t inw(const uint32_t _port);
- /**
- * @brief 读一个双字
- * @param _port 要读的端口
- * @return uint32_t 读取到的数据
- * @warning 不处理执行失败的问题
- */
- uint32_t ind(const uint32_t _port);
+/**
+ * @brief 读一个双字
+ * @param _port 要读的端口
+ * @return uint32_t 读取到的数据
+ * @warning 不处理执行失败的问题
+ */
+uint32_t ind(const uint32_t _port);
- /**
- * @brief 写一个字节
- * @param _port 要写的端口
- * @param _data 要写的数据
- * @warning 不处理执行失败的问题
- */
- void outb(const uint32_t _port, const uint8_t _data);
+/**
+ * @brief 写一个字节
+ * @param _port 要写的端口
+ * @param _data 要写的数据
+ * @warning 不处理执行失败的问题
+ */
+void outb(const uint32_t _port, const uint8_t _data);
- /**
- * @brief 写一个字
- * @param _port 要写的端口
- * @param _data 要写的数据
- * @warning 不处理执行失败的问题
- */
- void outw(const uint32_t _port, const uint16_t _data);
+/**
+ * @brief 写一个字
+ * @param _port 要写的端口
+ * @param _data 要写的数据
+ * @warning 不处理执行失败的问题
+ */
+void outw(const uint32_t _port, const uint16_t _data);
- /**
- * @brief 写一个双字
- * @param _port 要写的端口
- * @param _data 要写的数据
- * @warning 不处理执行失败的问题
- */
- void outd(const uint32_t _port, const uint32_t _data);
-};
+/**
+ * @brief 写一个双字
+ * @param _port 要写的端口
+ * @param _data 要写的数据
+ * @warning 不处理执行失败的问题
+ */
+void outd(const uint32_t _port, const uint32_t _data);
+}; // namespace PORT
-#endif /* _PORT_H_ */
+#endif /* SIMPLEKERNEL_PORT_H */
diff --git a/src/arch/ia32/x86_64/boot/boot.S b/src/arch/ia32/x86_64/boot/boot.S
index bae2ec0b5..6e434d7fb 100644
--- a/src/arch/ia32/x86_64/boot/boot.S
+++ b/src/arch/ia32/x86_64/boot/boot.S
@@ -1,89 +1,99 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-//
-// boot.S for Simple-XX/SimpleKernel.
-// 启动代码,进行一些设置后跳转到 kernel_main
+/**
+ * @file boot.S
+ * @brief 启动代码,进行一些设置后跳转到 kernel_main
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2021-01-01
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2021-01-02 MRNIU 迁移到 doxygen
+ *
+ */
// 以下是来自 multiboot2 规范的定义
// How many bytes from the start of the file we search for the header.
-#define MULTIBOOT_SEARCH 32768
-#define MULTIBOOT_HEADER_ALIGN 8
+#define MULTIBOOT_SEARCH 32768
+#define MULTIBOOT_HEADER_ALIGN 8
-// The magic field should contain this.
-#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
+// The magic field should contain this.
+#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
-// This should be in %eax.
-#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
+// This should be in %eax.
+#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
-// Alignment of multiboot modules.
-#define MULTIBOOT_MOD_ALIGN 0x00001000
+// Alignment of multiboot modules.
+#define MULTIBOOT_MOD_ALIGN 0x00001000
-// Alignment of the multiboot info structure.
-#define MULTIBOOT_INFO_ALIGN 0x00000008
+// Alignment of the multiboot info structure.
+#define MULTIBOOT_INFO_ALIGN 0x00000008
-// Flags set in the 'flags' member of the multiboot header.
+// Flags set in the 'flags' member of the multiboot header.
-#define MULTIBOOT_TAG_ALIGN 8
-#define MULTIBOOT_TAG_TYPE_END 0
-#define MULTIBOOT_TAG_TYPE_CMDLINE 1
-#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
-#define MULTIBOOT_TAG_TYPE_MODULE 3
-#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
-#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
-#define MULTIBOOT_TAG_TYPE_MMAP 6
-#define MULTIBOOT_TAG_TYPE_VBE 7
-#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
-#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
-#define MULTIBOOT_TAG_TYPE_APM 10
-#define MULTIBOOT_TAG_TYPE_EFI32 11
-#define MULTIBOOT_TAG_TYPE_EFI64 12
-#define MULTIBOOT_TAG_TYPE_SMBIOS 13
-#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
-#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
-#define MULTIBOOT_TAG_TYPE_NETWORK 16
-#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
-#define MULTIBOOT_TAG_TYPE_EFI_BS 18
-#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
-#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
-#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
+#define MULTIBOOT_TAG_ALIGN 8
+#define MULTIBOOT_TAG_TYPE_END 0
+#define MULTIBOOT_TAG_TYPE_CMDLINE 1
+#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
+#define MULTIBOOT_TAG_TYPE_MODULE 3
+#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
+#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
+#define MULTIBOOT_TAG_TYPE_MMAP 6
+#define MULTIBOOT_TAG_TYPE_VBE 7
+#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
+#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
+#define MULTIBOOT_TAG_TYPE_APM 10
+#define MULTIBOOT_TAG_TYPE_EFI32 11
+#define MULTIBOOT_TAG_TYPE_EFI64 12
+#define MULTIBOOT_TAG_TYPE_SMBIOS 13
+#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
+#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
+#define MULTIBOOT_TAG_TYPE_NETWORK 16
+#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
+#define MULTIBOOT_TAG_TYPE_EFI_BS 18
+#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
+#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
+#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
-#define MULTIBOOT_HEADER_TAG_END 0
-#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
-#define MULTIBOOT_HEADER_TAG_ADDRESS 2
-#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
-#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
-#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
-#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
-#define MULTIBOOT_HEADER_TAG_EFI_BS 7
-#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
-#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
-#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
+#define MULTIBOOT_HEADER_TAG_END 0
+#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
+#define MULTIBOOT_HEADER_TAG_ADDRESS 2
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
+#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
+#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
+#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
+#define MULTIBOOT_HEADER_TAG_EFI_BS 7
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
+#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
+#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
-#define MULTIBOOT_ARCHITECTURE_I386 0
-#define MULTIBOOT_ARCHITECTURE_MIPS32 4
-#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
+#define MULTIBOOT_ARCHITECTURE_I386 0
+#define MULTIBOOT_ARCHITECTURE_MIPS32 4
+#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
-#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
-#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
-#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
+#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
+#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
+#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
-#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
+#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
-
// 直接用 -m64 编译出来的是 64 位代码,
// 但是启动后的机器是 32 位的,相当于在 32 位机器上跑 64 位程序。
-// 得加一层跳转到 64 位的 -m32 代码,开启 long 模式后再跳转到以 -m64 编译的代码中
-// 对于 x86_64,需要在启动阶段进入长模式(IA32E),这意味着需要一个临时页表
-// See https://wiki.osdev.org/Creating_a_64-bit_kernel:
-// With a 32-bit bootstrap in your kernel
+// 得加一层跳转到 64 位的 -m32 代码,开启 long 模式后再跳转到以 -m64
+// 编译的代码中 对于
+// x86_64,需要在启动阶段进入长模式(IA32E),这意味着需要一个临时页表 See
+// https://wiki.osdev.org/Creating_a_64-bit_kernel: With a 32-bit bootstrap in
+// your kernel
+
+// clang-format off
// 这部分是从保护模式启动 long 模式的代码
// 工作在 32bit
// 声明这一段代码以 32 位模式编译
.code32
-
// multiboot2 文件头
// 计算头长度
.SET HEADER_LENGTH, multiboot_header_end - multiboot_header
@@ -92,7 +102,7 @@
// 8 字节对齐
.align MULTIBOOT_HEADER_ALIGN
// 声明所属段
-.section .multiboot_header
+.section .text.boot
multiboot_header:
// 魔数
.long MULTIBOOT2_HEADER_MAGIC
@@ -110,7 +120,7 @@ multiboot_header:
multiboot_header_end:
// 临时页表 4KB/页
-.section .data
+.section .data.boot
.align 0x1000
pml4:
.skip 0x1000
@@ -166,10 +176,10 @@ gdt64_pointer64:
.short gdt64_pointer-gdt64-1
.quad gdt64
-.section .text
+.section .text.boot
.global _start
.type _start, @function
-# 在 multiboot2.cpp 中定义
+// 在 multiboot2.cpp 中定义
.extern boot_info_addr
.extern multiboot2_magic
_start:
@@ -231,8 +241,7 @@ _start:
ret
.code64
-
-.section .text
+.section .text.boot
.global _start64
.type _start64, @function
.extern kernel_main
@@ -250,7 +259,7 @@ _start64:
mov %rax, %gs
mov %rax, %ss
// 设置栈地址
- mov $STACK_TOP, %rsp
+ mov $stack_top, %rsp
// 栈地址按照 4096 字节对齐
and $0xFFFFFFFFFFFFF000, %rsp
// 帧指针修改为 0
@@ -261,7 +270,12 @@ _start64:
hlt
ret
-.section .bss
-STACK:
- .skip 4096 * 4
-STACK_TOP:
+// 声明所属段
+.section .bss.boot
+// 16 字节对齐
+.align 16
+.global stack_top
+// 栈
+stack_top:
+ // 跳过 16KB
+ .space 4096 * 4
diff --git a/src/arch/ia32/x86_64/gdt/gdt.cpp b/src/arch/ia32/x86_64/gdt/gdt.cpp
index 636d928d1..487534388 100644
--- a/src/arch/ia32/x86_64/gdt/gdt.cpp
+++ b/src/arch/ia32/x86_64/gdt/gdt.cpp
@@ -14,58 +14,59 @@
*
*/
-#include "stdio.h"
#include "gdt.h"
+#include "cstdint"
+#include "cstdio"
namespace GDT {
- // 加载 GDTR
- extern "C" void gdt_load(uint32_t);
- // 全局 gdt 指针
- static gdt_ptr64_t gdt_ptr64;
- // 全局描述符表定义
- static gdt_entry_t gdt_entries[GDT_LENGTH] __attribute__((aligned(8)));
+// 加载 GDTR
+extern "C" void gdt_load(uint32_t);
+// 全局 gdt 指针
+static gdt_ptr64_t gdt_ptr64;
+// 全局描述符表定义
+static gdt_entry_t gdt_entries[GDT_LENGTH] __attribute__((aligned(8)));
- void set_gdt(uint8_t _idx, uint32_t _base, uint32_t _limit, uint8_t _type,
- uint8_t _s, uint8_t _dpl, uint8_t _p, uint8_t _avl, uint8_t _l,
- uint8_t _db, uint8_t _g) {
- gdt_entries[_idx].limit1 = (_limit & 0xFFFF);
- gdt_entries[_idx].base_addr1 = (_base & 0xFFFF);
- gdt_entries[_idx].base_addr2 = (_base >> 16) & 0xFF;
- gdt_entries[_idx].type = _type;
- gdt_entries[_idx].s = _s;
- gdt_entries[_idx].dpl = _dpl;
- gdt_entries[_idx].p = _p;
- gdt_entries[_idx].limit2 = (_limit >> 16) & 0x0F;
- gdt_entries[_idx].avl = _avl;
- gdt_entries[_idx].l = _l;
- gdt_entries[_idx].db = _db;
- gdt_entries[_idx].g = _g;
- gdt_entries[_idx].base_addr3 = (_base >> 24) & 0xFF;
- return;
- }
+void set_gdt(uint8_t _idx, uint32_t _base, uint32_t _limit, uint8_t _type,
+ uint8_t _s, uint8_t _dpl, uint8_t _p, uint8_t _avl, uint8_t _l,
+ uint8_t _db, uint8_t _g) {
+ gdt_entries[_idx].limit1 = (_limit & 0xFFFF);
+ gdt_entries[_idx].base_addr1 = (_base & 0xFFFF);
+ gdt_entries[_idx].base_addr2 = (_base >> 16) & 0xFF;
+ gdt_entries[_idx].type = _type;
+ gdt_entries[_idx].s = _s;
+ gdt_entries[_idx].dpl = _dpl;
+ gdt_entries[_idx].p = _p;
+ gdt_entries[_idx].limit2 = (_limit >> 16) & 0x0F;
+ gdt_entries[_idx].avl = _avl;
+ gdt_entries[_idx].l = _l;
+ gdt_entries[_idx].db = _db;
+ gdt_entries[_idx].g = _g;
+ gdt_entries[_idx].base_addr3 = (_base >> 24) & 0xFF;
+ return;
+}
- int32_t init(void) {
- // 全局描述符表界限 从 0 开始,所以总长要 - 1
- gdt_ptr64.limit = sizeof(gdt_entry_t) * GDT_LENGTH - 1;
- gdt_ptr64.base = (uint64_t)&gdt_entries;
- // 采用 Intel 平坦模型
- // Intel 文档要求首个描述符全 0
- set_gdt(GDT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
- // 内核指令段
- set_gdt(GDT_KERNEL_CODE, 0x0, 0x0, TYPE_CODE_EXECUTE_READ, S_CODE_DATA,
- CPU::DPL0, SEGMENT_PRESENT, 0x0, L_64BIT, 0x0, 0x0);
- // 内核数据段
- set_gdt(GDT_KERNEL_DATA, 0x0, 0x0, TYPE_DATA_READ_WRITE, S_CODE_DATA,
- CPU::DPL0, SEGMENT_PRESENT, 0x0, L_64BIT, 0x0, 0x0);
- // 用户模式代码段
- set_gdt(GDT_USER_CODE, 0x0, 0x0, TYPE_CODE_EXECUTE_READ, S_CODE_DATA,
- CPU::DPL3, SEGMENT_PRESENT, 0x0, L_64BIT, 0x0, 0x0);
- // 用户模式数据段
- set_gdt(GDT_USER_DATA, 0x0, 0x0, TYPE_DATA_READ_WRITE, S_CODE_DATA,
- CPU::DPL3, SEGMENT_PRESENT, 0x0, L_64BIT, 0x0, 0x0);
- // 加载全局描述符表地址到 GDTR 寄存器
- gdt_load((uint64_t)&gdt_ptr64);
- info("gdt init.\n");
- return 0;
- }
-};
+int32_t init(void) {
+ // 全局描述符表界限 从 0 开始,所以总长要 - 1
+ gdt_ptr64.limit = sizeof(gdt_entry_t) * GDT_LENGTH - 1;
+ gdt_ptr64.base = (uint64_t)&gdt_entries;
+ // 采用 Intel 平坦模型
+ // Intel 文档要求首个描述符全 0
+ set_gdt(GDT_NULL, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
+ // 内核指令段
+ set_gdt(GDT_KERNEL_CODE, 0x0, 0x0, TYPE_CODE_EXECUTE_READ, S_CODE_DATA,
+ CPU::DPL0, SEGMENT_PRESENT, 0x0, L_64BIT, 0x0, 0x0);
+ // 内核数据段
+ set_gdt(GDT_KERNEL_DATA, 0x0, 0x0, TYPE_DATA_READ_WRITE, S_CODE_DATA,
+ CPU::DPL0, SEGMENT_PRESENT, 0x0, L_64BIT, 0x0, 0x0);
+ // 用户模式代码段
+ set_gdt(GDT_USER_CODE, 0x0, 0x0, TYPE_CODE_EXECUTE_READ, S_CODE_DATA,
+ CPU::DPL3, SEGMENT_PRESENT, 0x0, L_64BIT, 0x0, 0x0);
+ // 用户模式数据段
+ set_gdt(GDT_USER_DATA, 0x0, 0x0, TYPE_DATA_READ_WRITE, S_CODE_DATA,
+ CPU::DPL3, SEGMENT_PRESENT, 0x0, L_64BIT, 0x0, 0x0);
+ // 加载全局描述符表地址到 GDTR 寄存器
+ gdt_load((uint64_t)&gdt_ptr64);
+ info("gdt init.\n");
+ return 0;
+}
+}; // namespace GDT
diff --git a/src/arch/ia32/x86_64/gdt/gdt_s.S b/src/arch/ia32/x86_64/gdt/gdt_s.S
index 17e025f90..db91c40ce 100644
--- a/src/arch/ia32/x86_64/gdt/gdt_s.S
+++ b/src/arch/ia32/x86_64/gdt/gdt_s.S
@@ -4,6 +4,8 @@
//
// gdt_s.S for Simple-XX/SimpleKernel.
+// clang-format off
+
.code64
.section .text
diff --git a/src/arch/ia32/x86_64/gdt/include/gdt.h b/src/arch/ia32/x86_64/gdt/include/gdt.h
index bad327eab..3f7eb09fc 100644
--- a/src/arch/ia32/x86_64/gdt/include/gdt.h
+++ b/src/arch/ia32/x86_64/gdt/include/gdt.h
@@ -14,269 +14,268 @@
*
*/
-#ifndef _GDT_H_
-#define _GDT_H_
+#ifndef SIMPLEKERNEL_GDT_H
+#define SIMPLEKERNEL_GDT_H
-#include "stdint.h"
#include "cpu.hpp"
+#include "cstdint"
/**
* @brief GDT 接口
* @see 64-ia-32-architectures-software-developer-vol-3a-manual Chapter3
*/
namespace GDT {
- /// 全局描述符表长度
- static constexpr const uint32_t GDT_LENGTH = 5;
- /// 各个内存段所在全局描述符表下标
- static constexpr const uint32_t GDT_NULL = 0;
- /// 内核代码段
- static constexpr const uint32_t GDT_KERNEL_CODE = 1;
- /// 内核数据段
- static constexpr const uint32_t GDT_KERNEL_DATA = 2;
- /// 用户代码段
- static constexpr const uint32_t GDT_USER_CODE = 3;
- /// 用户数据段
- static constexpr const uint32_t GDT_USER_DATA = 4;
- /// 内核代码段选择子 0x08
- static constexpr const uint32_t SEG_KERNEL_CODE = GDT_KERNEL_CODE << 3;
- /// 内核数据段选择子
- static constexpr const uint32_t SEG_KERNEL_DATA = GDT_KERNEL_DATA << 3;
- /// 用户代码段选择子
- static constexpr const uint32_t SEG_USER_CODE = GDT_USER_CODE << 3;
- /// 用户数据段选择子
- static constexpr const uint32_t SEG_USER_DATA = GDT_USER_DATA << 3;
+/// 全局描述符表长度
+static constexpr const uint32_t GDT_LENGTH = 5;
+/// 各个内存段所在全局描述符表下标
+static constexpr const uint32_t GDT_NULL = 0;
+/// 内核代码段
+static constexpr const uint32_t GDT_KERNEL_CODE = 1;
+/// 内核数据段
+static constexpr const uint32_t GDT_KERNEL_DATA = 2;
+/// 用户代码段
+static constexpr const uint32_t GDT_USER_CODE = 3;
+/// 用户数据段
+static constexpr const uint32_t GDT_USER_DATA = 4;
+/// 内核代码段选择子 0x08
+static constexpr const uint32_t SEG_KERNEL_CODE = GDT_KERNEL_CODE << 3;
+/// 内核数据段选择子
+static constexpr const uint32_t SEG_KERNEL_DATA = GDT_KERNEL_DATA << 3;
+/// 用户代码段选择子
+static constexpr const uint32_t SEG_USER_CODE = GDT_USER_CODE << 3;
+/// 用户数据段选择子
+static constexpr const uint32_t SEG_USER_DATA = GDT_USER_DATA << 3;
- // type 类型
- // Code-and Data-Segment Types, S=1
- /// @see 64-ia-32-architectures-software-developer-vol-3a-manual#3.4.5.1
- /// 数据段 只读
- static constexpr const uint32_t TYPE_DATA_READ_ONLY = 0x00;
- /// 数据段 只读,可访问
- static constexpr const uint32_t TYPE_DATA_READ_ONLY_ACCESSED = 0x01;
- /// 数据段 读写
- static constexpr const uint32_t TYPE_DATA_READ_WRITE = 0x02;
- /// 数据段,读写,可访问
- static constexpr const uint32_t TYPE_DATA_READ_WRITE_ACCESSED = 0x03;
- /// 数据段,只读,?
- static constexpr const uint32_t TYPE_DATA_READ_ONLY_EXPAND_DOWN = 0x04;
- /// 数据段,只读,?,可访问
- static constexpr const uint32_t TYPE_DATA_READ_ONLY_EXPAND_DOWN_ACCESSED =
- 0x05;
- /// 数据段,读写,?
- static constexpr const uint32_t TYPE_DATA_READ_WRITE_EXPAND_DOWN = 0x06;
- /// 数据段,读写,?可访问
- static constexpr const uint32_t TYPE_DATA_READ_WRITE_EXPAND_DOWN_ACCESSED =
- 0x07;
+// type 类型
+// Code-and Data-Segment Types, S=1
+/// @see 64-ia-32-architectures-software-developer-vol-3a-manual#3.4.5.1
+/// 数据段 只读
+static constexpr const uint32_t TYPE_DATA_READ_ONLY = 0x00;
+/// 数据段 只读,可访问
+static constexpr const uint32_t TYPE_DATA_READ_ONLY_ACCESSED = 0x01;
+/// 数据段 读写
+static constexpr const uint32_t TYPE_DATA_READ_WRITE = 0x02;
+/// 数据段,读写,可访问
+static constexpr const uint32_t TYPE_DATA_READ_WRITE_ACCESSED = 0x03;
+/// 数据段,只读,?
+static constexpr const uint32_t TYPE_DATA_READ_ONLY_EXPAND_DOWN = 0x04;
+/// 数据段,只读,?,可访问
+static constexpr const uint32_t TYPE_DATA_READ_ONLY_EXPAND_DOWN_ACCESSED = 0x05;
+/// 数据段,读写,?
+static constexpr const uint32_t TYPE_DATA_READ_WRITE_EXPAND_DOWN = 0x06;
+/// 数据段,读写,?可访问
+static constexpr const uint32_t TYPE_DATA_READ_WRITE_EXPAND_DOWN_ACCESSED
+ = 0x07;
- /// 代码段,仅执行
- static constexpr const uint32_t TYPE_CODE_EXECUTE_ONLY = 0x08;
- /// 代码段,仅执行,可访问
- static constexpr const uint32_t TYPE_CODE_EXECUTE_ONLY_ACCESSED = 0x09;
- /// 代码段,可执行,可读
- static constexpr const uint32_t TYPE_CODE_EXECUTE_READ = 0x0A;
- /// 代码段,可执行,可读,可访问
- static constexpr const uint32_t TYPE_CODE_EXECUTE_READ_ACCESSED = 0x0B;
- /// 代码段,仅执行,?
- static constexpr const uint32_t TYPE_CODE_EXECUTE_ONLY_CONFORMING = 0x0C;
- /// 代码段,仅执行,?,可访问
- static constexpr const uint32_t TYPE_CODE_EXECUTE_ONLY_CONFORMING_ACCESSED =
- 0x0D;
- /// 代码段,可执行,可读,?
- static constexpr const uint32_t TYPE_CODE_EXECUTE_READ_CONFORMING = 0x0E;
- /// 代码段,可执行,可读,?,可访问
- static constexpr const uint32_t TYPE_CODE_EXECUTE_READ_CONFORMING_ACCESSED =
- 0x0F;
+/// 代码段,仅执行
+static constexpr const uint32_t TYPE_CODE_EXECUTE_ONLY = 0x08;
+/// 代码段,仅执行,可访问
+static constexpr const uint32_t TYPE_CODE_EXECUTE_ONLY_ACCESSED = 0x09;
+/// 代码段,可执行,可读
+static constexpr const uint32_t TYPE_CODE_EXECUTE_READ = 0x0A;
+/// 代码段,可执行,可读,可访问
+static constexpr const uint32_t TYPE_CODE_EXECUTE_READ_ACCESSED = 0x0B;
+/// 代码段,仅执行,?
+static constexpr const uint32_t TYPE_CODE_EXECUTE_ONLY_CONFORMING = 0x0C;
+/// 代码段,仅执行,?,可访问
+static constexpr const uint32_t TYPE_CODE_EXECUTE_ONLY_CONFORMING_ACCESSED
+ = 0x0D;
+/// 代码段,可执行,可读,?
+static constexpr const uint32_t TYPE_CODE_EXECUTE_READ_CONFORMING = 0x0E;
+/// 代码段,可执行,可读,?,可访问
+static constexpr const uint32_t TYPE_CODE_EXECUTE_READ_CONFORMING_ACCESSED
+ = 0x0F;
- // System-Segment and Gate-Descriptor Types, 32bit, when S=0
- /// @see 64-ia-32-architectures-software-developer-vol-3a-manual#3.5
- /// LDT
- static constexpr const uint32_t TYPE_SYSTEM_LDT = 0x02;
- // 64 位 TSS,可用
- static constexpr const uint32_t TYPE_SYSTEM_64_TSS_AVAILABLE = 0x09;
- // 64 位 TSS,在用
- static constexpr const uint32_t TYPE_SYSTEM_64_TSS_BUSY = 0x0B;
- // 64 位 调用门
- static constexpr const uint32_t TYPE_SYSTEM_64_CALL_GATE = 0x0C;
- // 64 位 中断门
- static constexpr const uint32_t TYPE_SYSTEM_64_INTERRUPT_GATE = 0x0E;
- // 64 位 陷阱门
- static constexpr const uint32_t TYPE_SYSTEM_64_TRAP_GATE = 0x0F;
+// System-Segment and Gate-Descriptor Types, 32bit, when S=0
+/// @see 64-ia-32-architectures-software-developer-vol-3a-manual#3.5
+/// LDT
+static constexpr const uint32_t TYPE_SYSTEM_LDT = 0x02;
+// 64 位 TSS,可用
+static constexpr const uint32_t TYPE_SYSTEM_64_TSS_AVAILABLE = 0x09;
+// 64 位 TSS,在用
+static constexpr const uint32_t TYPE_SYSTEM_64_TSS_BUSY = 0x0B;
+// 64 位 调用门
+static constexpr const uint32_t TYPE_SYSTEM_64_CALL_GATE = 0x0C;
+// 64 位 中断门
+static constexpr const uint32_t TYPE_SYSTEM_64_INTERRUPT_GATE = 0x0E;
+// 64 位 陷阱门
+static constexpr const uint32_t TYPE_SYSTEM_64_TRAP_GATE = 0x0F;
- // S 位
- /// 系统段
- static constexpr const uint32_t S_SYSTEM = 0x00;
- /// 代码/数据段
- static constexpr const uint32_t S_CODE_DATA = 0x01;
+// S 位
+/// 系统段
+static constexpr const uint32_t S_SYSTEM = 0x00;
+/// 代码/数据段
+static constexpr const uint32_t S_CODE_DATA = 0x01;
- // 各个段的全局描述符表的选择子
- /// 内核代码段
- static constexpr const uint32_t KERNEL_CS = SEG_KERNEL_CODE | CPU::DPL0;
- /// 内核数据段
- static constexpr const uint32_t KERNEL_DS = SEG_KERNEL_DATA | CPU::DPL0;
- /// 用户代码段
- static constexpr const uint32_t USER_CS = SEG_USER_CODE | CPU::DPL3;
- /// 用户数据段
- static constexpr const uint32_t USER_DS = SEG_USER_DATA | CPU::DPL3;
+// 各个段的全局描述符表的选择子
+/// 内核代码段
+static constexpr const uint32_t KERNEL_CS = SEG_KERNEL_CODE | CPU::DPL0;
+/// 内核数据段
+static constexpr const uint32_t KERNEL_DS = SEG_KERNEL_DATA | CPU::DPL0;
+/// 用户代码段
+static constexpr const uint32_t USER_CS = SEG_USER_CODE | CPU::DPL3;
+/// 用户数据段
+static constexpr const uint32_t USER_DS = SEG_USER_DATA | CPU::DPL3;
- // P 位
- /// 无效
- static constexpr const uint32_t SEGMENT_NOT_PRESENT = 0x00;
- /// 有效
- static constexpr const uint32_t SEGMENT_PRESENT = 0x01;
- // AVL
- /// 无效
- static constexpr const uint32_t AVL_NOT_AVAILABLE = 0x00;
- /// 有效
- static constexpr const uint32_t AVL_AVAILABLE = 0x01;
- // L 位
- /// 32 位
- static constexpr const uint32_t L_32BIT = 0x00;
- /// 64 位
- static constexpr const uint32_t L_64BIT = 0x01;
- // D/B
- /// @todo
- static constexpr const uint32_t DB_EXECUTABLE_CODE_SEGMENT_16 = 0x00;
- /// @todo
- static constexpr const uint32_t DB_EXECUTABLE_CODE_SEGMENT_32 = 0x01;
- /// @todo
- static constexpr const uint32_t DB_STACK_SEGMENT_STACK_POINTER_16 = 0x00;
- /// @todo
- static constexpr const uint32_t DB_STACK_SEGMENT_STACK_POINTER_32 = 0x01;
- /// @todo
- static constexpr const uint32_t DB_EXPAND_DOWN_DATA_SEGMENT_64KB = 0x00;
- /// @todo
- static constexpr const uint32_t DB_EXPAND_DOWN_DATA_SEGMENT_4GB = 0x01;
- // G
- /// 字节粒度
- static constexpr const uint32_t G_BYTE = 0x00;
- /// 4KB 粒度
- static constexpr const uint32_t G_4KB = 0x01;
+// P 位
+/// 无效
+static constexpr const uint32_t SEGMENT_NOT_PRESENT = 0x00;
+/// 有效
+static constexpr const uint32_t SEGMENT_PRESENT = 0x01;
+// AVL
+/// 无效
+static constexpr const uint32_t AVL_NOT_AVAILABLE = 0x00;
+/// 有效
+static constexpr const uint32_t AVL_AVAILABLE = 0x01;
+// L 位
+/// 32 位
+static constexpr const uint32_t L_32BIT = 0x00;
+/// 64 位
+static constexpr const uint32_t L_64BIT = 0x01;
+// D/B
+/// @todo
+static constexpr const uint32_t DB_EXECUTABLE_CODE_SEGMENT_16 = 0x00;
+/// @todo
+static constexpr const uint32_t DB_EXECUTABLE_CODE_SEGMENT_32 = 0x01;
+/// @todo
+static constexpr const uint32_t DB_STACK_SEGMENT_STACK_POINTER_16 = 0x00;
+/// @todo
+static constexpr const uint32_t DB_STACK_SEGMENT_STACK_POINTER_32 = 0x01;
+/// @todo
+static constexpr const uint32_t DB_EXPAND_DOWN_DATA_SEGMENT_64KB = 0x00;
+/// @todo
+static constexpr const uint32_t DB_EXPAND_DOWN_DATA_SEGMENT_4GB = 0x01;
+// G
+/// 字节粒度
+static constexpr const uint32_t G_BYTE = 0x00;
+/// 4KB 粒度
+static constexpr const uint32_t G_4KB = 0x01;
- // 访问权限
- /// 内核读,执行
- static constexpr const uint32_t KREAD_EXEC = 0x9A;
- /// 内核写
- static constexpr const uint32_t KREAD_WRITE = 0x92;
- /// 用户读,执行
- static constexpr const uint32_t UREAD_EXEC = 0xFA;
- /// 用户写
- static constexpr const uint32_t UREAD_WRITE = 0xF2;
+// 访问权限
+/// 内核读,执行
+static constexpr const uint32_t KREAD_EXEC = 0x9A;
+/// 内核写
+static constexpr const uint32_t KREAD_WRITE = 0x92;
+/// 用户读,执行
+static constexpr const uint32_t UREAD_EXEC = 0xFA;
+/// 用户写
+static constexpr const uint32_t UREAD_WRITE = 0xF2;
- /// 段基址
- static constexpr const uint32_t BASE = 0x00;
- /// 段长度
- static constexpr const uint32_t LIMIT = 0x00;
+/// 段基址
+static constexpr const uint32_t BASE = 0x00;
+/// 段长度
+static constexpr const uint32_t LIMIT = 0x00;
- /**
- * @brief 全局描述符
- */
- struct gdt_entry_t {
- /// 段界限 15:00,long 模式下忽略
- uint64_t limit1 : 16;
- /// 基址 15:00,long 模式下忽略
- uint64_t base_addr1 : 16;
- /// 基址 23:16,long 模式下忽略
- uint64_t base_addr2 : 8;
- /// 类型
- uint64_t type : 4;
- /// Descriptor type (0 = system; 1 = code or data)
- uint64_t s : 1;
- /// Specifies the privilege level of the segment
- uint64_t dpl : 2;
- /// Indicates whether the segment is present in memory (set) or not
- /// present (clear).
- uint64_t p : 1;
- /// 段界限 19:16,long 模式下忽略
- uint64_t limit2 : 4;
- /// Available for use by system software
- uint64_t avl : 1;
- /// 64-bit code segment (IA-32e mode only)
- uint64_t l : 1;
- /// Default operation size(0 = 16 - bit segment; 1 = 32 - bit segment)
- /// long 模式下忽略
- uint64_t db : 1;
- /// Determines the scaling of the segment limit field. When the
- /// granularity flag is clear, the segment limit is interpreted in
- /// byte units; when flag is set, the segment limit is interpreted in
- /// 4-KByte units.
- /// long 模式下忽略
- uint64_t g : 1;
- /// 基址 31:24,long 模式下忽略
- uint64_t base_addr3 : 8;
- } __attribute__((packed));
+/**
+ * @brief 全局描述符
+ */
+struct gdt_entry_t {
+ /// 段界限 15:00,long 模式下忽略
+ uint64_t limit1 : 16;
+ /// 基址 15:00,long 模式下忽略
+ uint64_t base_addr1 : 16;
+ /// 基址 23:16,long 模式下忽略
+ uint64_t base_addr2 : 8;
+ /// 类型
+ uint64_t type : 4;
+ /// Descriptor type (0 = system; 1 = code or data)
+ uint64_t s : 1;
+ /// Specifies the privilege level of the segment
+ uint64_t dpl : 2;
+ /// Indicates whether the segment is present in memory (set) or not
+ /// present (clear).
+ uint64_t p : 1;
+ /// 段界限 19:16,long 模式下忽略
+ uint64_t limit2 : 4;
+ /// Available for use by system software
+ uint64_t avl : 1;
+ /// 64-bit code segment (IA-32e mode only)
+ uint64_t l : 1;
+ /// Default operation size(0 = 16 - bit segment; 1 = 32 - bit segment)
+ /// long 模式下忽略
+ uint64_t db : 1;
+ /// Determines the scaling of the segment limit field. When the
+ /// granularity flag is clear, the segment limit is interpreted in
+ /// byte units; when flag is set, the segment limit is interpreted in
+ /// 4-KByte units.
+ /// long 模式下忽略
+ uint64_t g : 1;
+ /// 基址 31:24,long 模式下忽略
+ uint64_t base_addr3 : 8;
+} __attribute__((packed));
- /**
- * @brief 全剧描述符寄存器
- * @see 64-ia-32-architectures-software-developer-vol-3a-manual#3.5.1
- */
- struct gdt_ptr64_t {
- // 全局描述符表限长
- uint16_t limit;
- // 全局描述符表 64位 基地址
- uint64_t base;
- } __attribute__((packed));
+/**
+ * @brief 全剧描述符寄存器
+ * @see 64-ia-32-architectures-software-developer-vol-3a-manual#3.5.1
+ */
+struct gdt_ptr64_t {
+ // 全局描述符表限长
+ uint16_t limit;
+ // 全局描述符表 64位 基地址
+ uint64_t base;
+} __attribute__((packed));
- /**
- * @brief 64 位 tss
- * @see 64-ia-32-architectures-software-developer-vol-3a-manual#7.7
- * @see 64-ia-32-architectures-software-developer-vol-3a-manual#7.2.3
- * @note 目前没有使用
- */
- struct tss64_t {
- uint32_t reserved0;
- uint32_t rsp0_lower32;
- uint32_t rsp0_upper32;
- uint32_t rsp1_lower32;
- uint32_t rsp1_upper32;
- uint32_t rsp2_lower32;
- uint32_t rsp2_upper32;
- uint32_t reserved1;
- uint32_t reserved2;
- uint32_t ist1_lower32;
- uint32_t ist1_upper32;
- uint32_t ist2_lower32;
- uint32_t ist2_upper32;
- uint32_t ist3_lower32;
- uint32_t ist3_upper32;
- uint32_t ist4_lower32;
- uint32_t ist4_upper32;
- uint32_t ist5_lower32;
- uint32_t ist5_upper32;
- uint32_t ist6_lower32;
- uint32_t ist6_upper32;
- uint32_t ist7_lower32;
- uint32_t ist7_upper32;
- uint32_t reserved3;
- uint32_t reserved4;
- uint16_t reserved5;
- uint16_t io_map_base_addr;
- } __attribute__((packed));
+/**
+ * @brief 64 位 tss
+ * @see 64-ia-32-architectures-software-developer-vol-3a-manual#7.7
+ * @see 64-ia-32-architectures-software-developer-vol-3a-manual#7.2.3
+ * @note 目前没有使用
+ */
+struct tss64_t {
+ uint32_t reserved0;
+ uint32_t rsp0_lower32;
+ uint32_t rsp0_upper32;
+ uint32_t rsp1_lower32;
+ uint32_t rsp1_upper32;
+ uint32_t rsp2_lower32;
+ uint32_t rsp2_upper32;
+ uint32_t reserved1;
+ uint32_t reserved2;
+ uint32_t ist1_lower32;
+ uint32_t ist1_upper32;
+ uint32_t ist2_lower32;
+ uint32_t ist2_upper32;
+ uint32_t ist3_lower32;
+ uint32_t ist3_upper32;
+ uint32_t ist4_lower32;
+ uint32_t ist4_upper32;
+ uint32_t ist5_lower32;
+ uint32_t ist5_upper32;
+ uint32_t ist6_lower32;
+ uint32_t ist6_upper32;
+ uint32_t ist7_lower32;
+ uint32_t ist7_upper32;
+ uint32_t reserved3;
+ uint32_t reserved4;
+ uint16_t reserved5;
+ uint16_t io_map_base_addr;
+} __attribute__((packed));
- /**
- * @brief 全局描述符表构造函数
- * @param _idx 描述符索引
- * @param _base 基址
- * @param _limit 长度
- * @param _type @todo
- * @param _s @todo
- * @param _dpl 权限
- * @param _p 有效
- * @param _avl @todo
- * @param _l 32/64位
- * @param _db @todo
- * @param _g 粒度
- */
- void set_gdt(uint8_t _idx, uint32_t _base, uint32_t _limit, uint8_t _type,
- uint8_t _s, uint8_t _dpl, uint8_t _p, uint8_t _avl, uint8_t _l,
- uint8_t _db, uint8_t _g);
+/**
+ * @brief 全局描述符表构造函数
+ * @param _idx 描述符索引
+ * @param _base 基址
+ * @param _limit 长度
+ * @param _type @todo
+ * @param _s @todo
+ * @param _dpl 权限
+ * @param _p 有效
+ * @param _avl @todo
+ * @param _l 32/64位
+ * @param _db @todo
+ * @param _g 粒度
+ */
+void set_gdt(uint8_t _idx, uint32_t _base, uint32_t _limit, uint8_t _type,
+ uint8_t _s, uint8_t _dpl, uint8_t _p, uint8_t _avl, uint8_t _l,
+ uint8_t _db, uint8_t _g);
- /**
- * @brief 初始化
- * @return int32_t 成功返回 0
- * @todo 与 32 位合并
- * @todo 精简代码
- */
- int32_t init(void);
-};
+/**
+ * @brief 初始化
+ * @return int32_t 成功返回 0
+ * @todo 与 32 位合并
+ * @todo 精简代码
+ */
+int32_t init(void);
+}; // namespace GDT
-#endif /* _GDT_H_ */
+#endif /* SIMPLEKERNEL_GDT_H */
diff --git a/src/arch/ia32/x86_64/intr/include/intr.h b/src/arch/ia32/x86_64/intr/include/intr.h
index 7a7b91058..fd6b3c172 100644
--- a/src/arch/ia32/x86_64/intr/include/intr.h
+++ b/src/arch/ia32/x86_64/intr/include/intr.h
@@ -14,10 +14,10 @@
*
*/
-#ifndef _INTR_H_
-#define _INTR_H_
+#ifndef SIMPLEKERNEL_INTR_H
+#define SIMPLEKERNEL_INTR_H
-#include "stdint.h"
+#include "cstdint"
/// @todo 升级为 APIC
class INTR {
@@ -26,9 +26,9 @@ class INTR {
* @brief 错误码结构
*/
struct error_code_t {
- uint32_t ext : 1;
- uint32_t idt : 1;
- uint32_t ti : 1;
+ uint32_t ext : 1;
+ uint32_t idt : 1;
+ uint32_t ti : 1;
uint32_t sec_idx : 28;
};
@@ -36,14 +36,14 @@ class INTR {
* @brief 缺页错误码结构
*/
struct page_fault_error_code_t {
- uint32_t p : 1;
- uint32_t wr : 1;
- uint32_t us : 1;
- uint32_t rsvd : 1;
- uint32_t id : 1;
- uint32_t pk : 1;
+ uint32_t p : 1;
+ uint32_t wr : 1;
+ uint32_t us : 1;
+ uint32_t rsvd : 1;
+ uint32_t id : 1;
+ uint32_t pk : 1;
uint32_t reserved1 : 9;
- uint32_t sgx : 1;
+ uint32_t sgx : 1;
uint32_t reserved2 : 16;
};
@@ -75,23 +75,23 @@ class INTR {
};
// 定义中断处理函数指针
- typedef void (*interrupt_handler_t)(intr_context_t *);
+ typedef void (*interrupt_handler_t)(intr_context_t*);
private:
/// 中断表最大值
- static constexpr const uint32_t INTERRUPT_MAX = 256;
+ static constexpr const uint32_t INTERRUPT_MAX = 256;
/// 8259A 相关定义
/// Master (IRQs 0-7)
- static constexpr const uint32_t IO_PIC1 = 0x20;
+ static constexpr const uint32_t IO_PIC1 = 0x20;
/// Slave (IRQs 8-15)
- static constexpr const uint32_t IO_PIC2 = 0xA0;
- static constexpr const uint32_t IO_PIC1C = IO_PIC1 + 1;
- static constexpr const uint32_t IO_PIC2C = IO_PIC2 + 1;
+ static constexpr const uint32_t IO_PIC2 = 0xA0;
+ static constexpr const uint32_t IO_PIC1C = IO_PIC1 + 1;
+ static constexpr const uint32_t IO_PIC2C = IO_PIC2 + 1;
/// End-of-interrupt command code
- static constexpr const uint32_t PIC_EOI = 0x20;
+ static constexpr const uint32_t PIC_EOI = 0x20;
/// 中断名数组
- static constexpr const char *const intrnames[] = {
+ static constexpr const char* const intrnames[] = {
"Divide Error",
"Debug Exception",
"NMI Interrupt",
@@ -121,26 +121,26 @@ class INTR {
*/
struct idt_entry64_t {
// 低位地址
- uint64_t offset0 : 16;
+ uint64_t offset0 : 16;
// 选择子
uint64_t selector : 16;
// 中断栈表
// 64-ia-32-architectures-software-developer-vol-3a-manual#6.14.5
- uint64_t ist : 3;
+ uint64_t ist : 3;
// 填充 0
- uint64_t zero0 : 5;
+ uint64_t zero0 : 5;
// 类型
- uint64_t type : 4;
+ uint64_t type : 4;
// 填充 0
- uint64_t zero1 : 1;
+ uint64_t zero1 : 1;
// 权限
- uint64_t dpl : 2;
+ uint64_t dpl : 2;
// 存在位
- uint64_t p : 1;
+ uint64_t p : 1;
// 中段地址
- uint64_t offset1 : 16;
+ uint64_t offset1 : 16;
// 高位地址
- uint64_t offset2 : 32;
+ uint64_t offset2 : 32;
// 保留
uint64_t reserved : 32;
} __attribute__((packed));
@@ -158,10 +158,10 @@ class INTR {
/// 中断处理函数指针数组
static interrupt_handler_t interrupt_handlers[INTERRUPT_MAX]
- __attribute__((aligned(4)));
+ __attribute__((aligned(4)));
/// 中断描述符表
static idt_entry64_t idt_entry64[INTERRUPT_MAX]
- __attribute__((aligned(16)));
+ __attribute__((aligned(16)));
/// IDTR
static idt_ptr_t idt_ptr;
@@ -175,24 +175,24 @@ class INTR {
* @param _dpl ?
* @param _p ?
*/
- void set_idt(uint8_t _num, uintptr_t _base, uint16_t _selector,
- uint8_t _ist, uint8_t _type, uint8_t _dpl, uint8_t _p);
+ void set_idt(uint8_t _num, uintptr_t _base, uint16_t _selector,
+ uint8_t _ist, uint8_t _type, uint8_t _dpl, uint8_t _p);
/**
* @brief 8259A 芯片初始化
*/
- void init_interrupt_chip(void);
+ void init_interrupt_chip(void);
/**
* @brief 重设 8259A 芯片
* @param _no 要重设的中断号
*/
- void clear_interrupt_chip(uint8_t _no);
+ void clear_interrupt_chip(uint8_t _no);
/**
* @brief 关闭 8259A 芯片的所有中断,为启动 APIC 作准备
*/
- void disable_interrupt_chip(void);
+ void disable_interrupt_chip(void);
public:
// External(hardware generated) interrupts.
@@ -213,60 +213,60 @@ class INTR {
static constexpr const uint32_t INT_GENERAL_PROTECT = 13;
static constexpr const uint32_t INT_PAGE_FAULT = 14;
// 15 没有使用
- static constexpr const uint32_t INT_X87_FPU = 16;
- static constexpr const uint32_t INT_ALIGNMENT = 17;
- static constexpr const uint32_t INT_MACHINE_CHECK = 18;
- static constexpr const uint32_t INT_SIMD_FLOAT = 19;
- static constexpr const uint32_t INT_VIRTUAL_EXCE = 20;
+ static constexpr const uint32_t INT_X87_FPU = 16;
+ static constexpr const uint32_t INT_ALIGNMENT = 17;
+ static constexpr const uint32_t INT_MACHINE_CHECK = 18;
+ static constexpr const uint32_t INT_SIMD_FLOAT = 19;
+ static constexpr const uint32_t INT_VIRTUAL_EXCE = 20;
// 21~31 保留
// 定义IRQ
// 电脑系统计时器
- static constexpr const uint32_t IRQ0 = 32;
+ static constexpr const uint32_t IRQ0 = 32;
// 键盘
- static constexpr const uint32_t IRQ1 = 33;
+ static constexpr const uint32_t IRQ1 = 33;
// 与 IRQ9 相接,MPU-401 MD 使用
- static constexpr const uint32_t IRQ2 = 34;
+ static constexpr const uint32_t IRQ2 = 34;
// 串口设备
- static constexpr const uint32_t IRQ3 = 35;
+ static constexpr const uint32_t IRQ3 = 35;
// 串口设备
- static constexpr const uint32_t IRQ4 = 36;
+ static constexpr const uint32_t IRQ4 = 36;
// 建议声卡使用
- static constexpr const uint32_t IRQ5 = 37;
+ static constexpr const uint32_t IRQ5 = 37;
// 软驱传输控制使用
- static constexpr const uint32_t IRQ6 = 38;
+ static constexpr const uint32_t IRQ6 = 38;
// 打印机传输控制使用
- static constexpr const uint32_t IRQ7 = 39;
+ static constexpr const uint32_t IRQ7 = 39;
// 即时时钟
- static constexpr const uint32_t IRQ8 = 40;
+ static constexpr const uint32_t IRQ8 = 40;
// 与 IRQ2 相接,可设定给其他硬件
- static constexpr const uint32_t IRQ9 = 41;
+ static constexpr const uint32_t IRQ9 = 41;
// 建议网卡使用
- static constexpr const uint32_t IRQ10 = 42;
+ static constexpr const uint32_t IRQ10 = 42;
// 建议 AGP 显卡使用
- static constexpr const uint32_t IRQ11 = 43;
+ static constexpr const uint32_t IRQ11 = 43;
// 接 PS/2 鼠标,也可设定给其他硬件
- static constexpr const uint32_t IRQ12 = 44;
+ static constexpr const uint32_t IRQ12 = 44;
// 协处理器使用
- static constexpr const uint32_t IRQ13 = 45;
+ static constexpr const uint32_t IRQ13 = 45;
// SATA 主硬盘
- static constexpr const uint32_t IRQ14 = 46;
+ static constexpr const uint32_t IRQ14 = 46;
// SATA 从硬盘
- static constexpr const uint32_t IRQ15 = 47;
+ static constexpr const uint32_t IRQ15 = 47;
// 系统调用
- static constexpr const uint32_t IRQ128 = 128;
+ static constexpr const uint32_t IRQ128 = 128;
/**
* @brief 获取单例
* @return INTR& 静态对象
*/
- static INTR &get_instance(void);
+ static INTR& get_instance(void);
/**
* @brief 中断初始化
* @return int32_t desc
*/
- int32_t init(void);
+ int32_t init(void);
/**
* @brief 执行中断
@@ -274,9 +274,9 @@ class INTR {
* @param _intr_context 上下文
* @return int32_t 保存中断处理后的返回值
*/
- int32_t call_irq(uint8_t _no, intr_context_t *_intr_context);
+ int32_t call_irq(uint8_t _no, intr_context_t* _intr_context);
- int32_t call_isr(uint8_t _no, intr_context_t *_intr_context);
+ int32_t call_isr(uint8_t _no, intr_context_t* _intr_context);
/**
* @brief 注册一个中断处理函数
@@ -302,7 +302,7 @@ class INTR {
* @param _no 中断号
* @return const char* 对应的中断名
*/
- const char *get_intr_name(uint8_t _no);
+ const char* get_intr_name(uint8_t _no);
};
/**
@@ -314,12 +314,12 @@ class TIMER {
* @brief 获取单例
* @return TIMER& 静态对象
*/
- static TIMER &get_instance(void);
+ static TIMER& get_instance(void);
/**
* @brief 初始化
*/
- void init(void);
+ void init(void);
};
-#endif /* _INTR_H_ */
+#endif /* SIMPLEKERNEL_INTR_H */
diff --git a/src/arch/ia32/x86_64/intr/intr.cpp b/src/arch/ia32/x86_64/intr/intr.cpp
index 27f53ba67..f3b33a4be 100644
--- a/src/arch/ia32/x86_64/intr/intr.cpp
+++ b/src/arch/ia32/x86_64/intr/intr.cpp
@@ -15,12 +15,12 @@
*
*/
-#include "io.h"
-#include "cpu.hpp"
-#include "stdio.h"
-#include "gdt.h"
#include "intr.h"
#include "apic.h"
+#include "cpu.hpp"
+#include "cstdio"
+#include "gdt.h"
+#include "io.h"
#include "keyboard.h"
// 声明中断处理函数 0 ~ 19 属于 CPU 的异常中断
@@ -109,7 +109,7 @@ extern "C" void idt_load(uint32_t);
/**
* @brief IRQ 处理函数
*/
-extern "C" void irq_handler(uint8_t _no, INTR::intr_context_t *_intr_context) {
+extern "C" void irq_handler(uint8_t _no, INTR::intr_context_t* _intr_context) {
INTR::get_instance().call_irq(_no, _intr_context);
return;
}
@@ -117,15 +117,15 @@ extern "C" void irq_handler(uint8_t _no, INTR::intr_context_t *_intr_context) {
/**
* @brief ISR 处理函数
*/
-extern "C" void isr_handler(uint8_t _no, INTR::intr_context_t *_intr_context,
- INTR::error_code_t *_err_code) {
+extern "C" void isr_handler(uint8_t _no, INTR::intr_context_t* _intr_context,
+ INTR::error_code_t* _err_code) {
(void)_err_code;
INTR::get_instance().call_isr(_no, _intr_context);
return;
}
// 默认处理函数
-static void handler_default(INTR::intr_context_t *) {
+static void handler_default(INTR::intr_context_t*) {
while (1) {
;
}
@@ -135,9 +135,9 @@ static void handler_default(INTR::intr_context_t *) {
// 中断处理函数指针数组
INTR::interrupt_handler_t INTR::interrupt_handlers[INTERRUPT_MAX];
// 中断描述符表
-INTR::idt_entry64_t INTR::idt_entry64[INTERRUPT_MAX];
+INTR::idt_entry64_t INTR::idt_entry64[INTERRUPT_MAX];
// IDTR
-INTR::idt_ptr_t INTR::idt_ptr;
+INTR::idt_ptr_t INTR::idt_ptr;
// 64-ia-32-architectures-software-developer-vol-3a-manual#6.14.1
void INTR::set_idt(uint8_t _num, uintptr_t _base, uint16_t _selector,
@@ -209,7 +209,7 @@ void INTR::disable_interrupt_chip(void) {
return;
}
-INTR &INTR::get_instance(void) {
+INTR& INTR::get_instance(void) {
/// 定义全局 INTR 对象
static INTR intr;
return intr;
@@ -358,7 +358,7 @@ int32_t INTR::init(void) {
return 0;
}
-int32_t INTR::call_irq(uint8_t _no, intr_context_t *_intr_context) {
+int32_t INTR::call_irq(uint8_t _no, intr_context_t* _intr_context) {
// 重设PIC芯片
clear_interrupt_chip(_no);
if (interrupt_handlers[_no] != nullptr) {
@@ -367,7 +367,7 @@ int32_t INTR::call_irq(uint8_t _no, intr_context_t *_intr_context) {
return 0;
}
-int32_t INTR::call_isr(uint8_t _no, intr_context_t *_intr_context) {
+int32_t INTR::call_isr(uint8_t _no, intr_context_t* _intr_context) {
if (interrupt_handlers[_no] != nullptr) {
interrupt_handlers[_no](_intr_context);
}
@@ -412,8 +412,8 @@ void INTR::disable_irq(uint8_t _no) {
return;
}
-const char *INTR::get_intr_name(uint8_t _no) {
- if (_no < sizeof(intrnames) / sizeof(const char *const)) {
+const char* INTR::get_intr_name(uint8_t _no) {
+ if (_no < sizeof(intrnames) / sizeof(const char* const)) {
return intrnames[_no];
}
return "(unknown trap)";
diff --git a/src/arch/ia32/x86_64/intr/intr_s.S b/src/arch/ia32/x86_64/intr/intr_s.S
index aec27c7da..3bf7f1344 100644
--- a/src/arch/ia32/x86_64/intr/intr_s.S
+++ b/src/arch/ia32/x86_64/intr/intr_s.S
@@ -1,8 +1,11 @@
-// This file is a part of Simple-XX/SimpleKernel (https://github.com/Simple-XX/SimpleKernel).
+// This file is a part of Simple-XX/SimpleKernel
+// (https://github.com/Simple-XX/SimpleKernel).
#
// intr_s.s for Simple-XX/SimpleKernel.
+// clang-format off
+
.code64
// 加载 idt
diff --git a/src/arch/ia32/x86_64/intr/timer.cpp b/src/arch/ia32/x86_64/intr/timer.cpp
index 1fff2cc79..e5a0b8aa1 100644
--- a/src/arch/ia32/x86_64/intr/timer.cpp
+++ b/src/arch/ia32/x86_64/intr/timer.cpp
@@ -14,21 +14,18 @@
*
*/
-#include "stdint.h"
-#include "stdio.h"
-#include "cpu.hpp"
+#include "cstdio"
#include "intr.h"
-#include "io.h"
/**
* @brief 时钟中断
*/
-void timer_intr(INTR::intr_context_t *) {
+void timer_intr(INTR::intr_context_t*) {
printf("timer.\n");
return;
}
-TIMER &TIMER::get_instance(void) {
+TIMER& TIMER::get_instance(void) {
/// 定义全局 TIMER 对象
static TIMER timer;
return timer;
diff --git a/src/arch/ia32/x86_64/link.ld b/src/arch/ia32/x86_64/link.ld
index dea73f61b..fecae84ec 100644
--- a/src/arch/ia32/x86_64/link.ld
+++ b/src/arch/ia32/x86_64/link.ld
@@ -2,75 +2,244 @@
/* This file is a part of Simple-XX/SimpleKernel
* (https://github.com/Simple-XX/SimpleKernel).
*
- * link.ld for Simple-XX/SimpleKernel.
- * 链接脚本,指定生成的二进制文件的布局 */
+ * link.ld for Simple-XX/SimpleKernel.
+ * 链接脚本,指定生成的二进制文件的布局
+ */
+/* Script for -z combreloc -z separate-code */
+/* Copyright (C) 2014-2022 Free Software Foundation, Inc.
+ Copying and distribution of this script, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. */
/* 指定输出格式 */
-OUTPUT_FORMAT(elf64-x86-64)
-/* 执行输出架构 */
+OUTPUT_FORMAT(
+ "elf64-x86-64",
+ "elf64-x86-64",
+ "elf64-x86-64"
+)
+/* 指定输出架构 */
OUTPUT_ARCH(i386:x86-64)
/* 设置入口点 */
ENTRY(_start)
/* 设置各个 section */
SECTIONS {
- . = 0;
-
- PROVIDE(kernel_start = .);
- /* 指定内核从地址 1M 处开始 */
- /* 0~1M 的空间为 BIOS 保留区域 */
- /* TODO: 这里似乎可以修改为任意地址 */
- . = 1M;
-
- PROVIDE(kernel_text_start = .);
- /* 代码段 */
- .text : ALIGN(4K) {
- *(.multiboot_header)
- *(.text*)
+ PROVIDE (__executable_start = SEGMENT_START("text-segment", 1M));
+ . = SEGMENT_START("text-segment", 1M);
+ .boot : { *(.text.boot) *(.data.boot) *(.bss.boot) }
+ .interp : { *(.interp) }
+ .note.gnu.build-id : { *(.note.gnu.build-id) }
+ .hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rela.dyn : {
+ *(.rela.init)
+ *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+ *(.rela.fini)
+ *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+ *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+ *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+ *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+ *(.rela.ctors)
+ *(.rela.dtors)
+ *(.rela.got)
+ *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+ *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
+ *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
+ *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
+ *(.rela.ifunc)
}
- PROVIDE(kernel_text_end = .);
-
- PROVIDE(kernel_rodata_start = .);
- /* 只读数据段 */
- .rodata : ALIGN(4K) {
- /* 构造函数起点 */
- PROVIDE(ctors_start = .);
- *(SORT_BY_INIT_PRIORITY (.init_array.*))
- *(SORT_BY_INIT_PRIORITY (.ctors.*))
- *(.init_array .ctors)
- /* 构造函数终点 */
- PROVIDE(ctors_end = .);
- /* 析构函数起点 */
- PROVIDE(dtors_start = .);
- *(.dtor*)
- /* 析构函数终点 */
- PROVIDE(dtors_end = .);
- *(.rodata*)
- *(.gcc_except_table)
- }
- PROVIDE(kernel_rodata_end = .);
-
- PROVIDE(kernel_data_start = .);
- /* 数据段 */
- .data : ALIGN(4K) {
- *(.data*)
- *(.eh_frame)
- *(.got*)
- }
- PROVIDE(kernel_data_end = .);
-
- PROVIDE(kernel_bss_start = .);
- /* 未初始化数据段 */
- .bss : ALIGN(4K) {
- *(.bss);
+ .rela.plt : {
+ *(.rela.plt)
+ PROVIDE_HIDDEN (__rela_iplt_start = .);
+ *(.rela.iplt)
+ PROVIDE_HIDDEN (__rela_iplt_end = .);
}
- PROVIDE(kernel_bss_end = .);
-
- PROVIDE(kernel_debug_start = .);
- /* 调试信息 */
- .debug : ALIGN(4K) {
- *(.debug*)
+ .relr.dyn : { *(.relr.dyn) }
+ . = ALIGN(CONSTANT (MAXPAGESIZE));
+ .init : {
+ KEEP (*(SORT_NONE(.init)))
}
- PROVIDE(kernel_debug_end = .);
-
- PROVIDE(kernel_end = .);
+ .plt : { *(.plt) *(.iplt) }
+ .plt.got : { *(.plt.got) }
+ .plt.sec : { *(.plt.sec) }
+ .text : {
+ *(.text.unlikely .text.*_unlikely .text.unlikely.*)
+ *(.text.exit .text.exit.*)
+ *(.text.startup .text.startup.*)
+ *(.text.hot .text.hot.*)
+ *(SORT(.text.sorted.*))
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ /* .gnu.warning sections are handled specially by elf.em. */
+ *(.gnu.warning)
+ }
+ .fini : {
+ KEEP (*(SORT_NONE(.fini)))
+ }
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+ . = ALIGN(CONSTANT (MAXPAGESIZE));
+ /* Adjust the address for the rodata segment. We want to adjust up to
+ the same address within the page on the next page up. */
+ . = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)));
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+ .rodata1 : { *(.rodata1) }
+ .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
+ .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
+ .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
+ .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }
+ /* These sections are generated by the Sun/Oracle C++ compiler. */
+ .exception_ranges : ONLY_IF_RO { *(.exception_ranges*) }
+ /* Adjust the address for the data segment. We want to adjust up to
+ the same address within the page on the next page up. */
+ . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+ /* Exception handling */
+ .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
+ .gnu_extab : ONLY_IF_RW { *(.gnu_extab) }
+ .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
+ .exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
+ /* Thread Local Storage sections */
+ .tdata : {
+ PROVIDE_HIDDEN (__tdata_start = .);
+ *(.tdata .tdata.* .gnu.linkonce.td.*)
+ }
+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+ .preinit_array : {
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ }
+ .init_array : {
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
+ KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ }
+ .fini_array : {
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
+ KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ }
+ .ctors : {
+ /* gcc uses crtbegin.o to find the start of
+ the constructors, so we make sure it is
+ first. Because this is a wildcard, it
+ doesn't matter if the user does not
+ actually link against crtbegin.o; the
+ linker won't look for a file to match a
+ wildcard. The wildcard also means that it
+ doesn't matter which directory crtbegin.o
+ is in. */
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*crtbegin?.o(.ctors))
+ /* We don't want to include the .ctor section from
+ the crtend.o file until after the sorted ctors.
+ The .ctor section from the crtend file contains the
+ end of ctors marker and it must be last */
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ }
+ .dtors : {
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*crtbegin?.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ }
+ .jcr : { KEEP (*(.jcr)) }
+ .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
+ .dynamic : { *(.dynamic) }
+ .got : { *(.got) *(.igot) }
+ . = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
+ .got.plt : { *(.got.plt) *(.igot.plt) }
+ .data : {
+ *(.data .data.* .gnu.linkonce.d.*)
+ SORT(CONSTRUCTORS)
+ }
+ .data1 : { *(.data1) }
+ _edata = .; PROVIDE (edata = .);
+ . = .;
+ __bss_start = .;
+ .bss : {
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ /* Align here to ensure that the .bss section occupies space up to
+ _end. Align after .bss to ensure correct alignment even if the
+ .bss section disappears because there are no input sections.
+ FIXME: Why do we need it? When there is no .bss section, we do not
+ pad the .data section. */
+ . = ALIGN(. != 0 ? 64 / 8 : 1);
+ }
+ .lbss : {
+ *(.dynlbss)
+ *(.lbss .lbss.* .gnu.linkonce.lb.*)
+ *(LARGE_COMMON)
+ }
+ . = ALIGN(64 / 8);
+ . = SEGMENT_START("ldata-segment", .);
+ .lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : {
+ *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
+ }
+ .ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : {
+ *(.ldata .ldata.* .gnu.linkonce.l.*)
+ . = ALIGN(. != 0 ? 64 / 8 : 1);
+ }
+ . = ALIGN(64 / 8);
+ _end = .; PROVIDE (end = .);
+ . = DATA_SEGMENT_END (.);
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1. */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions. */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2. */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2. */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions. */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ /* DWARF 3. */
+ .debug_pubtypes 0 : { *(.debug_pubtypes) }
+ .debug_ranges 0 : { *(.debug_ranges) }
+ /* DWARF 5. */
+ .debug_addr 0 : { *(.debug_addr) }
+ .debug_line_str 0 : { *(.debug_line_str) }
+ .debug_loclists 0 : { *(.debug_loclists) }
+ .debug_macro 0 : { *(.debug_macro) }
+ .debug_names 0 : { *(.debug_names) }
+ .debug_rnglists 0 : { *(.debug_rnglists) }
+ .debug_str_offsets 0 : { *(.debug_str_offsets) }
+ .debug_sup 0 : { *(.debug_sup) }
+ .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+ /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
}
diff --git a/src/arch/riscv64/boot/boot.S b/src/arch/riscv64/boot/boot.S
index 62509c3d7..be76a1113 100644
--- a/src/arch/riscv64/boot/boot.S
+++ b/src/arch/riscv64/boot/boot.S
@@ -1,12 +1,23 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-//
-// boot.S for Simple-XX/SimpleKernel.
-// 启动代码,进行一些设置后跳转到 kernel_main
+/**
+ * @file boot.S
+ * @brief 启动代码,进行一些设置后跳转到 kernel_main
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2021-01-01
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2021-01-01 MRNIU 迁移到 doxygen
+ *
+ */
-.section .init
-.globl _start
+// clang-format off
+
+.section .text.boot
+.global _start
.type _start, @function
.extern kernel_main
.extern cpp_init
@@ -24,9 +35,11 @@ _start:
call cpp_init
// 跳转到 C 代码执行
call kernel_main
+loop:
+ j loop
// 声明所属段
-.section .bss
+.section .bss.boot
// 16 字节对齐
.align 16
.global stack_top
diff --git a/src/arch/riscv64/context.S b/src/arch/riscv64/context.S
new file mode 100644
index 000000000..e1902d2eb
--- /dev/null
+++ b/src/arch/riscv64/context.S
@@ -0,0 +1,218 @@
+
+/**
+ * @file context.S
+ * @brief 上下文保存
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2021-01-01
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2021-01-01 MRNIU 迁移到 doxygen
+ *
+ */
+
+// clang-format off
+
+// 寄存器长度,8 字节
+.equ REG_BYTES, 8
+// 所有寄存器数量
+.equ ALL_REGS, 71
+// 保存所有寄存器需要的大小
+.equ ALL_SIZE, (ALL_REGS * REG_BYTES)
+
+// 将寄存器 a 保存在 c 偏移 b 的位置
+.macro sd_base a, b, c
+sd \a, ((\b) * REG_BYTES)(\c)
+.endm
+
+// 从 c 的偏移 b 处获取数据并赋值给寄存器 a
+.macro ld_base a, b, c
+ld \a, ((\b) * REG_BYTES)(\c)
+.endm
+
+// 将 float 寄存器 a 保存在 c 偏移 b 的位置
+.macro fsd_base a, b, c
+fsd \a, ((\b) * REG_BYTES)(\c)
+.endm
+
+// 从 c 的偏移 b 处获取数据并赋值给 float 寄存器 a
+.macro fld_base a, b, c
+fld \a, ((\b) * REG_BYTES)(\c)
+.endm
+
+/**
+ * @brief 保存所有寄存器
+ * @param _base 要保存到的基地址
+ */
+.macro all_regs_save _base
+ sd_base zero, 0, \_base
+ sd_base ra, 1, \_base
+ sd_base sp, 2, \_base
+ sd_base gp, 3, \_base
+ sd_base tp, 4, \_base
+ sd_base t0, 5, \_base
+ sd_base t1, 6, \_base
+ sd_base t2, 7, \_base
+ sd_base s0, 8, \_base
+ sd_base s1, 9, \_base
+ sd_base a0, 10, \_base
+ sd_base a1, 11, \_base
+ sd_base a2, 12, \_base
+ sd_base a3, 13, \_base
+ sd_base a4, 14, \_base
+ sd_base a5, 15, \_base
+ sd_base a6, 16, \_base
+ sd_base a7, 17, \_base
+ sd_base s2, 18, \_base
+ sd_base s3, 19, \_base
+ sd_base s4, 20, \_base
+ sd_base s5, 21, \_base
+ sd_base s6, 22, \_base
+ sd_base s7, 23, \_base
+ sd_base s8, 24, \_base
+ sd_base s9, 25, \_base
+ sd_base s10, 26, \_base
+ sd_base s11, 27, \_base
+ sd_base t3, 28, \_base
+ sd_base t4, 29, \_base
+ sd_base t5, 30, \_base
+ sd_base t6, 31, \_base
+
+ fsd_base ft0, 32, \_base
+ fsd_base ft1, 33, \_base
+ fsd_base ft2, 34, \_base
+ fsd_base ft3, 35, \_base
+ fsd_base ft4, 36, \_base
+ fsd_base ft5, 37, \_base
+ fsd_base ft6, 38, \_base
+ fsd_base ft7, 39, \_base
+ fsd_base fs0, 40, \_base
+ fsd_base fs1, 41, \_base
+ fsd_base fa0, 42, \_base
+ fsd_base fa1, 43, \_base
+ fsd_base fa2, 44, \_base
+ fsd_base fa3, 45, \_base
+ fsd_base fa4, 46, \_base
+ fsd_base fa5, 47, \_base
+ fsd_base fa6, 48, \_base
+ fsd_base fa7, 49, \_base
+ fsd_base fs2, 50, \_base
+ fsd_base fs3, 51, \_base
+ fsd_base fs4, 52, \_base
+ fsd_base fs5, 53, \_base
+ fsd_base fs6, 54, \_base
+ fsd_base fs7, 55, \_base
+ fsd_base fs8, 56, \_base
+ fsd_base fs9, 57, \_base
+ fsd_base fs10, 58, \_base
+ fsd_base fs11, 59, \_base
+ fsd_base ft8, 60, \_base
+ fsd_base ft9, 61, \_base
+ fsd_base ft10, 62, \_base
+ fsd_base ft11, 63, \_base
+
+ csrr t0, sepc
+ sd_base t0, 64, \_base
+ csrr t0, stval
+ sd_base t0, 65, \_base
+ csrr t0, scause
+ sd_base t0, 66, \_base
+ csrr t0, sie
+ sd_base t0, 67, \_base
+ csrr t0, sstatus
+ sd_base t0, 68, \_base
+ csrr t0, satp
+ sd_base t0, 69, \_base
+ csrr t0, sscratch
+ sd_base t0, 70, \_base
+.endm
+
+/**
+ * @brief 恢复所有寄存器
+ * @param _base 要恢复数据的基地址
+ */
+.macro all_regs_load _base
+ ld_base t0, 64, \_base
+ csrw sepc, t0
+ ld_base t0, 65, \_base
+ csrw stval, t0
+ ld_base t0, 66, \_base
+ csrw scause, t0
+ ld_base t0, 67, \_base
+ csrw sie, t0
+ ld_base t0, 68, \_base
+ csrw sstatus, t0
+ ld_base t0, 69, \_base
+ csrw satp, t0
+ ld_base t0, 70, \_base
+ csrw sscratch, t0
+
+ ld_base zero, 0, \_base
+ ld_base ra, 1, \_base
+ ld_base sp, 2, \_base
+ ld_base gp, 3, \_base
+ ld_base tp, 4, \_base
+ ld_base t0, 5, \_base
+ ld_base t1, 6, \_base
+ ld_base t2, 7, \_base
+ ld_base s0, 8, \_base
+ ld_base s1, 9, \_base
+ ld_base a0, 10, \_base
+ ld_base a1, 11, \_base
+ ld_base a2, 12, \_base
+ ld_base a3, 13, \_base
+ ld_base a4, 14, \_base
+ ld_base a5, 15, \_base
+ ld_base a6, 16, \_base
+ ld_base a7, 17, \_base
+ ld_base s2, 18, \_base
+ ld_base s3, 19, \_base
+ ld_base s4, 20, \_base
+ ld_base s5, 21, \_base
+ ld_base s6, 22, \_base
+ ld_base s7, 23, \_base
+ ld_base s8, 24, \_base
+ ld_base s9, 25, \_base
+ ld_base s10, 26, \_base
+ ld_base s11, 27, \_base
+ ld_base t3, 28, \_base
+ ld_base t4, 29, \_base
+ ld_base t5, 30, \_base
+ ld_base t6, 31, \_base
+
+ fld_base ft0, 32, \_base
+ fld_base ft1, 33, \_base
+ fld_base ft2, 34, \_base
+ fld_base ft3, 35, \_base
+ fld_base ft4, 36, \_base
+ fld_base ft5, 37, \_base
+ fld_base ft6, 38, \_base
+ fld_base ft7, 39, \_base
+ fld_base fs0, 40, \_base
+ fld_base fs1, 41, \_base
+ fld_base fa0, 42, \_base
+ fld_base fa1, 43, \_base
+ fld_base fa2, 44, \_base
+ fld_base fa3, 45, \_base
+ fld_base fa4, 46, \_base
+ fld_base fa5, 47, \_base
+ fld_base fa6, 48, \_base
+ fld_base fa7, 49, \_base
+ fld_base fs2, 50, \_base
+ fld_base fs3, 51, \_base
+ fld_base fs4, 52, \_base
+ fld_base fs5, 53, \_base
+ fld_base fs6, 54, \_base
+ fld_base fs7, 55, \_base
+ fld_base fs8, 56, \_base
+ fld_base fs9, 57, \_base
+ fld_base fs10, 58, \_base
+ fld_base fs11, 59, \_base
+ fld_base ft8, 60, \_base
+ fld_base ft9, 61, \_base
+ fld_base ft10, 62, \_base
+ fld_base ft11, 63, \_base
+.endm
diff --git a/src/arch/riscv64/cpu.hpp b/src/arch/riscv64/cpu.hpp
index 71f20e76e..896f4ee82 100644
--- a/src/arch/riscv64/cpu.hpp
+++ b/src/arch/riscv64/cpu.hpp
@@ -14,37 +14,304 @@
*
*/
-#ifndef _CPU_HPP_
-#define _CPU_HPP_
+#ifndef SIMPLEKERNEL_CPU_HPP
+#define SIMPLEKERNEL_CPU_HPP
-#include "stdio.h"
-#include "stdint.h"
-#include "stdbool.h"
+#include "cstdbool"
+#include "cstdint"
+#include "cstdio"
+#include "iostream"
/**
* @brief cpu 相关
* @todo
*/
namespace CPU {
+/**
+ * @brief pte 结构
+ * @todo 使用 pte 结构重写 vmm
+ */
+struct pte_t {
+ enum {
+ VALID_OFFSET = 0,
+ READ_OFFSET = 1,
+ WRITE_OFFSET = 2,
+ EXEC_OFFSET = 3,
+ USER_OFFSET = 4,
+ GLOBAL_OFFSET = 5,
+ ACCESSED_OFFSET = 6,
+ DIRTY_OFFSET = 7,
+ VALID = 1 << VALID_OFFSET,
+ READ = 1 << READ_OFFSET,
+ WRITE = 1 << WRITE_OFFSET,
+ EXEC = 1 << EXEC_OFFSET,
+ USER = 1 << USER_OFFSET,
+ GLOBAL = 1 << GLOBAL_OFFSET,
+ ACCESSED = 1 << ACCESSED_OFFSET,
+ DIRTY = 1 << DIRTY_OFFSET,
+ };
+
+ union {
+ struct {
+ uint64_t flags : 8;
+ uint64_t rsw : 2;
+ uint64_t ppn : 44;
+ uint64_t reserved : 10;
+ };
+
+ uint64_t val;
+ };
+
+ pte_t(void) {
+ val = 0;
+ return;
+ }
+
+ pte_t(uint64_t _val) : val(_val) {
+ return;
+ }
+
+ friend std::ostream& operator<<(std::ostream& _os, const pte_t& _pte) {
+ printf("val: 0x%p, valid: %s, read: %s, write: %s, exec: %s, user: %s, "
+ "global: %s, accessed: %s, dirty: %s, rsw: 0x%p, ppn: 0x%p",
+ _pte.val, (_pte.flags & VALID) == VALID ? "true" : "false",
+ (_pte.flags & READ) == READ ? "true" : "false",
+ (_pte.flags & WRITE) == WRITE ? "true" : "false",
+ (_pte.flags & EXEC) == EXEC ? "true" : "false",
+ (_pte.flags & USER) == USER ? "true" : "false",
+ (_pte.flags & GLOBAL) == GLOBAL ? "true" : "false",
+ (_pte.flags & ACCESSED) == ACCESSED ? "true" : "false",
+ (_pte.flags & DIRTY) == DIRTY ? "true" : "false", _pte.rsw,
+ _pte.ppn);
+ return _os;
+ }
+};
+
+/**
+ * @brief satp 结构
+ */
+struct satp_t {
+ enum {
+ NONE = 0,
+ SV39 = 8,
+ SV48 = 9,
+ SV57 = 10,
+ SV64 = 11,
+ };
+
+ static constexpr const char* MODE_NAME[] = {
+ [NONE] = "NONE", "UNKNOWN", "UNKNOWN", "UNKNOWN",
+ "UNKNOWN", "UNKNOWN", "UNKNOWN", "UNKNOWN",
+ [SV39] = "SV39", [SV48] = "SV48", [SV57] = "SV57", [SV64] = "SV64",
+ };
+
+ union {
+ struct {
+ uint64_t ppn : 44;
+ uint64_t asid : 16;
+ uint64_t mode : 4;
+ };
+
+ uint64_t val;
+ };
+
+ static constexpr const uint64_t PPN_OFFSET = 12;
+
+ satp_t(void) {
+ val = 0;
+ return;
+ }
+
+ satp_t(uint64_t _val) : val(_val) {
+ return;
+ }
+
+ friend std::ostream& operator<<(std::ostream& _os, const satp_t& _satp) {
+ printf("val: 0x%p, ppn: 0x%p, asid: 0x%p, mode: %s", _satp.val,
+ _satp.ppn, _satp.asid, MODE_NAME[_satp.mode]);
+ return _os;
+ }
+};
+
+/// 机器模式定义
+enum {
+ U_MODE = 0,
+ S_MODE = 1,
+ M_MODE = 3,
+};
+
+enum {
+ INTR_SOFT = 0,
+ /// U 态软中断
+ INTR_SOFT_U = INTR_SOFT + U_MODE,
+ /// S 态软中断
+ INTR_SOFT_S = INTR_SOFT + S_MODE,
+ /// M 态软中断
+ INTR_SOFT_M = INTR_SOFT + M_MODE,
+ INTR_TIMER = 4,
+ /// U 态时钟中断
+ INTR_TIMER_U = INTR_TIMER + U_MODE,
+ /// S 态时钟中断
+ INTR_TIMER_S = INTR_TIMER + S_MODE,
+ /// M 态时钟中断
+ INTR_TIMER_M = INTR_TIMER + M_MODE,
+ INTR_EXTERN = 8,
+ /// U 态外部中断
+ INTR_EXTERN_U = INTR_EXTERN + U_MODE,
+ /// S 态外部中断
+ INTR_EXTERN_S = INTR_EXTERN + S_MODE,
+ /// M 态外部中断
+ INTR_EXTERN_M = INTR_EXTERN + M_MODE,
+};
+
+enum {
+ EXCP_INSTRUCTION_ADDRESS_MISALIGNED = 0,
+ EXCP_INSTRUCTION_ACCESS_FAULT = 1,
+ EXCP_ILLEGAL_INSTRUCTION = 2,
+ EXCP_BREAKPOINT = 3,
+ EXCP_LOAD_ADDRESS_MISALIGNED = 4,
+ EXCP_LOAD_ACCESS_FAULT = 5,
+ EXCP_STORE_AMO_ADDRESS_MISALIGNED = 6,
+ EXCP_STORE_AMO_ACCESS_FAULT = 7,
+ EXCP_ECALL = 8,
+ EXCP_ECALL_U = EXCP_ECALL + U_MODE,
+ EXCP_ECALL_S = EXCP_ECALL + S_MODE,
+ EXCP_ECALL_M = EXCP_ECALL + M_MODE,
+ EXCP_INSTRUCTION_PAGE_FAULT = 12,
+ EXCP_LOAD_PAGE_FAULT = 13,
+ EXCP_STORE_AMO_PAGE_FAULT = 15,
+};
+
// Supervisor Status Register, sstatus
// User Interrupt Enable
-static constexpr const uint64_t SSTATUS_UIE = 1 << 0;
+static constexpr const uint64_t SSTATUS_UIE = 1 << 0;
// Supervisor Interrupt Enable
-static constexpr const uint64_t SSTATUS_SIE = 1 << 1;
+static constexpr const uint64_t SSTATUS_SIE = 1 << 1;
// User Previous Interrupt Enable
static constexpr const uint64_t SSTATUS_UPIE = 1 << 4;
// Supervisor Previous Interrupt Enable
static constexpr const uint64_t SSTATUS_SPIE = 1 << 5;
// Previous mode, 1=Supervisor, 0=User
-static constexpr const uint64_t SSTATUS_SPP = 1 << 8;
+static constexpr const uint64_t SSTATUS_SPP = 1 << 8;
+
+/**
+ * @brief mstatus 寄存器定义
+ */
+struct mstatus_t {
+ union {
+ struct {
+ // interrupt enable
+ uint64_t ie : 4;
+ // previous interrupt enable
+ uint64_t pie : 4;
+ // previous mode (supervisor)
+ uint64_t spp : 1;
+ uint64_t unused1 : 2;
+ // previous mode (machine)
+ uint64_t mpp : 2;
+ // FPU status
+ uint64_t fs : 2;
+ // extensions status
+ uint64_t xs : 2;
+ // modify privilege
+ uint64_t mprv : 1;
+ // permit supervisor user memory access
+ uint64_t sum : 1;
+ // make executable readable
+ uint64_t mxr : 1;
+ // trap virtual memory
+ uint64_t tvm : 1;
+ // timeout wait (trap WFI)
+ uint64_t tw : 1;
+ // trap SRET
+ uint64_t tsr : 1;
+ uint64_t unused2 : 9;
+ // U-mode XLEN
+ uint64_t uxl : 2;
+ // S-mode XLEN
+ uint64_t sxl : 2;
+ uint64_t unused3 : 27;
+ // status dirty
+ uint64_t sd : 1;
+ };
+
+ uint64_t val;
+ };
+
+ mstatus_t(void) {
+ val = 0;
+ return;
+ }
+
+ mstatus_t(uint64_t _val) : val(_val) {
+ return;
+ }
+};
+
+/**
+ * @brief sstatus 寄存器定义
+ */
+struct sstatus_t {
+ union {
+ struct {
+ // Reserved Writes Preserve Values, Reads Ignore Values (WPRI)
+ uint64_t wpri1 : 1;
+ // interrupt enable
+ uint64_t sie : 1;
+ uint64_t wpri12 : 3;
+ // previous interrupt enable
+ uint64_t spie : 1;
+ uint64_t ube : 1;
+ uint64_t wpri3 : 1;
+ // previous mode (supervisor)
+ uint64_t spp : 1;
+ uint64_t wpri4 : 4;
+ // FPU status
+ uint64_t fs : 2;
+ // extensions status
+ uint64_t xs : 2;
+ uint64_t wpri5 : 1;
+ // permit supervisor user memory access
+ uint64_t sum : 1;
+ // make executable readable
+ uint64_t mxr : 1;
+ uint64_t wpri6 : 12;
+ // U-mode XLEN
+ uint64_t uxl : 2;
+ uint64_t wpri7 : 29;
+ // status dirty
+ uint64_t sd : 1;
+ };
+
+ uint64_t val;
+ };
+
+ sstatus_t(void) {
+ val = 0;
+ return;
+ }
+
+ sstatus_t(uint64_t _val) : val(_val) {
+ return;
+ }
+
+ friend std::ostream&
+ operator<<(std::ostream& _os, const sstatus_t& _sstatus) {
+ printf("val: 0x%p, sie: %s, spie: %s, spp: %s", _sstatus.val,
+ (_sstatus.sie == true ? "enable" : "disable"),
+ (_sstatus.spie == true ? "enable" : "disable"),
+ (_sstatus.spp == true ? "S mode" : "U mode"));
+ return _os;
+ }
+};
/**
* @brief 读取 sstatus 寄存器
* @return uint64_t 读取到的值
*/
-static inline uint64_t READ_SSTATUS(void) {
- uint64_t x;
- __asm__ volatile("csrr %0, sstatus" : "=r"(x));
+inline static sstatus_t READ_SSTATUS(void) {
+ sstatus_t x;
+ asm("csrr %0, sstatus" : "=r"(x));
return x;
}
@@ -52,8 +319,8 @@ static inline uint64_t READ_SSTATUS(void) {
* @brief 写 sstatus 寄存器
* @param _x 要写的值
*/
-static inline void WRITE_SSTATUS(uint64_t _x) {
- __asm__ volatile("csrw sstatus, %0" : : "r"(_x));
+inline static void WRITE_SSTATUS(sstatus_t _x) {
+ asm("csrw sstatus, %0" : : "r"(_x));
}
/**
@@ -61,9 +328,9 @@ static inline void WRITE_SSTATUS(uint64_t _x) {
* @return uint64_t 读取到的值
* @note Supervisor Interrupt Pending
*/
-static inline uint64_t READ_SIP(void) {
+inline static uint64_t READ_SIP(void) {
uint64_t x;
- __asm__ volatile("csrr %0, sip" : "=r"(x));
+ asm("csrr %0, sip" : "=r"(x));
return x;
}
@@ -71,8 +338,8 @@ static inline uint64_t READ_SIP(void) {
* @brief 写 sip
* @param _x 要写的值
*/
-static inline void WRITE_SIP(uint64_t _x) {
- __asm__ volatile("csrw sip, %0" : : "r"(_x));
+inline static void WRITE_SIP(uint64_t _x) {
+ asm("csrw sip, %0" : : "r"(_x));
return;
}
@@ -88,9 +355,9 @@ static constexpr const uint64_t SIE_SEIE = 1 << 9;
* @brief 读 sie
* @return uint64_t 读到的值
*/
-static inline uint64_t READ_SIE(void) {
+inline static uint64_t READ_SIE(void) {
uint64_t x;
- __asm__ volatile("csrr %0, sie" : "=r"(x));
+ asm("csrr %0, sie" : "=r"(x));
return x;
}
@@ -98,8 +365,8 @@ static inline uint64_t READ_SIE(void) {
* @brief 写 sie
* @param _x 要写的值
*/
-static inline void WRITE_SIE(uint64_t _x) {
- __asm__ volatile("csrw sie, %0" : : "r"(_x));
+inline static void WRITE_SIE(uint64_t _x) {
+ asm("csrw sie, %0" : : "r"(_x));
return;
}
@@ -109,9 +376,9 @@ static inline void WRITE_SIE(uint64_t _x) {
* @note machine exception program counter, holds the instruction address to
* which a return from exception will go.
*/
-static inline uint64_t READ_SEPC(void) {
+inline static uint64_t READ_SEPC(void) {
uint64_t x;
- __asm__ volatile("csrr %0, sepc" : "=r"(x));
+ asm("csrr %0, sepc" : "=r"(x));
return x;
}
@@ -119,8 +386,8 @@ static inline uint64_t READ_SEPC(void) {
* @brief 写 sepc
* @param _x 要写的值
*/
-static inline void WRITE_SEPC(uint64_t _x) {
- __asm__ volatile("csrw sepc, %0" : : "r"(_x));
+inline static void WRITE_SEPC(uint64_t _x) {
+ asm("csrw sepc, %0" : : "r"(_x));
return;
}
@@ -129,9 +396,9 @@ static inline void WRITE_SEPC(uint64_t _x) {
* @return uint64_t 读到的值
* @note Supervisor Trap-Vector Base Address low two bits are mode.
*/
-static inline uint64_t READ_STVEC(void) {
+inline static uint64_t READ_STVEC(void) {
uint64_t x;
- __asm__ volatile("csrr %0, stvec" : "=r"(x));
+ asm("csrr %0, stvec" : "=r"(x));
return x;
}
@@ -139,20 +406,20 @@ static inline uint64_t READ_STVEC(void) {
* @brief 写 stvec
* @param _x 要写的值
*/
-static inline void WRITE_STVEC(uint64_t _x) {
- __asm__ volatile("csrw stvec, %0" : : "r"(_x));
+inline static void WRITE_STVEC(uint64_t _x) {
+ asm("csrw stvec, %0" : : "r"(_x));
return;
}
/// 中断模式 直接
-static constexpr const uint64_t TVEC_DIRECT = 0xFFFFFFFFFFFFFFFC;
+static constexpr const uint64_t TVEC_DIRECT = 0xFFFFFFFFFFFFFFFC;
/// 中断模式 向量
static constexpr const uint64_t TVEC_VECTORED = 0xFFFFFFFFFFFFFFFD;
/**
* @brief 设置中断模式,直接
*/
-static inline void STVEC_DIRECT(void) {
+inline static void STVEC_DIRECT(void) {
uint64_t stvec = READ_STVEC();
stvec = stvec & TVEC_DIRECT;
WRITE_STVEC(stvec);
@@ -162,57 +429,40 @@ static inline void STVEC_DIRECT(void) {
/**
* @brief 设置中断模式,向量
*/
-static inline void STVEC_VECTORED(void) {
+inline static void STVEC_VECTORED(void) {
uint64_t stvec = READ_STVEC();
stvec = stvec & TVEC_VECTORED;
WRITE_STVEC(stvec);
return;
}
-/// sv39 虚拟内存模式
-static constexpr const uint64_t SATP_SV39 = (uint64_t)8 << 60;
-
/**
- * @brief 设置 sv39 虚拟内存模式
- * @param _pgd 要设置的页目录
- * @return constexpr uintptr_t 设置好的页目录
- */
-static constexpr uintptr_t SET_SV39(uintptr_t _pgd) {
- return (SATP_SV39 | (_pgd >> 12));
-}
-
-/**
- * @brief 设置页目录
+ * @brief 设置页目录,仅更改 ppn
* @param _x 要设置的页目录
* @note supervisor address translation and protection; holds the address of
* the page table.
+ * @todo 需要判断 _x 是否已经处理过
*/
-static inline void SET_PGD(uintptr_t _x) {
- uintptr_t old;
+inline static void SET_PGD(uintptr_t _x) {
+ satp_t satp;
// 读取现在的 pgd
- __asm__ volatile("csrr %0, satp" : "=r"(old));
- // 如果开启了 sv39
- if ((old & SATP_SV39) == SATP_SV39) {
- // 将新的页目录也设为开启
- _x = SET_SV39(_x);
- }
- __asm__ volatile("csrw satp, %0" : : "r"(_x));
+ asm("csrr %0, satp" : "=r"(satp));
+ // 更改 ppn
+ // satp.ppn = _x & satp_t::PPN_MASK;
+ satp.ppn = _x >> satp_t::PPN_OFFSET;
+ // 写回
+ asm("csrw satp, %0" : : "r"(satp));
return;
}
/**
- * @brief 获取页目录
+ * @brief 获取页目录,仅获取 ppn
* @return uintptr_t 页目录
*/
-static inline uintptr_t GET_PGD(void) {
- uintptr_t x;
- __asm__ volatile("csrr %0, satp" : "=r"(x));
- // 如果开启了虚拟内存,恢复为原始格式
- if ((x & SATP_SV39) == SATP_SV39) {
- x = (x & 0x7FFFFFFFFF);
- x = (x << 12);
- }
- return x;
+inline static uintptr_t GET_PGD(void) {
+ satp_t satp;
+ asm("csrr %0, satp" : "=r"(satp));
+ return satp.ppn << satp_t::PPN_OFFSET;
}
/**
@@ -220,25 +470,48 @@ static inline uintptr_t GET_PGD(void) {
* @return true 成功
* @return false 失败
*/
-static inline bool ENABLE_PG(void) {
+inline static bool ENABLE_PG(void) {
uintptr_t x = GET_PGD();
- SET_PGD(SET_SV39(x));
+ satp_t satp;
+ satp.ppn = x >> satp_t::PPN_OFFSET;
+ satp.asid = 0;
+ satp.mode = satp_t::SV39;
+ asm("csrw satp, %0" : : "r"(satp));
info("paging enabled.\n");
return true;
}
-/// [31]=1 interrupt, else exception
-static constexpr const uint64_t CAUSE_INTR_MASK = 0x8000000000000000;
+/**
+ * @brief 读 sscratch 寄存器
+ * @param _x 要写的值
+ */
+inline static uint64_t READ_SSCRATCH(void) {
+ uint64_t x;
+ __asm__ volatile("csrr %0, sscratch" : "=r"(x));
+ return x;
+}
+
+/**
+ * @brief 写 sscratch 寄存器
+ * @param _x 要写的值
+ */
+inline static void WRITE_SSCRATCH(uint64_t _x) {
+ asm("csrw sscratch, %0" : : "r"(_x));
+ return;
+}
+
+/// [63]==1 interrupt, else exception
+static constexpr const uint64_t CAUSE_INTR_MASK = 1ULL << 63;
/// low bits show code
-static constexpr const uint64_t CAUSE_CODE_MASK = 0x7FFFFFFFFFFFFFFF;
+static constexpr const uint64_t CAUSE_CODE_MASK = ~CAUSE_INTR_MASK;
/**
* @brief 读 scause 寄存器 Supervisor Trap Cause
* @return uint64_t 读到的值
*/
-static inline uint64_t READ_SCAUSE(void) {
+inline static uint64_t READ_SCAUSE(void) {
uint64_t x;
- __asm__ volatile("csrr %0, scause" : "=r"(x));
+ asm("csrr %0, scause" : "=r"(x));
return x;
}
@@ -246,9 +519,9 @@ static inline uint64_t READ_SCAUSE(void) {
* @brief 读 stval 寄存器 Supervisor Trap Value
* @return uint64_t 读到的值
*/
-static inline uint64_t READ_STVAL(void) {
+inline static uint64_t READ_STVAL(void) {
uint64_t x;
- __asm__ volatile("csrr %0, stval" : "=r"(x));
+ asm("csrr %0, stval" : "=r"(x));
return x;
}
@@ -256,27 +529,45 @@ static inline uint64_t READ_STVAL(void) {
* @brief 读 time 寄存器 supervisor-mode cycle counter
* @return uint64_t 读到的值
*/
-static inline uint64_t READ_TIME(void) {
+inline static uint64_t READ_TIME(void) {
uint64_t x;
- // __asm__ volatile("csrr %0, time" : "=r" (x) );
+ // asm ("csrr %0, time" : "=r" (x) );
// this instruction will trap in SBI
- __asm__ volatile("rdtime %0" : "=r"(x));
+ asm("rdtime %0" : "=r"(x));
return x;
}
/**
* @brief 允许中断
*/
-static inline void ENABLE_INTR(void) {
- WRITE_SSTATUS(READ_SSTATUS() | SSTATUS_SIE);
+inline static void ENABLE_INTR(void) {
+ WRITE_SSTATUS(READ_SSTATUS().val | SSTATUS_SIE);
+ return;
+}
+
+/**
+ * @brief 允许中断
+ * @param _sstatus 要设置的 sstatus
+ */
+inline static void ENABLE_INTR(sstatus_t& _sstatus) {
+ _sstatus.sie = true;
+ return;
+}
+
+/**
+ * @brief 禁止中断
+ */
+inline static void DISABLE_INTR(void) {
+ WRITE_SSTATUS(READ_SSTATUS().val & ~SSTATUS_SIE);
return;
}
/**
* @brief 禁止中断
+ * @param _sstatus 要设置的原 sstatus 值
*/
-static inline void DISABLE_INTR(void) {
- WRITE_SSTATUS(READ_SSTATUS() & ~SSTATUS_SIE);
+inline static void DISABLE_INTR(sstatus_t& _sstatus) {
+ _sstatus.sie = false;
return;
}
@@ -285,18 +576,18 @@ static inline void DISABLE_INTR(void) {
* @return true 允许
* @return false 禁止
*/
-static inline bool STATUS_INTR(void) {
- uint64_t x = READ_SSTATUS();
- return (x & SSTATUS_SIE) != 0;
+inline static bool STATUS_INTR(void) {
+ sstatus_t x = READ_SSTATUS();
+ return x.sie;
}
/**
* @brief 读 sp 寄存器
* @return uint64_t 读到的值
*/
-static inline uint64_t READ_SP(void) {
+inline static uint64_t READ_SP(void) {
uint64_t x;
- __asm__ volatile("mv %0, sp" : "=r"(x));
+ asm("mv %0, sp" : "=r"(x));
return x;
}
@@ -304,9 +595,9 @@ static inline uint64_t READ_SP(void) {
* @brief 读 tp 寄存器
* @return uint64_t 读到的值
*/
-static inline uint64_t READ_TP(void) {
+inline static uint64_t READ_TP(void) {
uint64_t x;
- __asm__ volatile("mv %0, tp" : "=r"(x));
+ asm("mv %0, tp" : "=r"(x));
return x;
}
@@ -314,8 +605,8 @@ static inline uint64_t READ_TP(void) {
* @brief 写 tp 寄存器
* @param _x 要写的值
*/
-static inline void WRITE_TP(uint64_t _x) {
- __asm__ volatile("mv tp, %0" : : "r"(_x));
+inline static void WRITE_TP(uint64_t _x) {
+ asm("mv tp, %0" : : "r"(_x));
return;
}
@@ -323,21 +614,195 @@ static inline void WRITE_TP(uint64_t _x) {
* @brief 读 ra 寄存器
* @return uint64_t 读到的值
*/
-static inline uint64_t READ_RA(void) {
+inline static uint64_t READ_RA(void) {
uint64_t x;
- __asm__ volatile("mv %0, ra" : "=r"(x));
+ asm("mv %0, ra" : "=r"(x));
return x;
}
/**
* @brief 刷新 tlb
*/
-static inline void VMM_FLUSH(uintptr_t) {
+inline static void VMM_FLUSH(uintptr_t) {
// the zero, zero means flush all TLB entries.
- __asm__ volatile("sfence.vma zero, zero");
+ asm("sfence.vma zero, zero");
return;
}
-}; // namespace CPU
+/**
+ * @brief 通用寄存器
+ */
+struct xregs_t {
+ uintptr_t zero;
+ uintptr_t ra;
+ uintptr_t sp;
+ uintptr_t gp;
+ uintptr_t tp;
+ uintptr_t t0;
+ uintptr_t t1;
+ uintptr_t t2;
+ uintptr_t s0;
+ uintptr_t s1;
+ uintptr_t a0;
+ uintptr_t a1;
+ uintptr_t a2;
+ uintptr_t a3;
+ uintptr_t a4;
+ uintptr_t a5;
+ uintptr_t a6;
+ uintptr_t a7;
+ uintptr_t s2;
+ uintptr_t s3;
+ uintptr_t s4;
+ uintptr_t s5;
+ uintptr_t s6;
+ uintptr_t s7;
+ uintptr_t s8;
+ uintptr_t s9;
+ uintptr_t s10;
+ uintptr_t s11;
+ uintptr_t t3;
+ uintptr_t t4;
+ uintptr_t t5;
+ uintptr_t t6;
+
+ friend std::ostream& operator<<(std::ostream& _os, const xregs_t& _xregs) {
+ printf("zero: 0x%p, ", _xregs.zero);
+ printf("ra: 0x%p, ", _xregs.ra);
+ printf("sp: 0x%p, ", _xregs.sp);
+ printf("gp: 0x%p\n", _xregs.gp);
+ printf("tp: 0x%p, ", _xregs.tp);
+ printf("t0: 0x%p, ", _xregs.t0);
+ printf("t1: 0x%p, ", _xregs.t1);
+ printf("t2: 0x%p\n", _xregs.t2);
+ printf("s0: 0x%p, ", _xregs.s0);
+ printf("s1: 0x%p, ", _xregs.s1);
+ printf("a0: 0x%p, ", _xregs.a0);
+ printf("a1: 0x%p\n", _xregs.a1);
+ printf("a2: 0x%p, ", _xregs.a2);
+ printf("a3: 0x%p, ", _xregs.a3);
+ printf("a4: 0x%p, ", _xregs.a4);
+ printf("a5: 0x%p\n", _xregs.a5);
+ printf("a6: 0x%p, ", _xregs.a6);
+ printf("a7: 0x%p, ", _xregs.a7);
+ printf("s2: 0x%p, ", _xregs.s2);
+ printf("s3: 0x%p\n", _xregs.s3);
+ printf("s4: 0x%p, ", _xregs.s4);
+ printf("s5: 0x%p, ", _xregs.s5);
+ printf("s6: 0x%p, ", _xregs.s6);
+ printf("s7: 0x%p\n", _xregs.s7);
+ printf("s8: 0x%p, ", _xregs.s8);
+ printf("s9: 0x%p, ", _xregs.s9);
+ printf("s10: 0x%p, ", _xregs.s10);
+ printf("s11: 0x%p\n", _xregs.s11);
+ printf("t3: 0x%p, ", _xregs.t3);
+ printf("t4: 0x%p, ", _xregs.t4);
+ printf("t5: 0x%p, ", _xregs.t5);
+ printf("t6: 0x%p", _xregs.t6);
+ return _os;
+ }
+};
+
+/**
+ * @brief 浮点寄存器
+ */
+struct fregs_t {
+ uintptr_t ft0;
+ uintptr_t ft1;
+ uintptr_t ft2;
+ uintptr_t ft3;
+ uintptr_t ft4;
+ uintptr_t ft5;
+ uintptr_t ft6;
+ uintptr_t ft7;
+ uintptr_t fs0;
+ uintptr_t fs1;
+ uintptr_t fa0;
+ uintptr_t fa1;
+ uintptr_t fa2;
+ uintptr_t fa3;
+ uintptr_t fa4;
+ uintptr_t fa5;
+ uintptr_t fa6;
+ uintptr_t fa7;
+ uintptr_t fs2;
+ uintptr_t fs3;
+ uintptr_t fs4;
+ uintptr_t fs5;
+ uintptr_t fs6;
+ uintptr_t fs7;
+ uintptr_t fs8;
+ uintptr_t fs9;
+ uintptr_t fs10;
+ uintptr_t fs11;
+ uintptr_t ft8;
+ uintptr_t ft9;
+ uintptr_t ft10;
+ uintptr_t ft11;
+
+ friend std::ostream& operator<<(std::ostream& _os, const fregs_t& _fregs) {
+ printf("ft0: 0x%p, ", _fregs.ft0);
+ printf("ft1: 0x%p, ", _fregs.ft1);
+ printf("ft2: 0x%p, ", _fregs.ft2);
+ printf("ft3: 0x%p\n", _fregs.ft3);
+ printf("ft4: 0x%p, ", _fregs.ft4);
+ printf("ft5: 0x%p, ", _fregs.ft5);
+ printf("ft6: 0x%p, ", _fregs.ft6);
+ printf("ft7: 0x%p\n", _fregs.ft7);
+ printf("fs0: 0x%p, ", _fregs.fs0);
+ printf("fs1: 0x%p, ", _fregs.fs1);
+ printf("fa0: 0x%p, ", _fregs.fa0);
+ printf("fa1: 0x%p\n", _fregs.fa1);
+ printf("fa2: 0x%p, ", _fregs.fa2);
+ printf("fa3: 0x%p, ", _fregs.fa3);
+ printf("fa4: 0x%p, ", _fregs.fa4);
+ printf("fa5: 0x%p\n", _fregs.fa5);
+ printf("fa6: 0x%p, ", _fregs.fa6);
+ printf("fa7: 0x%p, ", _fregs.fa7);
+ printf("fs2: 0x%p, ", _fregs.fs2);
+ printf("fs3: 0x%p\n", _fregs.fs3);
+ printf("fs4: 0x%p, ", _fregs.fs4);
+ printf("fs5: 0x%p, ", _fregs.fs5);
+ printf("fs6: 0x%p, ", _fregs.fs6);
+ printf("fs7: 0x%p\n", _fregs.fs7);
+ printf("fs8: 0x%p, ", _fregs.fs8);
+ printf("fs9: 0x%p, ", _fregs.fs9);
+ printf("fs10: 0x%p, ", _fregs.fs10);
+ printf("fs11: 0x%p\n", _fregs.fs11);
+ printf("ft8: 0x%p, ", _fregs.ft8);
+ printf("ft9: 0x%p, ", _fregs.ft9);
+ printf("ft10: 0x%p, ", _fregs.ft10);
+ printf("ft11: 0x%p", _fregs.ft11);
+ return _os;
+ }
+};
+
+/**
+ * @brief 所有寄存器,在中断时使用,共 32+32+7=71 个
+ */
+struct all_regs_t {
+ xregs_t xregs;
+ fregs_t fregs;
+ uintptr_t sepc;
+ uintptr_t stval;
+ uintptr_t scause;
+ uintptr_t sie;
+ sstatus_t sstatus;
+ satp_t satp;
+ uintptr_t sscratch;
+
+ friend std::ostream&
+ operator<<(std::ostream& _os, const all_regs_t& _all_regs) {
+ (void)_all_regs.fregs;
+ _os << _all_regs.xregs << std::endl;
+ printf("sepc: 0x%p, stval: 0x%p, scause: 0x%p, sie: 0x%p, sstatus: "
+ "0x%p, satp: 0x%p, sscratch: 0x%p",
+ _all_regs.sepc, _all_regs.stval, _all_regs.scause, _all_regs.sie,
+ _all_regs.sstatus.val, _all_regs.satp.val, _all_regs.sscratch);
+ return _os;
+ }
+};
+
+}; // namespace CPU
-#endif /* _CPU_HPP_ */
+#endif /* SIMPLEKERNEL_CPU_HPP */
diff --git a/src/arch/riscv64/intr/clint.cpp b/src/arch/riscv64/intr/clint.cpp
index 33e877537..d9f0edd5f 100644
--- a/src/arch/riscv64/intr/clint.cpp
+++ b/src/arch/riscv64/intr/clint.cpp
@@ -15,15 +15,14 @@
*
*/
-#include "cpu.hpp"
-#include "stdio.h"
-#include "vmm.h"
#include "boot_info.h"
-#include "resource.h"
-#include "intr.h"
#include "cpu.hpp"
+#include "cstdio"
+#include "intr.h"
+#include "resource.h"
+#include "vmm.h"
-CLINT &CLINT::get_instance(void) {
+CLINT& CLINT::get_instance(void) {
/// 定义全局 CLINT 对象
static CLINT clint;
return clint;
@@ -32,8 +31,8 @@ CLINT &CLINT::get_instance(void) {
int32_t CLINT::init(void) {
// 映射 clint 地址
resource_t resource = BOOT_INFO::get_clint();
- for (uintptr_t a = resource.mem.addr;
- a < resource.mem.addr + resource.mem.len; a += 0x1000) {
+ for (uintptr_t a = resource.mem.addr;
+ a < resource.mem.addr + resource.mem.len; a += COMMON::PAGE_SIZE) {
VMM::get_instance().mmap(VMM::get_instance().get_pgd(), a, a,
VMM_PAGE_READABLE | VMM_PAGE_WRITABLE);
}
diff --git a/src/arch/riscv64/intr/include/intr.h b/src/arch/riscv64/intr/include/intr.h
index 1c6ce77f2..ed102cdc1 100644
--- a/src/arch/riscv64/intr/include/intr.h
+++ b/src/arch/riscv64/intr/include/intr.h
@@ -14,54 +14,62 @@
*
*/
-#ifndef _INTR_H_
-#define _INTR_H_
+#ifndef SIMPLEKERNEL_INTR_H
+#define SIMPLEKERNEL_INTR_H
-#include "stdint.h"
+#include "cpu.hpp"
+#include "cstdint"
void handler_default(void);
class INTR {
public:
- /// 中断处理函数指针
- typedef void (*interrupt_handler_t)(void);
+ /**
+ * @brief 中断处理函数指针
+ * @param _argc 参数个数
+ * @param _argv 参数列表
+ * @return int32_t 返回值,0 成功
+ */
+ typedef int32_t (*interrupt_handler_t)(int _argc, char** _argv);
private:
/// 异常名
- static constexpr const char *const excp_names[] = {
- "Instruction Address Misaligned",
- "Instruction Access Fault",
- "Illegal Instruction",
- "Breakpoint",
- "Load Address Misaligned",
- "Load Access Fault",
- "Store/AMO Address Misaligned",
- "Store/AMO Access Fault",
- "Environment Call from U-mode",
- "Environment Call from S-mode",
+ static constexpr const char* const excp_names[] = {
+ [CPU::EXCP_INSTRUCTION_ADDRESS_MISALIGNED]
+ = "Instruction Address Misaligned",
+ [CPU::EXCP_INSTRUCTION_ACCESS_FAULT] = "Instruction Access Fault",
+ [CPU::EXCP_ILLEGAL_INSTRUCTION] = "Illegal Instruction",
+ [CPU::EXCP_BREAKPOINT] = "Breakpoint",
+ [CPU::EXCP_LOAD_ADDRESS_MISALIGNED] = "Load Address Misaligned",
+ [CPU::EXCP_LOAD_ACCESS_FAULT] = "Load Access Fault",
+ [CPU::EXCP_STORE_AMO_ADDRESS_MISALIGNED]
+ = "Store/AMO Address Misaligned",
+ [CPU::EXCP_STORE_AMO_ACCESS_FAULT] = "Store/AMO Access Fault",
+ [CPU::EXCP_ECALL_U] = "Environment Call from U-mode",
+ [CPU::EXCP_ECALL_S] = "Environment Call from S-mode",
"Reserved",
- "Environment Call from M-mode",
- "Instruction Page Fault",
- "Load Page Fault",
+ [CPU::EXCP_ECALL_M] = "Environment Call from M-mode",
+ [CPU::EXCP_INSTRUCTION_PAGE_FAULT] = "Instruction Page Fault",
+ [CPU::EXCP_LOAD_PAGE_FAULT] = "Load Page Fault",
"Reserved",
- "Store/AMO Page Fault",
+ [CPU::EXCP_STORE_AMO_PAGE_FAULT] = "Store/AMO Page Fault",
"Reserved",
};
/// 中断名
- static constexpr const char *const intr_names[] = {
- "User Software Interrupt",
- "Supervisor Software Interrupt",
+ static constexpr const char* const intr_names[] = {
+ [CPU::INTR_SOFT_U] = "User Software Interrupt",
+ [CPU::INTR_SOFT_S] = "Supervisor Software Interrupt",
"Reserved",
- "Machine Software Interrupt",
- "User Timer Interrupt",
- "Supervisor Timer Interrupt",
+ [CPU::INTR_SOFT_M] = "Machine Software Interrupt",
+ [CPU::INTR_TIMER_U] = "User Timer Interrupt",
+ [CPU::INTR_TIMER_S] = "Supervisor Timer Interrupt",
"Reserved",
- "Machine Timer Interrupt",
- "User External Interrupt",
- "Supervisor External Interrupt",
+ [CPU::INTR_TIMER_M] = "Machine Timer Interrupt",
+ [CPU::INTR_EXTERN_U] = "User External Interrupt",
+ [CPU::INTR_EXTERN_S] = "Supervisor External Interrupt",
"Reserved",
- "Machine External Interrupt",
+ [CPU::INTR_EXTERN_M] = "Machine External Interrupt",
"Reserved",
"Reserved",
"Reserved",
@@ -72,35 +80,26 @@ class INTR {
/// 最大中断数
static constexpr const uint32_t INTERRUPT_MAX = 16;
/// 最大异常数
- static constexpr const uint32_t EXCP_MAX = 16;
+ static constexpr const uint32_t EXCP_MAX = 16;
/// 中断处理函数数组
- interrupt_handler_t interrupt_handlers[INTERRUPT_MAX]
- __attribute__((aligned(4)));
+ interrupt_handler_t interrupt_handlers[INTERRUPT_MAX]
+ __attribute__((aligned(4)));
/// 异常处理函数数组
interrupt_handler_t excp_handlers[EXCP_MAX] __attribute__((aligned(4)));
public:
- /// 页读错误
- static constexpr const uint8_t EXCP_LOAD_PAGE_FAULT = 13;
- /// 页写错误
- static constexpr const uint8_t EXCP_STORE_PAGE_FAULT = 15;
- /// S 态时钟中断
- static constexpr const uint8_t INTR_S_TIMER = 5;
- /// S 态外部中断
- static constexpr const uint8_t INTR_S_EXTERNEL = 9;
-
/**
* @brief 获取单例
* @return INTR& 静态对象
*/
- static INTR &get_instance(void);
+ static INTR& get_instance(void);
/**
* @brief 中断初始化
* @return int32_t 成功返回 0
*/
- int32_t init(void);
+ int32_t init(void);
/**
* @brief 注册中断处理函数
@@ -108,42 +107,48 @@ class INTR {
* @param _interrupt_handler 中断处理函数
*/
void
- register_interrupt_handler(uint8_t _no,
- INTR::interrupt_handler_t _interrupt_handler);
+ register_interrupt_handler(uint8_t _no,
+ INTR::interrupt_handler_t _interrupt_handler);
/**
* @brief 注册异常处理函数
* @param _no 异常号
* @param _interrupt_handler 异常处理函数
*/
- void register_excp_handler(uint8_t _no,
- INTR::interrupt_handler_t _interrupt_handler);
+ void register_excp_handler(uint8_t _no,
+ INTR::interrupt_handler_t _interrupt_handler);
/**
* @brief 执行中断处理
* @param _no 中断号
+ * @param _argc 参数个数
+ * @param _argv 参数列表
+ * @return int32_t 返回值,0 成功
*/
- void do_interrupt(uint8_t _no);
+ int32_t do_interrupt(uint8_t _no, int32_t _argc, char** _argv);
/**
* @brief 执行异常处理
* @param _no 异常号
+ * @param _argc 参数个数
+ * @param _argv 参数列表
+ * @return int32_t 返回值,0 成功
*/
- void do_excp(uint8_t _no);
+ int32_t do_excp(uint8_t _no, int32_t _argc, char** _argv);
/**
* @brief 获取中断名
* @param _no 中断号
* @return const char* 中断名
*/
- const char *get_intr_name(uint8_t _no) const;
+ const char* get_intr_name(uint8_t _no) const;
/**
* @brief 获取异常名
* @param _no 异常号
* @return const char* 异常名
*/
- const char *get_excp_name(uint8_t _no) const;
+ const char* get_excp_name(uint8_t _no) const;
};
/**
@@ -157,13 +162,13 @@ class CLINT {
* @brief 获取单例
* @return CLINT& 静态对象
*/
- static CLINT &get_instance(void);
+ static CLINT& get_instance(void);
/**
* @brief 初始化
* @return int32_t 成功返回 0
*/
- int32_t init(void);
+ int32_t init(void);
};
/**
@@ -174,44 +179,49 @@ class CLINT {
class PLIC {
private:
/// 基地址,由 dtb 传递
- uintptr_t base_addr;
+ static uintptr_t base_addr;
/// @todo ?
- uint64_t PLIC_PRIORITY;
+ static uint64_t PLIC_PRIORITY;
/// @todo ?
- uint64_t PLIC_PENDING;
+ static uint64_t PLIC_PENDING;
/// @todo ?
- uint64_t PLIC_SENABLE(uint64_t hart);
+ inline static uint64_t PLIC_SENABLE(uint64_t _hart);
+
+ inline static uint64_t PLIC_MENABLE(uint64_t _hart);
/// @todo ?
- uint64_t PLIC_SPRIORITY(uint64_t hart);
+ inline static uint64_t PLIC_SPRIORITY(uint64_t _hart);
+ inline static uint64_t PLIC_MPRIORITY(uint64_t _hart);
/// @todo ?
- uint64_t PLIC_SCLAIM(uint64_t hart);
+ inline static uint64_t PLIC_SCLAIM(uint64_t _hart);
+ inline static uint64_t PLIC_MCLAIM(uint64_t _hart);
protected:
+
public:
/**
* @brief 获取单例
* @return PLIC& 静态对象
*/
- static PLIC &get_instance(void);
+ static PLIC& get_instance(void);
/**
* @brief 初始化
* @return int32_t 成功返回 0
*/
- int32_t init(void);
+ int32_t init(void);
/**
* @brief 向 PLIC 询问中断
* 返回发生的外部中断号
* @return uint8_t 中断号
*/
- uint8_t get(void);
+ uint8_t get(void);
/**
* @brief 告知 PLIC 已经处理了当前 IRQ
* @param _no 中断号
*/
- void done(uint8_t _no);
+ void done(uint8_t _no);
/**
* @brief 设置中断状态
@@ -219,7 +229,7 @@ class PLIC {
* @param _status 状态
* @todo 不确定
*/
- void set(uint8_t _no, bool _status);
+ void set(uint8_t _no, bool _status);
};
/**
@@ -231,12 +241,23 @@ class TIMER {
* @brief 获取单例
* @return TIMER& 静态对象
*/
- static TIMER &get_instance(void);
+ static TIMER& get_instance(void);
/**
* @brief 初始化
*/
- void init(void);
+ void init(void);
};
-#endif /* _INTR_H_ */
+/**
+ * @brief 缺页读处理
+ */
+int32_t pg_load_excp(int, char**);
+
+/**
+ * @brief 缺页写处理
+ * @todo 需要读权限吗?测试发现没有读权限不行,原因未知
+ */
+int32_t pg_store_excp(int, char**);
+
+#endif /* SIMPLEKERNEL_INTR_H */
diff --git a/src/arch/riscv64/intr/intr.cpp b/src/arch/riscv64/intr/intr.cpp
index d1e613de1..12b9497da 100644
--- a/src/arch/riscv64/intr/intr.cpp
+++ b/src/arch/riscv64/intr/intr.cpp
@@ -1,7 +1,7 @@
/**
* @file intr.cpp
- * @brief 中断抽象
+ * @brief 中断实现
* @author Zone.N (Zone.Niuzh@hotmail.com)
* @version 1.0
* @date 2021-09-18
@@ -14,39 +14,56 @@
*
*/
-#include "cpu.hpp"
-#include "stdio.h"
#include "intr.h"
#include "cpu.hpp"
-#include "vmm.h"
+#include "cstdio"
/**
* @brief 中断处理函数
* @param _scause 原因
* @param _sepc 值
* @param _stval 值
+ * @param _scause 值
+ * @param _all_regs 保存在栈上的所有寄存器,实际上是 sp
+ * @param _sie 值
+ * @param _sstatus 值
+ * @param _sscratch 值
*/
-extern "C" void trap_handler(uint64_t _scause, uint64_t _sepc,
- uint64_t _stval) {
-
+extern "C" void
+trap_handler(uintptr_t _sepc, uintptr_t _stval, uintptr_t _scause,
+ CPU::all_regs_t* _all_regs, uintptr_t _sie,
+ CPU::sstatus_t _sstatus, CPU::satp_t _satp, uintptr_t _sscratch) {
// 消除 unused 警告
(void)_sepc;
(void)_stval;
+ (void)_scause;
+ (void)_all_regs;
+ (void)_sie;
+ (void)_sstatus;
+ (void)_satp;
+ (void)_sscratch;
#define DEBUG
#ifdef DEBUG
- info("scause: 0x%p, sepc: 0x%p, stval: 0x%p.\n", _scause, _sepc, _stval);
-#undef DEBUG
+ info("sepc: 0x%p, stval: 0x%p, scause: 0x%p, all_regs(sp): 0x%p, sie: "
+ "0x%p\nsstatus: ",
+ _sepc, _stval, _scause, _all_regs, _sie);
+ std::cout << _sstatus << ", \nsatp: " << _satp << ", \n";
+ info("sscratch: 0x%p\n", _sscratch);
+// std::cout << *_all_regs << std::endl;
+# undef DEBUG
#endif
if (_scause & CPU::CAUSE_INTR_MASK) {
// 中断
// #define DEBUG
#ifdef DEBUG
- info("intr: %s.\n", INTR::get_instance().get_intr_name(
- _scause & CPU::CAUSE_CODE_MASK));
-#undef DEBUG
+ info("intr: %s.\n",
+ INTR::get_instance().get_intr_name(_scause
+ & CPU::CAUSE_CODE_MASK));
+# undef DEBUG
#endif
// 跳转到对应的处理函数
- INTR::get_instance().do_interrupt(_scause & CPU::CAUSE_CODE_MASK);
+ INTR::get_instance().do_interrupt(_scause & CPU::CAUSE_CODE_MASK, 0,
+ nullptr);
}
else {
// 异常
@@ -54,10 +71,12 @@ extern "C" void trap_handler(uint64_t _scause, uint64_t _sepc,
// #define DEBUG
#ifdef DEBUG
warn("excp: %s.\n",
- INTR::get_instance().excp_name(_scause & CPU::CAUSE_CODE_MASK));
-#undef DEBUG
+ INTR::get_instance().get_excp_name(_scause
+ & CPU::CAUSE_CODE_MASK));
+# undef DEBUG
#endif
- INTR::get_instance().do_excp(_scause & CPU::CAUSE_CODE_MASK);
+ INTR::get_instance().do_excp(_scause & CPU::CAUSE_CODE_MASK, 0,
+ nullptr);
}
return;
}
@@ -65,41 +84,17 @@ extern "C" void trap_handler(uint64_t _scause, uint64_t _sepc,
/// 中断处理入口 intr_s.S
extern "C" void trap_entry(void);
-/**
- * @brief 缺页处理
- */
-void pg_load_excp(void) {
- uintptr_t addr = CPU::READ_STVAL();
- // 映射页
- VMM::get_instance().mmap(VMM::get_instance().get_pgd(), addr, addr,
- VMM_PAGE_READABLE);
- info("pg_load_excp done: 0x%p.\n", addr);
- return;
-}
-
-/**
- * @brief 缺页处理
- */
-void pg_store_excp(void) {
- uintptr_t addr = CPU::READ_STVAL();
- // 映射页
- VMM::get_instance().mmap(VMM::get_instance().get_pgd(), addr, addr,
- VMM_PAGE_WRITABLE | VMM_PAGE_READABLE);
- info("pg_store_excp done: 0x%p.\n", addr);
- return;
-}
-
/**
* @brief 默认使用的中断处理函数
*/
-void handler_default(void) {
+int32_t handler_default(int, char**) {
while (1) {
;
}
- return;
+ return 0;
}
-INTR &INTR::get_instance(void) {
+INTR& INTR::get_instance(void) {
/// 定义全局 INTR 对象
static INTR intr;
return intr;
@@ -110,27 +105,27 @@ int32_t INTR::init(void) {
CPU::WRITE_STVEC((uintptr_t)trap_entry);
// 直接跳转到处理函数
CPU::STVEC_DIRECT();
- // 内部中断初始化
- CLINT::get_instance().init();
- // 外部中断初始化
- PLIC::get_instance().init();
// 设置处理函数
- for (auto &i : interrupt_handlers) {
+ for (auto& i : interrupt_handlers) {
i = handler_default;
}
- for (auto &i : excp_handlers) {
+ for (auto& i : excp_handlers) {
i = handler_default;
}
+ // 内部中断初始化
+ CLINT::get_instance().init();
+ // 外部中断初始化
+ PLIC::get_instance().init();
// 注册缺页中断
- register_excp_handler(EXCP_LOAD_PAGE_FAULT, pg_load_excp);
+ register_excp_handler(CPU::EXCP_LOAD_PAGE_FAULT, pg_load_excp);
// 注册缺页中断
- register_excp_handler(EXCP_STORE_PAGE_FAULT, pg_store_excp);
+ register_excp_handler(CPU::EXCP_STORE_AMO_PAGE_FAULT, pg_store_excp);
info("intr init.\n");
return 0;
}
void INTR::register_interrupt_handler(
- uint8_t _no, INTR::interrupt_handler_t _interrupt_handler) {
+ uint8_t _no, INTR::interrupt_handler_t _interrupt_handler) {
interrupt_handlers[_no] = _interrupt_handler;
return;
}
@@ -141,20 +136,18 @@ void INTR::register_excp_handler(uint8_t _no,
return;
}
-void INTR::do_interrupt(uint8_t _no) {
- interrupt_handlers[_no]();
- return;
+int32_t INTR::do_interrupt(uint8_t _no, int32_t _argc, char** _argv) {
+ return interrupt_handlers[_no](_argc, _argv);
}
-void INTR::do_excp(uint8_t _no) {
- excp_handlers[_no]();
- return;
+int32_t INTR::do_excp(uint8_t _no, int32_t _argc, char** _argv) {
+ return excp_handlers[_no](_argc, _argv);
}
-const char *INTR::get_intr_name(uint8_t _no) const {
+const char* INTR::get_intr_name(uint8_t _no) const {
return intr_names[_no];
}
-const char *INTR::get_excp_name(uint8_t _no) const {
+const char* INTR::get_excp_name(uint8_t _no) const {
return excp_names[_no];
}
diff --git a/src/arch/riscv64/intr/intr_s.S b/src/arch/riscv64/intr/intr_s.S
index a122c998f..5b26ad1a1 100644
--- a/src/arch/riscv64/intr/intr_s.S
+++ b/src/arch/riscv64/intr/intr_s.S
@@ -14,80 +14,37 @@
*
*/
-.equ REGBYTES, 8
-.equ SAVE_REGS, 16
-.equ CONTEXT_SIZE, (SAVE_REGS * REGBYTES)
+#include "context.S"
-.macro lx a, b
-ld \a, \b
-.endm
-
-.macro sx a, b
-sd \a, \b
-.endm
-
-.macro lxsp a, b
-ld \a, ((\b)*REGBYTES)(sp)
-.endm
-
-.macro sxsp a, b
-sd \a, ((\b)*REGBYTES)(sp)
-.endm
+// clang-format off
.section .text
-
-// push all registers, call trap_handler(), restore, return.
-.extern irq_handler
+// 保存所有寄存器
.globl trap_entry
.extern trap_handler
.align 4
trap_entry:
- // make room to save registers.
- addi sp, sp, -CONTEXT_SIZE
-
- sxsp ra, 0
- sxsp a0, 1
- sxsp a1, 2
- sxsp a2, 3
- sxsp a3, 4
- sxsp a4, 5
- sxsp a5, 6
- sxsp a6, 7
- sxsp a7, 8
- sxsp t0, 9
- sxsp t1, 10
- sxsp t2, 11
- sxsp t3, 12
- sxsp t4, 13
- sxsp t5, 14
- sxsp t6, 15
-
- // Invoke the handler.
- // intr.cpp
- csrr a0, scause
- csrr a1, sepc
- csrr a2, stval
+ // 将所有寄存器保存到栈上
+ // 在栈上留出保存寄存器的空间
+ addi sp, sp, -ALL_SIZE
+ all_regs_save sp
+
+ // 调用 intr.cpp: trap_handler
+ // 传递参数
+ csrr a0, sepc
+ csrr a1, stval
+ csrr a2, scause
+ mv a3, sp
+ csrr a4, sie
+ csrr a5, sstatus
+ csrr a6, satp
+ csrr a7, sscratch
jal trap_handler
- // Restore registers.
- lxsp ra, 0
- lxsp a0, 1
- lxsp a1, 2
- lxsp a2, 3
- lxsp a3, 4
- lxsp a4, 5
- lxsp a5, 6
- lxsp a6, 7
- lxsp a7, 8
- lxsp t0, 9
- lxsp t1, 10
- lxsp t2, 11
- lxsp t3, 12
- lxsp t4, 13
- lxsp t5, 14
- lxsp t6, 15
-
- addi sp, sp, CONTEXT_SIZE
+ // 从栈上恢复所有寄存器
+ all_regs_load sp
+ // 释放栈上用于保存寄存器的空间
+ addi sp, sp, ALL_SIZE
- // return to whatever we were doing in the kernel.
+ // 跳转到 sepc 处执行
sret
diff --git a/src/arch/riscv64/intr/page_fault.cpp b/src/arch/riscv64/intr/page_fault.cpp
new file mode 100644
index 000000000..1d452d208
--- /dev/null
+++ b/src/arch/riscv64/intr/page_fault.cpp
@@ -0,0 +1,63 @@
+
+/**
+ * @file page_fault.cpp
+ * @brief 页错误处理
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2022-03-27
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2022-03-27 Zone.Niuzh 新建文件
+ *
+ */
+
+#include "cpu.hpp"
+#include "cstdint"
+#include "cstdio"
+#include "pmm.h"
+#include "vmm.h"
+
+int32_t pg_load_excp(int, char**) {
+ uintptr_t addr = CPU::READ_STVAL();
+ uintptr_t pa = 0x0;
+ auto is_mmap
+ = VMM::get_instance().get_mmap(VMM::get_instance().get_pgd(), addr, &pa);
+ // 如果 is_mmap 为 true,说明已经应映射过了
+ if (is_mmap == true) {
+ // 直接映射
+ VMM::get_instance().mmap(VMM::get_instance().get_pgd(), addr, pa,
+ VMM_PAGE_READABLE);
+ }
+ else {
+ // 分配一页物理内存进行映射
+ pa = PMM::get_instance().alloc_page_kernel();
+ VMM::get_instance().mmap(VMM::get_instance().get_pgd(), addr, pa,
+ VMM_PAGE_READABLE);
+ }
+ info("pg_load_excp done: 0x%p.\n", addr);
+ return 0;
+}
+
+int32_t pg_store_excp(int, char**) {
+ uintptr_t addr = CPU::READ_STVAL();
+ uintptr_t pa = 0x0;
+ auto is_mmap
+ = VMM::get_instance().get_mmap(VMM::get_instance().get_pgd(), addr, &pa);
+ // 如果 is_mmap 为 true,说明已经应映射过了
+ if (is_mmap == true) {
+ // 直接映射
+ VMM::get_instance().mmap(VMM::get_instance().get_pgd(), addr, pa,
+ VMM_PAGE_READABLE | VMM_PAGE_WRITABLE);
+ }
+ else {
+ // 分配一页物理内存进行映射
+ pa = PMM::get_instance().alloc_page_kernel();
+ VMM::get_instance().mmap(VMM::get_instance().get_pgd(), addr, pa,
+ VMM_PAGE_READABLE | VMM_PAGE_WRITABLE);
+ }
+ info("pg_store_excp done: 0x%p.\n", addr);
+ return 0;
+}
diff --git a/src/arch/riscv64/intr/plic.cpp b/src/arch/riscv64/intr/plic.cpp
index 048840583..3b58c3b6d 100755
--- a/src/arch/riscv64/intr/plic.cpp
+++ b/src/arch/riscv64/intr/plic.cpp
@@ -14,42 +14,54 @@
*
*/
-#include "stdint.h"
-#include "stdio.h"
-#include "cpu.hpp"
-#include "pmm.h"
-#include "vmm.h"
#include "boot_info.h"
-#include "io.h"
+#include "cpu.hpp"
+#include "cstdint"
+#include "cstdio"
#include "intr.h"
+#include "io.h"
+#include "vmm.h"
-/// 这个值在启动时由 opensbi 传递,暂时写死
-static constexpr const uint64_t hart = 0;
+uint64_t PLIC::base_addr;
+uint64_t PLIC::PLIC_PRIORITY;
+uint64_t PLIC::PLIC_PENDING;
/**
* @brief 外部中断处理
*/
-static void externel_intr(void) {
+static int32_t external_intr(int, char**) {
// 读取中断号
auto no = PLIC::get_instance().get();
// 根据中断号判断设备
- printf("externel_intr: 0x%X.\n", no);
- return;
+ printf("external_intr: 0x%X.\n", no);
+ return 0;
}
uint64_t PLIC::PLIC_SENABLE(uint64_t _hart) {
return base_addr + 0x2080 + _hart * 0x100;
}
+uint64_t PLIC::PLIC_MENABLE(uint64_t _hart) {
+ return base_addr + 0x2000 + _hart * 0x100;
+}
+
uint64_t PLIC::PLIC_SPRIORITY(uint64_t _hart) {
return base_addr + 0x201000 + _hart * 0x2000;
}
+uint64_t PLIC::PLIC_MPRIORITY(uint64_t _hart) {
+ return base_addr + 0x200000 + _hart * 0x2000;
+}
+
uint64_t PLIC::PLIC_SCLAIM(uint64_t _hart) {
return base_addr + 0x201004 + _hart * 0x2000;
}
-PLIC &PLIC::get_instance(void) {
+uint64_t PLIC::PLIC_MCLAIM(uint64_t _hart) {
+ return base_addr + 0x200004 + _hart * 0x2000;
+}
+
+PLIC& PLIC::get_instance(void) {
/// 定义全局 PLIC 对象
static PLIC plic;
return plic;
@@ -61,17 +73,18 @@ int32_t PLIC::init(void) {
base_addr = resource.mem.addr;
PLIC_PRIORITY = base_addr + 0x0;
PLIC_PENDING = base_addr + 0x1000;
- for (uintptr_t a = resource.mem.addr;
- a < resource.mem.addr + resource.mem.len; a += 0x1000) {
+ for (uintptr_t a = resource.mem.addr;
+ a < resource.mem.addr + resource.mem.len; a += COMMON::PAGE_SIZE) {
VMM::get_instance().mmap(VMM::get_instance().get_pgd(), a, a,
VMM_PAGE_READABLE | VMM_PAGE_WRITABLE);
}
// TODO: 多核情况下设置所有 hart
// 将当前 hart 的 S 模式优先级阈值设置为 0
- IO::get_instance().write32((void *)PLIC_SPRIORITY(hart), 0);
+ IO::get_instance().write32((void*)PLIC_SPRIORITY(BOOT_INFO::dtb_init_hart),
+ 0);
// 注册外部中断处理函数
- INTR::get_instance().register_interrupt_handler(INTR::INTR_S_EXTERNEL,
- externel_intr);
+ INTR::get_instance().register_interrupt_handler(CPU::INTR_EXTERN_S,
+ external_intr);
// 开启外部中断
CPU::WRITE_SIE(CPU::READ_SIE() | CPU::SIE_SEIE);
info("plic init.\n");
@@ -80,28 +93,33 @@ int32_t PLIC::init(void) {
void PLIC::set(uint8_t _no, bool _status) {
// 设置 IRQ 的属性为非零,即启用 plic
- IO::get_instance().write32((void *)(base_addr + _no * 4), _status);
+ IO::get_instance().write32((void*)(base_addr + _no * 4), _status);
// TODO: 多核情况下设置所有 hart
// 为当前 hart 的 S 模式设置 uart 的 enable
if (_status) {
IO::get_instance().write32(
- (void *)PLIC_SENABLE(hart),
- IO::get_instance().read32((void *)PLIC_SENABLE(hart)) | (1 << _no));
+ (void*)PLIC_SENABLE(BOOT_INFO::dtb_init_hart),
+ IO::get_instance().read32((void*)
+ PLIC_SENABLE(BOOT_INFO::dtb_init_hart))
+ | (1 << _no));
}
else {
IO::get_instance().write32(
- (void *)PLIC_SENABLE(hart),
- IO::get_instance().read32((void *)PLIC_SENABLE(hart)) &
- ~(1 << _no));
+ (void*)PLIC_SENABLE(BOOT_INFO::dtb_init_hart),
+ IO::get_instance().read32((void*)
+ PLIC_SENABLE(BOOT_INFO::dtb_init_hart))
+ & ~(1 << _no));
}
return;
}
uint8_t PLIC::get(void) {
- return IO::get_instance().read32((void *)PLIC_SCLAIM(hart));
+ return IO::get_instance().read32((void*)
+ PLIC_SCLAIM(BOOT_INFO::dtb_init_hart));
}
void PLIC::done(uint8_t _no) {
- IO::get_instance().write32((void *)PLIC_SCLAIM(hart), _no);
+ IO::get_instance().write32((void*)PLIC_SCLAIM(BOOT_INFO::dtb_init_hart),
+ _no);
return;
}
diff --git a/src/arch/riscv64/intr/timer.cpp b/src/arch/riscv64/intr/timer.cpp
index 365bbd797..d1b17cad5 100644
--- a/src/arch/riscv64/intr/timer.cpp
+++ b/src/arch/riscv64/intr/timer.cpp
@@ -14,11 +14,11 @@
*
*/
-#include "stdint.h"
-#include "stdio.h"
#include "cpu.hpp"
-#include "opensbi.h"
+#include "cstdint"
+#include "cstdio"
#include "intr.h"
+#include "opensbi.h"
/// timer interrupt interval
/// @todo 从 dts 读取
@@ -27,7 +27,7 @@ static constexpr const uint64_t INTERVAL = 390000000 / 20;
/**
* @brief 设置下一次时钟
*/
-void set_next(void) {
+void set_next(void) {
// 调用 opensbi 提供的接口设置时钟
OPENSBI::get_instance().set_timer(CPU::READ_TIME() + INTERVAL);
return;
@@ -36,13 +36,13 @@ void set_next(void) {
/**
* @brief 时钟中断
*/
-void timer_intr(void) {
+int32_t timer_intr(int, char**) {
// 每次执行中断时设置下一次中断的时间
set_next();
- return;
+ return 0;
}
-TIMER &TIMER::get_instance(void) {
+TIMER& TIMER::get_instance(void) {
/// 定义全局 TIMER 对象
static TIMER timer;
return timer;
@@ -50,7 +50,8 @@ TIMER &TIMER::get_instance(void) {
void TIMER::init(void) {
// 注册中断函数
- INTR::get_instance().register_interrupt_handler(INTR::INTR_S_TIMER, timer_intr);
+ INTR::get_instance().register_interrupt_handler(CPU::INTR_TIMER_S,
+ timer_intr);
// 设置初次中断
OPENSBI::get_instance().set_timer(CPU::READ_TIME());
// 开启时钟中断
diff --git a/src/arch/riscv64/link.ld b/src/arch/riscv64/link.ld
index 6dfc364e8..0001413ec 100644
--- a/src/arch/riscv64/link.ld
+++ b/src/arch/riscv64/link.ld
@@ -1,74 +1,253 @@
/* This file is a part of Simple-XX/SimpleKernel
* (https://github.com/Simple-XX/SimpleKernel).
- *
- * link.ld for Simple-XX/SimpleKernel.
- * 链接脚本,指定生成的二进制文件的布局 */
+ * Based on gnu-ld
+ * link.ld for Simple-XX/SimpleKernel.
+ * 链接脚本,指定生成的二进制文件的布局
+ */
+/* Script for -z combreloc */
+/* Copyright (C) 2014-2022 Free Software Foundation, Inc.
+ Copying and distribution of this script, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. */
/* 指定输出格式 */
-OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv", "elf64-littleriscv")
-/* 执行输出架构 */
+OUTPUT_FORMAT(
+ "elf64-littleriscv",
+ "elf64-littleriscv",
+ "elf64-littleriscv"
+)
+/* 指定输出架构 */
OUTPUT_ARCH(riscv)
/* 设置入口点 */
ENTRY(_start)
/* 设置各个 section */
SECTIONS {
- . = 0x80000000;
- PROVIDE(kernel_start = .);
+ /* Read-only sections, merged into text segment: */
+ PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x80200000));
/* 设置起始地址 */
- . = 0x80200000;
-
- PROVIDE(kernel_text_start = .);
+ . = SEGMENT_START("text-segment", 0x80200000);
+ .boot : { *(.text.boot) *(.data.boot) *(.bss.boot) }
+ .interp : { *(.interp) }
+ .note.gnu.build-id : { *(.note.gnu.build-id) }
+ .hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rela.dyn : {
+ *(.rela.init)
+ *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+ *(.rela.fini)
+ *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+ *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+ *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+ *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+ *(.rela.ctors)
+ *(.rela.dtors)
+ *(.rela.got)
+ *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*)
+ *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*)
+ *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*)
+ *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*)
+ *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+ *(.rela.ifunc)
+ }
+ .rela.plt : {
+ *(.rela.plt)
+ PROVIDE_HIDDEN (__rela_iplt_start = .);
+ *(.rela.iplt)
+ PROVIDE_HIDDEN (__rela_iplt_end = .);
+ }
+ .init : {
+ KEEP (*(SORT_NONE(.init)))
+ }
+ .plt : { *(.plt) *(.iplt) }
/* 代码段 */
- .text : ALIGN(4K) {
- *(.init)
- *(.text*)
+ .text : {
+ *(.text.unlikely .text.*_unlikely .text.unlikely.*)
+ *(.text.exit .text.exit.*)
+ *(.text.startup .text.startup.*)
+ *(.text.hot .text.hot.*)
+ *(SORT(.text.sorted.*))
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ /* .gnu.warning sections are handled specially by elf.em. */
+ *(.gnu.warning)
}
- PROVIDE(kernel_text_end = .);
-
- PROVIDE(kernel_rodata_start = .);
- /* 只读数据段 */
- .rodata : ALIGN(4K) {
- /* 构造函数起点 */
- PROVIDE(ctors_start = .);
- *(SORT_BY_INIT_PRIORITY (.init_array.*))
- *(SORT_BY_INIT_PRIORITY (.ctors.*))
- *(.init_array .ctors)
- /* 构造函数终点 */
- PROVIDE(ctors_end = .);
- /* 析构函数起点 */
- PROVIDE(dtors_start = .);
- *(.dtor*)
- /* 析构函数终点 */
- PROVIDE(dtors_end = .);
- *(.rodata*)
- *(.gcc_except_table)
- *(.riscv.attributes)
- }
- PROVIDE(kernel_rodata_end = .);
-
- PROVIDE(kernel_data_start = .);
- /* 数据段 */
- .data : ALIGN(4K) {
- *(.data*)
- *(.eh_frame)
- *(.got*)
- }
- PROVIDE(kernel_data_end = .);
-
- PROVIDE(kernel_bss_start = .);
- /* 未初始化数据段 */
- .bss : ALIGN(4K) {
- *(.bss);
+ .fini : {
+ KEEP (*(SORT_NONE(.fini)))
}
- PROVIDE(kernel_bss_end = .);
-
- PROVIDE(kernel_debug_start = .);
- /* 调试信息 */
- .debug : ALIGN(4K) {
- *(.debug*)
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+ .rodata1 : { *(.rodata1) }
+ .sdata2 : {
+ *(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
}
- PROVIDE(kernel_debug_end = .);
-
- PROVIDE(kernel_end = .);
+ .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) }
+ .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
+ .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
+ .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
+ .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }
+ /* These sections are generated by the Sun/Oracle C++ compiler. */
+ .exception_ranges : ONLY_IF_RO { *(.exception_ranges*) }
+ /* Adjust the address for the data segment. We want to adjust up to
+ the same address within the page on the next page up. */
+ . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+ /* Exception handling */
+ .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
+ .gnu_extab : ONLY_IF_RW { *(.gnu_extab) }
+ .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
+ .exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
+ /* Thread Local Storage sections */
+ .tdata : {
+ PROVIDE_HIDDEN (__tdata_start = .);
+ *(.tdata .tdata.* .gnu.linkonce.td.*)
+ }
+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+ .preinit_array : {
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ }
+ .init_array : {
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
+ KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ }
+ .fini_array : {
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
+ KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ }
+ .ctors : {
+ /* gcc uses crtbegin.o to find the start of
+ the constructors, so we make sure it is
+ first. Because this is a wildcard, it
+ doesn't matter if the user does not
+ actually link against crtbegin.o; the
+ linker won't look for a file to match a
+ wildcard. The wildcard also means that it
+ doesn't matter which directory crtbegin.o
+ is in. */
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*crtbegin?.o(.ctors))
+ /* We don't want to include the .ctor section from
+ the crtend.o file until after the sorted ctors.
+ The .ctor section from the crtend file contains the
+ end of ctors marker and it must be last */
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ }
+ .dtors : {
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*crtbegin?.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ }
+ .jcr : { KEEP (*(.jcr)) }
+ .data.rel.ro : {
+ *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*)
+ *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*)
+ }
+ .dynamic : { *(.dynamic) }
+ . = DATA_SEGMENT_RELRO_END (0, .);
+ .data : {
+ __DATA_BEGIN__ = .;
+ *(.data .data.* .gnu.linkonce.d.*)
+ SORT(CONSTRUCTORS)
+ }
+ .data1 : { *(.data1) }
+ .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) }
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+ .sdata : {
+ __SDATA_BEGIN__ = .;
+ *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4)
+ *(.srodata.cst2) *(.srodata .srodata.*)
+ *(.sdata .sdata.* .gnu.linkonce.s.*)
+ }
+ _edata = .; PROVIDE (edata = .);
+ . = .;
+ __bss_start = .;
+ .sbss : {
+ *(.dynsbss)
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
+ *(.scommon)
+ }
+ .bss : {
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ /* Align here to ensure that the .bss section occupies space up to
+ _end. Align after .bss to ensure correct alignment even if the
+ .bss section disappears because there are no input sections.
+ FIXME: Why do we need it? When there is no .bss section, we do not
+ pad the .data section. */
+ . = ALIGN(. != 0 ? 64 / 8 : 1);
+ }
+ . = ALIGN(64 / 8);
+ . = SEGMENT_START("ldata-segment", .);
+ . = ALIGN(64 / 8);
+ __BSS_END__ = .;
+ __global_pointer$ = MIN(__SDATA_BEGIN__ + 0x800,
+ MAX(__DATA_BEGIN__ + 0x800, __BSS_END__ - 0x800));
+ _end = .; PROVIDE (end = .);
+ . = DATA_SEGMENT_END (.);
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1. */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions. */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2. */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2. */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions. */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ /* DWARF 3. */
+ .debug_pubtypes 0 : { *(.debug_pubtypes) }
+ .debug_ranges 0 : { *(.debug_ranges) }
+ /* DWARF 5. */
+ .debug_addr 0 : { *(.debug_addr) }
+ .debug_line_str 0 : { *(.debug_line_str) }
+ .debug_loclists 0 : { *(.debug_loclists) }
+ .debug_macro 0 : { *(.debug_macro) }
+ .debug_names 0 : { *(.debug_names) }
+ .debug_rnglists 0 : { *(.debug_rnglists) }
+ .debug_str_offsets 0 : { *(.debug_str_offsets) }
+ .debug_sup 0 : { *(.debug_sup) }
+ .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+ /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
}
diff --git a/src/drv/CMakeLists.txt b/src/drv/CMakeLists.txt
index 624d5a889..af70a1cea 100644
--- a/src/drv/CMakeLists.txt
+++ b/src/drv/CMakeLists.txt
@@ -1,5 +1,6 @@
-# This file is a part of Simple-XX/SimpleKernel (https://github.com/Simple-XX/SimpleKernel).
+# This file is a part of Simple-XX/SimpleKernel
+# (https://github.com/Simple-XX/SimpleKernel).
#
# CMakeLists.txt for Simple-XX/SimpleKernel.
# 驱动子模块的编译规则
@@ -14,11 +15,11 @@ if (SimpleKernelArch STREQUAL ia32/i386 OR SimpleKernelArch STREQUAL ia32/x86_64
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/multiboot2 multiboot2_src)
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/keyboard keyboard_src)
set(drv_src ${tui_src} ${multiboot2_src} ${keyboard_src})
-# arm 驱动
+ # arm 驱动
elseif (SimpleKernelArch STREQUAL arm)
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/uart uart_src)
set(drv_src ${uart_src})
-# riscv64 驱动
+ # riscv64 驱动
elseif (SimpleKernelArch STREQUAL riscv64)
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/opensbi opensbi_src)
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/sbi_console sbi_console_src)
@@ -26,7 +27,7 @@ elseif (SimpleKernelArch STREQUAL riscv64)
set(drv_src ${opensbi_src} ${sbi_console_src} ${dtb_src})
endif ()
-# 添加子模块
+# 添加子模块
add_library(${PROJECT_NAME} OBJECT ${drv_src})
# 添加头文件搜索路径
diff --git a/src/drv/dtb/dtb.cpp b/src/drv/dtb/dtb.cpp
index f6a91a4b6..14c081051 100644
--- a/src/drv/dtb/dtb.cpp
+++ b/src/drv/dtb/dtb.cpp
@@ -15,25 +15,25 @@
*
*/
-#include "stdint.h"
-#include "stdio.h"
-#include "endian.h"
-#include "assert.h"
-#include "common.h"
+#include "dtb.h"
#include "boot_info.h"
+#include "cassert"
+#include "common.h"
+#include "cstdint"
+#include "cstdio"
+#include "endian.h"
#include "resource.h"
-#include "dtb.h"
// 所有节点
-DTB::node_t DTB::nodes[MAX_NODES];
+DTB::node_t DTB::nodes[MAX_NODES];
// 节点数
-size_t DTB::node_t::count = 0;
+size_t DTB::node_t::count = 0;
// 所有 phandle
DTB::phandle_map_t DTB::phandle_map[MAX_NODES];
// phandle 数
-size_t DTB::phandle_map_t::count = 0;
+size_t DTB::phandle_map_t::count = 0;
-bool DTB::path_t::operator==(const DTB::path_t *_path) {
+bool DTB::path_t::operator==(const DTB::path_t* _path) {
if (len != _path->len) {
return false;
}
@@ -45,7 +45,7 @@ bool DTB::path_t::operator==(const DTB::path_t *_path) {
return true;
}
-bool DTB::path_t::operator==(const char *_path) {
+bool DTB::path_t::operator==(const char* _path) {
// 路径必须以 ‘/’ 开始
if (_path[0] != '/') {
return false;
@@ -61,7 +61,7 @@ bool DTB::path_t::operator==(const char *_path) {
return true;
}
-DTB::node_t *DTB::get_phandle(uint32_t _phandle) {
+DTB::node_t* DTB::get_phandle(uint32_t _phandle) {
// 在 phandle_map 中寻找对应的节点
for (size_t i = 0; i < phandle_map[0].count; i++) {
if (phandle_map[i].phandle == _phandle) {
@@ -71,7 +71,7 @@ DTB::node_t *DTB::get_phandle(uint32_t _phandle) {
return nullptr;
}
-DTB::dt_fmt_t DTB::get_fmt(const char *_prop_name) {
+DTB::dt_fmt_t DTB::get_fmt(const char* _prop_name) {
// 默认为 FMT_UNKNOWN
dt_fmt_t res = FMT_UNKNOWN;
for (size_t i = 0; i < sizeof(props) / sizeof(dt_prop_fmt_t); i++) {
@@ -83,14 +83,14 @@ DTB::dt_fmt_t DTB::get_fmt(const char *_prop_name) {
return res;
}
-void DTB::print_attr_propenc(const iter_data_t *_iter, size_t *_cells,
+void DTB::print_attr_propenc(const iter_data_t* _iter, size_t* _cells,
size_t _len) {
// 字节总数
- uint32_t entry_size = 0;
+ uint32_t entry_size = 0;
// 属性长度
- uint32_t remain = _iter->prop_len;
+ uint32_t remain = _iter->prop_len;
// 属性数据
- uint32_t *reg = _iter->prop_addr;
+ uint32_t* reg = _iter->prop_addr;
printf("%s: ", _iter->prop_name);
// 计算
@@ -126,11 +126,18 @@ void DTB::print_attr_propenc(const iter_data_t *_iter, size_t *_cells,
return;
}
-void DTB::fill_resource(resource_t *_resource, const node_t *_node,
- const prop_t *_prop) {
- // 如果 _resource 名称为空则使用 _node 路径填充
+void DTB::fill_resource(resource_t* _resource, const node_t* _node,
+ const prop_t* _prop) {
+ // 如果 _resource 名称为空则使用 compatible,如果没有找到则使用 _node 路径
if (_resource->name == nullptr) {
- _resource->name = _node->path.path[_node->path.len - 1];
+ for (size_t i = 0; i < _node->prop_count; i++) {
+ if (strcmp(_node->props[i].name, "compatible") == 0) {
+ _resource->name = (char*)_node->props[i].addr;
+ }
+ if (_resource->name == nullptr) {
+ _resource->name = _node->path.path[_node->path.len - 1];
+ }
+ }
}
// 内存类型
if ((_resource->type & resource_t::MEM) && (_resource->mem.len == 0)) {
@@ -138,28 +145,28 @@ void DTB::fill_resource(resource_t *_resource, const node_t *_node,
// resource 一般来说两者是相等的
if (_node->parent->address_cells == 1) {
assert(_node->parent->size_cells == 1);
- _resource->mem.addr = be32toh(((uint32_t *)_prop->addr)[0]);
- _resource->mem.len = be32toh(((uint32_t *)_prop->addr)[1]);
+ _resource->mem.addr = be32toh(((uint32_t*)_prop->addr)[0]);
+ _resource->mem.len = be32toh(((uint32_t*)_prop->addr)[1]);
}
else if (_node->parent->address_cells == 2) {
assert(_node->parent->size_cells == 2);
- _resource->mem.addr = be32toh(((uint32_t *)_prop->addr)[0]) +
- be32toh(((uint32_t *)_prop->addr)[1]);
- _resource->mem.len = be32toh(((uint32_t *)_prop->addr)[2]) +
- be32toh(((uint32_t *)_prop->addr)[3]);
+ _resource->mem.addr = be32toh(((uint32_t*)_prop->addr)[0])
+ + be32toh(((uint32_t*)_prop->addr)[1]);
+ _resource->mem.len = be32toh(((uint32_t*)_prop->addr)[2])
+ + be32toh(((uint32_t*)_prop->addr)[3]);
}
else {
assert(0);
}
}
else if (_resource->type & resource_t::INTR_NO) {
- _resource->intr_no = be32toh(((uint32_t *)_prop->addr)[0]);
+ _resource->intr_no = be32toh(((uint32_t*)_prop->addr)[0]);
}
return;
}
-DTB::node_t *DTB::find_node_via_path(const char *_path) {
- node_t *res = nullptr;
+DTB::node_t* DTB::find_node_via_path(const char* _path) {
+ node_t* res = nullptr;
// 遍历 nodes
for (size_t i = 0; i < nodes[0].count; i++) {
// 如果 nodes[i] 中有属性/值对符合要求
@@ -172,7 +179,7 @@ DTB::node_t *DTB::find_node_via_path(const char *_path) {
}
void DTB::dtb_mem_reserved(void) {
- fdt_reserve_entry_t *entry = dtb_info.reserved;
+ fdt_reserve_entry_t* entry = dtb_info.reserved;
if (entry->addr_le || entry->size_le) {
// 目前没有考虑这种情况,先报错
assert(0);
@@ -180,18 +187,18 @@ void DTB::dtb_mem_reserved(void) {
return;
}
-void DTB::dtb_iter(uint8_t _cb_flags, bool (*_cb)(const iter_data_t *, void *),
- void *_data, uintptr_t _addr) {
+void DTB::dtb_iter(uint8_t _cb_flags, bool (*_cb)(const iter_data_t*, void*),
+ void* _data, uintptr_t _addr) {
// 迭代变量
iter_data_t iter;
// 路径深度
- iter.path.len = 0;
+ iter.path.len = 0;
// 数据地址
- iter.addr = (uint32_t *)_addr;
+ iter.addr = (uint32_t*)_addr;
// 节点索引
iter.nodes_idx = 0;
// 开始 flag
- bool begin = true;
+ bool begin = true;
while (1) {
//
@@ -204,7 +211,7 @@ void DTB::dtb_iter(uint8_t _cb_flags, bool (*_cb)(const iter_data_t *, void *),
}
case FDT_BEGIN_NODE: {
// 第 len 深底的名称
- iter.path.path[iter.path.len] = (char *)(iter.addr + 1);
+ iter.path.path[iter.path.len] = (char*)(iter.addr + 1);
// 深度+1
iter.path.len++;
iter.nodes_idx = begin ? 0 : (iter.nodes_idx + 1);
@@ -217,8 +224,7 @@ void DTB::dtb_iter(uint8_t _cb_flags, bool (*_cb)(const iter_data_t *, void *),
// 跳过 type
iter.addr++;
// 跳过 name
- iter.addr +=
- COMMON::ALIGN(strlen((char *)iter.addr) + 1, 4) / 4;
+ iter.addr += COMMON::ALIGN(strlen((char*)iter.addr) + 1, 4) / 4;
break;
}
case FDT_END_NODE: {
@@ -235,7 +241,7 @@ void DTB::dtb_iter(uint8_t _cb_flags, bool (*_cb)(const iter_data_t *, void *),
}
case FDT_PROP: {
iter.prop_len = be32toh(iter.addr[1]);
- iter.prop_name = (char *)(dtb_info.str + be32toh(iter.addr[2]));
+ iter.prop_name = (char*)(dtb_info.str + be32toh(iter.addr[2]));
iter.prop_addr = iter.addr + 3;
if (_cb_flags & DT_ITER_PROP) {
if (_cb(&iter, _data)) {
@@ -251,8 +257,8 @@ void DTB::dtb_iter(uint8_t _cb_flags, bool (*_cb)(const iter_data_t *, void *),
// 跳过 nameoff
iter.addr++;
// 跳过 data,并进行对齐
- iter.addr += COMMON::ALIGN(iter.prop_len, 4) / 4;
- iter.prop_len = 0;
+ iter.addr += COMMON::ALIGN(iter.prop_len, 4) / 4;
+ iter.prop_len = 0;
break;
}
case FDT_END: {
@@ -272,7 +278,7 @@ DTB::dtb_info_t DTB::dtb_info;
/*
* This callback constructs tracking information about each node.
*/
-bool DTB::dtb_init_cb(const iter_data_t *_iter, void *) {
+bool DTB::dtb_init_cb(const iter_data_t* _iter, void*) {
// 索引
size_t idx = _iter->nodes_idx;
// 根据类型
@@ -280,9 +286,9 @@ bool DTB::dtb_init_cb(const iter_data_t *_iter, void *) {
// 开始
case FDT_BEGIN_NODE: {
// 设置节点基本信息
- nodes[idx].path = _iter->path;
- nodes[idx].addr = _iter->addr;
- nodes[idx].depth = _iter->path.len;
+ nodes[idx].path = _iter->path;
+ nodes[idx].addr = _iter->addr;
+ nodes[idx].depth = _iter->path.len;
// 设置默认值
nodes[idx].address_cells = 2;
nodes[idx].size_cells = 2;
@@ -321,15 +327,15 @@ bool DTB::dtb_init_cb(const iter_data_t *_iter, void *) {
nodes[idx].phandle = be32toh(_iter->addr[3]);
// 更新 phandle_map
phandle_map[phandle_map[0].count].phandle = nodes[idx].phandle;
- phandle_map[phandle_map[0].count].node = &nodes[idx];
+ phandle_map[phandle_map[0].count].node = &nodes[idx];
phandle_map[0].count++;
}
// 添加属性
nodes[idx].props[nodes[idx].prop_count].name = _iter->prop_name;
- nodes[idx].props[nodes[idx].prop_count].addr =
- (uintptr_t)(_iter->addr + 3);
- nodes[idx].props[nodes[idx].prop_count].len =
- be32toh(_iter->addr[1]);
+ nodes[idx].props[nodes[idx].prop_count].addr
+ = (uintptr_t)(_iter->addr + 3);
+ nodes[idx].props[nodes[idx].prop_count].len
+ = be32toh(_iter->addr[1]);
nodes[idx].prop_count++;
break;
}
@@ -343,10 +349,10 @@ bool DTB::dtb_init_cb(const iter_data_t *_iter, void *) {
return false;
}
-bool DTB::dtb_init_interrupt_cb(const iter_data_t *_iter, void *) {
+bool DTB::dtb_init_interrupt_cb(const iter_data_t* _iter, void*) {
uint8_t idx = _iter->nodes_idx;
uint32_t phandle;
- node_t *parent;
+ node_t* parent;
// 设置中断父节点
if (strcmp(_iter->prop_name, "interrupt-parent") == 0) {
phandle = be32toh(_iter->addr[3]);
@@ -359,7 +365,7 @@ bool DTB::dtb_init_interrupt_cb(const iter_data_t *_iter, void *) {
return false;
}
-DTB &DTB::get_instance(void) {
+DTB& DTB::get_instance(void) {
/// 定义全局 DTB 对象
static DTB dtb;
return dtb;
@@ -367,7 +373,7 @@ DTB &DTB::get_instance(void) {
bool DTB::dtb_init(void) {
// 头信息
- dtb_info.header = (fdt_header_t *)BOOT_INFO::boot_info_addr;
+ dtb_info.header = (fdt_header_t*)BOOT_INFO::boot_info_addr;
// 魔数
assert(be32toh(dtb_info.header->magic) == FDT_MAGIC);
// 版本
@@ -375,15 +381,15 @@ bool DTB::dtb_init(void) {
// 设置大小
BOOT_INFO::boot_info_size = be32toh(dtb_info.header->totalsize);
// 内存保留区
- dtb_info.reserved =
- (fdt_reserve_entry_t *)(BOOT_INFO::boot_info_addr +
- be32toh(dtb_info.header->off_mem_rsvmap));
+ dtb_info.reserved
+ = (fdt_reserve_entry_t*)(BOOT_INFO::boot_info_addr
+ + be32toh(dtb_info.header->off_mem_rsvmap));
// 数据区
- dtb_info.data =
- BOOT_INFO::boot_info_addr + be32toh(dtb_info.header->off_dt_struct);
+ dtb_info.data
+ = BOOT_INFO::boot_info_addr + be32toh(dtb_info.header->off_dt_struct);
// 字符区
- dtb_info.str =
- BOOT_INFO::boot_info_addr + be32toh(dtb_info.header->off_dt_strings);
+ dtb_info.str
+ = BOOT_INFO::boot_info_addr + be32toh(dtb_info.header->off_dt_strings);
// 检查保留内存
dtb_mem_reserved();
// 初始化 map
@@ -403,18 +409,18 @@ bool DTB::dtb_init(void) {
printf("%s: ", nodes[i].props[j].name);
for (size_t k = 0; k < nodes[i].props[j].len / 4; k++) {
printf("0x%X ",
- be32toh(((uint32_t *)nodes[i].props[j].addr)[k]));
+ be32toh(((uint32_t*)nodes[i].props[j].addr)[k]));
}
printf("\n");
}
}
-#undef DEBUG
+# undef DEBUG
#endif
return true;
}
/// @todo 这里看起来似乎可以优化
-bool DTB::find_via_path(const char *_path, resource_t *_resource) {
+bool DTB::find_via_path(const char* _path, resource_t* _resource) {
// 找到节点
auto node = find_node_via_path(_path);
// std::cout << node->path << std::endl;
@@ -436,13 +442,14 @@ bool DTB::find_via_path(const char *_path, resource_t *_resource) {
}
/// @todo 这里看起来似乎可以优化
-size_t DTB::find_via_prefix(const char *_prefix, resource_t *_resource) {
+size_t DTB::find_via_prefix(const char* _prefix, resource_t* _resource) {
size_t res = 0;
// 遍历所有节点,查找
// 由于 @ 均为最底层节点,所以直接比较最后一级即可
for (size_t i = 0; i < nodes[0].count; i++) {
if (strncmp(nodes[i].path.path[nodes[i].path.len - 1], _prefix,
- strlen(_prefix)) == 0) {
+ strlen(_prefix))
+ == 0) {
// 找到 reg
for (size_t j = 0; j < nodes[i].prop_count; j++) {
if (strcmp(nodes[i].props[j].name, "reg") == 0) {
@@ -464,7 +471,7 @@ size_t DTB::find_via_prefix(const char *_prefix, resource_t *_resource) {
return res;
}
-std::ostream &operator<<(std::ostream &_os, const DTB::iter_data_t &_iter) {
+std::ostream& operator<<(std::ostream& _os, const DTB::iter_data_t& _iter) {
// 输出路径
_os << _iter.path << ": ";
// 根据属性类型输出
@@ -483,24 +490,24 @@ std::ostream &operator<<(std::ostream &_os, const DTB::iter_data_t &_iter) {
// 32 位整数
case DTB::FMT_U32: {
printf("%s: 0x%X", _iter.prop_name,
- be32toh(*(uint32_t *)_iter.prop_addr));
+ be32toh(*(uint32_t*)_iter.prop_addr));
break;
}
// 64 位整数
case DTB::FMT_U64: {
printf("%s: 0x%p", _iter.prop_name,
- be32toh(*(uint64_t *)_iter.prop_addr));
+ be32toh(*(uint64_t*)_iter.prop_addr));
break;
}
// 字符串
case DTB::FMT_STRING: {
- _os << _iter.prop_name << ": " << (char *)_iter.prop_addr;
+ _os << _iter.prop_name << ": " << (char*)_iter.prop_addr;
break;
}
// phandle
case DTB::FMT_PHANDLE: {
uint32_t phandle = be32toh(_iter.addr[3]);
- DTB::node_t *ref = DTB::get_instance().get_phandle(phandle);
+ DTB::node_t* ref = DTB::get_instance().get_phandle(phandle);
if (ref != nullptr) {
printf("%s: ", _iter.prop_name, ref->path.path[0]);
}
@@ -512,13 +519,13 @@ std::ostream &operator<<(std::ostream &_os, const DTB::iter_data_t &_iter) {
// 字符串列表
case DTB::FMT_STRINGLIST: {
size_t len = 0;
- char *str = (char *)_iter.prop_addr;
+ char* str = (char*)_iter.prop_addr;
_os << _iter.prop_name << ": [";
while (len < _iter.prop_len) {
// 用 "" 分隔
_os << "\"" << str << "\"";
len += strlen(str) + 1;
- str = (char *)((uint8_t *)_iter.prop_addr + len);
+ str = (char*)((uint8_t*)_iter.prop_addr + len);
}
_os << "]";
break;
@@ -526,31 +533,33 @@ std::ostream &operator<<(std::ostream &_os, const DTB::iter_data_t &_iter) {
// reg,不定长的 32 位数据
case DTB::FMT_REG: {
// 获取节点索引
- uint8_t idx = _iter.nodes_idx;
+ uint8_t idx = _iter.nodes_idx;
// 全部 cells 大小
// devicetree-specification-v0.3.pdf#2.3.6
- size_t cells[] = {
+ size_t cells[] = {
DTB::nodes[idx].parent->address_cells,
DTB::nodes[idx].parent->size_cells,
};
// 调用辅助函数进行输出
- DTB::get_instance().print_attr_propenc(
- &_iter, cells, sizeof(cells) / sizeof(size_t));
+ DTB::get_instance().print_attr_propenc(&_iter, cells,
+ sizeof(cells)
+ / sizeof(size_t));
break;
}
case DTB::FMT_RANGES: {
// 获取节点索引
- uint8_t idx = _iter.nodes_idx;
+ uint8_t idx = _iter.nodes_idx;
// 全部 cells 大小
// devicetree-specification-v0.3.pdf#2.3.8
- size_t cells[] = {
+ size_t cells[] = {
DTB::nodes[idx].address_cells,
DTB::nodes[idx].parent->address_cells,
DTB::nodes[idx].size_cells,
};
// 调用辅助函数进行输出
- DTB::get_instance().print_attr_propenc(
- &_iter, cells, sizeof(cells) / sizeof(size_t));
+ DTB::get_instance().print_attr_propenc(&_iter, cells,
+ sizeof(cells)
+ / sizeof(size_t));
break;
}
default: {
@@ -561,7 +570,7 @@ std::ostream &operator<<(std::ostream &_os, const DTB::iter_data_t &_iter) {
return _os;
}
-std::ostream &operator<<(std::ostream &_os, const DTB::path_t &_path) {
+std::ostream& operator<<(std::ostream& _os, const DTB::path_t& _path) {
if (_path.len == 1) {
_os << "/";
}
@@ -576,13 +585,13 @@ namespace BOOT_INFO {
// 地址
uintptr_t boot_info_addr;
// 长度
-size_t boot_info_size;
+size_t boot_info_size;
// 启动核
-size_t dtb_init_hart;
+size_t dtb_init_hart;
-bool inited = false;
+bool inited = false;
-bool init(void) {
+bool init(void) {
auto res = DTB::get_instance().dtb_init();
if (inited == false) {
inited = true;
@@ -601,7 +610,7 @@ resource_t get_memory(void) {
return resource;
}
-size_t find_via_prefix(const char *_prefix, resource_t *_resource) {
+size_t find_via_prefix(const char* _prefix, resource_t* _resource) {
return DTB::get_instance().find_via_prefix(_prefix, _resource);
}
@@ -620,4 +629,5 @@ resource_t get_plic(void) {
assert(DTB::get_instance().find_via_prefix("plic@", &resource) == 1);
return resource;
}
-}; // namespace BOOT_INFO
+
+}; // namespace BOOT_INFO
diff --git a/src/drv/dtb/include/dtb.h b/src/drv/dtb/include/dtb.h
index 383d27987..52d4e9daa 100644
--- a/src/drv/dtb/include/dtb.h
+++ b/src/drv/dtb/include/dtb.h
@@ -15,15 +15,15 @@
*
*/
-#ifndef _DTB_H_
-#define _DTB_H_
+#ifndef SIMPLEKERNEL_DTB_H
+#define SIMPLEKERNEL_DTB_H
-#include "stdint.h"
-#include "stdbool.h"
#include "boot_info.h"
-#include "resource.h"
+#include "cstdbool"
+#include "cstdint"
#include "endian.h"
#include "iostream"
+#include "resource.h"
/// @see devicetree-specification-v0.3.pdf
/// @see https://e-mailky.github.io/2016-12-06-dts-introduce
@@ -40,19 +40,19 @@ class DTB {
/// node 开始标记
static constexpr const uint32_t FDT_BEGIN_NODE = 0x1;
/// node 结束标记
- static constexpr const uint32_t FDT_END_NODE = 0x2;
+ static constexpr const uint32_t FDT_END_NODE = 0x2;
/// 属性开始标记
- static constexpr const uint32_t FDT_PROP = 0x3;
+ static constexpr const uint32_t FDT_PROP = 0x3;
/// 无效标记
- static constexpr const uint32_t FDT_NOP = 0x4;
+ static constexpr const uint32_t FDT_NOP = 0x4;
/// 数据区结束标记
- static constexpr const uint32_t FDT_END = 0x9;
+ static constexpr const uint32_t FDT_END = 0x9;
/// @see devicetree-specification-v0.3.pdf#5.1
/// 魔数
- static constexpr const uint32_t FDT_MAGIC = 0xD00DFEED;
+ static constexpr const uint32_t FDT_MAGIC = 0xD00DFEED;
/// 版本 17
- static constexpr const uint32_t FDT_VERSION = 0x11;
+ static constexpr const uint32_t FDT_VERSION = 0x11;
/**
* @brief fdt 格式头
@@ -114,20 +114,20 @@ class DTB {
/// 最大节点数
static constexpr const size_t MAX_NODES = 128;
/// 最大属性数
- static constexpr const size_t PROP_MAX = 16;
+ static constexpr const size_t PROP_MAX = 16;
/**
* @brief dtb 信息
*/
struct dtb_info_t {
/// dtb 头
- fdt_header_t *header;
+ fdt_header_t* header;
/// 保留区
- fdt_reserve_entry_t *reserved;
+ fdt_reserve_entry_t* reserved;
/// 数据区
- uintptr_t data;
+ uintptr_t data;
/// 字符区
- uintptr_t str;
+ uintptr_t str;
};
/**
@@ -135,11 +135,11 @@ class DTB {
*/
struct prop_t {
/// 属性名
- char *name;
+ char* name;
/// 属性地址
uintptr_t addr;
/// 属性长度
- size_t len;
+ size_t len;
};
/**
@@ -147,7 +147,7 @@ class DTB {
*/
struct path_t {
/// 当前路径
- char *path[MAX_DEPTH];
+ char* path[MAX_DEPTH];
/// 长度
size_t len;
/**
@@ -156,8 +156,8 @@ class DTB {
* @return true 相同
* @return false 不同
*/
- bool operator==(const path_t *_path);
- bool operator==(const char *_path);
+ bool operator==(const path_t* _path);
+ bool operator==(const char* _path);
};
/**
@@ -165,31 +165,31 @@ class DTB {
*/
struct node_t {
/// 节点路径
- path_t path;
+ path_t path;
/// 节点地址
- uint32_t *addr;
+ uint32_t* addr;
/// 父节点
- node_t *parent;
+ node_t* parent;
/// 中断父节点
- node_t *interrupt_parent;
+ node_t* interrupt_parent;
/// 1 cell == 4 bytes
/// 地址长度 单位为 bytes
- uint32_t address_cells;
+ uint32_t address_cells;
/// 长度长度 单位为 bytes
- uint32_t size_cells;
+ uint32_t size_cells;
/// 中断长度 单位为 bytes
- uint32_t interrupt_cells;
- uint32_t phandle;
+ uint32_t interrupt_cells;
+ uint32_t phandle;
/// 路径深度
- uint8_t depth;
+ uint8_t depth;
/// 属性
- prop_t props[PROP_MAX];
+ prop_t props[PROP_MAX];
/// 属性数
- size_t prop_count;
+ size_t prop_count;
/// 节点数
static size_t count;
/// 查找节点中的键值对
- bool find(const char *_prop_name, const char *_val);
+ bool find(const char* _prop_name, const char* _val);
};
/**
@@ -197,19 +197,19 @@ class DTB {
*/
struct iter_data_t {
/// 路径,不包括节点名
- path_t path;
+ path_t path;
/// 节点地址
- uint32_t *addr;
+ uint32_t* addr;
/// 节点类型
- uint32_t type;
+ uint32_t type;
/// 如果节点类型为 PROP, 保存节点属性名
- char *prop_name;
+ char* prop_name;
/// 如果节点类型为 PROP, 保存属性长度 单位为 byte
- uint32_t prop_len;
+ uint32_t prop_len;
/// 如果节点类型为 PROP, 保存属性地址
- uint32_t *prop_addr;
+ uint32_t* prop_addr;
/// 在 nodes 数组的下标
- uint8_t nodes_idx;
+ uint8_t nodes_idx;
};
// 部分属性及格式
@@ -244,7 +244,7 @@ class DTB {
*/
struct dt_prop_fmt_t {
/// 属性名
- char *prop_name;
+ char* prop_name;
/// 格式
enum dt_fmt_t fmt;
};
@@ -254,26 +254,26 @@ class DTB {
* @see 格式信息请查看 devicetree-specification-v0.3#2.3,#2.4 等部分
*/
static constexpr const dt_prop_fmt_t props[] = {
- {.prop_name = (char *)"", .fmt = FMT_EMPTY},
- {.prop_name = (char *)"compatible", .fmt = FMT_STRINGLIST},
- {.prop_name = (char *)"model", .fmt = FMT_STRING},
- {.prop_name = (char *)"phandle", .fmt = FMT_U32},
- {.prop_name = (char *)"status", .fmt = FMT_STRING},
- {.prop_name = (char *)"#address-cells", .fmt = FMT_U32},
- {.prop_name = (char *)"#size-cells", .fmt = FMT_U32},
- {.prop_name = (char *)"#interrupt-cells", .fmt = FMT_U32},
- {.prop_name = (char *)"reg", .fmt = FMT_REG},
- {.prop_name = (char *)"virtual-reg", .fmt = FMT_U32},
- {.prop_name = (char *)"ranges", .fmt = FMT_RANGES},
- {.prop_name = (char *)"dma-ranges", .fmt = FMT_RANGES},
- {.prop_name = (char *)"name", .fmt = FMT_STRING},
- {.prop_name = (char *)"device_type", .fmt = FMT_STRING},
- {.prop_name = (char *)"interrupts", .fmt = FMT_U32},
- {.prop_name = (char *)"interrupt-parent", .fmt = FMT_PHANDLE},
- {.prop_name = (char *)"interrupt-controller", .fmt = FMT_EMPTY},
- {.prop_name = (char *)"value", .fmt = FMT_U32},
- {.prop_name = (char *)"offset", .fmt = FMT_U32},
- {.prop_name = (char *)"regmap", .fmt = FMT_U32},
+ { .prop_name = (char*)"", .fmt = FMT_EMPTY},
+ { .prop_name = (char*)"compatible", .fmt = FMT_STRINGLIST},
+ { .prop_name = (char*)"model", .fmt = FMT_STRING},
+ { .prop_name = (char*)"phandle", .fmt = FMT_U32},
+ { .prop_name = (char*)"status", .fmt = FMT_STRING},
+ { .prop_name = (char*)"#address-cells", .fmt = FMT_U32},
+ { .prop_name = (char*)"#size-cells", .fmt = FMT_U32},
+ { .prop_name = (char*)"#interrupt-cells", .fmt = FMT_U32},
+ { .prop_name = (char*)"reg", .fmt = FMT_REG},
+ { .prop_name = (char*)"virtual-reg", .fmt = FMT_U32},
+ { .prop_name = (char*)"ranges", .fmt = FMT_RANGES},
+ { .prop_name = (char*)"dma-ranges", .fmt = FMT_RANGES},
+ { .prop_name = (char*)"name", .fmt = FMT_STRING},
+ { .prop_name = (char*)"device_type", .fmt = FMT_STRING},
+ { .prop_name = (char*)"interrupts", .fmt = FMT_U32},
+ { .prop_name = (char*)"interrupt-parent", .fmt = FMT_PHANDLE},
+ {.prop_name = (char*)"interrupt-controller", .fmt = FMT_EMPTY},
+ { .prop_name = (char*)"value", .fmt = FMT_U32},
+ { .prop_name = (char*)"offset", .fmt = FMT_U32},
+ { .prop_name = (char*)"regmap", .fmt = FMT_U32},
};
/**
@@ -281,29 +281,29 @@ class DTB {
* @param _prop_name 要查找的属性
* @return dt_fmt_t 在 dt_fmt_t 中的索引
*/
- dt_fmt_t get_fmt(const char *_prop_name);
+ dt_fmt_t get_fmt(const char* _prop_name);
/**
* @brief phandles 与 node 的映射关系
*/
struct phandle_map_t {
- uint32_t phandle;
- node_t *node;
+ uint32_t phandle;
+ node_t* node;
/// phandle 数量
static size_t count;
};
/// dtb 信息
- static dtb_info_t dtb_info;
+ static dtb_info_t dtb_info;
/// 节点数组
- static node_t nodes[MAX_NODES];
+ static node_t nodes[MAX_NODES];
/// phandle 数组
static phandle_map_t phandle_map[MAX_NODES];
/**
* @brief 输出 reserved 内存
*/
- void dtb_mem_reserved(void);
+ void dtb_mem_reserved(void);
/**
* @brief 迭代函数
@@ -312,15 +312,15 @@ class DTB {
* @param _data 要传递的数据
* @param _addr dtb 数据地址
*/
- void dtb_iter(uint8_t _cb_flags, bool (*_cb)(const iter_data_t *, void *),
- void *_data, uintptr_t _addr = dtb_info.data);
+ void dtb_iter(uint8_t _cb_flags, bool (*_cb)(const iter_data_t*, void*),
+ void* _data, uintptr_t _addr = dtb_info.data);
/**
* @brief 查找 phandle 映射
* @param _phandle 要查找的 phandle
* @return node_t* _phandle 指向的节点
*/
- node_t *get_phandle(uint32_t _phandle);
+ node_t* get_phandle(uint32_t _phandle);
/**
* @brief 初始化节点
@@ -329,7 +329,7 @@ class DTB {
* @return true 成功
* @return false 失败
*/
- static bool dtb_init_cb(const iter_data_t *_iter, void *_data);
+ static bool dtb_init_cb(const iter_data_t* _iter, void* _data);
/**
* @brief 初始化中断信息
@@ -338,7 +338,7 @@ class DTB {
* @return true 成功
* @return false 失败
*/
- static bool dtb_init_interrupt_cb(const iter_data_t *_iter, void *_data);
+ static bool dtb_init_interrupt_cb(const iter_data_t* _iter, void* _data);
/**
* @brief 输出不定长度的数据
@@ -347,8 +347,8 @@ class DTB {
* @param _len 长度
* @todo 补充说明
*/
- void print_attr_propenc(const iter_data_t *_iter, size_t *_cells,
- size_t _len);
+ void
+ print_attr_propenc(const iter_data_t* _iter, size_t* _cells, size_t _len);
/**
* @brief 填充 resource_t
@@ -356,38 +356,39 @@ class DTB {
* @param _node 源节点
* @param _prop 填充的数据
*/
- void fill_resource(resource_t *_resource, const node_t *_node,
- const prop_t *_prop);
+ void fill_resource(resource_t* _resource, const node_t* _node,
+ const prop_t* _prop);
/**
* @brief 通过路径寻找节点
* @param _path 路径
* @return node_t* 找到的节点
*/
- node_t *find_node_via_path(const char *_path);
+ node_t* find_node_via_path(const char* _path);
protected:
+
public:
// 用于控制处理哪些属性
/// 处理节点开始
static constexpr const uint8_t DT_ITER_BEGIN_NODE = 0x01;
/// 处理节点结束
- static constexpr const uint8_t DT_ITER_END_NODE = 0x02;
+ static constexpr const uint8_t DT_ITER_END_NODE = 0x02;
/// 处理节点属性
- static constexpr const uint8_t DT_ITER_PROP = 0x04;
+ static constexpr const uint8_t DT_ITER_PROP = 0x04;
/**
* @brief 获取单例
* @return DTB& 静态对象
*/
- static DTB &get_instance(void);
+ static DTB& get_instance(void);
/**
* @brief 初始化
* @return true 成功
* @return false 失败
*/
- bool dtb_init(void);
+ bool dtb_init(void);
/**
* @brief 根据路径查找节点,返回使用的资源
@@ -396,7 +397,7 @@ class DTB {
* @return true 成功
* @return false 失败
*/
- bool find_via_path(const char *_path, resource_t *_resource);
+ bool find_via_path(const char* _path, resource_t* _resource);
/**
* @brief 根据节点名进行前缀查找
@@ -405,7 +406,7 @@ class DTB {
* @return size_t _resource 长度
* @note 根据节点 @ 前的名称查找,可能返回多个 resource
*/
- size_t find_via_prefix(const char *_prefix, resource_t *_resource);
+ size_t find_via_prefix(const char* _prefix, resource_t* _resource);
/**
* @brief iter 输出
@@ -413,20 +414,15 @@ class DTB {
* @param _iter 要输出的 iter
* @return std::ostream& 输出流
*/
- friend std::ostream &operator<<(std::ostream &_os,
- const iter_data_t &_iter);
+ friend std::ostream&
+ operator<<(std::ostream& _os, const iter_data_t& _iter);
/**
* @brief 路径输出
* @param _os 输出流
* @param _path 要输出的 path
* @return std::ostream& 输出流
*/
- friend std::ostream &operator<<(std::ostream &_os, const path_t &_path);
+ friend std::ostream& operator<<(std::ostream& _os, const path_t& _path);
};
-namespace BOOT_INFO {
-/// 保存 sbi 传递的启动核
-extern "C" size_t dtb_init_hart;
-}; // namespace BOOT_INFO
-
-#endif /* _DTB_H_ */
+#endif /* SIMPLEKERNEL_DTB_H */
diff --git a/src/drv/keyboard/include/keyboard.h b/src/drv/keyboard/include/keyboard.h
index c9aac3162..eecd1b0c7 100644
--- a/src/drv/keyboard/include/keyboard.h
+++ b/src/drv/keyboard/include/keyboard.h
@@ -18,7 +18,7 @@
#ifndef _KEYBOARD_H_
#define _KEYBOARD_H_
-#include "stdint.h"
+#include "cstdint"
#include "intr.h"
/**
@@ -27,27 +27,27 @@
class KEYBOARD {
private:
/// 键盘缓冲区大小
- static constexpr const uint32_t KB_BUFSIZE = 128;
+ static constexpr const uint32_t KB_BUFSIZE = 128;
- static constexpr const uint32_t KB_DATA = 0x60;
- static constexpr const uint32_t KB_WRITE = 0x60;
- static constexpr const uint32_t KB_STATUS = 0x64;
- static constexpr const uint32_t KB_CMD = 0x64;
+ static constexpr const uint32_t KB_DATA = 0x60;
+ static constexpr const uint32_t KB_WRITE = 0x60;
+ static constexpr const uint32_t KB_STATUS = 0x64;
+ static constexpr const uint32_t KB_CMD = 0x64;
/// 特殊键的扫描码
- static constexpr const uint32_t KB_BACKSPACE = 0x0E;
- static constexpr const uint32_t KB_ENTER = 0x1C;
- static constexpr const uint32_t KB_TAB = 0x0F;
- static constexpr const uint32_t KB_ESC = 0x01;
- static constexpr const uint32_t KB_SHIFT_L = 0x2A;
- static constexpr const uint32_t KB_SHIFT_R = 0x36;
- static constexpr const uint32_t KB_ALT_L = 0x38;
- static constexpr const uint32_t KB_CAPS_LOCK = 0x3A;
- static constexpr const uint32_t KB_CTRL_L = 0x1D;
- static constexpr const uint32_t KB_NUM_LOCK = 0x45;
+ static constexpr const uint32_t KB_BACKSPACE = 0x0E;
+ static constexpr const uint32_t KB_ENTER = 0x1C;
+ static constexpr const uint32_t KB_TAB = 0x0F;
+ static constexpr const uint32_t KB_ESC = 0x01;
+ static constexpr const uint32_t KB_SHIFT_L = 0x2A;
+ static constexpr const uint32_t KB_SHIFT_R = 0x36;
+ static constexpr const uint32_t KB_ALT_L = 0x38;
+ static constexpr const uint32_t KB_CAPS_LOCK = 0x3A;
+ static constexpr const uint32_t KB_CTRL_L = 0x1D;
+ static constexpr const uint32_t KB_NUM_LOCK = 0x45;
/// Number of columns in keyma
- static constexpr const uint32_t MAP_COLS = 3;
+ static constexpr const uint32_t MAP_COLS = 3;
/// Number of scan codes (rows in keymap)
static constexpr const uint32_t NR_SCAN_CODES = 0x80;
static constexpr const uint32_t SC_MAX = NR_SCAN_CODES * MAP_COLS;
@@ -58,164 +58,164 @@ class KEYBOARD {
static constexpr const uint32_t RELEASED_MASK = 0x80;
/// Normal function keys
- static constexpr const uint32_t FLAG_EXT = 0x00;
+ static constexpr const uint32_t FLAG_EXT = 0x00;
/// Special keys
/// Esc
- static constexpr const uint32_t ESC = (0x01 & FLAG_EXT);
+ static constexpr const uint32_t ESC = (0x01 & FLAG_EXT);
/// Tab
- static constexpr const uint32_t TAB = (0x02 & FLAG_EXT);
+ static constexpr const uint32_t TAB = (0x02 & FLAG_EXT);
/// Enter
- static constexpr const uint32_t ENTER = (0x03 & FLAG_EXT);
+ static constexpr const uint32_t ENTER = (0x03 & FLAG_EXT);
/// BackSpace
- static constexpr const uint32_t BACKSPACE = (0x04 & FLAG_EXT);
+ static constexpr const uint32_t BACKSPACE = (0x04 & FLAG_EXT);
/// L GUI
- static constexpr const uint32_t GUI_L = (0x05 & FLAG_EXT);
+ static constexpr const uint32_t GUI_L = (0x05 & FLAG_EXT);
/// R GUI
- static constexpr const uint32_t GUI_R = (0x06 & FLAG_EXT);
+ static constexpr const uint32_t GUI_R = (0x06 & FLAG_EXT);
/// APPS
- static constexpr const uint32_t APPS = (0x07 & FLAG_EXT);
+ static constexpr const uint32_t APPS = (0x07 & FLAG_EXT);
/// Shift, Ctrl, Alt
/// L Shift
- static constexpr const uint32_t SHIFT_L = (0x08 & FLAG_EXT);
+ static constexpr const uint32_t SHIFT_L = (0x08 & FLAG_EXT);
/// R Shift
- static constexpr const uint32_t SHIFT_R = (0x09 & FLAG_EXT);
+ static constexpr const uint32_t SHIFT_R = (0x09 & FLAG_EXT);
/// L Ctrl
- static constexpr const uint32_t CTRL_L = (0x0A & FLAG_EXT);
+ static constexpr const uint32_t CTRL_L = (0x0A & FLAG_EXT);
/// R Ctrl
- static constexpr const uint32_t CTRL_R = (0x0B & FLAG_EXT);
+ static constexpr const uint32_t CTRL_R = (0x0B & FLAG_EXT);
/// L Alt
- static constexpr const uint32_t ALT_L = (0x0C & FLAG_EXT);
+ static constexpr const uint32_t ALT_L = (0x0C & FLAG_EXT);
/// R Alt
- static constexpr const uint32_t ALT_R = (0x0D & FLAG_EXT);
+ static constexpr const uint32_t ALT_R = (0x0D & FLAG_EXT);
/// Lock keys
/// Caps Lock
- static constexpr const uint32_t CAPS_LOCK = (0x0E & FLAG_EXT);
+ static constexpr const uint32_t CAPS_LOCK = (0x0E & FLAG_EXT);
/// Number Lock
- static constexpr const uint32_t NUM_LOCK = (0x0F & FLAG_EXT);
+ static constexpr const uint32_t NUM_LOCK = (0x0F & FLAG_EXT);
/// Scroll Lock
- static constexpr const uint32_t SCROLL_LOCK = (0x10 & FLAG_EXT);
+ static constexpr const uint32_t SCROLL_LOCK = (0x10 & FLAG_EXT);
/// Function keys
/// F1
- static constexpr const uint32_t F1 = (0x11 & FLAG_EXT);
+ static constexpr const uint32_t F1 = (0x11 & FLAG_EXT);
/// F2
- static constexpr const uint32_t F2 = (0x12 & FLAG_EXT);
+ static constexpr const uint32_t F2 = (0x12 & FLAG_EXT);
/// F3
- static constexpr const uint32_t F3 = (0x13 & FLAG_EXT);
+ static constexpr const uint32_t F3 = (0x13 & FLAG_EXT);
/// F4
- static constexpr const uint32_t F4 = (0x14 & FLAG_EXT);
+ static constexpr const uint32_t F4 = (0x14 & FLAG_EXT);
/// F5
- static constexpr const uint32_t F5 = (0x15 & FLAG_EXT);
+ static constexpr const uint32_t F5 = (0x15 & FLAG_EXT);
/// F6
- static constexpr const uint32_t F6 = (0x16 & FLAG_EXT);
+ static constexpr const uint32_t F6 = (0x16 & FLAG_EXT);
/// F7
- static constexpr const uint32_t F7 = (0x17 & FLAG_EXT);
+ static constexpr const uint32_t F7 = (0x17 & FLAG_EXT);
/// F8
- static constexpr const uint32_t F8 = (0x18 & FLAG_EXT);
+ static constexpr const uint32_t F8 = (0x18 & FLAG_EXT);
/// F9
- static constexpr const uint32_t F9 = (0x19 & FLAG_EXT);
+ static constexpr const uint32_t F9 = (0x19 & FLAG_EXT);
/// F10
- static constexpr const uint32_t F10 = (0x1A & FLAG_EXT);
+ static constexpr const uint32_t F10 = (0x1A & FLAG_EXT);
/// F11
- static constexpr const uint32_t F11 = (0x1B & FLAG_EXT);
+ static constexpr const uint32_t F11 = (0x1B & FLAG_EXT);
/// F12
- static constexpr const uint32_t F12 = (0x1C & FLAG_EXT);
+ static constexpr const uint32_t F12 = (0x1C & FLAG_EXT);
/// Control Pad
/// Print Screen
- static constexpr const uint32_t PRINTSCREEN = (0x1D & FLAG_EXT);
+ static constexpr const uint32_t PRINTSCREEN = (0x1D & FLAG_EXT);
/// Pause/Break
- static constexpr const uint32_t PAUSEBREAK = (0x1E & FLAG_EXT);
+ static constexpr const uint32_t PAUSEBREAK = (0x1E & FLAG_EXT);
/// Insert
- static constexpr const uint32_t INSERT = (0x1F & FLAG_EXT);
+ static constexpr const uint32_t INSERT = (0x1F & FLAG_EXT);
/// Delete
- static constexpr const uint32_t DELETE = (0x20 & FLAG_EXT);
+ static constexpr const uint32_t DELETE = (0x20 & FLAG_EXT);
/// Home
- static constexpr const uint32_t HOME = (0x21 & FLAG_EXT);
+ static constexpr const uint32_t HOME = (0x21 & FLAG_EXT);
/// End
- static constexpr const uint32_t END = (0x22 & FLAG_EXT);
+ static constexpr const uint32_t END = (0x22 & FLAG_EXT);
/// Page Up
- static constexpr const uint32_t PAGEUP = (0x23 & FLAG_EXT);
+ static constexpr const uint32_t PAGEUP = (0x23 & FLAG_EXT);
/// Page Down
- static constexpr const uint32_t PAGEDOWN = (0x24 & FLAG_EXT);
+ static constexpr const uint32_t PAGEDOWN = (0x24 & FLAG_EXT);
/// Up
- static constexpr const uint32_t UP = (0x25 & FLAG_EXT);
+ static constexpr const uint32_t UP = (0x25 & FLAG_EXT);
/// Down
- static constexpr const uint32_t DOWN = (0x26 & FLAG_EXT);
+ static constexpr const uint32_t DOWN = (0x26 & FLAG_EXT);
/// Left
- static constexpr const uint32_t LEFT = (0x27 & FLAG_EXT);
+ static constexpr const uint32_t LEFT = (0x27 & FLAG_EXT);
/// Right
- static constexpr const uint32_t RIGHT = (0x28 & FLAG_EXT);
+ static constexpr const uint32_t RIGHT = (0x28 & FLAG_EXT);
/// ACPI keys
/// Power
- static constexpr const uint32_t POWER = (0x29 & FLAG_EXT);
+ static constexpr const uint32_t POWER = (0x29 & FLAG_EXT);
/// Sleep
- static constexpr const uint32_t SLEEP = (0x2A & FLAG_EXT);
+ static constexpr const uint32_t SLEEP = (0x2A & FLAG_EXT);
/// Wake Up
- static constexpr const uint32_t WAKE = (0x2B & FLAG_EXT);
+ static constexpr const uint32_t WAKE = (0x2B & FLAG_EXT);
/// Num Pad
/// /
- static constexpr const uint32_t PAD_SLASH = (0x2C & FLAG_EXT);
+ static constexpr const uint32_t PAD_SLASH = (0x2C & FLAG_EXT);
/// *
- static constexpr const uint32_t PAD_STAR = (0x2D & FLAG_EXT);
+ static constexpr const uint32_t PAD_STAR = (0x2D & FLAG_EXT);
/// -
- static constexpr const uint32_t PAD_MINUS = (0x2E & FLAG_EXT);
+ static constexpr const uint32_t PAD_MINUS = (0x2E & FLAG_EXT);
/// &
- static constexpr const uint32_t PAD_PLUS = (0x2F & FLAG_EXT);
+ static constexpr const uint32_t PAD_PLUS = (0x2F & FLAG_EXT);
/// Enter
- static constexpr const uint32_t PAD_ENTER = (0x30 & FLAG_EXT);
+ static constexpr const uint32_t PAD_ENTER = (0x30 & FLAG_EXT);
/// .
- static constexpr const uint32_t PAD_DOT = (0x31 & FLAG_EXT);
+ static constexpr const uint32_t PAD_DOT = (0x31 & FLAG_EXT);
/// 0
- static constexpr const uint32_t PAD_0 = (0x32 & FLAG_EXT);
+ static constexpr const uint32_t PAD_0 = (0x32 & FLAG_EXT);
/// 1
- static constexpr const uint32_t PAD_1 = (0x33 & FLAG_EXT);
+ static constexpr const uint32_t PAD_1 = (0x33 & FLAG_EXT);
/// 2
- static constexpr const uint32_t PAD_2 = (0x34 & FLAG_EXT);
+ static constexpr const uint32_t PAD_2 = (0x34 & FLAG_EXT);
/// 3
- static constexpr const uint32_t PAD_3 = (0x35 & FLAG_EXT);
+ static constexpr const uint32_t PAD_3 = (0x35 & FLAG_EXT);
/// 4
- static constexpr const uint32_t PAD_4 = (0x36 & FLAG_EXT);
+ static constexpr const uint32_t PAD_4 = (0x36 & FLAG_EXT);
/// 5
- static constexpr const uint32_t PAD_5 = (0x37 & FLAG_EXT);
+ static constexpr const uint32_t PAD_5 = (0x37 & FLAG_EXT);
/// 6
- static constexpr const uint32_t PAD_6 = (0x38 & FLAG_EXT);
+ static constexpr const uint32_t PAD_6 = (0x38 & FLAG_EXT);
/// 7
- static constexpr const uint32_t PAD_7 = (0x39 & FLAG_EXT);
+ static constexpr const uint32_t PAD_7 = (0x39 & FLAG_EXT);
/// 8
- static constexpr const uint32_t PAD_8 = (0x3A & FLAG_EXT);
+ static constexpr const uint32_t PAD_8 = (0x3A & FLAG_EXT);
/// 9
- static constexpr const uint32_t PAD_9 = (0x3B & FLAG_EXT);
+ static constexpr const uint32_t PAD_9 = (0x3B & FLAG_EXT);
/// Up
- static constexpr const uint32_t PAD_UP = PAD_8;
+ static constexpr const uint32_t PAD_UP = PAD_8;
/// Down
- static constexpr const uint32_t PAD_DOWN = PAD_2;
+ static constexpr const uint32_t PAD_DOWN = PAD_2;
/// Left
- static constexpr const uint32_t PAD_LEFT = PAD_4;
+ static constexpr const uint32_t PAD_LEFT = PAD_4;
/// Right
- static constexpr const uint32_t PAD_RIGHT = PAD_6;
+ static constexpr const uint32_t PAD_RIGHT = PAD_6;
/// Home
- static constexpr const uint32_t PAD_HOME = PAD_7;
+ static constexpr const uint32_t PAD_HOME = PAD_7;
/// End
- static constexpr const uint32_t PAD_END = PAD_1;
+ static constexpr const uint32_t PAD_END = PAD_1;
/// Page Up
- static constexpr const uint32_t PAD_PAGEUP = PAD_9;
+ static constexpr const uint32_t PAD_PAGEUP = PAD_9;
/// Page Down
- static constexpr const uint32_t PAD_PAGEDOWN = PAD_3;
+ static constexpr const uint32_t PAD_PAGEDOWN = PAD_3;
/// Ins
- static constexpr const uint32_t PAD_INS = PAD_0;
+ static constexpr const uint32_t PAD_INS = PAD_0;
/// Middle key
- static constexpr const uint32_t PAD_MID = PAD_5;
+ static constexpr const uint32_t PAD_MID = PAD_5;
/// Del
- static constexpr const uint32_t PAD_DEL = PAD_DOT;
+ static constexpr const uint32_t PAD_DEL = PAD_DOT;
/// 键盘映射
- static constexpr const uint8_t keymap[NR_SCAN_CODES * MAP_COLS] = {
+ static constexpr const uint8_t keymap[NR_SCAN_CODES * MAP_COLS] = {
/* scan-code !Shift Shift E0 XX
*/
/* ====================================================================
@@ -612,6 +612,7 @@ class KEYBOARD {
bool alt;
protected:
+
public:
KEYBOARD(void);
~KEYBOARD(void);
@@ -620,26 +621,26 @@ class KEYBOARD {
* @brief 获取单例
* @return KEYBOARD& 静态对象
*/
- static KEYBOARD &get_instance(void);
+ static KEYBOARD& get_instance(void);
/**
* @brief 初始化
* @return int32_t 成功返回 0
*/
- int32_t init(void);
+ int32_t init(void);
/**
* @brief 从键盘读
* @return uint8_t 读到的数据
*/
- uint8_t read(void);
+ uint8_t read(void);
/**
* @brief 设置键盘中断处理函数
* @param _h 处理函数
* @return int32_t 设置成功返回 0
*/
- int32_t set_handle(INTR::interrupt_handler_t _h);
+ int32_t set_handle(INTR::interrupt_handler_t _h);
};
#endif /* _KEYBOARD_H_ */
diff --git a/src/drv/keyboard/keyboard.cpp b/src/drv/keyboard/keyboard.cpp
index 3813d8f26..1eb116afb 100644
--- a/src/drv/keyboard/keyboard.cpp
+++ b/src/drv/keyboard/keyboard.cpp
@@ -15,16 +15,14 @@
*
*/
-#include "stddef.h"
-#include "stdbool.h"
-#include "io.h"
-#include "stdio.h"
#include "keyboard.h"
+#include "cstdio"
+#include "io.h"
/**
* @brief 默认处理函数
*/
-static void default_keyboard_handle(INTR::intr_context_t *) {
+static void default_keyboard_handle(INTR::intr_context_t*) {
KEYBOARD::get_instance().read();
return;
}
@@ -113,7 +111,7 @@ uint8_t KEYBOARD::read(void) {
return letter;
}
-KEYBOARD &KEYBOARD::get_instance(void) {
+KEYBOARD& KEYBOARD::get_instance(void) {
/// 定义全局 KEYBOARD 对象
static KEYBOARD keyboard;
return keyboard;
diff --git a/src/drv/multiboot2/include/multiboot2.h b/src/drv/multiboot2/include/multiboot2.h
index 22de1d9b7..62b077ad3 100644
--- a/src/drv/multiboot2/include/multiboot2.h
+++ b/src/drv/multiboot2/include/multiboot2.h
@@ -14,12 +14,12 @@
*
*/
-#ifndef _MULTIBOOT2_H_
-#define _MULTIBOOT2_H_
+#ifndef SIMPLEKERNEL_MULTIBOOT2_H
+#define SIMPLEKERNEL_MULTIBOOT2_H
-#include "stdint.h"
-#include "stdbool.h"
#include "boot_info.h"
+#include "cstdbool"
+#include "cstdint"
/// @see Multiboot2 Specification version 2.0.pdf
// 启动后,在 32 位内核进入点,机器状态如下:
@@ -39,26 +39,26 @@
class MULTIBOOT2 {
private:
/* How many bytes from the start of the file we search for the header. */
- static constexpr const uint32_t MULTIBOOT_SEARCH = 32768;
- static constexpr const uint32_t MULTIBOOT_HEADER_ALIGN = 8;
+ static constexpr const uint32_t MULTIBOOT_SEARCH = 32768;
+ static constexpr const uint32_t MULTIBOOT_HEADER_ALIGN = 8;
/* The magic field should contain this. */
- static constexpr const uint32_t MULTIBOOT2_HEADER_MAGIC = 0xe85250d6;
+ static constexpr const uint32_t MULTIBOOT2_HEADER_MAGIC = 0xe85250d6;
/* This should be in %eax. */
static constexpr const uint32_t MULTIBOOT2_BOOTLOADER_MAGIC = 0x36d76289;
/* Alignment of multiboot modules. */
- static constexpr const uint32_t MULTIBOOT_MOD_ALIGN = 0x00001000;
+ static constexpr const uint32_t MULTIBOOT_MOD_ALIGN = 0x00001000;
/* Alignment of the multiboot info structure. */
- static constexpr const uint32_t MULTIBOOT_INFO_ALIGN = 0x00000008;
+ static constexpr const uint32_t MULTIBOOT_INFO_ALIGN = 0x00000008;
/* Flags set in the 'flags' member of the multiboot header. */
- static constexpr const uint32_t MULTIBOOT_TAG_ALIGN = 8;
- static constexpr const uint32_t MULTIBOOT_TAG_TYPE_END = 0;
- static constexpr const uint32_t MULTIBOOT_TAG_TYPE_CMDLINE = 1;
+ static constexpr const uint32_t MULTIBOOT_TAG_ALIGN = 8;
+ static constexpr const uint32_t MULTIBOOT_TAG_TYPE_END = 0;
+ static constexpr const uint32_t MULTIBOOT_TAG_TYPE_CMDLINE = 1;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME = 2;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_MODULE = 3;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_BASIC_MEMINFO = 4;
@@ -80,33 +80,33 @@ class MULTIBOOT2 {
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_EFI64_IH = 20;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR = 21;
- static constexpr const uint32_t MULTIBOOT_HEADER_TAG_END = 0;
- static constexpr const uint32_t MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST =
- 1;
+ static constexpr const uint32_t MULTIBOOT_HEADER_TAG_END = 0;
+ static constexpr const uint32_t MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST
+ = 1;
static constexpr const uint32_t MULTIBOOT_HEADER_TAG_ADDRESS = 2;
static constexpr const uint32_t MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS = 3;
static constexpr const uint32_t MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS = 4;
static constexpr const uint32_t MULTIBOOT_HEADER_TAG_FRAMEBUFFER = 5;
static constexpr const uint32_t MULTIBOOT_HEADER_TAG_MODULE_ALIGN = 6;
static constexpr const uint32_t MULTIBOOT_HEADER_TAG_EFI_BS = 7;
- static constexpr const uint32_t MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 =
- 8;
- static constexpr const uint32_t MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 =
- 9;
+ static constexpr const uint32_t MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32
+ = 8;
+ static constexpr const uint32_t MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64
+ = 9;
static constexpr const uint32_t MULTIBOOT_HEADER_TAG_RELOCATABLE = 10;
- static constexpr const uint32_t MULTIBOOT_ARCHITECTURE_I386 = 0;
- static constexpr const uint32_t MULTIBOOT_ARCHITECTURE_MIPS32 = 4;
- static constexpr const uint32_t MULTIBOOT_HEADER_TAG_OPTIONAL = 1;
+ static constexpr const uint32_t MULTIBOOT_ARCHITECTURE_I386 = 0;
+ static constexpr const uint32_t MULTIBOOT_ARCHITECTURE_MIPS32 = 4;
+ static constexpr const uint32_t MULTIBOOT_HEADER_TAG_OPTIONAL = 1;
- static constexpr const uint32_t MULTIBOOT_LOAD_PREFERENCE_NONE = 0;
- static constexpr const uint32_t MULTIBOOT_LOAD_PREFERENCE_LOW = 1;
- static constexpr const uint32_t MULTIBOOT_LOAD_PREFERENCE_HIGH = 2;
+ static constexpr const uint32_t MULTIBOOT_LOAD_PREFERENCE_NONE = 0;
+ static constexpr const uint32_t MULTIBOOT_LOAD_PREFERENCE_LOW = 1;
+ static constexpr const uint32_t MULTIBOOT_LOAD_PREFERENCE_HIGH = 2;
- static constexpr const uint32_t MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED =
- 1;
- static constexpr const uint32_t MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED =
- 2;
+ static constexpr const uint32_t MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED
+ = 1;
+ static constexpr const uint32_t MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED
+ = 2;
struct multiboot_header_t {
// Must be MULTIBOOT_MAGIC - see above.
@@ -172,6 +172,7 @@ class MULTIBOOT2 {
static constexpr const uint32_t MULTIBOOT_MEMORY_ACPI_RECLAIMABLE = 3;
static constexpr const uint32_t MULTIBOOT_MEMORY_NVS = 4;
static constexpr const uint32_t MULTIBOOT_MEMORY_BADRAM = 5;
+
struct multiboot_mmap_entry_t {
uint64_t addr;
uint64_t len;
@@ -220,10 +221,10 @@ class MULTIBOOT2 {
};
struct multiboot_tag_vbe_t : multiboot_tag_t {
- uint16_t vbe_mode;
- uint16_t vbe_interface_seg;
- uint16_t vbe_interface_off;
- uint16_t vbe_interface_len;
+ uint16_t vbe_mode;
+ uint16_t vbe_interface_seg;
+ uint16_t vbe_interface_off;
+ uint16_t vbe_interface_len;
multiboot_vbe_info_block_t vbe_control_info;
multiboot_vbe_mode_info_block_t vbe_mode_info;
@@ -306,22 +307,21 @@ class MULTIBOOT2 {
* @brief 获取单例
* @return MULTIBOOT2& 静态对象
*/
- static MULTIBOOT2 &get_instance(void);
+ static MULTIBOOT2& get_instance(void);
/**
* @brief 初始化
* @return true 成功
* @return false 失败
*/
- bool multiboot2_init(void);
+ bool multiboot2_init(void);
/**
* @brief 迭代器
* @param _fun 迭代操作
* @param _data 数据
*/
- void multiboot2_iter(bool (*_fun)(const iter_data_t *, void *),
- void *_data);
+ void multiboot2_iter(bool (*_fun)(const iter_data_t*, void*), void* _data);
/**
* @brief 获取内存信息
@@ -330,12 +330,12 @@ class MULTIBOOT2 {
* @return true 成功
* @return false 失败
*/
- static bool get_memory(const iter_data_t *_iter_data, void *_data);
+ static bool get_memory(const iter_data_t* _iter_data, void* _data);
};
namespace BOOT_INFO {
/// 魔数
extern "C" uint32_t multiboot2_magic;
-}; // namespace BOOT_INFO
+}; // namespace BOOT_INFO
-#endif /* _MULTIBOOT2_H_ */
+#endif /* SIMPLEKERNEL_MULTIBOOT2_H */
diff --git a/src/drv/multiboot2/multiboot2.cpp b/src/drv/multiboot2/multiboot2.cpp
index d4f603b0a..463a3dedb 100644
--- a/src/drv/multiboot2/multiboot2.cpp
+++ b/src/drv/multiboot2/multiboot2.cpp
@@ -14,14 +14,14 @@
*
*/
-#include "assert.h"
-#include "stdio.h"
-#include "common.h"
#include "multiboot2.h"
#include "boot_info.h"
+#include "cassert"
+#include "common.h"
+#include "cstdio"
#include "resource.h"
-MULTIBOOT2 &MULTIBOOT2::get_instance(void) {
+MULTIBOOT2& MULTIBOOT2::get_instance(void) {
/// 定义全局 MULTIBOOT2 对象
static MULTIBOOT2 multiboot2;
return multiboot2;
@@ -33,18 +33,18 @@ bool MULTIBOOT2::multiboot2_init(void) {
assert(BOOT_INFO::multiboot2_magic == MULTIBOOT2_BOOTLOADER_MAGIC);
assert((reinterpret_cast(addr) & 7) == 0);
// addr+0 保存大小
- BOOT_INFO::boot_info_size = *(uint32_t *)addr;
+ BOOT_INFO::boot_info_size = *(uint32_t*)addr;
return true;
}
/// @todo 优化
-void MULTIBOOT2::multiboot2_iter(bool (*_fun)(const iter_data_t *, void *),
- void *_data) {
- uintptr_t addr = BOOT_INFO::boot_info_addr;
+void MULTIBOOT2::multiboot2_iter(bool (*_fun)(const iter_data_t*, void*),
+ void* _data) {
+ uintptr_t addr = BOOT_INFO::boot_info_addr;
// 下一字节开始为 tag 信息
- iter_data_t *tag = (iter_data_t *)(addr + 8);
+ iter_data_t* tag = (iter_data_t*)(addr + 8);
for (; tag->type != MULTIBOOT_TAG_TYPE_END;
- tag = (iter_data_t *)((uint8_t *)tag + COMMON::ALIGN(tag->size, 8))) {
+ tag = (iter_data_t*)((uint8_t*)tag + COMMON::ALIGN(tag->size, 8))) {
if (_fun(tag, _data) == true) {
return;
}
@@ -61,26 +61,28 @@ void MULTIBOOT2::multiboot2_iter(bool (*_fun)(const iter_data_t *, void *),
// 0x100000(0x7EF0000) 0x1
// 0x7FF0000(0x10000) 0x3
// 0xFFFC0000(0x40000) 0x2
-bool MULTIBOOT2::get_memory(const iter_data_t *_iter_data, void *_data) {
+bool MULTIBOOT2::get_memory(const iter_data_t* _iter_data, void* _data) {
if (_iter_data->type != MULTIBOOT2::MULTIBOOT_TAG_TYPE_MMAP) {
return false;
}
- resource_t *resource = (resource_t *)_data;
- resource->type |= resource_t::MEM;
- resource->name = (char *)"available phy memory";
- resource->mem.addr = 0x0;
- resource->mem.len = 0;
- MULTIBOOT2::multiboot_mmap_entry_t *mmap =
- ((MULTIBOOT2::multiboot_tag_mmap_t *)_iter_data)->entries;
- for (; (uint8_t *)mmap < (uint8_t *)_iter_data + _iter_data->size;
- mmap = (MULTIBOOT2::multiboot_mmap_entry_t
- *)((uint8_t *)mmap +
- ((MULTIBOOT2::multiboot_tag_mmap_t *)_iter_data)
- ->entry_size)) {
+ resource_t* resource = (resource_t*)_data;
+ resource->type |= resource_t::MEM;
+ resource->name = (char*)"available phy memory";
+ resource->mem.addr = 0x0;
+ resource->mem.len = 0;
+ MULTIBOOT2::multiboot_mmap_entry_t* mmap
+ = ((MULTIBOOT2::multiboot_tag_mmap_t*)_iter_data)->entries;
+ for (; (uint8_t*)mmap < (uint8_t*)_iter_data + _iter_data->size;
+ mmap
+ = (MULTIBOOT2::
+ multiboot_mmap_entry_t*)((uint8_t*)mmap
+ + ((MULTIBOOT2::multiboot_tag_mmap_t*)
+ _iter_data)
+ ->entry_size)) {
// 如果是可用内存或地址小于 1M
// 这里将 0~1M 的空间全部算为可用,在 c++ 库可用后进行优化
- if (mmap->type == MULTIBOOT_MEMORY_AVAILABLE ||
- mmap->addr < 1 * COMMON::MB) {
+ if (mmap->type == MULTIBOOT_MEMORY_AVAILABLE
+ || mmap->addr < 1 * COMMON::MB) {
// 长度+
resource->mem.len += mmap->len;
}
@@ -92,13 +94,13 @@ namespace BOOT_INFO {
// 地址
uintptr_t boot_info_addr;
// 长度
-size_t boot_info_size;
+size_t boot_info_size;
// 魔数
-uint32_t multiboot2_magic;
+uint32_t multiboot2_magic;
-bool inited = false;
+bool inited = false;
-bool init(void) {
+bool init(void) {
auto res = MULTIBOOT2::get_instance().multiboot2_init();
if (inited == false) {
inited = true;
@@ -116,4 +118,4 @@ resource_t get_memory(void) {
&resource);
return resource;
}
-}; // namespace BOOT_INFO
+}; // namespace BOOT_INFO
diff --git a/src/drv/opensbi/include/opensbi.h b/src/drv/opensbi/include/opensbi.h
index b2d449145..c02b641a1 100644
--- a/src/drv/opensbi/include/opensbi.h
+++ b/src/drv/opensbi/include/opensbi.h
@@ -14,10 +14,10 @@
*
*/
-#ifndef _OPENSBI_H_
-#define _OPENSBI_H_
+#ifndef SIMPLEKERNEL_OPENSBI_H
+#define SIMPLEKERNEL_OPENSBI_H
-#include "stdint.h"
+#include "cstdint"
/**
* @brief opensbi 接口抽象
@@ -41,6 +41,7 @@ class OPENSBI {
ERR_ALREADY_STARTED = -7,
ERR_ALREADY_STOPPED = -8,
};
+
/// 错误码
long error;
/// 返回值
@@ -49,8 +50,8 @@ class OPENSBI {
private:
/// 设置定时器
- static constexpr const uint32_t FID_SET_TIMER = 0x0;
- static constexpr const uint32_t EID_SET_TIMER = 0x54494D45;
+ static constexpr const uint32_t FID_SET_TIMER = 0x0;
+ static constexpr const uint32_t EID_SET_TIMER = 0x54494D45;
/// uart 输出字符
static constexpr const uint32_t FID_CONSOLE_PUTCHAR = 0x0;
@@ -61,20 +62,20 @@ class OPENSBI {
static constexpr const uint32_t EID_CONSOLE_GETCHAR = 0x2;
/// 清空 IPI
- static constexpr const uint32_t FID_CLEAR_IPI = 0x0;
- static constexpr const uint32_t EID_CLEAR_IPI = 0x3;
+ static constexpr const uint32_t FID_CLEAR_IPI = 0x0;
+ static constexpr const uint32_t EID_CLEAR_IPI = 0x3;
/// 发送 IPI
- static constexpr const uint32_t FID_SEND_IPI = 0x0;
- static constexpr const uint32_t EID_SEND_IPI = 0x735049;
+ static constexpr const uint32_t FID_SEND_IPI = 0x0;
+ static constexpr const uint32_t EID_SEND_IPI = 0x735049;
/// 关机
- static constexpr const uint32_t FID_SHUTDOWN = 0x0;
- static constexpr const uint32_t EID_SHUTDOWN = 0x8;
+ static constexpr const uint32_t FID_SHUTDOWN = 0x0;
+ static constexpr const uint32_t EID_SHUTDOWN = 0x8;
/// 启动 hart
- static constexpr const uint32_t FID_HART_START = 0x0;
- static constexpr const uint32_t EID_HART_START = 0x48534D;
+ static constexpr const uint32_t FID_HART_START = 0x0;
+ static constexpr const uint32_t EID_HART_START = 0x48534D;
/**
* @brief ecall 借口
@@ -88,38 +89,39 @@ class OPENSBI {
* @param _eid 使用 a7 传递
* @return sbiret_t
*/
- sbiret_t ecall(unsigned long _arg0, unsigned long _arg1,
- unsigned long _arg2, unsigned long _arg3,
- unsigned long _arg4, unsigned long _arg5, int _fid,
- int _eid);
+ sbiret_t
+ ecall(unsigned long _arg0, unsigned long _arg1, unsigned long _arg2,
+ unsigned long _arg3, unsigned long _arg4, unsigned long _arg5,
+ int _fid, int _eid);
protected:
+
public:
/**
* @brief 获取单例
* @return OPENSBI& 静态对象
*/
- static OPENSBI &get_instance(void);
+ static OPENSBI& get_instance(void);
/**
* @brief 输出一个字符
* @param _c 要输出的字符
*/
- void put_char(const char _c);
+ void put_char(const char _c);
/**
* @brief 从 uart 读取一个字符
* @return uint8_t 读取到的字符,没有读到数据返回 0xFF
* @note 不会阻塞
*/
- uint8_t get_char(void);
+ uint8_t get_char(void);
/**
* @brief 设置时钟
* @param _value 要设置的时间
* @return sbiret_t 返回值
*/
- sbiret_t set_timer(uint64_t _value);
+ sbiret_t set_timer(uint64_t _value);
/**
* @brief 发送 ipi(inter-processor interrupt) 给指定的 hart
@@ -130,7 +132,7 @@ class OPENSBI {
* number of bits in an unsigned long, rounded up to the next integer.
* @return sbiret_t 返回值
*/
- sbiret_t send_ipi(const unsigned long *_hart_mask);
+ sbiret_t send_ipi(const unsigned long* _hart_mask);
/**
* @brief 启动指定的 hart
@@ -146,8 +148,8 @@ class OPENSBI {
* a0: hartid
* a1: _opaque
*/
- sbiret_t hart_start(unsigned long _hartid, unsigned long _start_addr,
- unsigned long _opaque);
+ sbiret_t hart_start(unsigned long _hartid, unsigned long _start_addr,
+ unsigned long _opaque);
};
-#endif /* _OPENSBI_H_ */
+#endif /* SIMPLEKERNEL_OPENSBI_H */
diff --git a/src/drv/opensbi/opensbi.cpp b/src/drv/opensbi/opensbi.cpp
index 45565ec03..c544d469d 100644
--- a/src/drv/opensbi/opensbi.cpp
+++ b/src/drv/opensbi/opensbi.cpp
@@ -16,10 +16,10 @@
#include "opensbi.h"
-OPENSBI::sbiret_t OPENSBI::ecall(unsigned long _arg0, unsigned long _arg1,
- unsigned long _arg2, unsigned long _arg3,
- unsigned long _arg4, unsigned long _arg5,
- int _fid, int _eid) {
+OPENSBI::sbiret_t
+OPENSBI::ecall(unsigned long _arg0, unsigned long _arg1, unsigned long _arg2,
+ unsigned long _arg3, unsigned long _arg4, unsigned long _arg5,
+ int _fid, int _eid) {
OPENSBI::sbiret_t ret;
register uintptr_t a0 asm("a0") = (uintptr_t)(_arg0);
register uintptr_t a1 asm("a1") = (uintptr_t)(_arg1);
@@ -29,16 +29,16 @@ OPENSBI::sbiret_t OPENSBI::ecall(unsigned long _arg0, unsigned long _arg1,
register uintptr_t a5 asm("a5") = (uintptr_t)(_arg5);
register uintptr_t a6 asm("a6") = (uintptr_t)(_fid);
register uintptr_t a7 asm("a7") = (uintptr_t)(_eid);
- asm volatile("ecall"
- : "+r"(a0), "+r"(a1)
- : "r"(a2), "r"(a3), "r"(a4), "r"(a5), "r"(a6), "r"(a7)
- : "memory");
+ asm("ecall"
+ : "+r"(a0), "+r"(a1)
+ : "r"(a2), "r"(a3), "r"(a4), "r"(a5), "r"(a6), "r"(a7)
+ : "memory");
ret.error = a0;
ret.value = a1;
return ret;
}
-OPENSBI &OPENSBI::get_instance(void) {
+OPENSBI& OPENSBI::get_instance(void) {
/// 定义全局 OPENSBI 对象
static OPENSBI opensbi;
return opensbi;
@@ -52,21 +52,21 @@ void OPENSBI::put_char(const char _c) {
uint8_t OPENSBI::get_char(void) {
return (uint8_t)ecall(0, 0, 0, 0, 0, 0, FID_CONSOLE_GETCHAR,
EID_CONSOLE_GETCHAR)
- .value;
+ .value;
}
OPENSBI::sbiret_t OPENSBI::set_timer(uint64_t _value) {
return ecall(_value, 0, 0, 0, 0, 0, FID_SET_TIMER, EID_SET_TIMER);
}
-OPENSBI::sbiret_t OPENSBI::send_ipi(const unsigned long *_hart_mask) {
+OPENSBI::sbiret_t OPENSBI::send_ipi(const unsigned long* _hart_mask) {
return ecall((uintptr_t)_hart_mask, 0, 0, 0, 0, 0, FID_SEND_IPI,
EID_SEND_IPI);
}
-OPENSBI::sbiret_t OPENSBI::hart_start(unsigned long _hartid,
- unsigned long _start_addr,
- unsigned long _opaque) {
+OPENSBI::sbiret_t
+OPENSBI::hart_start(unsigned long _hartid, unsigned long _start_addr,
+ unsigned long _opaque) {
return ecall(_hartid, _start_addr, _opaque, 0, 0, 0, FID_HART_START,
EID_HART_START);
}
diff --git a/src/drv/sbi_console/include/sbi_console.h b/src/drv/sbi_console/include/sbi_console.h
index fd588224d..b71dcb862 100644
--- a/src/drv/sbi_console/include/sbi_console.h
+++ b/src/drv/sbi_console/include/sbi_console.h
@@ -14,11 +14,12 @@
*
*/
-#ifndef _SBI_CONSOLE_H_
-#define _SBI_CONSOLE_H_
+#ifndef SIMPLEKERNEL_SBI_CONSOLE_H
+#define SIMPLEKERNEL_SBI_CONSOLE_H
-#include "stdint.h"
#include "color.h"
+#include "cstddef"
+#include "cstdint"
class SBI_CONSOLE {
private:
@@ -26,6 +27,7 @@ class SBI_CONSOLE {
static COLOR::color_t color;
protected:
+
public:
SBI_CONSOLE(void);
~SBI_CONSOLE(void);
@@ -34,34 +36,34 @@ class SBI_CONSOLE {
* @brief 写字符
* @param _c 要写的字符
*/
- void put_char(const char _c) const;
+ void put_char(const char _c) const;
/**
* @brief 写字符串
* @param _s 要写的字符串
*/
- void write_string(const char *_s) const;
+ void write_string(const char* _s) const;
/**
* @brief 写指定长度的字符串
* @param _s 要写的字符串
* @param _len 要写的长度
*/
- void write(const char *_s, size_t _len) const;
+ void write(const char* _s, size_t _len) const;
/**
* @brief 读一个字符
* @return uint8_t 读取到的字符
* @todo
*/
- uint8_t get_char(void) const;
+ uint8_t get_char(void) const;
/**
* @brief 设置颜色
* @param _color 要设置的颜色
* @todo
*/
- void set_color(const COLOR::color_t _color) const;
+ void set_color(const COLOR::color_t _color) const;
/**
* @brief 获取正在使用的颜色
@@ -71,4 +73,4 @@ class SBI_CONSOLE {
COLOR::color_t get_color(void) const;
};
-#endif /* _SBI_CONSOLE_H_ */
+#endif /* SIMPLEKERNEL_SBI_CONSOLE_H */
diff --git a/src/drv/sbi_console/sbi_console.cpp b/src/drv/sbi_console/sbi_console.cpp
index 540da1292..20b1f7e5d 100644
--- a/src/drv/sbi_console/sbi_console.cpp
+++ b/src/drv/sbi_console/sbi_console.cpp
@@ -14,11 +14,9 @@
*
*/
-#include "stddef.h"
-#include "string.h"
-#include "stdlib.h"
-#include "opensbi.h"
#include "sbi_console.h"
+#include "cstring"
+#include "opensbi.h"
// 默认颜色为白色
COLOR::color_t SBI_CONSOLE::color = COLOR::WHITE;
@@ -39,12 +37,12 @@ void SBI_CONSOLE::put_char(const char _c) const {
return;
}
-void SBI_CONSOLE::write_string(const char *_s) const {
+void SBI_CONSOLE::write_string(const char* _s) const {
write(_s, strlen(_s));
return;
}
-void SBI_CONSOLE::write(const char *_s, size_t _len) const {
+void SBI_CONSOLE::write(const char* _s, size_t _len) const {
for (size_t i = 0; i < _len; i++) {
put_char(_s[i]);
}
@@ -57,70 +55,70 @@ uint8_t SBI_CONSOLE::get_char(void) const {
void SBI_CONSOLE::set_color(const COLOR::color_t _color) const {
// 根据 _color 构造字符串
- char *tmp = nullptr;
+ char* tmp = nullptr;
switch (_color) {
case COLOR::BLACK: {
- tmp = (char *)"\033[30m";
+ tmp = (char*)"\033[30m";
break;
}
case COLOR::RED: {
- tmp = (char *)"\033[31m";
+ tmp = (char*)"\033[31m";
break;
}
case COLOR::GREEN: {
- tmp = (char *)"\033[32m";
+ tmp = (char*)"\033[32m";
break;
}
case COLOR::YELLOW: {
- tmp = (char *)"\033[33m";
+ tmp = (char*)"\033[33m";
break;
}
case COLOR::BLUE: {
- tmp = (char *)"\033[34m";
+ tmp = (char*)"\033[34m";
break;
}
case COLOR::PURPLE: {
- tmp = (char *)"\033[35m";
+ tmp = (char*)"\033[35m";
break;
}
case COLOR::CYAN: {
- tmp = (char *)"\033[36m";
+ tmp = (char*)"\033[36m";
break;
}
case COLOR::WHITE: {
- tmp = (char *)"\033[37m";
+ tmp = (char*)"\033[37m";
break;
}
case COLOR::GREY: {
- tmp = (char *)"\033[90m";
+ tmp = (char*)"\033[90m";
break;
}
case COLOR::LIGHT_RED: {
- tmp = (char *)"\033[91m";
+ tmp = (char*)"\033[91m";
break;
}
case COLOR::LIGHT_GREEN: {
- tmp = (char *)"\033[92m";
+ tmp = (char*)"\033[92m";
break;
}
case COLOR::LIGHT_YELLOW: {
- tmp = (char *)"\033[93m";
+ tmp = (char*)"\033[93m";
break;
}
case COLOR::LIGHT_BLUE: {
- tmp = (char *)"\033[94m";
+ tmp = (char*)"\033[94m";
break;
}
case COLOR::LIGHT_PURPLE: {
- tmp = (char *)"\033[95m";
+ tmp = (char*)"\033[95m";
break;
}
case COLOR::LIGHT_CYAN: {
- tmp = (char *)"\033[96m";
+ tmp = (char*)"\033[96m";
break;
}
case COLOR::LIGHT_WHITE: {
- tmp = (char *)"\033[97m";
+ tmp = (char*)"\033[97m";
break;
}
}
diff --git a/src/drv/tui/include/tui.h b/src/drv/tui/include/tui.h
index bb7a6a6dc..435964d9b 100644
--- a/src/drv/tui/include/tui.h
+++ b/src/drv/tui/include/tui.h
@@ -1,6 +1,6 @@
/**
- * @file tui.cpp
+ * @file tui.h
* @brief TUI 接口头文件
* @author Zone.N (Zone.Niuzh@hotmail.com)
* @version 1.0
@@ -14,12 +14,12 @@
*
*/
-#ifndef _TUI_H_
-#define _TUI_H_
+#ifndef SIMPLEKERNEL_TUI_H
+#define SIMPLEKERNEL_TUI_H
-#include "stdint.h"
-#include "stddef.h"
#include "color.h"
+#include "cstddef"
+#include "cstdint"
/**
* @brief 位置信息
@@ -77,7 +77,7 @@ class char_t {
// 字符
uint8_t c;
// 颜色
- col_t color;
+ col_t color;
};
/**
@@ -86,9 +86,9 @@ class char_t {
class TUI {
private:
/// CRT 控制寄存器-地址
- static constexpr const uint32_t TUI_ADDR = 0x3D4;
+ static constexpr const uint32_t TUI_ADDR = 0x3D4;
/// CRT 控制寄存器-数据
- static constexpr const uint32_t TUI_DATA = 0x3D5;
+ static constexpr const uint32_t TUI_DATA = 0x3D5;
/// 光标高位
static constexpr const uint32_t TUI_CURSOR_H = 0xE;
/// 光标低位
@@ -98,19 +98,19 @@ class TUI {
static constexpr const uint32_t TUI_MEM_BASE = 0xB8000;
/// TUI 缓存大小
/// @todo 从 grub 获取
- static constexpr size_t TUI_MEM_SIZE = 0x8000;
+ static constexpr size_t TUI_MEM_SIZE = 0x8000;
/// 规定显示行数
/// @todo 从 grub 获取
- static constexpr const size_t WIDTH = 80;
+ static constexpr const size_t WIDTH = 80;
/// 规定显示列数
/// @todo 从 grub 获取
- static constexpr const size_t HEIGHT = 25;
+ static constexpr const size_t HEIGHT = 25;
// TUI 缓存
- char_t *const buffer = (char_t *)TUI_MEM_BASE;
+ char_t* const buffer = (char_t*)TUI_MEM_BASE;
/// 记录当前位置
- static pos_t pos;
+ static pos_t pos;
/// 记录当前命令行颜色
- static col_t color;
+ static col_t color;
/**
* @brief 在指定位置输出
@@ -136,6 +136,7 @@ class TUI {
void scroll(void);
protected:
+
public:
TUI(void);
~TUI(void);
@@ -145,7 +146,7 @@ class TUI {
* @param _color 要设置的颜色
* @todo 支持分别字体与背景色
*/
- void set_color(const COLOR::color_t _color);
+ void set_color(const COLOR::color_t _color);
/**
* @brief 获取颜色
@@ -157,70 +158,70 @@ class TUI {
* @brief 设置光标位置
* @param _pos 要设置的位置
*/
- void set_pos(const pos_t _pos);
+ void set_pos(const pos_t _pos);
/**
* @brief 设置行
* @param _row 要设置的行
*/
- void set_pos_row(const size_t _row);
+ void set_pos_row(const size_t _row);
/**
* @brief 设置列
* @param _col 要设置的列
*/
- void set_pos_col(const size_t _col);
+ void set_pos_col(const size_t _col);
/**
* @brief 获取光标位置
* @return pos_t 光标的位置
*/
- pos_t get_pos(void) const;
+ pos_t get_pos(void) const;
/**
* @brief 写 TUI 缓存
* @param _idx 要写的位置
* @param _data 要写的数据
*/
- void write(const size_t _idx, const char_t _data);
+ void write(const size_t _idx, const char_t _data);
/**
* @brief 读 TUI 缓存
* @param _idx 要读的位置
* @return char_t 该位置处的 char_t 对象
*/
- char_t read(const size_t _idx) const;
+ char_t read(const size_t _idx) const;
/**
* @brief 写字符
* @param _c 要写的字符
*/
- void put_char(const char _c);
+ void put_char(const char _c);
/**
* @brief 读字符
* @return uint8_t 读到的字符
* @note tui 没有读字符的操作,这里只是保持接口一致
*/
- uint8_t get_char(void) const;
+ uint8_t get_char(void) const;
/**
* @brief 写字符串
* @param _s 要写的字符串
*/
- void write_string(const char *_s);
+ void write_string(const char* _s);
/**
* @brief 写指定长度的字符串
* @param _s 要写的字符串
* @param _len 要写的长度
*/
- void write(const char *_s, const size_t _len);
+ void write(const char* _s, const size_t _len);
/**
* @brief 清屏,清空 TUI 缓存
*/
- void clear(void);
+ void clear(void);
};
-#endif /* _TUI_H_ */
+#endif /* SIMPLEKERNEL_TUI_H */
diff --git a/src/drv/tui/tui.cpp b/src/drv/tui/tui.cpp
index a2b64cb4c..a927215ac 100644
--- a/src/drv/tui/tui.cpp
+++ b/src/drv/tui/tui.cpp
@@ -14,11 +14,10 @@
*
*/
-#include "stddef.h"
-#include "stdint.h"
-#include "stdarg.h"
-#include "string.h"
#include "tui.h"
+#include "cstddef"
+#include "cstdint"
+#include "cstring"
#include "port.h"
pos_t::pos_t(const uint8_t _col, const uint8_t _row) : col(_col), row(_row) {
@@ -193,12 +192,12 @@ uint8_t TUI::get_char(void) const {
return 0;
}
-void TUI::write_string(const char *_s) {
+void TUI::write_string(const char* _s) {
write(_s, strlen(_s));
return;
}
-void TUI::write(const char *_s, const size_t _len) {
+void TUI::write(const char* _s, const size_t _len) {
for (size_t i = 0; i < _len; i++) {
put_char(_s[i]);
}
diff --git a/src/drv/uart/include/uart.h b/src/drv/uart/include/uart.h
index 9bea5e5a7..1467950f6 100644
--- a/src/drv/uart/include/uart.h
+++ b/src/drv/uart/include/uart.h
@@ -1,15 +1,25 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-//
-// uart.h for Simple-XX/SimpleKernel.
+/**
+ * @file uart.h
+ * @brief uart 驱动
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
-#ifndef _UART_H_
-#define _UART_H_
+#ifndef SIMPLEKERNEL_UART_H
+#define SIMPLEKERNEL_UART_H
-#include "stddef.h"
-#include "stdint.h"
#include "color.h"
+#include "cstddef"
+#include "cstdint"
#include "hardware.h"
class UART {
@@ -38,20 +48,21 @@ class UART {
void delay(int32_t count) const;
protected:
+
public:
UART(void);
~UART(void);
- void put_char(const char _c) const;
+ void put_char(const char _c) const;
// 写字符串
- void write_string(const char *_s) const;
+ void write_string(const char* _s) const;
// 写字符串
- void write(const char *_s, size_t _len) const;
+ void write(const char* _s, size_t _len) const;
// 读字符 TODO
- uint8_t get_char(void) const;
+ uint8_t get_char(void) const;
// 设置颜色 TODO
- void set_color(const COLOR::color_t _color) const;
+ void set_color(const COLOR::color_t _color) const;
// 获取颜色 TODO
COLOR::color_t get_color(void) const;
};
-#endif /* _UART_H_ */
+#endif /* SIMPLEKERNEL_UART_H */
diff --git a/src/drv/uart/uart.cpp b/src/drv/uart/uart.cpp
index adb74cf04..20c40e186 100644
--- a/src/drv/uart/uart.cpp
+++ b/src/drv/uart/uart.cpp
@@ -1,12 +1,23 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-// Based on https://wiki.osdev.org/Raspberry_Pi_Bare_Bones
-// uart.cpp for Simple-XX/SimpleKernel.
+/**
+ * @file uart.cpp
+ * @brief uart 驱动实现
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * Based on https://wiki.osdev.org/Raspberry_Pi_Bare_Bones
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
-#include "stddef.h"
-#include "string.h"
#include "uart.h"
+#include "cstddef"
+#include "cstring"
#include "port.h"
UART::UART(void) {
@@ -41,8 +52,8 @@ UART::UART(void) {
PORT::outd(UART0_LCRH, (1 << 4) | (1 << 5) | (1 << 6));
// Mask all interrupts.
- PORT::outd(UART0_IMSC, (1 << 1) | (1 << 4) | (1 << 5) | (1 << 6) |
- (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10));
+ PORT::outd(UART0_IMSC, (1 << 1) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7)
+ | (1 << 8) | (1 << 9) | (1 << 10));
// Enable UART0, receive & transfer part of UART.
PORT::outd(UART0_CR, (1 << 0) | (1 << 8) | (1 << 9));
@@ -71,12 +82,12 @@ void UART::put_char(const char _c) const {
return;
}
-void UART::write_string(const char *_s) const {
+void UART::write_string(const char* _s) const {
write(_s, strlen(_s));
return;
}
-void UART::write(const char *_s, size_t _len) const {
+void UART::write(const char* _s, size_t _len) const {
for (size_t i = 0; i < _len; i++) {
put_char(_s[i]);
}
diff --git a/src/include/boot_info.h b/src/include/boot_info.h
index a0c39330b..b9e7d497f 100644
--- a/src/include/boot_info.h
+++ b/src/include/boot_info.h
@@ -14,10 +14,10 @@
*
*/
-#ifndef _BOOT_INFO_H_
-#define _BOOT_INFO_H_
+#ifndef SIMPLEKERNEL_BOOT_INFO_H
+#define SIMPLEKERNEL_BOOT_INFO_H
-#include "stdint.h"
+#include "cstdint"
#include "resource.h"
/**
@@ -32,36 +32,38 @@
namespace BOOT_INFO {
/// 声明,定义在具体的实现中
/// 是否已经初始化过
-extern bool inited;
+extern bool inited;
/// 地址
extern "C" uintptr_t boot_info_addr;
/// 长度
-extern size_t boot_info_size;
+extern size_t boot_info_size;
+/// 保存 sbi 传递的启动核
+extern "C" size_t dtb_init_hart;
/**
* @brief 初始化,定义在具体实现中
* @return true 成功
* @return false 成功
*/
-extern bool init(void);
+extern bool init(void);
/**
* @brief 获取物理内存信息
* @return resource_t 物理内存资源信息
*/
-extern resource_t get_memory(void);
+extern resource_t get_memory(void);
/**
* @brief 获取 clint 信息
* @return resource_t clint 资源信息
*/
-extern resource_t get_clint(void);
+extern resource_t get_clint(void);
/**
* @brief 获取 plic 信息
* @return resource_t plic 资源信息
*/
-extern resource_t get_plic(void);
-}; // namespace BOOT_INFO
+extern resource_t get_plic(void);
+}; // namespace BOOT_INFO
-#endif /* _BOOT_INFO_H_ */
+#endif /* SIMPLEKERNEL_BOOT_INFO_H */
diff --git a/src/include/color.h b/src/include/color.h
index 2ace8ce79..252323782 100644
--- a/src/include/color.h
+++ b/src/include/color.h
@@ -14,10 +14,10 @@
*
*/
-#ifndef _COLOR_H_
-#define _COLOR_H_
+#ifndef SIMPLEKERNEL_COLOR_H
+#define SIMPLEKERNEL_COLOR_H
-#include "stdint.h"
+#include "cstdint"
/**
* @brief 颜色定义
@@ -25,60 +25,60 @@
* @todo 标准化
*/
namespace COLOR {
- typedef enum : uint8_t {
+typedef enum : uint8_t {
#if defined(__i386__) || defined(__x86_64__)
- /// RGB: 0 0 0
- BLACK = 0,
- /// RGB: 0 0 170
- BLUE = 1,
- /// RGB: 0 170 0
- GREEN = 2,
- /// RGB: 0 170 170
- CYAN = 3,
- /// RGB: 170 0 0
- RED = 4,
- /// RGB: 170 0 170
- PURPLE = 5,
- /// RGB: 170 85 0
- BROWN = 6,
- /// RGB: 170 170 170
- GREY = 7,
- /// RGB: 85 85 85
- DARK_GREY = 8,
- /// RGB: 85 85 255
- LIGHT_BLUE = 9,
- /// RGB: 85 255 85
- LIGHT_GREEN = 10,
- /// RGB: 85 255 255
- LIGHT_CYAN = 11,
- /// RGB: 255 85 85
- LIGHT_RED = 12,
- /// RGB: 255 85 255
- LIGHT_PURPLE = 13,
- /// RGB: 255 255 85
- YELLOW = 14,
- /// RGB: 255 255 255
- WHITE = 15,
+ /// RGB: 0 0 0
+ BLACK = 0,
+ /// RGB: 0 0 170
+ BLUE = 1,
+ /// RGB: 0 170 0
+ GREEN = 2,
+ /// RGB: 0 170 170
+ CYAN = 3,
+ /// RGB: 170 0 0
+ RED = 4,
+ /// RGB: 170 0 170
+ PURPLE = 5,
+ /// RGB: 170 85 0
+ BROWN = 6,
+ /// RGB: 170 170 170
+ GREY = 7,
+ /// RGB: 85 85 85
+ DARK_GREY = 8,
+ /// RGB: 85 85 255
+ LIGHT_BLUE = 9,
+ /// RGB: 85 255 85
+ LIGHT_GREEN = 10,
+ /// RGB: 85 255 255
+ LIGHT_CYAN = 11,
+ /// RGB: 255 85 85
+ LIGHT_RED = 12,
+ /// RGB: 255 85 255
+ LIGHT_PURPLE = 13,
+ /// RGB: 255 255 85
+ YELLOW = 14,
+ /// RGB: 255 255 255
+ WHITE = 15,
#elif defined(__riscv)
- /// @see https://en.wikipedia.org/wiki/ANSI_escape_code
- BLACK = 30,
- RED = 31,
- GREEN = 32,
- YELLOW = 33,
- BLUE = 34,
- PURPLE = 35,
- CYAN = 36,
- WHITE = 37,
- GREY = 90,
- LIGHT_RED = 91,
- LIGHT_GREEN = 92,
- LIGHT_YELLOW = 93,
- LIGHT_BLUE = 94,
- LIGHT_PURPLE = 95,
- LIGHT_CYAN = 96,
- LIGHT_WHITE = 97,
+ /// @see https://en.wikipedia.org/wiki/ANSI_escape_code
+ BLACK = 30,
+ RED = 31,
+ GREEN = 32,
+ YELLOW = 33,
+ BLUE = 34,
+ PURPLE = 35,
+ CYAN = 36,
+ WHITE = 37,
+ GREY = 90,
+ LIGHT_RED = 91,
+ LIGHT_GREEN = 92,
+ LIGHT_YELLOW = 93,
+ LIGHT_BLUE = 94,
+ LIGHT_PURPLE = 95,
+ LIGHT_CYAN = 96,
+ LIGHT_WHITE = 97,
#endif
- } color_t;
-};
+} color_t;
+}; // namespace COLOR
-#endif /* _COLOR_H_ */
+#endif /* SIMPLEKERNEL_COLOR_H */
diff --git a/src/include/common.h b/src/include/common.h
index 078e447ea..17c96190e 100644
--- a/src/include/common.h
+++ b/src/include/common.h
@@ -14,99 +14,82 @@
*
*/
-#ifndef _COMMON_H_
-#define _COMMON_H_
+#ifndef SIMPLEKERNEL_COMMON_H
+#define SIMPLEKERNEL_COMMON_H
-#include "stdint.h"
-#include "stddef.h"
+#include "cstddef"
+#include "cstdint"
namespace COMMON {
- // 引用链接脚本中的变量
- /// @see http://wiki.osdev.org/Using_Linker_Script_Values
- /// 内核开始
- extern "C" void *kernel_start[];
- /// 内核代码段开始
- extern "C" void *kernel_text_start[];
- /// 内核代码段结束
- extern "C" void *kernel_text_end[];
- /// 内核数据段开始
- extern "C" void *kernel_data_start[];
- /// 内核数据段结束
- extern "C" void *kernel_data_end[];
- /// 内核结束
- extern "C" void *kernel_end[];
+// 引用链接脚本中的变量
+/// @see http://wiki.osdev.org/Using_Linker_Script_Values
+/// 内核开始
+extern "C" void* __executable_start[];
+/// 内核结束
+extern "C" void* end[];
- /// 内核开始
- static const uintptr_t KERNEL_START_ADDR =
- reinterpret_cast(kernel_start);
- /// 内核代码段开始
- static const uintptr_t KERNEL_TEXT_START_ADDR __attribute__((unused)) =
- reinterpret_cast(kernel_text_start);
- /// 内核代码段结束
- static const uintptr_t KERNEL_TEXT_END_ADDR __attribute__((unused)) =
- reinterpret_cast(kernel_text_end);
- /// 内核数据段开始
- static const uintptr_t KERNEL_DATA_START_ADDR __attribute__((unused)) =
- reinterpret_cast(kernel_data_start);
- /// 内核数据段结束
- static const uintptr_t KERNEL_DATA_END_ADDR __attribute__((unused)) =
- reinterpret_cast(kernel_data_end);
- /// 内核结束
- static const uintptr_t KERNEL_END_ADDR =
- reinterpret_cast(kernel_end);
+/// 内核开始
+static const uintptr_t KERNEL_START_ADDR
+ = reinterpret_cast(__executable_start);
+/// 内核结束
+static const uintptr_t KERNEL_END_ADDR = reinterpret_cast(end);
- // 规定数据大小,方便用
- /// 一个字节,8 bits
- static constexpr const size_t BYTE = 0x1;
- /// 1KB
- static constexpr const size_t KB = 0x400;
- /// 1MB
- static constexpr const size_t MB = 0x100000;
- /// 1GB
- static constexpr const size_t GB = 0x40000000;
- /// 页大小 4KB
- static constexpr const size_t PAGE_SIZE = 4 * KB;
- /// 内核空间占用大小,包括内核代码部分与预留的,8MB
- static constexpr const uint32_t KERNEL_SPACE_SIZE = 8 * MB;
- /// 映射内核空间需要的页数
- static constexpr const uint64_t KERNEL_SPACE_PAGES =
- KERNEL_SPACE_SIZE / PAGE_SIZE;
+// 规定数据大小,方便用
+/// 一个字节,8 bits
+static constexpr const size_t BYTE = 0x1;
+/// 1KB
+static constexpr const size_t KB = 0x400;
+/// 1MB
+static constexpr const size_t MB = 0x100000;
+/// 1GB
+static constexpr const size_t GB = 0x40000000;
+/// 页大小 4KB
+static constexpr const size_t PAGE_SIZE = 4 * KB;
+/// 内核空间占用大小,包括内核代码部分与预留的,8MB
+static constexpr const uint32_t KERNEL_SPACE_SIZE = 8 * MB;
+/// 映射内核空间需要的页数
+static constexpr const uint64_t KERNEL_SPACE_PAGES
+ = KERNEL_SPACE_SIZE / PAGE_SIZE;
+/// 栈大小
+static constexpr const uintptr_t STACK_SIZE = 4 * KB;
- // 页掩码
- static constexpr const uintptr_t PAGE_MASK = ~(PAGE_SIZE - 1);
+// 页掩码
+static constexpr const uintptr_t PAGE_MASK = ~(PAGE_SIZE - 1);
- /**
- * @brief 对齐
- * @tparam T
- * @param _addr 要对齐的地址
- * @param _align 要对齐的目标
- * @return T 对齐过的地址
- * @note 向上取整
- * @note 针对指针
- */
- template
- inline T ALIGN(const T _addr, size_t _align) {
- uint8_t *tmp = (uint8_t *)_addr;
- return (T)((uintptr_t)(tmp + _align - 1) & (~(_align - 1)));
- }
+/**
+ * @brief 对齐
+ * @tparam T
+ * @param _addr 要对齐的地址
+ * @param _align 要对齐的目标
+ * @return T 对齐过的地址
+ * @note 向上取整
+ * @note 针对指针
+ */
+template
+inline T ALIGN(const T _addr, const size_t _align) {
+ uint8_t* tmp = reinterpret_cast(_addr);
+ return (T)((ptrdiff_t)(tmp + _align - 1) & (~(_align - 1)));
+}
+
+/**
+ * @brief 对齐
+ * @tparam T
+ * @param _addr 要对齐的整数
+ * @param _align 要对齐的目标
+ * @return T 对齐过的整数
+ * @note 向上取整
+ * @note 针对整数
+ */
+template <>
+inline uint32_t ALIGN(uint32_t _x, size_t _align) {
+ return ((_x + _align - 1) & (~(_align - 1)));
+}
+
+template <>
+inline uint64_t ALIGN(uint64_t _x, size_t _align) {
+ return ((_x + _align - 1) & (~(_align - 1)));
+}
- /**
- * @brief 对齐
- * @tparam T
- * @param _addr 要对齐的整数
- * @param _align 要对齐的目标
- * @return T 对齐过的整数
- * @note 向上取整
- * @note 针对整数
- */
- template <>
- inline uint32_t ALIGN(uint32_t _x, size_t _align) {
- return ((_x + _align - 1) & (~(_align - 1)));
- }
- template <>
- inline uint64_t ALIGN(uint64_t _x, size_t _align) {
- return ((_x + _align - 1) & (~(_align - 1)));
- }
-};
+}; // namespace COMMON
-#endif /* _COMMON_H_ */
+#endif /* SIMPLEKERNEL_COMMON_H */
diff --git a/src/include/io.h b/src/include/io.h
index 2f5ef456a..b29cc1f14 100644
--- a/src/include/io.h
+++ b/src/include/io.h
@@ -14,19 +14,19 @@
*
*/
-#ifndef _IO_H_
-#define _IO_H_
+#ifndef SIMPLEKERNEL_IO_H
+#define SIMPLEKERNEL_IO_H
-#include "stdint.h"
#include "color.h"
+#include "cstdint"
// 根据不同架构选择不同的输出方式
#if defined(__i386__) || defined(__x86_64__)
-#include "tui.h"
+# include "tui.h"
#elif defined(__arm__) || defined(__aarch64__)
-#include "uart.h"
+# include "uart.h"
#elif defined(__riscv)
-#include "sbi_console.h"
+# include "sbi_console.h"
#endif
/**
@@ -47,138 +47,139 @@ class IO {
#endif
protected:
+
public:
/// 缓冲区大小
- static constexpr const size_t BUF_SIZE = 128;
+ static constexpr const size_t BUF_SIZE = 512;
/**
* @brief 获取单例
* @return IO& 静态对象
*/
- static IO &get_instance(void);
+ static IO& get_instance(void);
/**
* @brief 端口读字节
* @param _port 要读的端口
* @return uint8_t 读到的数据
*/
- uint8_t inb(const uint32_t _port);
+ static uint8_t inb(const uint32_t _port);
/**
* @brief 端口读字
* @param _port 要读的端口
* @return uint16_t 读到的数据
*/
- uint16_t inw(const uint32_t _port);
+ static uint16_t inw(const uint32_t _port);
/**
* @brief 端口读双字
* @param _port 要读的端口
* @return uint32_t 读到的数据
*/
- uint32_t ind(const uint32_t _port);
+ static uint32_t ind(const uint32_t _port);
/**
* @brief 端口写字节
* @param _port 要写的端口
* @param _data 要写的数据
*/
- void outb(const uint32_t _port, const uint8_t _data);
+ static void outb(const uint32_t _port, const uint8_t _data);
/**
* @brief 端口写字
* @param _port 要写的端口
* @param _data 要写的数据
*/
- void outw(const uint32_t _port, const uint16_t _data);
+ static void outw(const uint32_t _port, const uint16_t _data);
/**
* @brief 端口写双字
* @param _port 要写的端口
* @param _data 要写的数据
*/
- void outd(const uint32_t _port, const uint32_t _data);
+ static void outd(const uint32_t _port, const uint32_t _data);
/**
* @brief MMIO 读字节
* @param _addr 要读的地址
* @return uint8_t 读到的数据
*/
- uint8_t read8(void *_addr);
+ static uint8_t read8(void* _addr);
/**
* @brief MMIO 写字节
* @param _addr 要写的地址
* @param _val 要写的值
*/
- void write8(void *_addr, uint8_t _val);
+ static void write8(void* _addr, uint8_t _val);
/**
* @brief MMIO 读字
* @param _addr 要读的地址
* @return uint16_t 读到的数据
*/
- uint16_t read16(void *_addr);
+ static uint16_t read16(void* _addr);
/**
* @brief MMIO 写字
* @param _addr 要写的地址
* @param _val 要写的值
*/
- void write16(void *_addr, uint16_t _val);
+ static void write16(void* _addr, uint16_t _val);
/**
* @brief MMIO 读双字
* @param _addr 要读的地址
* @return uint32_t 读到的数据
*/
- uint32_t read32(void *_addr);
+ static uint32_t read32(void* _addr);
/**
* @brief MMIO 写双字
* @param _addr 要写的地址
* @param _val 要写的数据
*/
- void write32(void *_addr, uint32_t _val);
+ static void write32(void* _addr, uint32_t _val);
/**
* @brief MMIO 读四字
* @param _addr 要读的地址
* @return uint64_t 读到的数据
*/
- uint64_t read64(void *_addr);
+ static uint64_t read64(void* _addr);
/**
* @brief MMIO 写四字
* @param _addr 要写的地址
* @param _val 要写的数据
*/
- void write64(void *_addr, uint64_t _val);
+ static void write64(void* _addr, uint64_t _val);
/**
* @brief 获取当前颜色
* @return COLOR::color_t 当前使用的颜色
*/
- COLOR::color_t get_color(void);
+ COLOR::color_t get_color(void);
/**
* @brief 设置当前颜色
* @param _color 要设置的颜色
*/
- void set_color(const COLOR::color_t _color);
+ void set_color(const COLOR::color_t _color);
/**
* @brief 输出字符
* @param _c 要输出的字符
*/
- void put_char(const char _c);
+ void put_char(const char _c);
/**
* @brief 输入字符
* @return char 读到的字符
* @todo
*/
- char get_char(void);
+ char get_char(void);
/**
* @brief 输出字符串
@@ -186,7 +187,7 @@ class IO {
* @return int32_t 输出的长度
* @todo 返回值
*/
- int32_t write_string(const char *_s);
+ int32_t write_string(const char* _s);
};
-#endif /* _IO_H_ */
+#endif /* SIMPLEKERNEL_IO_H */
diff --git a/src/include/mem/allocator.h b/src/include/mem/allocator.h
index c25cc4512..9fa7f2a3e 100644
--- a/src/include/mem/allocator.h
+++ b/src/include/mem/allocator.h
@@ -14,28 +14,29 @@
*
*/
-#ifndef _ALLOCATOR_H_
-#define _ALLOCATOR_H_
+#ifndef SIMPLEKERNEL_ALLOCATOR_H
+#define SIMPLEKERNEL_ALLOCATOR_H
-#include "stddef.h"
-#include "stdint.h"
+#include "cstddef"
+#include "cstdint"
/**
* @brief 内存分配器抽象类
*/
class ALLOCATOR {
private:
+
protected:
/// 分配器名称
- const char *name;
+ const char* name;
/// 当前管理的内存区域地址
- uintptr_t allocator_start_addr;
+ uintptr_t allocator_start_addr;
/// 当前管理的内存区域长度
- size_t allocator_length;
+ size_t allocator_length;
/// 当前管理的内存区域空闲长度
- size_t allocator_free_count;
+ size_t allocator_free_count;
/// 当前管理的内存区域已使用长度
- size_t allocator_used_count;
+ size_t allocator_used_count;
public:
/**
@@ -44,16 +45,16 @@ class ALLOCATOR {
* @param _addr 要管理的内存开始地址
* @param _len 要管理的内存长度,单位以具体实现为准
*/
- ALLOCATOR(const char *_name, uintptr_t _addr, size_t _len);
+ ALLOCATOR(const char* _name, uintptr_t _addr, size_t _len);
- virtual ~ALLOCATOR(void) = 0;
+ virtual ~ALLOCATOR(void) = 0;
/**
* @brief 分配 _len 页
* @param _len 页数
* @return uintptr_t 分配到的地址
*/
- virtual uintptr_t alloc(size_t _len) = 0;
+ virtual uintptr_t alloc(size_t _len) = 0;
/**
* @brief 在指定地址分配 _len 长度
@@ -62,26 +63,26 @@ class ALLOCATOR {
* @return true 成功
* @return false 失败
*/
- virtual bool alloc(uintptr_t _addr, size_t _len) = 0;
+ virtual bool alloc(uintptr_t _addr, size_t _len) = 0;
/**
* @brief 释放 _len 长度
* @param _addr 地址
* @param _len 长度
*/
- virtual void free(uintptr_t _addr, size_t _len) = 0;
+ virtual void free(uintptr_t _addr, size_t _len) = 0;
/**
* @brief 已使用数量
* @return size_t 数量
*/
- virtual size_t get_used_count(void) const = 0;
+ virtual size_t get_used_count(void) const = 0;
/**
* @brief 空闲数量
* @return size_t 数量
*/
- virtual size_t get_free_count(void) const = 0;
+ virtual size_t get_free_count(void) const = 0;
};
-#endif /* _ALLOCATOR_H_ */
+#endif /* SIMPLEKERNEL_ALLOCATOR_H */
diff --git a/src/include/mem/firstfit.h b/src/include/mem/firstfit.h
index cccc1b56e..5df8a17ed 100644
--- a/src/include/mem/firstfit.h
+++ b/src/include/mem/firstfit.h
@@ -14,13 +14,13 @@
*
*/
-#ifndef _FIRTSTFIT_H_
-#define _FIRTSTFIT_H_
+#ifndef SIMPLEKERNEL_FIRTSTFIT_H
+#define SIMPLEKERNEL_FIRTSTFIT_H
-#include "stdint.h"
-#include "stddef.h"
-#include "common.h"
#include "allocator.h"
+#include "common.h"
+#include "cstddef"
+#include "cstdint"
/**
* @brief 使用 first fit 算法的分配器
@@ -31,19 +31,19 @@ class FIRSTFIT : ALLOCATOR {
static constexpr const uint64_t BITS_PER_WORD = sizeof(uintptr_t);
#if __WORDSIZE == 64
/// 字长为 64 时的 掩码
- static constexpr const uint64_t MASK = 0x3F;
+ static constexpr const uint64_t MASK = 0x3F;
/// 2^6==64
static constexpr const uint64_t SHIFT = 6;
#elif __WORDSIZE == 32
/// 字长为 32 时的 掩码
- static constexpr const uint64_t MASK = 0x1F;
+ static constexpr const uint64_t MASK = 0x1F;
/// 2^5==32
static constexpr const uint64_t SHIFT = 5;
#endif
/// 位图数组长度,设置为占用一个页,4kb,32768 个位,每个 bit
/// 代表一页,最大表示 128MB
- static constexpr const size_t BITS_ARR_SIZE =
- COMMON::PAGE_SIZE / BITS_PER_WORD;
+ static constexpr const size_t BITS_ARR_SIZE
+ = COMMON::PAGE_SIZE / BITS_PER_WORD;
/// 位图,每一位表示一页内存,1 表示已使用,0 表示未使用
uintptr_t map[BITS_ARR_SIZE];
@@ -51,13 +51,13 @@ class FIRSTFIT : ALLOCATOR {
* @brief 置位 _idx
* @param _idx 要置位的索引
*/
- void set(size_t _idx);
+ void set(size_t _idx);
/**
* @brief 清零 _idx
* @param _idx 要清零的索引
*/
- void clr(size_t _idx);
+ void clr(size_t _idx);
/**
* @brief 测试 _idx
@@ -65,7 +65,7 @@ class FIRSTFIT : ALLOCATOR {
* @return true 已使用
* @return false 未使用
*/
- bool test(size_t _idx) const;
+ bool test(size_t _idx) const;
/**
* @brief 寻找连续 _len 个 _val 位,返回开始索引
@@ -73,9 +73,10 @@ class FIRSTFIT : ALLOCATOR {
* @param _val 值
* @return size_t 开始索引
*/
- size_t find_len(size_t _len, bool _val) const;
+ size_t find_len(size_t _len, bool _val) const;
protected:
+
public:
/**
* @brief 创建分配器
@@ -83,7 +84,7 @@ class FIRSTFIT : ALLOCATOR {
* @param _addr 开始地址
* @param _len 长度,页
*/
- FIRSTFIT(const char *_name, uintptr_t _addr, size_t _len);
+ FIRSTFIT(const char* _name, uintptr_t _addr, size_t _len);
~FIRSTFIT(void);
@@ -101,26 +102,26 @@ class FIRSTFIT : ALLOCATOR {
* @return true 成功
* @return false 失败
*/
- bool alloc(uintptr_t _addr, size_t _len) override;
+ bool alloc(uintptr_t _addr, size_t _len) override;
/**
* @brief 释放 _addr 处 _len 页的内存
* @param _addr 要释放内存起点地址
* @param _len 页数
*/
- void free(uintptr_t _addr, size_t _len) override;
+ void free(uintptr_t _addr, size_t _len) override;
/**
* @brief 获取已使用页数
* @return size_t 已经使用的页数
*/
- size_t get_used_count(void) const override;
+ size_t get_used_count(void) const override;
/**
* @brief 获取未使用页数
* @return size_t 未使用的页数
*/
- size_t get_free_count(void) const override;
+ size_t get_free_count(void) const override;
};
-#endif /* _FIRTSTFIT_H_ */
+#endif /* SIMPLEKERNEL_FIRTSTFIT_H */
diff --git a/src/include/mem/heap.h b/src/include/mem/heap.h
index cc01066b0..464083e65 100644
--- a/src/include/mem/heap.h
+++ b/src/include/mem/heap.h
@@ -14,13 +14,13 @@
*
*/
-#ifndef _HEAP_H_
-#define _HEAP_H_
+#ifndef SIMPLEKERNEL_HEAP_H
+#define SIMPLEKERNEL_HEAP_H
-#include "stdint.h"
-#include "stddef.h"
-#include "slab.h"
#include "allocator.h"
+#include "cstddef"
+#include "cstdint"
+#include "slab.h"
/**
* @brief 堆抽象
@@ -28,35 +28,50 @@
class HEAP {
private:
// 堆分配器
- ALLOCATOR *allocator;
+ ALLOCATOR* allocator_kernel;
+ ALLOCATOR* allocator_non_kernel;
protected:
+
public:
/**
* @brief 获取单例
* @return HEAP& 静态对象
*/
- static HEAP &get_instance(void);
+ static HEAP& get_instance(void);
/** 初始化
* @brief 堆初始化
* @return true 成功
* @return false 失败
*/
- bool init(void);
+ bool init(void);
+
+ /**
+ * @brief 内核地址内存申请
+ * @param _byte 要申请的 bytes
+ * @return void* 申请到的地址
+ */
+ void* kmalloc(size_t _byte);
+
+ /**
+ * @brief 内核地址内存释放
+ * @param _p 要释放的内存地址
+ */
+ void kfree(void* _p);
/**
* @brief 内存申请
* @param _byte 要申请的 bytes
* @return void* 申请到的地址
*/
- void *malloc(size_t _byte);
+ void* malloc(size_t _byte);
/**
* @brief 内存释放
* @param _p 要释放的内存地址
*/
- void free(void *_p);
+ void free(void* _p);
};
-#endif /* _HEAP_H_ */
+#endif /* SIMPLEKERNEL_HEAP_H */
diff --git a/src/include/mem/pmm.h b/src/include/mem/pmm.h
index 190d1bca9..17e4a8c96 100644
--- a/src/include/mem/pmm.h
+++ b/src/include/mem/pmm.h
@@ -14,13 +14,13 @@
*
*/
-#ifndef _PMM_H_
-#define _PMM_H_
+#ifndef SIMPLEKERNEL_PMM_H
+#define SIMPLEKERNEL_PMM_H
-#include "stddef.h"
-#include "stdint.h"
-#include "firstfit.h"
#include "allocator.h"
+#include "cstddef"
+#include "cstdint"
+#include "firstfit.h"
/**
* @brief 物理内存管理接口
@@ -35,38 +35,39 @@
class PMM {
private:
/// 物理内存开始地址
- uintptr_t start;
+ uintptr_t start;
/// 物理内存长度,单位为 bytes
- size_t length;
+ size_t length;
/// 物理内存页数
- size_t total_pages;
+ size_t total_pages;
/// 内核空间起始地址
- uintptr_t kernel_space_start;
+ uintptr_t kernel_space_start;
/// 内核空间大小,单位为 bytes
- size_t kernel_space_length;
+ size_t kernel_space_length;
/// 非内核空间起始地址
- uintptr_t non_kernel_space_start;
+ uintptr_t non_kernel_space_start;
/// 非内核空间大小,单位为 bytes
- size_t non_kernel_space_length;
+ size_t non_kernel_space_length;
/// 内核空间不会位于内存中间,导致出现非内核空间被切割为两部分的情况
/// 物理内存分配器,分配内核空间
- ALLOCATOR *kernel_space_allocator;
+ ALLOCATOR* kernel_space_allocator;
/// 物理内存分配器,分配非内核空间
- ALLOCATOR *allocator;
+ ALLOCATOR* allocator;
/**
* @brief 将 multiboot2/dtb 信息移动到内核空间
*/
- void move_boot_info(void);
+ void move_boot_info(void);
protected:
+
public:
/**
* @brief 获取单例
* @return PMM& 静态对象
*/
- static PMM &get_instance(void);
+ static PMM& get_instance(void);
/**
* @brief 初始化
@@ -74,50 +75,62 @@ class PMM {
* @return false 失败
* @todo 移动到构造函数去
*/
- bool init(void);
+ bool init(void);
/**
* @brief 获取物理内存长度
* @return size_t 物理内存长度
*/
- size_t get_pmm_length(void) const;
+ size_t get_pmm_length(void) const;
+
+ /**
+ * @brief 获取内核空间起始地址
+ * @return uintptr_t 内核空间起始地址
+ */
+ uintptr_t get_kernel_space_start(void) const;
+
+ /**
+ * @brief 获取内核空间大小,单位为 byte
+ * @return size_t 内核空间大小
+ */
+ size_t get_kernel_space_length(void) const;
/**
* @brief 获取非内核空间起始地址
* @return uintptr_t 非内核空间起始地址
*/
- uintptr_t get_non_kernel_space_start(void) const;
+ uintptr_t get_non_kernel_space_start(void) const;
/**
* @brief 获取非内核空间大小,单位为 byte
* @return size_t 非内核空间大小
*/
- size_t get_non_kernel_space_length(void) const;
+ size_t get_non_kernel_space_length(void) const;
/**
* @brief 获取当前已使用页数
* @return size_t 已使用页数
*/
- size_t get_used_pages_count(void) const;
+ size_t get_used_pages_count(void) const;
/**
* @brief 获取当前空闲页
* @return size_t 空闲页数
*/
- size_t get_free_pages_count(void) const;
+ size_t get_free_pages_count(void) const;
/**
* @brief 分配一页
* @return uintptr_t 分配的内存起始地址
*/
- uintptr_t alloc_page(void);
+ uintptr_t alloc_page(void);
/**
* @brief 分配多页
* @param _len 页数
* @return uintptr_t 分配的内存起始地址
*/
- uintptr_t alloc_pages(size_t _len);
+ uintptr_t alloc_pages(size_t _len);
/**
* @brief 分配以指定地址开始的 _len 页
@@ -126,20 +139,20 @@ class PMM {
* @return true 成功
* @return false 失败
*/
- bool alloc_pages(uintptr_t _addr, size_t _len);
+ bool alloc_pages(uintptr_t _addr, size_t _len);
/**
* @brief 在内核空间申请一页
* @return uintptr_t 分配的内存起始地址
*/
- uintptr_t alloc_page_kernel(void);
+ uintptr_t alloc_page_kernel(void);
/**
* @brief 在内核空间分配 _len 页
* @param _len 页数
* @return uintptr_t 分配到的内存起始地址
*/
- uintptr_t alloc_pages_kernel(size_t _len);
+ uintptr_t alloc_pages_kernel(size_t _len);
/**
* @brief 在内核空间分配以指定地址开始的 _len 页
@@ -148,20 +161,20 @@ class PMM {
* @return true 成功
* @return false 失败
*/
- bool alloc_pages_kernel(uintptr_t _addr, size_t _len);
+ bool alloc_pages_kernel(uintptr_t _addr, size_t _len);
/**
* @brief 回收一页
* @param _addr 要回收的地址
*/
- void free_page(uintptr_t _addr);
+ void free_page(uintptr_t _addr);
/**
* @brief 回收多页
* @param _addr 要回收的地址
* @param _len 页数
*/
- void free_pages(uintptr_t _addr, size_t _len);
+ void free_pages(uintptr_t _addr, size_t _len);
};
-#endif /* _PMM_H_ */
+#endif /* SIMPLEKERNEL_PMM_H */
diff --git a/src/include/mem/slab.h b/src/include/mem/slab.h
index 7489cb65b..a1b88c621 100644
--- a/src/include/mem/slab.h
+++ b/src/include/mem/slab.h
@@ -14,12 +14,13 @@
*
*/
-#ifndef _SLAB_H_
-#define _SLAB_H_
+#ifndef SIMPLEKERNEL_SLAB_H
+#define SIMPLEKERNEL_SLAB_H
-#include "stdint.h"
-#include "stddef.h"
#include "allocator.h"
+#include "cstddef"
+#include "cstdint"
+#include "cstdio"
#include "iostream"
/**
@@ -40,14 +41,14 @@ class SLAB : ALLOCATOR {
/// 头节点标识
static constexpr const uintptr_t HEAD = 0xCDCD;
// chunk_t 结构的物理地址
- uintptr_t addr;
+ uintptr_t addr;
// 长度,不包括自身大小 单位为 byte
// 记录的是实际使用的长度
// 按照 8byte 对齐
- size_t len;
+ size_t len;
/// 双向循环链表指针
- chunk_t *prev;
- chunk_t *next;
+ chunk_t* prev;
+ chunk_t* next;
/**
* @brief 构造函数只会在 SLAB 初始化时调用,且只用于构造头节点
@@ -60,23 +61,23 @@ class SLAB : ALLOCATOR {
* @brief 插入新节点
* @param _new_node 要插入的节点
*/
- void push_back(chunk_t *_new_node);
+ void push_back(chunk_t* _new_node);
/**
* @brief 获取链表长度
* @return size_t desc
*/
- size_t size(void) const;
+ size_t size(void) const;
- bool operator==(const chunk_t &_node) const;
- bool operator!=(const chunk_t &_node) const;
+ bool operator==(const chunk_t& _node) const;
+ bool operator!=(const chunk_t& _node) const;
/**
* @brief 返回相对头节点的第 _idx 项
* @param _idx 第几项
* @return chunk_t& chunk 对象
*/
- chunk_t &operator[](size_t _idx) const;
+ chunk_t& operator[](size_t _idx) const;
};
/**
@@ -90,7 +91,7 @@ class SLAB : ALLOCATOR {
* @param _list 目标链表
* @param _node 要移动的节点
*/
- void move(chunk_t &_list, chunk_t *_node);
+ void move(chunk_t& _list, chunk_t* _node);
/**
* @brief 申请物理内存,返回申请到的地址起点,已经初始化过,且加入 free
@@ -98,12 +99,12 @@ class SLAB : ALLOCATOR {
* @param _len 要申请的长度
* @return chunk_t* 申请到的 chunk
*/
- chunk_t *alloc_pmm(size_t _len);
+ chunk_t* alloc_pmm(size_t _len);
/**
* @brief 释放内存
*/
- void free_pmm(void);
+ void free_pmm(void);
/**
* @brief 分割一个节点
@@ -112,13 +113,13 @@ class SLAB : ALLOCATOR {
* @note 如果剩余部分符合要求,新建节点并加入 part 链表
* 同时将 _node->len 设置为 _len
*/
- void split(chunk_t *_node, size_t _len);
+ void split(chunk_t* _node, size_t _len);
/**
* @brief 合并 part 中地址连续的链表项,如果有可回收的回调用 free_pmm
* 进行回收
*/
- void merge(void);
+ void merge(void);
/**
* @brief 在 _which 链表中查找长度符合的
@@ -127,34 +128,37 @@ class SLAB : ALLOCATOR {
* @param _alloc 如果未找到是否分配
* @return chunk_t* 未找到返回 nullptr
*/
- chunk_t *find(chunk_t &_which, size_t _len, bool _alloc);
+ chunk_t* find(chunk_t& _which, size_t _len, bool _alloc);
protected:
+
public:
// 当前 cache 的长度,单位为 byte
- size_t len;
+ size_t len;
// 这三个作为头节点使用,不会实际使用
// full/part/free 是相对于 pmm
// 分配的一个或多个连续的页而言的
// 已经分配的 len 长度的内存,当然 len 不一定全部使用,真实使用的长度由
// chunk 记录
- chunk_t full;
+ chunk_t full;
// 申请的内存使用了一部分
- chunk_t part;
+ chunk_t part;
// 一整段申请的内存都没有使用
- chunk_t free;
+ chunk_t free;
+ /// 管理的是否为内核地址
+ bool is_kernel_space;
// 查找长度符合的
- chunk_t *find(size_t _len);
+ chunk_t* find(size_t _len);
/**
* @brief 释放一个 full 的链表项
* @param _node 要释放的节点
*/
- void remove(chunk_t *_node);
+ void remove(chunk_t* _node);
- friend std::ostream &operator<<(std::ostream &_out,
- SLAB::slab_cache_t &_cache) {
+ friend std::ostream&
+ operator<<(std::ostream& _out, SLAB::slab_cache_t& _cache) {
printf("_cache.full.size(): 0x%X\n", _cache.full.size());
for (size_t i = 0; i < _cache.full.size(); i++) {
printf("full 0x%X addr: 0x%X, len: 0x%X\n", i,
@@ -194,29 +198,34 @@ class SLAB : ALLOCATOR {
};
/// 最小为 256 bytes
- static constexpr const size_t MIN = 256;
- static constexpr const size_t SHIFT = 8;
+ static constexpr const size_t MIN = 256;
+ static constexpr const size_t SHIFT = 8;
/// 支持 256(256<<(CACHAE_LEN-1)) bytes
/// slab_cache[0] 即为内存为 256 字节的 chunk_t 结构链表
static constexpr const size_t CACHAE_LEN = 9;
slab_cache_t slab_cache[CACHAE_LEN];
+ /// 管理的是否为内核地址
+ bool is_kernel_space;
+
/**
* @brief 根据 _len 获取对应的 slab_cache 下标
* @param _len 长度
* @return size_t 对应的下标
*/
- size_t get_idx(size_t _len) const;
+ size_t get_idx(size_t _len) const;
protected:
+
public:
/**
* @brief 构造函数
* @param _name 分配器名称
* @param _addr 管理地址起始
* @param _len 要管理的长度
+ * @param _is_kernel 管理的是否为内核地址
*/
- SLAB(const char *_name, uintptr_t _addr, size_t _len);
+ SLAB(const char* _name, uintptr_t _addr, size_t _len, bool _is_kernel);
~SLAB(void);
@@ -228,18 +237,18 @@ class SLAB : ALLOCATOR {
uintptr_t alloc(size_t _len) override;
// slab 不支持这个函数
- bool alloc(uintptr_t _addr, size_t _len) override;
+ bool alloc(uintptr_t _addr, size_t _len) override;
/**
* @brief 释放内存
* @param _addr 要释放的地址
* @note slab 不使用第二个参数
*/
- void free(uintptr_t _addr, size_t) override;
+ void free(uintptr_t _addr, size_t) override;
// 暂时不支持
- size_t get_used_count(void) const override;
- size_t get_free_count(void) const override;
+ size_t get_used_count(void) const override;
+ size_t get_free_count(void) const override;
};
-#endif /* _SLAB_H_ */
+#endif /* SIMPLEKERNEL_SLAB_H */
diff --git a/src/include/mem/vmm.h b/src/include/mem/vmm.h
index 964fa6825..27fbdb446 100644
--- a/src/include/mem/vmm.h
+++ b/src/include/mem/vmm.h
@@ -14,105 +14,106 @@
*
*/
-#ifndef _VMM_H_
-#define _VMM_H_
+#ifndef SIMPLEKERNEL_VMM_H
+#define SIMPLEKERNEL_VMM_H
-#include "limits.h"
+#include "climits"
#include "common.h"
+#include "cpu.hpp"
// TODO: 可以优化
/// 页表项,最底层
-typedef uintptr_t pte_t;
+typedef uintptr_t pte_t;
/// 页表,也可以是页目录,它们的结构是一样的
-typedef uintptr_t *pt_t;
+typedef uintptr_t* pt_t;
/// 每个页表能映射多少页 = 页大小/页表项大小: 2^9
-static constexpr const size_t VMM_PAGES_PRE_PAGE_TABLE =
- COMMON::PAGE_SIZE / sizeof(pte_t);
+static constexpr const size_t VMM_PAGES_PRE_PAGE_TABLE
+ = COMMON::PAGE_SIZE / sizeof(pte_t);
/// 映射内核空间的大小
static constexpr const size_t VMM_KERNEL_SPACE_SIZE = COMMON::KERNEL_SPACE_SIZE;
/// 内核映射的页数
-static constexpr const size_t VMM_KERNEL_SPACE_PAGES =
- VMM_KERNEL_SPACE_SIZE / COMMON::PAGE_SIZE;
+static constexpr const size_t VMM_KERNEL_SPACE_PAGES
+ = VMM_KERNEL_SPACE_SIZE / COMMON::PAGE_SIZE;
#if defined(__i386__)
/// P = 1 表示有效; P = 0 表示无效。
-static constexpr const uint8_t VMM_PAGE_VALID = 1 << 0;
+static constexpr const uint8_t VMM_PAGE_VALID = 1 << 0;
/// 如果为 0 表示页面只读或可执行。
static constexpr const uint8_t VMM_PAGE_READABLE = 0;
static constexpr const uint8_t VMM_PAGE_WRITABLE = 1 << 1;
static constexpr const uint8_t VMM_PAGE_EXECUTABLE = 0;
/// U/S-- 位 2 是用户 / 超级用户 (User/Supervisor) 标志。
/// 如果为 1 那么运行在任何特权级上的程序都可以访问该页面。
-static constexpr const uint8_t VMM_PAGE_USER = 1 << 2;
+static constexpr const uint8_t VMM_PAGE_USER = 1 << 2;
/// 内核虚拟地址相对物理地址的偏移
-static constexpr const size_t KERNEL_OFFSET = 0x0;
+static constexpr const size_t KERNEL_OFFSET = 0x0;
/// PTE 属性位数
-static constexpr const size_t VMM_PTE_PROP_BITS = 12;
+static constexpr const size_t VMM_PTE_PROP_BITS = 12;
/// PTE 页内偏移位数
-static constexpr const size_t VMM_PAGE_OFF_BITS = 12;
+static constexpr const size_t VMM_PAGE_OFF_BITS = 12;
/// VPN 位数
-static constexpr const size_t VMM_VPN_BITS = 10;
+static constexpr const size_t VMM_VPN_BITS = 10;
/// VPN 位数掩码,10 位 VPN
-static constexpr const size_t VMM_VPN_BITS_MASK = 0x3FF;
+static constexpr const size_t VMM_VPN_BITS_MASK = 0x3FF;
/// i386 使用了两级页表
-static constexpr const size_t VMM_PT_LEVEL = 2;
+static constexpr const size_t VMM_PT_LEVEL = 2;
#elif defined(__x86_64__)
/// P = 1 表示有效; P = 0 表示无效。
-static constexpr const uint8_t VMM_PAGE_VALID = 1 << 0;
+static constexpr const uint8_t VMM_PAGE_VALID = 1 << 0;
/// 如果为 0 表示页面只读或可执行。
static constexpr const uint8_t VMM_PAGE_READABLE = 0;
static constexpr const uint8_t VMM_PAGE_WRITABLE = 1 << 1;
static constexpr const uint8_t VMM_PAGE_EXECUTABLE = 0;
/// U/S-- 位 2 是用户 / 超级用户 (User/Supervisor) 标志。
/// 如果为 1 那么运行在任何特权级上的程序都可以访问该页面。
-static constexpr const uint8_t VMM_PAGE_USER = 1 << 2;
+static constexpr const uint8_t VMM_PAGE_USER = 1 << 2;
/// 内核虚拟地址相对物理地址的偏移
-static constexpr const size_t KERNEL_OFFSET = 0x0;
+static constexpr const size_t KERNEL_OFFSET = 0x0;
/// PTE 属性位数
-static constexpr const size_t VMM_PTE_PROP_BITS = 12;
+static constexpr const size_t VMM_PTE_PROP_BITS = 12;
/// PTE 页内偏移位数
-static constexpr const size_t VMM_PAGE_OFF_BITS = 12;
+static constexpr const size_t VMM_PAGE_OFF_BITS = 12;
/// VPN 位数
-static constexpr const size_t VMM_VPN_BITS = 9;
+static constexpr const size_t VMM_VPN_BITS = 9;
/// VPN 位数掩码,9 位 VPN
-static constexpr const size_t VMM_VPN_BITS_MASK = 0x1FF;
+static constexpr const size_t VMM_VPN_BITS_MASK = 0x1FF;
/// x86_64 使用了四级页表
-static constexpr const size_t VMM_PT_LEVEL = 4;
+static constexpr const size_t VMM_PT_LEVEL = 4;
#elif defined(__riscv)
/// 有效位
-static constexpr const uint8_t VMM_PAGE_VALID = 1 << 0;
+static constexpr const uint8_t VMM_PAGE_VALID = CPU::pte_t::VALID;
/// 可读位
-static constexpr const uint8_t VMM_PAGE_READABLE = 1 << 1;
-/// 可写位
-static constexpr const uint8_t VMM_PAGE_WRITABLE = 1 << 2;
+static constexpr const uint8_t VMM_PAGE_READABLE = CPU::pte_t::READ;
+/// 可写位s
+static constexpr const uint8_t VMM_PAGE_WRITABLE = CPU::pte_t::WRITE;
/// 可执行位
-static constexpr const uint8_t VMM_PAGE_EXECUTABLE = 1 << 3;
+static constexpr const uint8_t VMM_PAGE_EXECUTABLE = CPU::pte_t::EXEC;
/// 用户位
-static constexpr const uint8_t VMM_PAGE_USER = 1 << 4;
+static constexpr const uint8_t VMM_PAGE_USER = CPU::pte_t::USER;
/// 全局位,我们不会使用
-static constexpr const uint8_t VMM_PAGE_GLOBAL = 1 << 5;
+static constexpr const uint8_t VMM_PAGE_GLOBAL = CPU::pte_t::GLOBAL;
/// 已使用位,用于替换算法
-static constexpr const uint8_t VMM_PAGE_ACCESSED = 1 << 6;
+static constexpr const uint8_t VMM_PAGE_ACCESSED = CPU::pte_t::ACCESSED;
/// 已修改位,用于替换算法
-static constexpr const uint8_t VMM_PAGE_DIRTY = 1 << 7;
+static constexpr const uint8_t VMM_PAGE_DIRTY = CPU::pte_t::DIRTY;
/// 内核虚拟地址相对物理地址的偏移
-static constexpr const size_t KERNEL_OFFSET = 0x0;
+static constexpr const size_t KERNEL_OFFSET = 0x0;
/// PTE 属性位数
-static constexpr const size_t VMM_PTE_PROP_BITS = 10;
+static constexpr const size_t VMM_PTE_PROP_BITS = 10;
/// PTE 页内偏移位数
-static constexpr const size_t VMM_PAGE_OFF_BITS = 12;
+static constexpr const size_t VMM_PAGE_OFF_BITS = 12;
/// VPN 位数
-static constexpr const size_t VMM_VPN_BITS = 9;
+static constexpr const size_t VMM_VPN_BITS = 9;
/// VPN 位数掩码,9 位 VPN
-static constexpr const size_t VMM_VPN_BITS_MASK = 0x1FF;
+static constexpr const size_t VMM_VPN_BITS_MASK = 0x1FF;
/// riscv64 使用了三级页表
-static constexpr const size_t VMM_PT_LEVEL = 3;
+static constexpr const size_t VMM_PT_LEVEL = 3;
#endif
/**
@@ -184,34 +185,35 @@ class VMM {
* @param _alloc 是否分配
* @return pte_t* 未找到返回 nullptr
*/
- pte_t *find(const pt_t _pgd, uintptr_t _va, bool _alloc);
+ pte_t* find(const pt_t _pgd, uintptr_t _va, bool _alloc);
protected:
+
public:
/**
* @brief 获取单例
* @return VMM& 静态对象
*/
- static VMM &get_instance(void);
+ static VMM& get_instance(void);
/**
* @brief 初始化
* @return true 成功
* @return false 失败
*/
- bool init(void);
+ bool init(void);
/**
* @brief 获取当前页目录
* @return pt_t 当前页目录
*/
- pt_t get_pgd(void);
+ pt_t get_pgd(void);
/**
* @brief 设置当前页目录
* @param _pgd 要设置的页目录
*/
- void set_pgd(const pt_t _pgd);
+ void set_pgd(const pt_t _pgd);
/**
* @brief 映射物理地址到虚拟地址
@@ -237,7 +239,7 @@ class VMM {
* @return true 已映射
* @return false 未映射
*/
- bool get_mmap(const pt_t _pgd, uintptr_t _va, const void *_pa);
+ bool get_mmap(const pt_t _pgd, uintptr_t _va, const void* _pa);
};
-#endif /* _VMM_H */
+#endif /* SIMPLEKERNEL_VMM_H */
diff --git a/src/include/resource.h b/src/include/resource.h
index d82f681fa..1db61684b 100644
--- a/src/include/resource.h
+++ b/src/include/resource.h
@@ -14,12 +14,12 @@
*
*/
-#ifndef _RESOURCE_H_
-#define _RESOURCE_H_
+#ifndef SIMPLEKERNEL_RESOURCE_H
+#define SIMPLEKERNEL_RESOURCE_H
-#include "stdint.h"
+#include "cassert"
+#include "cstdint"
#include "iostream"
-#include "assert.h"
/**
* @brief 用于表示一种资源
@@ -28,18 +28,21 @@ struct resource_t {
/// 资源类型
enum : uint8_t {
/// 内存
- MEM = 1 << 0,
+ MEM = 1 << 0,
/// 中断号
INTR_NO = 1 << 1,
};
+
uint8_t type;
/// 资源名称
- char *name;
+ char* name;
+
/// 内存信息
struct {
uintptr_t addr;
size_t len;
} mem;
+
/// 中断号
uint8_t intr_no;
@@ -56,7 +59,7 @@ struct resource_t {
* @param _res 要输出的 resource_t
* @return std::ostream& 输出流
*/
- friend std::ostream &operator<<(std::ostream &_os, const resource_t &_res) {
+ friend std::ostream& operator<<(std::ostream& _os, const resource_t& _res) {
printf("%s: ", _res.name);
if (_res.type & MEM) {
printf("MEM(0x%p, 0x%p)", _res.mem.addr, _res.mem.len);
@@ -68,4 +71,4 @@ struct resource_t {
}
};
-#endif /* _RESOURCE_H_ */
+#endif /* SIMPLEKERNEL_RESOURCE_H */
diff --git a/src/kernel/allocator.cpp b/src/kernel/allocator.cpp
index dbfd049dc..40b447b3b 100644
--- a/src/kernel/allocator.cpp
+++ b/src/kernel/allocator.cpp
@@ -14,13 +14,11 @@
*
*/
-#include "stddef.h"
-#include "stdint.h"
-#include "assert.h"
-#include "common.h"
#include "allocator.h"
+#include "cstddef"
+#include "cstdint"
-ALLOCATOR::ALLOCATOR(const char *_name, uintptr_t _addr, size_t _len) {
+ALLOCATOR::ALLOCATOR(const char* _name, uintptr_t _addr, size_t _len) {
// 默认名字
name = _name;
allocator_start_addr = _addr;
diff --git a/src/kernel/firstfit.cpp b/src/kernel/firstfit.cpp
index 943e94ff9..9b97f06b5 100644
--- a/src/kernel/firstfit.cpp
+++ b/src/kernel/firstfit.cpp
@@ -14,11 +14,11 @@
*
*/
-#include "stdint.h"
-#include "string.h"
-#include "pmm.h"
-#include "stdio.h"
#include "firstfit.h"
+#include "common.h"
+#include "cstdint"
+#include "cstdio"
+#include "cstring"
void FIRSTFIT::set(size_t _idx) {
map[_idx >> SHIFT] |= (uintptr_t)1 << (_idx & MASK);
@@ -53,7 +53,7 @@ size_t FIRSTFIT::find_len(size_t _len, bool _val) const {
return ~(size_t)0;
}
-FIRSTFIT::FIRSTFIT(const char *_name, uintptr_t _addr, size_t _len)
+FIRSTFIT::FIRSTFIT(const char* _name, uintptr_t _addr, size_t _len)
: ALLOCATOR(_name, _addr, _len) {
// 所有清零
bzero(map, sizeof(map));
@@ -70,7 +70,7 @@ FIRSTFIT::~FIRSTFIT(void) {
uintptr_t FIRSTFIT::alloc(size_t _len) {
uintptr_t res_addr = 0;
// 在位图中寻找连续 _len 的位置
- size_t idx = find_len(_len, false);
+ size_t idx = find_len(_len, false);
// 如果为 ~0 说明未找到
if (idx == ~(size_t)0) {
// err("NO ENOUGH MEM.\n");
@@ -83,7 +83,7 @@ uintptr_t FIRSTFIT::alloc(size_t _len) {
}
// 计算实际地址
// 分配器起始地址+页长度*第几页
- res_addr = allocator_start_addr + (COMMON::PAGE_SIZE * idx);
+ res_addr = allocator_start_addr + (COMMON::PAGE_SIZE * idx);
// 更新统计信息
allocator_free_count -= _len;
allocator_used_count += _len;
@@ -92,9 +92,9 @@ uintptr_t FIRSTFIT::alloc(size_t _len) {
bool FIRSTFIT::alloc(uintptr_t _addr, size_t _len) {
// _addr 不在管理范围内
- if ((_addr < allocator_start_addr) ||
- (_addr >=
- allocator_start_addr + allocator_length * COMMON::PAGE_SIZE)) {
+ if ((_addr < allocator_start_addr)
+ || (_addr
+ >= allocator_start_addr + allocator_length * COMMON::PAGE_SIZE)) {
return false;
}
// 计算 _addr 在 map 中的索引
@@ -120,9 +120,9 @@ bool FIRSTFIT::alloc(uintptr_t _addr, size_t _len) {
void FIRSTFIT::free(uintptr_t _addr, size_t _len) {
// _addr 不在管理范围内
- if ((_addr < allocator_start_addr) ||
- (_addr >=
- allocator_start_addr + allocator_length * COMMON::PAGE_SIZE)) {
+ if ((_addr < allocator_start_addr)
+ || (_addr
+ >= allocator_start_addr + allocator_length * COMMON::PAGE_SIZE)) {
return;
}
// 计算 _addr 在 map 中的索引
diff --git a/src/kernel/heap.cpp b/src/kernel/heap.cpp
index 40b4a90f0..dfbb6a156 100644
--- a/src/kernel/heap.cpp
+++ b/src/kernel/heap.cpp
@@ -14,35 +14,72 @@
*
*/
-#include "stdio.h"
+#include "heap.h"
#include "common.h"
+#include "cstdio"
#include "pmm.h"
-#include "heap.h"
-HEAP &HEAP::get_instance(void) {
+HEAP& HEAP::get_instance(void) {
/// 定义全局 HEAP 对象
static HEAP heap;
return heap;
}
bool HEAP::init(void) {
- static SLAB slab_allocator(
- "SLAB Allocator", PMM::get_instance().get_non_kernel_space_start(),
- PMM::get_instance().get_non_kernel_space_length() * COMMON::PAGE_SIZE);
- allocator = (ALLOCATOR *)&slab_allocator;
+ // 内核空间
+ static SLAB slab_allocator_kernel(
+ "SLAB Allocator Kernel", PMM::get_instance().get_kernel_space_start(),
+ PMM::get_instance().get_kernel_space_length() * COMMON::PAGE_SIZE, true);
+ allocator_kernel = (ALLOCATOR*)&slab_allocator_kernel;
+ // 非内核空间
+ static SLAB slab_allocator_non_kernel(
+ "SLAB Allocator", PMM::get_instance().get_non_kernel_space_start(),
+ PMM::get_instance().get_non_kernel_space_length() * COMMON::PAGE_SIZE,
+ false);
+ allocator_non_kernel = (ALLOCATOR*)&slab_allocator_non_kernel;
info("heap init.\n");
return 0;
}
-void *HEAP::malloc(size_t _byte) {
- void *ret = nullptr;
- ret = (void *)allocator->alloc(_byte);
+void* HEAP::kmalloc(size_t _byte) {
+ void* ret = nullptr;
+ ret = (void*)allocator_kernel->alloc(_byte);
return ret;
}
-void HEAP::free(void *_addr) {
+void HEAP::kfree(void* _addr) {
// 堆不需要 _len 参数
- allocator->free((uintptr_t)_addr, 0);
+ allocator_kernel->free((uintptr_t)_addr, 0);
+ return;
+}
+
+void* HEAP::malloc(size_t _byte) {
+ void* ret = nullptr;
+ ret = (void*)allocator_non_kernel->alloc(_byte);
+ return ret;
+}
+
+void HEAP::free(void* _addr) {
+ // 堆不需要 _len 参数
+ allocator_non_kernel->free((uintptr_t)_addr, 0);
+ return;
+}
+
+/**
+ * @brief 分配内核空间内存
+ * @param _size 要申请的 bytes
+ * @return void* 申请到的地址
+ */
+extern "C" void* kmalloc(size_t _size) {
+ return (void*)HEAP::get_instance().kmalloc(_size);
+}
+
+/**
+ * @brief 释放内核空间内存
+ * @param _p 要释放的内存地址
+ */
+extern "C" void kfree(void* _p) {
+ HEAP::get_instance().kfree(_p);
return;
}
@@ -51,15 +88,15 @@ void HEAP::free(void *_addr) {
* @param _size 要申请的 bytes
* @return void* 申请到的地址
*/
-extern "C" void *malloc(size_t _size) {
- return (void *)HEAP::get_instance().malloc(_size);
+extern "C" void* malloc(size_t _size) {
+ return (void*)HEAP::get_instance().malloc(_size);
}
/**
* @brief free 定义
* @param _p 要释放的内存地址
*/
-extern "C" void free(void *_p) {
+extern "C" void free(void* _p) {
HEAP::get_instance().free(_p);
return;
}
diff --git a/src/kernel/include/kernel.h b/src/kernel/include/kernel.h
index 293f8d1fe..32361ecca 100644
--- a/src/kernel/include/kernel.h
+++ b/src/kernel/include/kernel.h
@@ -14,8 +14,8 @@
*
*/
-#ifndef _KERNEL_H_
-#define _KERNEL_H_
+#ifndef SIMPLEKERNEL_KERNEL_H
+#define SIMPLEKERNEL_KERNEL_H
/**
* @brief 声明 kernel_main 用 C 方法编译
@@ -27,23 +27,29 @@ extern "C" void kernel_main(void);
* @brief 物理内存测试函数
* @return int 0 成功
*/
-int test_pmm(void);
+int test_pmm(void);
/**
* @brief 虚拟内存测试函数
* @return int 0 成功
*/
-int test_vmm(void);
+int test_vmm(void);
/**
* @brief 堆测试函数
- * @return int desc
+ * @return int 0 成功
+ */
+int test_heap(void);
+
+/**
+ * @brief 中断测试函数
+ * @return int 0 成功
*/
-int test_heap(void);
+int test_intr(void);
/**
* @brief 输出系统信息
*/
-void show_info(void);
+void show_info(void);
-#endif /* _KERNEL_H_ */
+#endif /* SIMPLEKERNEL_KERNEL_H */
diff --git a/src/kernel/io.cpp b/src/kernel/io.cpp
index fe6329c02..66ad0d6e6 100644
--- a/src/kernel/io.cpp
+++ b/src/kernel/io.cpp
@@ -1,20 +1,28 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-//
-// io.cpp for Simple-XX/SimpleKernel.
-// IO 接口实现
-
-#include "stddef.h"
-#include "stdarg.h"
-#include "string.h"
+/**
+ * @file io.cpp
+ * @brief IO 接口实现
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2021-09-18
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2021-09-18 digmouse233 迁移到 doxygen
+ *
+ */
+
+#include "cstdarg"
+#include "cstring"
#ifndef __riscv
-#include "port.h"
+# include "port.h"
#endif
+#include "cstdio"
#include "io.h"
-#include "stdio.h"
-IO &IO::get_instance(void) {
+IO& IO::get_instance(void) {
/// 定义全局 IO 对象
static IO io;
return io;
@@ -51,39 +59,39 @@ void IO::outd(const uint32_t port, const uint32_t data) {
#endif
// MMIO 实现
-uint8_t IO::read8(void *_addr) {
- return *(uint8_t *)_addr;
+uint8_t IO::read8(void* _addr) {
+ return *(uint8_t*)_addr;
}
-void IO::write8(void *_addr, uint8_t _val) {
- *(uint8_t *)_addr = _val;
+void IO::write8(void* _addr, uint8_t _val) {
+ *(uint8_t*)_addr = _val;
return;
}
-uint16_t IO::read16(void *_addr) {
- return *(uint16_t *)_addr;
+uint16_t IO::read16(void* _addr) {
+ return *(uint16_t*)_addr;
}
-void IO::write16(void *_addr, uint16_t _val) {
- *(uint16_t *)_addr = _val;
+void IO::write16(void* _addr, uint16_t _val) {
+ *(uint16_t*)_addr = _val;
return;
}
-uint32_t IO::read32(void *_addr) {
- return *(uint32_t *)_addr;
+uint32_t IO::read32(void* _addr) {
+ return *(uint32_t*)_addr;
}
-void IO::write32(void *_addr, uint32_t _val) {
- *(uint32_t *)_addr = _val;
+void IO::write32(void* _addr, uint32_t _val) {
+ *(uint32_t*)_addr = _val;
return;
}
-uint64_t IO::read64(void *_addr) {
- return *(uint64_t *)_addr;
+uint64_t IO::read64(void* _addr) {
+ return *(uint64_t*)_addr;
}
-void IO::write64(void *_addr, uint64_t _val) {
- *(uint64_t *)_addr = _val;
+void IO::write64(void* _addr, uint64_t _val) {
+ *(uint64_t*)_addr = _val;
return;
}
@@ -104,20 +112,20 @@ void IO::put_char(char c) {
return;
}
-int32_t IO::write_string(const char *s) {
+int32_t IO::write_string(const char* s) {
io.write_string(s);
return 0;
}
/// 输出缓冲区
-char buf[IO::BUF_SIZE];
+char buf[IO::BUF_SIZE];
/**
* @brief printf 定义
* @param _fmt 格式化字符串
* @return int32_t 输出的长度
*/
-extern "C" int32_t printf(const char *_fmt, ...) {
+extern "C" int32_t printf(const char* _fmt, ...) {
va_list va;
va_start(va, _fmt);
// 交给 src/libc/src/stdio/vsprintf.c 中的 _vsnprintf
@@ -134,13 +142,13 @@ extern "C" int32_t printf(const char *_fmt, ...) {
/**
* @brief 与 printf 类似,只是颜色不同
*/
-extern "C" int32_t info(const char *_fmt, ...) {
+extern "C" int32_t info(const char* _fmt, ...) {
COLOR::color_t curr_color = IO::get_instance().get_color();
IO::get_instance().set_color(COLOR::CYAN);
va_list va;
int32_t i;
va_start(va, _fmt);
- i = vsnprintf_(buf, (size_t)-1, _fmt, va);
+ i = vsnprintf_(buf, IO::BUF_SIZE, _fmt, va);
va_end(va);
IO::get_instance().write_string(buf);
bzero(buf, IO::BUF_SIZE);
@@ -151,13 +159,13 @@ extern "C" int32_t info(const char *_fmt, ...) {
/**
* @brief 与 printf 类似,只是颜色不同
*/
-extern "C" int32_t warn(const char *_fmt, ...) {
+extern "C" int32_t warn(const char* _fmt, ...) {
COLOR::color_t curr_color = IO::get_instance().get_color();
IO::get_instance().set_color(COLOR::YELLOW);
va_list va;
int32_t i;
va_start(va, _fmt);
- i = vsnprintf_(buf, (size_t)-1, _fmt, va);
+ i = vsnprintf_(buf, IO::BUF_SIZE, _fmt, va);
va_end(va);
IO::get_instance().write_string(buf);
bzero(buf, IO::BUF_SIZE);
@@ -168,13 +176,13 @@ extern "C" int32_t warn(const char *_fmt, ...) {
/**
* @brief 与 printf 类似,只是颜色不同
*/
-extern "C" int32_t err(const char *_fmt, ...) {
+extern "C" int32_t err(const char* _fmt, ...) {
COLOR::color_t curr_color = IO::get_instance().get_color();
IO::get_instance().set_color(COLOR::LIGHT_RED);
va_list va;
int32_t i;
va_start(va, _fmt);
- i = vsnprintf_(buf, (size_t)-1, _fmt, va);
+ i = vsnprintf_(buf, IO::BUF_SIZE, _fmt, va);
va_end(va);
IO::get_instance().write_string(buf);
bzero(buf, IO::BUF_SIZE);
diff --git a/src/kernel/kernel_main.cpp b/src/kernel/kernel_main.cpp
index 81aade5de..fe66c4883 100644
--- a/src/kernel/kernel_main.cpp
+++ b/src/kernel/kernel_main.cpp
@@ -14,23 +14,18 @@
*
*/
-#include "cxxabi.h"
-#include "common.h"
-#include "stdio.h"
-#include "stdlib.h"
-#include "iostream"
-#include "assert.h"
#include "boot_info.h"
-#include "pmm.h"
-#include "vmm.h"
+#include "cassert"
+#include "common.h"
+#include "cpu.hpp"
+#include "cstdio"
+#include "cstdlib"
#include "heap.h"
#include "intr.h"
-#include "cpu.hpp"
+#include "iostream"
#include "kernel.h"
-#include "dtb.h"
-
-/// @todo gdb 调试
-/// @todo clion 环境
+#include "pmm.h"
+#include "vmm.h"
/**
* @brief 内核主要逻辑
@@ -54,6 +49,8 @@ void kernel_main(void) {
test_heap();
// 中断初始化
INTR::get_instance().init();
+ // 测试中断
+ test_intr();
// 时钟中断初始化
TIMER::get_instance().init();
// 允许中断
@@ -76,10 +73,10 @@ void show_info(void) {
// 内核实际大小
auto kernel_size = COMMON::KERNEL_END_ADDR - COMMON::KERNEL_START_ADDR;
// 内核实际占用页数
- auto kernel_pages =
- (COMMON::ALIGN(COMMON::KERNEL_END_ADDR, COMMON::PAGE_SIZE) -
- COMMON::ALIGN(COMMON::KERNEL_START_ADDR, COMMON::PAGE_SIZE)) /
- COMMON::PAGE_SIZE;
+ auto kernel_pages
+ = (COMMON::ALIGN(COMMON::KERNEL_END_ADDR, COMMON::PAGE_SIZE)
+ - COMMON::ALIGN(COMMON::KERNEL_START_ADDR, COMMON::PAGE_SIZE))
+ / COMMON::PAGE_SIZE;
info("Kernel start: 0x%p, end 0x%p, size: 0x%X bytes, 0x%X pages.\n",
COMMON::KERNEL_START_ADDR, COMMON::KERNEL_END_ADDR, kernel_size,
kernel_pages);
diff --git a/src/kernel/pmm.cpp b/src/kernel/pmm.cpp
index 09fd7a424..8225724ad 100644
--- a/src/kernel/pmm.cpp
+++ b/src/kernel/pmm.cpp
@@ -14,13 +14,13 @@
*
*/
-#include "stdio.h"
-#include "string.h"
-#include "assert.h"
-#include "common.h"
+#include "pmm.h"
#include "boot_info.h"
+#include "cassert"
+#include "common.h"
+#include "cstdio"
+#include "cstring"
#include "resource.h"
-#include "pmm.h"
// 将启动信息移动到内核空间
void PMM::move_boot_info(void) {
@@ -32,7 +32,7 @@ void PMM::move_boot_info(void) {
// 申请空间
uintptr_t new_addr = get_instance().alloc_pages_kernel(pages);
// 复制过来,完成后以前的内存就可以使用了
- memcpy((void *)new_addr, (void *)BOOT_INFO::boot_info_addr,
+ memcpy((void*)new_addr, (void*)BOOT_INFO::boot_info_addr,
pages * COMMON::PAGE_SIZE);
// 设置地址
BOOT_INFO::boot_info_addr = (uintptr_t)new_addr;
@@ -41,7 +41,7 @@ void PMM::move_boot_info(void) {
return;
}
-PMM &PMM::get_instance(void) {
+PMM& PMM::get_instance(void) {
/// 定义全局 PMM 对象
static PMM pmm;
return pmm;
@@ -51,46 +51,47 @@ bool PMM::init(void) {
// 获取物理内存信息
resource_t mem_info = BOOT_INFO::get_memory();
// 设置物理地址的起点与长度
- start = mem_info.mem.addr;
- length = mem_info.mem.len;
+ start = mem_info.mem.addr;
+ length = mem_info.mem.len;
// 计算页数
- total_pages = length / COMMON::PAGE_SIZE;
+ total_pages = length / COMMON::PAGE_SIZE;
// 内核空间地址开始
- kernel_space_start = COMMON::KERNEL_START_ADDR;
+ kernel_space_start = COMMON::KERNEL_START_ADDR;
// 长度手动指定
kernel_space_length = COMMON::KERNEL_SPACE_SIZE;
// 非内核空间在内核空间结束后
- non_kernel_space_start =
- COMMON::KERNEL_START_ADDR + COMMON::KERNEL_SPACE_SIZE;
+ non_kernel_space_start
+ = COMMON::KERNEL_START_ADDR + COMMON::KERNEL_SPACE_SIZE;
// 长度为总长度减去内核长度
non_kernel_space_length = length - kernel_space_length;
// 创建分配器
// 内核空间
static FIRSTFIT first_fit_allocator_kernel(
- "First Fit Allocator(kernel space)", kernel_space_start,
- kernel_space_length / COMMON::PAGE_SIZE);
- kernel_space_allocator = (ALLOCATOR *)&first_fit_allocator_kernel;
-
+ "First Fit Allocator(kernel space)", kernel_space_start,
+ kernel_space_length / COMMON::PAGE_SIZE);
+ kernel_space_allocator = (ALLOCATOR*)&first_fit_allocator_kernel;
// 非内核空间
- static FIRSTFIT first_fit_allocator(
- "First Fit Allocator", non_kernel_space_start,
- non_kernel_space_length / COMMON::PAGE_SIZE);
- allocator = (ALLOCATOR *)&first_fit_allocator;
+ static FIRSTFIT first_fit_allocator("First Fit Allocator",
+ non_kernel_space_start,
+ non_kernel_space_length
+ / COMMON::PAGE_SIZE);
+ allocator = (ALLOCATOR*)&first_fit_allocator;
// 内核实际占用页数 这里也算了 0~1M 的 reserved 内存
- size_t kernel_pages =
- (COMMON::ALIGN(COMMON::KERNEL_END_ADDR, COMMON::PAGE_SIZE) -
- COMMON::ALIGN(COMMON::KERNEL_START_ADDR, COMMON::PAGE_SIZE)) /
- COMMON::PAGE_SIZE;
+ size_t kernel_pages
+ = (COMMON::ALIGN(COMMON::KERNEL_END_ADDR, COMMON::PAGE_SIZE)
+ - COMMON::ALIGN(COMMON::KERNEL_START_ADDR, COMMON::PAGE_SIZE))
+ / COMMON::PAGE_SIZE;
// 将内核已使用部分划分出来
if (alloc_pages_kernel(COMMON::KERNEL_START_ADDR, kernel_pages) == true) {
// 将 multiboot2/dtb 信息移动到内核空间
- get_instance().move_boot_info();
+ move_boot_info();
info("pmm init.\n");
return true;
}
else {
+ assert(0);
return false;
}
}
@@ -99,6 +100,14 @@ size_t PMM::get_pmm_length(void) const {
return length;
}
+uintptr_t PMM::get_kernel_space_start(void) const {
+ return kernel_space_start;
+}
+
+size_t PMM::get_kernel_space_length(void) const {
+ return kernel_space_length;
+}
+
uintptr_t PMM::get_non_kernel_space_start(void) const {
return non_kernel_space_start;
}
@@ -108,14 +117,14 @@ size_t PMM::get_non_kernel_space_length(void) const {
}
size_t PMM::get_used_pages_count(void) const {
- size_t ret =
- kernel_space_allocator->get_used_count() + allocator->get_used_count();
+ size_t ret
+ = kernel_space_allocator->get_used_count() + allocator->get_used_count();
return ret;
}
size_t PMM::get_free_pages_count(void) const {
- size_t ret =
- kernel_space_allocator->get_free_count() + allocator->get_free_count();
+ size_t ret
+ = kernel_space_allocator->get_free_count() + allocator->get_free_count();
return ret;
}
@@ -151,12 +160,12 @@ bool PMM::alloc_pages_kernel(uintptr_t _addr, size_t _len) {
void PMM::free_page(uintptr_t _addr) {
// 判断应该使用哪个分配器
- if (_addr >= kernel_space_start &&
- _addr < kernel_space_start + kernel_space_length) {
+ if (_addr >= kernel_space_start
+ && _addr < kernel_space_start + kernel_space_length) {
kernel_space_allocator->free(_addr, 1);
}
- else if (_addr >= non_kernel_space_start &&
- _addr < non_kernel_space_start + non_kernel_space_length) {
+ else if (_addr >= non_kernel_space_start
+ && _addr < non_kernel_space_start + non_kernel_space_length) {
allocator->free(_addr, 1);
}
else {
@@ -168,12 +177,12 @@ void PMM::free_page(uintptr_t _addr) {
void PMM::free_pages(uintptr_t _addr, size_t _len) {
// 判断应该使用哪个分配器
- if (_addr >= kernel_space_start &&
- _addr < kernel_space_start + kernel_space_length) {
+ if (_addr >= kernel_space_start
+ && _addr < kernel_space_start + kernel_space_length) {
kernel_space_allocator->free(_addr, _len);
}
- else if (_addr >= non_kernel_space_start &&
- _addr < non_kernel_space_start + non_kernel_space_length) {
+ else if (_addr >= non_kernel_space_start
+ && _addr < non_kernel_space_start + non_kernel_space_length) {
allocator->free(_addr, _len);
}
// 如果都不是说明有问题
diff --git a/src/kernel/slab.cpp b/src/kernel/slab.cpp
index 9b6b08b9f..2ef5f6007 100644
--- a/src/kernel/slab.cpp
+++ b/src/kernel/slab.cpp
@@ -14,12 +14,12 @@
*
*/
-#include "stdio.h"
-#include "string.h"
+#include "slab.h"
#include "assert.h"
+#include "cstdio"
#include "pmm.h"
+#include "string.h"
#include "vmm.h"
-#include "slab.h"
SLAB::chunk_t::chunk_t(void) {
addr = HEAD;
@@ -35,7 +35,7 @@ SLAB::chunk_t::~chunk_t(void) {
size_t SLAB::chunk_t::size(void) const {
size_t res = 0;
- chunk_t *tmp = this->next;
+ chunk_t* tmp = this->next;
while (tmp != this) {
res++;
tmp = tmp->next;
@@ -43,22 +43,22 @@ size_t SLAB::chunk_t::size(void) const {
return res;
}
-bool SLAB::chunk_t::operator==(const chunk_t &_node) const {
- return addr == _node.addr && len == _node.len && prev == _node.prev &&
- next == _node.next;
+bool SLAB::chunk_t::operator==(const chunk_t& _node) const {
+ return addr == _node.addr && len == _node.len && prev == _node.prev
+ && next == _node.next;
}
-bool SLAB::chunk_t::operator!=(const chunk_t &_node) const {
- return addr != _node.addr || len != _node.len || prev != _node.prev ||
- next != _node.next;
+bool SLAB::chunk_t::operator!=(const chunk_t& _node) const {
+ return addr != _node.addr || len != _node.len || prev != _node.prev
+ || next != _node.next;
}
-SLAB::chunk_t &SLAB::chunk_t::operator[](size_t _idx) const {
+SLAB::chunk_t& SLAB::chunk_t::operator[](size_t _idx) const {
// 判断越界
assert(_idx < size());
- const chunk_t *res = nullptr;
+ const chunk_t* res = nullptr;
// 找到头节点
- const chunk_t *tmp = this;
+ const chunk_t* tmp = this;
while (tmp->next != this) {
if (tmp->addr == HEAD && tmp->len == HEAD) {
res = tmp;
@@ -72,11 +72,11 @@ SLAB::chunk_t &SLAB::chunk_t::operator[](size_t _idx) const {
}
// res 必不为空
assert(res != nullptr);
- return *(const_cast(res));
+ return *(const_cast(res));
}
// 由于是循环队列,相当于在头节点前面插入
-void SLAB::chunk_t::push_back(chunk_t *_new_node) {
+void SLAB::chunk_t::push_back(chunk_t* _new_node) {
_new_node->next = this;
_new_node->prev = prev;
prev->next = _new_node;
@@ -84,36 +84,53 @@ void SLAB::chunk_t::push_back(chunk_t *_new_node) {
return;
}
-void SLAB::slab_cache_t::move(chunk_t &_list, chunk_t *_node) {
+void SLAB::slab_cache_t::move(chunk_t& _list, chunk_t* _node) {
// 从当前链表中删除
_node->prev->next = _node->next;
_node->next->prev = _node->prev;
// 重置指针
- _node->prev = _node;
- _node->next = _node;
+ _node->prev = _node;
+ _node->next = _node;
// 插入新链表
_list.push_back(_node);
return;
}
-SLAB::chunk_t *SLAB::slab_cache_t::alloc_pmm(size_t _len) {
+SLAB::chunk_t* SLAB::slab_cache_t::alloc_pmm(size_t _len) {
// 计算页数
size_t pages = _len / COMMON::PAGE_SIZE;
if (_len % COMMON::PAGE_SIZE != 0) {
pages += 1;
}
// 申请
- chunk_t *new_node = (chunk_t *)PMM::get_instance().alloc_pages(pages);
+ chunk_t* new_node = nullptr;
+ if (is_kernel_space == true) {
+ new_node = (chunk_t*)PMM::get_instance().alloc_pages_kernel(pages);
+ }
+ else {
+ new_node = (chunk_t*)PMM::get_instance().alloc_pages(pages);
+ }
// 如果没有映射则进行映射
uintptr_t tmp = 0;
for (size_t i = 0; i < pages; i++) {
// 地址=初始地址+页数偏移
- tmp = (uintptr_t)((uint8_t *)new_node + i * COMMON::PAGE_SIZE);
- if (VMM::get_instance().get_mmap(VMM::get_instance().get_pgd(), tmp,
- 0) == false) {
- VMM::get_instance().mmap(VMM::get_instance().get_pgd(),
- (uintptr_t)new_node, (uintptr_t)new_node,
- VMM_PAGE_READABLE | VMM_PAGE_WRITABLE);
+ tmp = (uintptr_t)((uint8_t*)new_node + i * COMMON::PAGE_SIZE);
+ if ((VMM::get_instance().get_mmap(VMM::get_instance().get_pgd(), tmp, 0)
+ == false)
+ || (is_kernel_space)) {
+ if (is_kernel_space == true) {
+ VMM::get_instance().mmap(VMM::get_instance().get_pgd(),
+ (uintptr_t)new_node,
+ (uintptr_t)new_node,
+ VMM_PAGE_READABLE | VMM_PAGE_WRITABLE);
+ }
+ else {
+ VMM::get_instance().mmap(VMM::get_instance().get_pgd(),
+ (uintptr_t)new_node,
+ (uintptr_t)new_node,
+ VMM_PAGE_READABLE | VMM_PAGE_WRITABLE
+ | VMM_PAGE_USER);
+ }
}
// 已经映射的情况是不应该出现的
else {
@@ -126,7 +143,7 @@ SLAB::chunk_t *SLAB::slab_cache_t::alloc_pmm(size_t _len) {
// 自身的地址
new_node->addr = (uintptr_t)new_node;
// 长度需要减去 chunk_t 的长度
- new_node->len = (pages * COMMON::PAGE_SIZE) - CHUNK_SIZE;
+ new_node->len = (pages * COMMON::PAGE_SIZE) - CHUNK_SIZE;
// 链表指针
new_node->prev = new_node;
new_node->next = new_node;
@@ -137,19 +154,19 @@ SLAB::chunk_t *SLAB::slab_cache_t::alloc_pmm(size_t _len) {
}
void SLAB::slab_cache_t::free_pmm(void) {
- size_t pages = 0;
+ size_t pages = 0;
// 遍历 free 链表
- chunk_t *tmp = free.next;
+ chunk_t* tmp = free.next;
while (tmp != &free) {
pages = (tmp->len + CHUNK_SIZE) / COMMON::PAGE_SIZE;
// 必须是整数个页
assert(((tmp->len + CHUNK_SIZE) % COMMON::PAGE_SIZE) == 0);
PMM::get_instance().free_pages(tmp->addr, pages);
// 删除节点
- tmp->prev->next = tmp->next;
- tmp->next->prev = tmp->prev;
+ tmp->prev->next = tmp->next;
+ tmp->next->prev = tmp->prev;
// 取消映射后无法访问 tmp,所以提前保存
- auto tmp_next = tmp->next;
+ auto tmp_next = tmp->next;
// 取消映射
// 因为每次只能取消映射 1 页,所以需要循环
uintptr_t tmp_addr = 0;
@@ -165,11 +182,11 @@ void SLAB::slab_cache_t::free_pmm(void) {
return;
}
-void SLAB::slab_cache_t::split(chunk_t *_node, size_t _len) {
+void SLAB::slab_cache_t::split(chunk_t* _node, size_t _len) {
// 记录原大小
size_t old_len = _node->len;
// 更新旧节点
- _node->len = _len;
+ _node->len = _len;
// 旧节点移动到 full
move(full, _node);
// 原长度大于要分配的长度+新 chunk 长度
@@ -177,14 +194,14 @@ void SLAB::slab_cache_t::split(chunk_t *_node, size_t _len) {
if (old_len > _len + CHUNK_SIZE) {
// 处理新节点
// 新节点地址为原本地址+chunk大小+要分配出去的长度
- chunk_t *new_node = (chunk_t *)(_node->addr + CHUNK_SIZE + _len);
+ chunk_t* new_node = (chunk_t*)(_node->addr + CHUNK_SIZE + _len);
new_node->addr = (uintptr_t)new_node;
// 剩余长度为原本的长度减去要分配给 _node 的长度,减去新节点的 chunk
// 大小
- new_node->len = old_len - _len - CHUNK_SIZE;
+ new_node->len = old_len - _len - CHUNK_SIZE;
// 手动初始化节点
- new_node->prev = new_node;
- new_node->next = new_node;
+ new_node->prev = new_node;
+ new_node->next = new_node;
// 判断剩余空间是否可以容纳至少一个节点,即大于等于 len+CHUNK_SIZE
// 如果大于等于则建立新的节点,小于的话不用新建
// 这里只有 len 是因为 chunk 的大小并不包括在 chunk->len
@@ -206,8 +223,8 @@ void SLAB::slab_cache_t::merge(void) {
// 合并的条件
// node1->addr+CHUNK_SIZE+node1->len==node2->addr
// 暴力遍历
- chunk_t *chunk = part.next;
- chunk_t *tmp = chunk->next;
+ chunk_t* chunk = part.next;
+ chunk_t* tmp = chunk->next;
// 外层循环
while (chunk != &part) {
// 内层循环
@@ -216,12 +233,12 @@ void SLAB::slab_cache_t::merge(void) {
if (chunk->addr + CHUNK_SIZE + chunk->len == tmp->addr) {
// 进行合并
// 加上 tmp 的 chunk 长度
- chunk->len += CHUNK_SIZE;
+ chunk->len += CHUNK_SIZE;
// 加上 tmp 的 len 长度
- chunk->len += tmp->len;
+ chunk->len += tmp->len;
// 删除 tmp
- tmp->prev->next = tmp->next;
- tmp->next->prev = tmp->prev;
+ tmp->prev->next = tmp->next;
+ tmp->next->prev = tmp->prev;
break;
}
tmp = tmp->next;
@@ -250,11 +267,11 @@ void SLAB::slab_cache_t::merge(void) {
return;
}
-SLAB::chunk_t *SLAB::slab_cache_t::find(chunk_t &_which, size_t _len,
- bool _alloc) {
- chunk_t *res = nullptr;
+SLAB::chunk_t*
+SLAB::slab_cache_t::find(chunk_t& _which, size_t _len, bool _alloc) {
+ chunk_t* res = nullptr;
// 在 _which 中查找,直接遍历即可
- chunk_t *tmp = _which.next;
+ chunk_t* tmp = _which.next;
while (tmp != &_which) {
// 如果 tmp 节点的长度大于等于 _len
if (tmp->len >= _len) {
@@ -279,16 +296,16 @@ SLAB::chunk_t *SLAB::slab_cache_t::find(chunk_t &_which, size_t _len,
return res;
}
-SLAB::chunk_t *SLAB::slab_cache_t::find(size_t _len) {
- chunk_t *chunk = nullptr;
+SLAB::chunk_t* SLAB::slab_cache_t::find(size_t _len) {
+ chunk_t* chunk = nullptr;
// 在 part 里找,如果没有找到允许申请新的空间
- chunk = find(part, _len, true);
+ chunk = find(part, _len, true);
// 如果到这里 chunk 还为 nullptr 说明空间不够了
assert(chunk != nullptr);
return chunk;
}
-void SLAB::slab_cache_t::remove(chunk_t *_node) {
+void SLAB::slab_cache_t::remove(chunk_t* _node) {
// 将 _node 移动到 part 即可
move(part, _node);
// merge 会处理节点合并的情况
@@ -297,9 +314,9 @@ void SLAB::slab_cache_t::remove(chunk_t *_node) {
}
size_t SLAB::get_idx(size_t _len) const {
- size_t res = 0;
+ size_t res = 0;
// _len 向上取整
- _len += _len - 1;
+ _len += _len - 1;
while (1) {
// 每次右移一位
_len = _len >> 1;
@@ -309,7 +326,6 @@ size_t SLAB::get_idx(size_t _len) const {
res = 0;
}
else {
-
res -= SHIFT;
}
break;
@@ -319,11 +335,12 @@ size_t SLAB::get_idx(size_t _len) const {
return res;
}
-SLAB::SLAB(const char *_name, uintptr_t _addr, size_t _len)
- : ALLOCATOR(_name, _addr, _len) {
+SLAB::SLAB(const char* _name, uintptr_t _addr, size_t _len, bool _is_kernel)
+ : ALLOCATOR(_name, _addr, _len), is_kernel_space(_is_kernel) {
// 初始化 slab_cache
for (size_t i = LEN256; i < LEN65536; i++) {
- slab_cache[i].len = MIN << i;
+ slab_cache[i].len = MIN << i;
+ slab_cache[i].is_kernel_space = _is_kernel;
}
info("%s: 0x%p(0x%p bytes) init.\n", name, allocator_start_addr,
allocator_length);
@@ -342,11 +359,11 @@ uintptr_t SLAB::alloc(size_t _len) {
// 大小不能超过 65536B
if (_len > 0 && _len <= MIN << LEN65536) {
// _len 按照 8bytes 对齐
- _len = COMMON::ALIGN(_len, 8);
+ _len = COMMON::ALIGN(_len, 8);
// 根据大小确定 slab_cache 索引
- auto idx = get_idx(_len);
+ auto idx = get_idx(_len);
// 寻找合适的 slab 节点
- chunk_t *chunk = slab_cache[idx].find(_len);
+ chunk_t* chunk = slab_cache[idx].find(_len);
// 不为空的话计算地址
if (chunk != nullptr) {
assert((uintptr_t)chunk == chunk->addr);
@@ -357,7 +374,7 @@ uintptr_t SLAB::alloc(size_t _len) {
#ifdef DEBUG
info("slab alloc\n");
std::cout << slab_cache[idx];
-#undef DEBUG
+# undef DEBUG
#endif
}
// 更新统计数据
@@ -378,7 +395,7 @@ void SLAB::free(uintptr_t _addr, size_t) {
}
// 要释放一个 chunk
// 1. 计算 chunk 地址
- chunk_t *chunk = (chunk_t *)(_addr - CHUNK_SIZE);
+ chunk_t* chunk = (chunk_t*)(_addr - CHUNK_SIZE);
assert((uintptr_t)chunk == chunk->addr);
// 2. 计算所属 slab_cache 索引
auto a = chunk->len;
@@ -390,7 +407,7 @@ void SLAB::free(uintptr_t _addr, size_t) {
#ifdef DEBUG
info("slab free\n");
std::cout << slab_cache[idx];
-#undef DEBUG
+# undef DEBUG
#endif
// 更新统计数据
allocator_used_count -= a;
diff --git a/src/kernel/test.cpp b/src/kernel/test.cpp
index 05eaf356f..0cfae3ae8 100644
--- a/src/kernel/test.cpp
+++ b/src/kernel/test.cpp
@@ -1,26 +1,36 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-//
-// test.cpp for Simple-XX/SimpleKernel.
+/**
+ * @file test.cpp
+ * @brief 测试
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
+#include "cassert"
#include "common.h"
-#include "stdio.h"
-#include "iostream"
-#include "assert.h"
-#include "pmm.h"
-#include "vmm.h"
+#include "cstdio"
+#include "cstdlib"
#include "heap.h"
#include "kernel.h"
+#include "pmm.h"
+#include "vmm.h"
int32_t test_pmm(void) {
// 保存现有 pmm 空闲页数量
size_t free_pages = PMM::get_instance().get_free_pages_count();
// 计算内核实际占用页数
- auto kernel_pages =
- (COMMON::ALIGN(COMMON::KERNEL_END_ADDR, COMMON::PAGE_SIZE) -
- COMMON::ALIGN(COMMON::KERNEL_START_ADDR, COMMON::PAGE_SIZE)) /
- COMMON::PAGE_SIZE;
+ auto kernel_pages
+ = (COMMON::ALIGN(COMMON::KERNEL_END_ADDR, COMMON::PAGE_SIZE)
+ - COMMON::ALIGN(COMMON::KERNEL_START_ADDR, COMMON::PAGE_SIZE))
+ / COMMON::PAGE_SIZE;
// 再加上启动信息使用的页,一般为一页
kernel_pages++;
// TODO: 替换宏
@@ -29,9 +39,9 @@ int32_t test_pmm(void) {
kernel_pages++;
#endif
// 空闲页数应该等于物理内存大小-内核使用
- assert(free_pages ==
- (PMM::get_instance().get_pmm_length() / COMMON::PAGE_SIZE) -
- kernel_pages);
+ assert(free_pages
+ == (PMM::get_instance().get_pmm_length() / COMMON::PAGE_SIZE)
+ - kernel_pages);
// 获取已使用页数
size_t used_pages = PMM::get_instance().get_used_pages_count();
// 已使用页数应该等于内核使用页数
@@ -59,60 +69,100 @@ int32_t test_pmm(void) {
PMM::get_instance().free_pages(addr4, 100);
// 现在内存使用情况应该与此函数开始时相同
assert(PMM::get_instance().get_free_pages_count() == free_pages);
+ // 下面测试内核空间物理内存分配
+ // 已使用页数应该等于内核使用页数
+ assert(used_pages == kernel_pages);
+ // 分配
+ addr1 = PMM::get_instance().alloc_pages_kernel(2);
+ // 已使用应该会更新
+ assert(PMM::get_instance().get_used_pages_count() == 2 + kernel_pages);
+ // 同上
+ addr2 = PMM::get_instance().alloc_pages_kernel(3);
+ assert(PMM::get_instance().get_used_pages_count() == 5 + kernel_pages);
+ // 同上
+ addr3 = PMM::get_instance().alloc_pages_kernel(100);
+ assert(PMM::get_instance().get_used_pages_count() == 105 + kernel_pages);
+ // 同上
+ addr4 = PMM::get_instance().alloc_pages_kernel(100);
+ assert(PMM::get_instance().get_used_pages_count() == 205 + kernel_pages);
+ // 分配超过限度的内存,应该返回 nullptr
+ addr5 = PMM::get_instance().alloc_pages_kernel(0xFFFFFFFF);
+ assert(addr5 == 0);
+ // 全部释放
+ PMM::get_instance().free_pages(addr1, 2);
+ PMM::get_instance().free_pages(addr2, 3);
+ PMM::get_instance().free_pages(addr3, 100);
+ PMM::get_instance().free_pages(addr4, 100);
+ // 现在内存使用情况应该与此函数开始时相同
+ assert(PMM::get_instance().get_free_pages_count() == free_pages);
info("pmm test done.\n");
return 0;
}
+/// @note riscv 内核模式下无法测试 VMM_PAGE_USER,默认状态下 S/U
+/// 模式的页无法互相访问
+/// @see
+/// https://five-embeddev.com/riscv-isa-manual/latest/supervisor.html#sec:translation
int32_t test_vmm(void) {
uintptr_t addr = 0;
// 首先确认内核空间被映射了
assert(VMM::get_instance().get_pgd() != nullptr);
assert(VMM::get_instance().get_mmap(VMM::get_instance().get_pgd(),
(COMMON::KERNEL_START_ADDR + 0x1000),
- &addr) == 1);
+ &addr)
+ == 1);
assert(addr == COMMON::KERNEL_START_ADDR + 0x1000);
addr = 0;
assert(VMM::get_instance().get_mmap(VMM::get_instance().get_pgd(),
- COMMON::KERNEL_START_ADDR +
- VMM_KERNEL_SPACE_SIZE - 1,
- &addr) == 1);
- assert(addr == ((COMMON::KERNEL_START_ADDR + VMM_KERNEL_SPACE_SIZE - 1) &
- COMMON::PAGE_MASK));
+ COMMON::KERNEL_START_ADDR
+ + VMM_KERNEL_SPACE_SIZE - 1,
+ &addr)
+ == 1);
+ assert(addr
+ == ((COMMON::KERNEL_START_ADDR + VMM_KERNEL_SPACE_SIZE - 1)
+ & COMMON::PAGE_MASK));
addr = 0;
assert(VMM::get_instance().get_mmap(
- VMM::get_instance().get_pgd(),
- (COMMON::ALIGN(COMMON::KERNEL_START_ADDR, 4 * COMMON::KB) +
- VMM_KERNEL_SPACE_SIZE),
- &addr) == 0);
+ VMM::get_instance().get_pgd(),
+ (COMMON::ALIGN(COMMON::KERNEL_START_ADDR, 4 * COMMON::KB)
+ + VMM_KERNEL_SPACE_SIZE),
+ &addr)
+ == 0);
assert(addr == 0);
addr = 0;
assert(VMM::get_instance().get_mmap(
- VMM::get_instance().get_pgd(),
- (COMMON::ALIGN(COMMON::KERNEL_START_ADDR, 4 * COMMON::KB) +
- VMM_KERNEL_SPACE_SIZE + 0x1024),
- 0) == 0);
+ VMM::get_instance().get_pgd(),
+ (COMMON::ALIGN(COMMON::KERNEL_START_ADDR, 4 * COMMON::KB)
+ + VMM_KERNEL_SPACE_SIZE + 0x1024),
+ 0)
+ == 0);
// 测试映射与取消映射
- addr = 0;
+ addr = 0;
// 准备映射的虚拟地址 3GB 处
uintptr_t va = 0xC0000000;
- // 准备映射的物理地址 0.75GB 处
- uintptr_t pa = 0x30000000;
+ // 分配要映射的物理地址
+ uintptr_t pa = PMM::get_instance().alloc_page_kernel();
// 确定一块未映射的内存
assert(VMM::get_instance().get_mmap(VMM::get_instance().get_pgd(), va,
- nullptr) == 0);
+ nullptr)
+ == 0);
// 映射
VMM::get_instance().mmap(VMM::get_instance().get_pgd(), va, pa,
VMM_PAGE_READABLE | VMM_PAGE_WRITABLE);
assert(VMM::get_instance().get_mmap(VMM::get_instance().get_pgd(), va,
- &addr) == 1);
+ &addr)
+ == 1);
assert(addr == pa);
// 写测试
- *(uintptr_t *)va = 0xCD;
- //取消映射
+ *(uintptr_t*)va = 0xCD;
+ // 取消映射
VMM::get_instance().unmmap(VMM::get_instance().get_pgd(), va);
assert(VMM::get_instance().get_mmap(VMM::get_instance().get_pgd(), va,
- &addr) == 0);
+ &addr)
+ == 0);
assert(addr == 0);
+ // 回收物理地址
+ PMM::get_instance().free_page(pa);
info("vmm test done.\n");
return 0;
}
@@ -121,41 +171,57 @@ int32_t test_vmm(void) {
int test_heap(void) {
// 根据字长不同 CHUNK_SIZE 是不一样的
size_t chunk_size = 0;
- if (sizeof(void *) == 4) {
+ if (sizeof(void*) == 4) {
chunk_size = 0x10;
}
- else if (sizeof(void *) == 8) {
+ else if (sizeof(void*) == 8) {
chunk_size = 0x20;
}
- void *addr1 = nullptr;
- void *addr2 = nullptr;
- void *addr3 = nullptr;
- void *addr4 = nullptr;
+ void* addr1 = nullptr;
+ void* addr2 = nullptr;
+ void* addr3 = nullptr;
+ void* addr4 = nullptr;
// 申请超过最大允许的内存 65536B
- addr1 = HEAP::get_instance().malloc(0x10001);
+ addr1 = kmalloc(0x10001);
// 应该返回 nullptr
assert(addr1 == nullptr);
// 申请小块内存
- addr2 = HEAP::get_instance().malloc(0x1);
+ addr2 = kmalloc(0x1);
assert(addr2 != nullptr);
// 第一块被申请的内存,减去 chunk 大小后应该是 4k 对齐的
- assert(((uintptr_t)((uint8_t *)addr2 - chunk_size) & 0xFFF) == 0x0);
+ assert(((uintptr_t)((uint8_t*)addr2 - chunk_size) & 0xFFF) == 0x0);
// 在 LEN512 申请新的内存
- addr3 = HEAP::get_instance().malloc(0x200);
+ addr3 = kmalloc(0x200);
assert(addr3 != nullptr);
// 第一块被申请的内存,减去 chunk 大小后应该是 4k 对齐的
- assert(((uintptr_t)((uint8_t *)addr3 - chunk_size) & 0xFFF) == 0x0);
+ assert(((uintptr_t)((uint8_t*)addr3 - chunk_size) & 0xFFF) == 0x0);
// 加上 chunk 大小长度刚好是 LEN256
- addr4 = HEAP::get_instance().malloc(0x80);
+ addr4 = kmalloc(0x80);
assert(addr4 != nullptr);
// LEN256 区域第二块被申请的内存,地址可以计算出来
// 前一个块的地址+chunk 长度+数据长度+对齐长度
- assert(addr4 == (uint8_t *)addr2 + chunk_size + 0x1 + 0x7);
+ assert(addr4 == (uint8_t*)addr2 + chunk_size + 0x1 + 0x7);
+ /// @bug 这里释放会同时 unmmap,导致后面的分支出现 pg
// 全部释放
- HEAP::get_instance().free(addr1);
- HEAP::get_instance().free(addr2);
- HEAP::get_instance().free(addr3);
- HEAP::get_instance().free(addr4);
+ // kfree(addr1);
+ // kfree(addr2);
+ // kfree(addr3);
+ // kfree(addr4);
info("heap test done.\n");
return 0;
}
+
+// TODO: 更多测试
+int test_intr(void) {
+ // 触发 pg 中断
+ uintptr_t* addr = (uintptr_t*)0xC0000000;
+ int tmp = 0x666;
+ tmp = *addr;
+ assert(tmp == 0);
+ *addr = 0x233;
+ tmp = *addr;
+ assert(tmp == 0x233);
+ *addr = 0x0;
+ info("intr test done.\n");
+ return 0;
+}
diff --git a/src/kernel/vmm.cpp b/src/kernel/vmm.cpp
index 77b4f904c..00dfe6156 100644
--- a/src/kernel/vmm.cpp
+++ b/src/kernel/vmm.cpp
@@ -14,27 +14,27 @@
*
*/
-#include "stdint.h"
-#include "string.h"
-#include "stdio.h"
-#include "assert.h"
+#include "cassert"
#include "cpu.hpp"
+#include "cstdint"
+#include "cstdio"
+#include "cstring"
#if defined(__i386__) || defined(__x86_64__)
-#include "gdt.h"
+# include "gdt.h"
#endif
#include "pmm.h"
#include "vmm.h"
// 在 _pgd 中查找 _va 对应的页表项
// 如果未找到,_alloc 为真时会进行分配
-pte_t *VMM::find(const pt_t _pgd, uintptr_t _va, bool _alloc) {
+pte_t* VMM::find(const pt_t _pgd, uintptr_t _va, bool _alloc) {
pt_t pgd = _pgd;
// sv39 共有三级页表,一级一级查找
// -1 是因为最后一级是具体的某一页,在函数最后直接返回
for (size_t level = VMM_PT_LEVEL - 1; level > 0; level--) {
// 每次循环会找到 _va 的第 level 级页表 pgd
// 相当于 pgd_level[VPN_level],这样相当于得到了第 level 级页表的地址
- pte_t *pte = (pte_t *)&pgd[PX(level, _va)];
+ pte_t* pte = (pte_t*)&pgd[PX(level, _va)];
// 解引用 pte,如果有效,获取 level+1 级页表,
if ((*pte & VMM_PAGE_VALID) == 1) {
// pgd 指向下一级页表
@@ -70,7 +70,7 @@ pte_t *VMM::find(const pt_t _pgd, uintptr_t _va, bool _alloc) {
return &pgd[PX(0, _va)];
}
-VMM &VMM::get_instance(void) {
+VMM& VMM::get_instance(void) {
/// 定义全局 VMM 对象
static VMM vmm;
return vmm;
@@ -112,27 +112,28 @@ void VMM::set_pgd(const pt_t _pgd) {
}
void VMM::mmap(const pt_t _pgd, uintptr_t _va, uintptr_t _pa, uint32_t _flag) {
- pte_t *pte = find(_pgd, _va, true);
+ pte_t* pte = find(_pgd, _va, true);
// 一般情况下不应该为空
assert(pte != nullptr);
// 已经映射过了 且 flag 没有变化
- if (((*pte & VMM_PAGE_VALID) == VMM_PAGE_VALID) &&
- ((*pte & _flag) == _flag)) {
+ if (((*pte & VMM_PAGE_VALID) == VMM_PAGE_VALID)
+ && ((*pte & ((1 << VMM_PTE_PROP_BITS) - 1)) == _flag)) {
warn("remap.\n");
}
// 没有映射,或更改了 flag
else {
// 那么设置 *pte
// pte 解引用后的值是页表项
- *pte = PA2PTE(_pa) | _flag | VMM_PAGE_VALID;
+ *pte = PA2PTE(_pa) | _flag | (*pte & ((1 << VMM_PTE_PROP_BITS) - 1))
+ | VMM_PAGE_VALID;
// 刷新缓存
- CPU::VMM_FLUSH((uintptr_t)_va);
+ CPU::VMM_FLUSH(0);
}
return;
}
void VMM::unmmap(const pt_t _pgd, uintptr_t _va) {
- pte_t *pte = find(_pgd, _va, false);
+ pte_t* pte = find(_pgd, _va, false);
// 找到页表项
// 未找到
if (pte == nullptr) {
@@ -146,13 +147,13 @@ void VMM::unmmap(const pt_t _pgd, uintptr_t _va) {
// 置零
*pte = 0x00;
// 刷新缓存
- CPU::VMM_FLUSH((uintptr_t)_va);
+ CPU::VMM_FLUSH(0);
// TODO: 如果一页表都被 unmap,释放占用的物理内存
return;
}
-bool VMM::get_mmap(const pt_t _pgd, uintptr_t _va, const void *_pa) {
- pte_t *pte = find(_pgd, _va, false);
+bool VMM::get_mmap(const pt_t _pgd, uintptr_t _va, const void* _pa) {
+ pte_t* pte = find(_pgd, _va, false);
bool res = false;
// pte 不为空且有效,说明映射了
if ((pte != nullptr) && ((*pte & VMM_PAGE_VALID) == 1)) {
@@ -160,7 +161,7 @@ bool VMM::get_mmap(const pt_t _pgd, uintptr_t _va, const void *_pa) {
if (_pa != nullptr) {
// 设置 _pa
// 将页表项转换为物理地址
- *(uintptr_t *)_pa = PTE2PA(*pte);
+ *(uintptr_t*)_pa = PTE2PA(*pte);
}
// 返回 true
res = true;
@@ -170,7 +171,7 @@ bool VMM::get_mmap(const pt_t _pgd, uintptr_t _va, const void *_pa) {
// 如果 _pa 不为空
if (_pa != nullptr) {
// 设置 _pa
- *(uintptr_t *)_pa = (uintptr_t) nullptr;
+ *(uintptr_t*)_pa = (uintptr_t) nullptr;
}
}
return res;
diff --git a/src/libc/CMakeLists.txt b/src/libc/CMakeLists.txt
index 2030abe50..4e9453e64 100644
--- a/src/libc/CMakeLists.txt
+++ b/src/libc/CMakeLists.txt
@@ -1,5 +1,6 @@
-# This file is a part of Simple-XX/SimpleKernel (https://github.com/Simple-XX/SimpleKernel).
+# This file is a part of Simple-XX/SimpleKernel
+# (https://github.com/Simple-XX/SimpleKernel).
#
# CMakeLists.txt for Simple-XX/SimpleKernel.
diff --git a/src/libc/include/assert.h b/src/libc/include/assert.h
index c09fa38bb..f72e7435e 100644
--- a/src/libc/include/assert.h
+++ b/src/libc/include/assert.h
@@ -1,16 +1,36 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-//
-// assert.h for Simple-XX/SimpleKernel.
+/**
+ * @file assert.h
+ * @brief assert 实现
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * Based on https://wiki.osdev.org/Raspberry_Pi_Bare_Bones
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
-#ifndef _ASSERT_H_
-#define _ASSERT_H_
+#ifndef SIMPLEKERNEL_ASSERT_H
+#define SIMPLEKERNEL_ASSERT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
#include "stdio.h"
-#define assert(e) ((void)((e) ? ((void)0) : __assert(#e, __FILE__, __LINE__)))
-#define __assert(e, file, line) \
- ((void)err("%s:%d: failed assertion `%s'\n", file, line, e))
+#define assert(_e) \
+ ((void)((_e) ? ((void)0) : __assert(#_e, __FILE__, __LINE__)))
+#define __assert(_e, _file, _line) \
+ ((void)err("%s:%d: failed assertion `%s'\n", _file, _line, _e))
+
+#ifdef __cplusplus
+}
+#endif
-#endif /* _ASSERT_H_ */
+#endif /* SIMPLEKERNEL_ASSERT_H */
diff --git a/src/libc/include/ctype.h b/src/libc/include/ctype.h
index b1c94e324..269611839 100644
--- a/src/libc/include/ctype.h
+++ b/src/libc/include/ctype.h
@@ -1,23 +1,33 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-//
-// ctype.h for Simple-XX/SimpleKernel.
+/**
+ * @file ctype.h
+ * @brief ctype 定义
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
-#ifndef _CTYPE_H_
-#define _CTYPE_H_
+#ifndef SIMPLEKERNEL_CTYPE_H
+#define SIMPLEKERNEL_CTYPE_H
#ifdef __cplusplus
extern "C" {
#endif
-#define isupper(c) (c >= 'A' && c <= 'Z')
-#define isalpha(c) ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
-#define isspace(c) (c == ' ' || c == '\t' || c == '\n' || c == '\12')
-#define isdigit(c) (c >= '0' && c <= '9')
+#define isupper(_c) (_c >= 'A' && _c <= 'Z')
+#define isalpha(_c) ((_c >= 'A' && _c <= 'Z') || (_c >= 'a' && _c <= 'z'))
+#define isspace(_c) (_c == ' ' || _c == '\t' || _c == '\n' || _c == '\12')
+#define isdigit(_c) (_c >= '0' && _c <= '9')
#ifdef __cplusplus
}
#endif
-#endif /* _CTYPE_H_ */
+#endif /* SIMPLEKERNEL_CTYPE_H */
diff --git a/src/libc/include/endian.h b/src/libc/include/endian.h
index 335fc0299..27b5b7c7c 100644
--- a/src/libc/include/endian.h
+++ b/src/libc/include/endian.h
@@ -1,11 +1,21 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-//
-// endian.h for Simple-XX/SimpleKernel.
-
-#ifndef _ENDIAN_H_
-#define _ENDIAN_H_
+/**
+ * @file endian.h
+ * @brief endian 定义
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
+
+#ifndef SIMPLEKERNEL_ENDIAN_H
+#define SIMPLEKERNEL_ENDIAN_H
#ifdef __cplusplus
extern "C" {
@@ -17,87 +27,89 @@ extern "C" {
static union {
char c[4];
unsigned long mylong;
-} endian_test __attribute__((unused)) = {{'l', '?', '?', 'b'}};
+} endian_test __attribute__((unused)) = {
+ {'l', '?', '?', 'b'}
+};
// 'l' 为小端,'b' 为大端
-#define ENDIANNESS ((char)endian_test.mylong)
+#define ENDIANNESS ((char)endian_test.mylong)
#define __LITTLE_ENDIAN 1234
-#define __BIG_ENDIAN 4321
-#define __PDP_ENDIAN 3412
+#define __BIG_ENDIAN 4321
+#define __PDP_ENDIAN 3412
#if defined(__riscv) || defined(__i386__) || defined(__x86_64__)
-#define __BYTE_ORDER __LITTLE_ENDIAN
+# define __BYTE_ORDER __LITTLE_ENDIAN
#else
-#define __BYTE_ORDER __BIG_ENDIAN
+# define __BYTE_ORDER __BIG_ENDIAN
#endif
-#define BIG_ENDIAN __BIG_ENDIAN
+#define BIG_ENDIAN __BIG_ENDIAN
#define LITTLE_ENDIAN __LITTLE_ENDIAN
-#define PDP_ENDIAN __PDP_ENDIAN
-#define BYTE_ORDER __BYTE_ORDER
+#define PDP_ENDIAN __PDP_ENDIAN
+#define BYTE_ORDER __BYTE_ORDER
-static inline uint16_t __bswap16(uint16_t __x) {
+inline static uint16_t __bswap16(uint16_t __x) {
return (__x << 8) | (__x >> 8);
}
-static inline uint32_t __bswap32(uint32_t __x) {
- return (__x >> 24) | (__x >> 8 & 0xff00) | (__x << 8 & 0xff0000) |
- (__x << 24);
+inline static uint32_t __bswap32(uint32_t __x) {
+ return (__x >> 24) | (__x >> 8 & 0xff00) | (__x << 8 & 0xff0000)
+ | (__x << 24);
}
-static inline uint64_t __bswap64(uint64_t __x) {
+inline static uint64_t __bswap64(uint64_t __x) {
return (__bswap32(__x) + (0ULL << 32)) | __bswap32(__x >> 32);
}
#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define htobe16(x) __bswap16(x)
-#define be16toh(x) __bswap16(x)
-#define htobe32(x) __bswap32(x)
-#define be32toh(x) __bswap32(x)
-#define htobe64(x) __bswap64(x)
-#define be64toh(x) __bswap64(x)
-#define htole16(x) (uint16_t)(x)
-#define le16toh(x) (uint16_t)(x)
-#define htole32(x) (uint32_t)(x)
-#define le32toh(x) (uint32_t)(x)
-#define htole64(x) (uint64_t)(x)
-#define le64toh(x) (uint64_t)(x)
+# define htobe16(x) __bswap16(x)
+# define be16toh(x) __bswap16(x)
+# define htobe32(x) __bswap32(x)
+# define be32toh(x) __bswap32(x)
+# define htobe64(x) __bswap64(x)
+# define be64toh(x) __bswap64(x)
+# define htole16(x) (uint16_t)(x)
+# define le16toh(x) (uint16_t)(x)
+# define htole32(x) (uint32_t)(x)
+# define le32toh(x) (uint32_t)(x)
+# define htole64(x) (uint64_t)(x)
+# define le64toh(x) (uint64_t)(x)
#else
-#define htobe16(x) (uint16_t)(x)
-#define be16toh(x) (uint16_t)(x)
-#define htobe32(x) (uint32_t)(x)
-#define be32toh(x) (uint32_t)(x)
-#define htobe64(x) (uint64_t)(x)
-#define be64toh(x) (uint64_t)(x)
-#define htole16(x) __bswap16(x)
-#define le16toh(x) __bswap16(x)
-#define htole32(x) __bswap32(x)
-#define le32toh(x) __bswap32(x)
-#define htole64(x) __bswap64(x)
-#define le64toh(x) __bswap64(x)
+# define htobe16(x) (uint16_t)(x)
+# define be16toh(x) (uint16_t)(x)
+# define htobe32(x) (uint32_t)(x)
+# define be32toh(x) (uint32_t)(x)
+# define htobe64(x) (uint64_t)(x)
+# define be64toh(x) (uint64_t)(x)
+# define htole16(x) __bswap16(x)
+# define le16toh(x) __bswap16(x)
+# define htole32(x) __bswap32(x)
+# define le32toh(x) __bswap32(x)
+# define htole64(x) __bswap64(x)
+# define le64toh(x) __bswap64(x)
#endif
#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-#define betoh16(x) __bswap16(x)
-#define betoh32(x) __bswap32(x)
-#define betoh64(x) __bswap64(x)
-#define letoh16(x) (uint16_t)(x)
-#define letoh32(x) (uint32_t)(x)
-#define letoh64(x) (uint64_t)(x)
-#else
-#define betoh16(x) (uint16_t)(x)
-#define betoh32(x) (uint32_t)(x)
-#define betoh64(x) (uint64_t)(x)
-#define letoh16(x) __bswap16(x)
-#define letoh32(x) __bswap32(x)
-#define letoh64(x) __bswap64(x)
-#endif
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+# define betoh16(x) __bswap16(x)
+# define betoh32(x) __bswap32(x)
+# define betoh64(x) __bswap64(x)
+# define letoh16(x) (uint16_t)(x)
+# define letoh32(x) (uint32_t)(x)
+# define letoh64(x) (uint64_t)(x)
+# else
+# define betoh16(x) (uint16_t)(x)
+# define betoh32(x) (uint32_t)(x)
+# define betoh64(x) (uint64_t)(x)
+# define letoh16(x) __bswap16(x)
+# define letoh32(x) __bswap32(x)
+# define letoh64(x) __bswap64(x)
+# endif
#endif
#ifdef __cplusplus
}
#endif
-#endif /* _ENDIAN_H_ */
+#endif /* SIMPLEKERNEL_ENDIAN_H */
diff --git a/src/libc/include/float.h b/src/libc/include/float.h
index 4362fcabc..3b02c7816 100644
--- a/src/libc/include/float.h
+++ b/src/libc/include/float.h
@@ -1,11 +1,21 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-//
-// float.h for Simple-XX/SimpleKernel.
+/**
+ * @file float.h
+ * @brief float 定义
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
-#ifndef _FLOAT_H_
-#define _FLOAT_H_
+#ifndef SIMPLEKERNEL_FLOAT_H
+#define SIMPLEKERNEL_FLOAT_H
#ifdef __cplusplus
extern "C" {
@@ -17,4 +27,4 @@ extern "C" {
}
#endif
-#endif /* _FLOAT_H_ */
+#endif /* SIMPLEKERNEL_FLOAT_H */
diff --git a/src/libc/include/limits.h b/src/libc/include/limits.h
index 2659c2590..a4c30cd38 100644
--- a/src/libc/include/limits.h
+++ b/src/libc/include/limits.h
@@ -1,53 +1,63 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-//
-// limits.h for Simple-XX/SimpleKernel.
-
-#ifndef _LIMITS_H_
-#define _LIMITS_H_
+/**
+ * @file limits.h
+ * @brief limits 定义
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
+
+#ifndef SIMPLEKERNEL_LIMITS_H
+#define SIMPLEKERNEL_LIMITS_H
#ifdef __cplusplus
extern "C" {
#endif
// int8_t
-#define SCHAR_MIN (-128)
-#define SCHAR_MAX (127)
+#define SCHAR_MIN (-128)
+#define SCHAR_MAX (127)
// uint8_t
-#define UCHAR_MAX (0xFF)
+#define UCHAR_MAX (0xFF)
// int16_t
-#define SHRT_MIN (-32768)
-#define SHRT_MAX (32767)
+#define SHRT_MIN (-32768)
+#define SHRT_MAX (32767)
// uint16_t
-#define USHRT_MAX (0xFFFF)
+#define USHRT_MAX (0xFFFF)
// 4字节 int和unsigned int类型
// int32_t
-#define INT_MIN (-2147483647 - 1)
-#define INT_MAX (2147483647)
+#define INT_MIN (-2147483647 - 1)
+#define INT_MAX (2147483647)
// uint32_t
-#define UINT_MAX (0xFFFFFFFF)
+#define UINT_MAX (0xFFFFFFFF)
// 32bit 与 64bit 不同
// 0x7FFFFFFF
-#define LONG_MAX ((long)(ULONG_MAX >> 1))
+#define LONG_MAX ((long)(ULONG_MAX >> 1))
// 0x80000000
-#define LONG_MIN ((long)(~LONG_MAX))
+#define LONG_MIN ((long)(~LONG_MAX))
// 0xFFFFFFFF
-#define ULONG_MAX ((unsigned long)(~0L))
+#define ULONG_MAX ((unsigned long)(~0L))
// 8字节 long long int和 unsigned long long int类型
// 0xFFFFFFFFFFFFFFFF
#define ULLONG_MAX (~(unsigned long long)0)
// 0x7FFFFFFFFFFFFFFF
-#define LLONG_MAX ((long long)(ULLONG_MAX >> 1))
+#define LLONG_MAX ((long long)(ULLONG_MAX >> 1))
// 0x8000000000000000
-#define LLONG_MIN (~LLONG_MAX)
+#define LLONG_MIN (~LLONG_MAX)
#ifdef __cplusplus
}
#endif
-#endif /* _LIMITS_H_ */
+#endif /* SIMPLEKERNEL_LIMITS_H */
diff --git a/src/libc/include/math.h b/src/libc/include/math.h
index 3bc44c05b..33d540b48 100644
--- a/src/libc/include/math.h
+++ b/src/libc/include/math.h
@@ -1,11 +1,22 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-// Based on libgcc
-// math.h for Simple-XX/SimpleKernel.
+/**
+ * @file math.h
+ * @brief math 定义
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * Based on libgcc
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
-#ifndef _MATH_H_
-#define _MATH_H_
+#ifndef SIMPLEKERNEL_MATH_H
+#define SIMPLEKERNEL_MATH_H
#ifdef __cplusplus
extern "C" {
@@ -14,14 +25,14 @@ extern "C" {
// TODO: 更多支持
// TODO: 浮点数
-long long divmoddi4(long long num, long long den, long long *rem_p);
-unsigned long long udivmoddi4(unsigned long long num, unsigned long long den,
- unsigned long long *rem_p);
-unsigned long long udivdi3(unsigned long long num, unsigned long long den);
-unsigned long long umoddi3(unsigned long long num, unsigned long long den);
+long long divmoddi4(long long _num, long long _den, long long* _rem_p);
+unsigned long long udivmoddi4(unsigned long long _num, unsigned long long _den,
+ unsigned long long* _rem_p);
+unsigned long long udivdi3(unsigned long long _num, unsigned long long _den);
+unsigned long long umoddi3(unsigned long long _num, unsigned long long _den);
#ifdef __cplusplus
}
#endif
-#endif /* _MATH_H_ */
+#endif /* SIMPLEKERNEL_MATH_H */
diff --git a/src/libc/include/stdarg.h b/src/libc/include/stdarg.h
index 7dcc49690..53376d274 100644
--- a/src/libc/include/stdarg.h
+++ b/src/libc/include/stdarg.h
@@ -1,24 +1,34 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-//
-// stdarg.h for Simple-XX/SimpleKernel.
+/**
+ * @file stdarg.h
+ * @brief stdarg 定义
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
-#ifndef _STDARG_H_
-#define _STDARG_H_
+#ifndef SIMPLEKERNEL_STDARG_H
+#define SIMPLEKERNEL_STDARG_H
#ifdef __cplusplus
extern "C" {
#endif
-#define va_list __builtin_va_list
-#define va_start(v, l) __builtin_va_start(v, l)
-#define va_arg(v, l) __builtin_va_arg(v, l)
-#define va_end(v) __builtin_va_end(v)
-#define va_copy(d, s) __builtin_va_copy(d, s)
+#define va_list __builtin_va_list
+#define va_start(_v, _l) __builtin_va_start(_v, _l)
+#define va_arg(_v, _l) __builtin_va_arg(_v, _l)
+#define va_end(_v) __builtin_va_end(_v)
+#define va_copy(_d, _s) __builtin_va_copy(_d, _s)
#ifdef __cplusplus
}
#endif
-#endif /* _STDARG_H_ */
+#endif /* SIMPLEKERNEL_STDARG_H */
diff --git a/src/libc/include/stdbool.h b/src/libc/include/stdbool.h
index 6af2b77b3..51639a9ee 100644
--- a/src/libc/include/stdbool.h
+++ b/src/libc/include/stdbool.h
@@ -1,33 +1,44 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-// Baseed on GCC stdbool.h
-// stdbool.h for Simple-XX/SimpleKernel.
-
-#ifndef _STDBOOL_H_
-#define _STDBOOL_H_
+/**
+ * @file stdbool.h
+ * @brief stdbool 定义
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * Baseed on GCC stdbool.h
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
+
+#ifndef SIMPLEKERNEL_STDBOOL_H
+#define SIMPLEKERNEL_STDBOOL_H
#ifndef __cplusplus
-#define bool _Bool
-#define true 1
-#define false 0
+# define bool _Bool
+# define true 1
+# define false 0
#else /* __cplusplus */
/* Supporting _Bool in C++ is a GCC extension. */
-#define _Bool bool
+# define _Bool bool
-#if __cplusplus < 201103L
+# if __cplusplus < 201103L
/* Defining these macros in C++98 is a GCC extension. */
-#define bool bool
-#define false false
-#define true true
-#endif
+# define bool bool
+# define false false
+# define true true
+# endif
#endif /* __cplusplus */
/* Signal that all the definitions are present. */
#define __bool_true_false_are_defined 1
-#endif /* _STDBOOL_H_ */
+#endif /* SIMPLEKERNEL_STDBOOL_H */
diff --git a/src/libc/include/stddef.h b/src/libc/include/stddef.h
index 15feb9961..1693e100b 100644
--- a/src/libc/include/stddef.h
+++ b/src/libc/include/stddef.h
@@ -1,53 +1,63 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-//
-// stddef.h for Simple-XX/SimpleKernel.
-
-#ifndef _STDDEF_H_
-#define _STDDEF_H_
+/**
+ * @file stddef.h
+ * @brief stddef 定义
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
+
+#ifndef SIMPLEKERNEL_STDDEF_H
+#define SIMPLEKERNEL_STDDEF_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _PTRDIFF_T
-#define _PTRDIFF_T
+# define _PTRDIFF_T
typedef long ptrdiff_t;
#endif
#ifndef _SIZE_T
-#define _SIZE_T
-#undef size_t
-#if defined(__i386__)
+# define _SIZE_T
+# undef size_t
+# if defined(__i386__)
typedef unsigned int size_t;
-#elif defined(__riscv) || defined(__x86_64__)
+# elif defined(__riscv) || defined(__x86_64__)
typedef long unsigned int size_t;
-#endif
+# endif
#endif
#ifndef _SSIZE_T
-#define _SSIZE_T
-#undef ssize_t
-#if defined(__i386__)
+# define _SSIZE_T
+# undef ssize_t
+# if defined(__i386__)
typedef int ssize_t;
-#elif defined(__riscv) || defined(__x86_64__)
+# elif defined(__riscv) || defined(__x86_64__)
typedef long int ssize_t;
-#endif
+# endif
#endif
#ifndef _SSIZE_T
-#define _SSIZE_T
-#undef ssize_t
+# define _SSIZE_T
+# undef ssize_t
typedef int ssize_t;
#endif
#ifndef NULL
-#define NULL ((void *)0)
+# define NULL ((void*)0)
#endif
#ifdef __cplusplus
}
#endif
-#endif /* _STDDEF_H_ */
+#endif /* SIMPLEKERNEL_STDDEF_H */
diff --git a/src/libc/include/stdint.h b/src/libc/include/stdint.h
index 820e578b4..c9133a36e 100644
--- a/src/libc/include/stdint.h
+++ b/src/libc/include/stdint.h
@@ -1,26 +1,37 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-// Based on GNU C Lib
-// stdint.h for Simple-XX/SimpleKernel.
-
-#ifndef _STDINT_H_
-#define _STDINT_H_
+/**
+ * @file stdint.h
+ * @brief stdint 定义
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * Based on GNU C Lib
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
+
+#ifndef SIMPLEKERNEL_STDINT_H
+#define SIMPLEKERNEL_STDINT_H
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__x86_64__) || defined(__riscv)
-#define __WORDSIZE 64
+# define __WORDSIZE 64
#else
-#define __WORDSIZE 32
+# define __WORDSIZE 32
#endif
#ifdef __x86_64__
-#define __WORDSIZE_TIME64_COMPAT32 1
+# define __WORDSIZE_TIME64_COMPAT32 1
/* Both x86-64 and x32 use the 64-bit system call interface. */
-#define __SYSCALL_WORDSIZE 64
+# define __SYSCALL_WORDSIZE 64
#endif
/* Exact integral types. */
@@ -29,15 +40,15 @@ extern "C" {
/* There is some amount of overlap with as known by inet code */
#ifndef __int8_t_defined
-#define __int8_t_defined
+# define __int8_t_defined
typedef signed char int8_t;
typedef short int int16_t;
typedef int int32_t;
-#if __WORDSIZE == 64
+# if __WORDSIZE == 64
typedef long int int64_t;
-#else
+# else
__extension__ typedef long long int int64_t;
-#endif
+# endif
#endif
/* Unsigned. */
@@ -45,7 +56,7 @@ typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
#ifndef __uint32_t_defined
typedef unsigned int uint32_t;
-#define __uint32_t_defined
+# define __uint32_t_defined
#endif
#if __WORDSIZE == 64
typedef unsigned long int uint64_t;
@@ -103,16 +114,16 @@ __extension__ typedef unsigned long long int uint_fast64_t;
/* Types for `void *' pointers. */
#if __WORDSIZE == 64
-#ifndef __intptr_t_defined
+# ifndef __intptr_t_defined
typedef long int intptr_t;
-#define __intptr_t_defined
-#endif
+# define __intptr_t_defined
+# endif
typedef unsigned long int uintptr_t;
#else
-#ifndef __intptr_t_defined
+# ifndef __intptr_t_defined
typedef int intptr_t;
-#define __intptr_t_defined
-#endif
+# define __intptr_t_defined
+# endif
typedef unsigned int uintptr_t;
#endif
@@ -126,97 +137,97 @@ __extension__ typedef unsigned long long int uintmax_t;
#endif
#ifndef __INT64_C
-#if __WORDSIZE == 64
-#define __INT64_C(c) c##L
-#define __UINT64_C(c) c##UL
-#else
-#define __INT64_C(c) c##LL
-#define __UINT64_C(c) c##ULL
-#endif
+# if __WORDSIZE == 64
+# define __INT64_C(c) c##L
+# define __UINT64_C(c) c##UL
+# else
+# define __INT64_C(c) c##LL
+# define __UINT64_C(c) c##ULL
+# endif
#endif
/* Limits of integral types. */
/* Minimum of signed integral types. */
-#define INT8_MIN (-128)
-#define INT16_MIN (-32767 - 1)
-#define INT32_MIN (-2147483647 - 1)
-#define INT64_MIN (-__INT64_C(9223372036854775807) - 1)
+#define INT8_MIN (-128)
+#define INT16_MIN (-32767 - 1)
+#define INT32_MIN (-2147483647 - 1)
+#define INT64_MIN (-__INT64_C(9223372036854775807) - 1)
/* Maximum of signed integral types. */
-#define INT8_MAX (127)
-#define INT16_MAX (32767)
-#define INT32_MAX (2147483647)
-#define INT64_MAX (__INT64_C(9223372036854775807))
+#define INT8_MAX (127)
+#define INT16_MAX (32767)
+#define INT32_MAX (2147483647)
+#define INT64_MAX (__INT64_C(9223372036854775807))
/* Maximum of unsigned integral types. */
-#define UINT8_MAX (255)
-#define UINT16_MAX (65535)
-#define UINT32_MAX (4294967295U)
-#define UINT64_MAX (__UINT64_C(18446744073709551615))
+#define UINT8_MAX (255)
+#define UINT16_MAX (65535)
+#define UINT32_MAX (4294967295U)
+#define UINT64_MAX (__UINT64_C(18446744073709551615))
/* Minimum of signed integral types having a minimum size. */
-#define INT_LEAST8_MIN (-128)
-#define INT_LEAST16_MIN (-32767 - 1)
-#define INT_LEAST32_MIN (-2147483647 - 1)
-#define INT_LEAST64_MIN (-__INT64_C(9223372036854775807) - 1)
+#define INT_LEAST8_MIN (-128)
+#define INT_LEAST16_MIN (-32767 - 1)
+#define INT_LEAST32_MIN (-2147483647 - 1)
+#define INT_LEAST64_MIN (-__INT64_C(9223372036854775807) - 1)
/* Maximum of signed integral types having a minimum size. */
-#define INT_LEAST8_MAX (127)
-#define INT_LEAST16_MAX (32767)
-#define INT_LEAST32_MAX (2147483647)
-#define INT_LEAST64_MAX (__INT64_C(9223372036854775807))
+#define INT_LEAST8_MAX (127)
+#define INT_LEAST16_MAX (32767)
+#define INT_LEAST32_MAX (2147483647)
+#define INT_LEAST64_MAX (__INT64_C(9223372036854775807))
/* Maximum of unsigned integral types having a minimum size. */
-#define UINT_LEAST8_MAX (255)
+#define UINT_LEAST8_MAX (255)
#define UINT_LEAST16_MAX (65535)
#define UINT_LEAST32_MAX (4294967295U)
#define UINT_LEAST64_MAX (__UINT64_C(18446744073709551615))
/* Minimum of fast signed integral types having a minimum size. */
-#define INT_FAST8_MIN (-128)
+#define INT_FAST8_MIN (-128)
#if __WORDSIZE == 64
-#define INT_FAST16_MIN (-9223372036854775807L - 1)
-#define INT_FAST32_MIN (-9223372036854775807L - 1)
+# define INT_FAST16_MIN (-9223372036854775807L - 1)
+# define INT_FAST32_MIN (-9223372036854775807L - 1)
#else
-#define INT_FAST16_MIN (-2147483647 - 1)
-#define INT_FAST32_MIN (-2147483647 - 1)
+# define INT_FAST16_MIN (-2147483647 - 1)
+# define INT_FAST32_MIN (-2147483647 - 1)
#endif
#define INT_FAST64_MIN (-__INT64_C(9223372036854775807) - 1)
/* Maximum of fast signed integral types having a minimum size. */
-#define INT_FAST8_MAX (127)
+#define INT_FAST8_MAX (127)
#if __WORDSIZE == 64
-#define INT_FAST16_MAX (9223372036854775807L)
-#define INT_FAST32_MAX (9223372036854775807L)
+# define INT_FAST16_MAX (9223372036854775807L)
+# define INT_FAST32_MAX (9223372036854775807L)
#else
-#define INT_FAST16_MAX (2147483647)
-#define INT_FAST32_MAX (2147483647)
+# define INT_FAST16_MAX (2147483647)
+# define INT_FAST32_MAX (2147483647)
#endif
#define INT_FAST64_MAX (__INT64_C(9223372036854775807))
/* Maximum of fast unsigned integral types having a minimum size. */
#define UINT_FAST8_MAX (255)
#if __WORDSIZE == 64
-#define UINT_FAST16_MAX (18446744073709551615UL)
-#define UINT_FAST32_MAX (18446744073709551615UL)
+# define UINT_FAST16_MAX (18446744073709551615UL)
+# define UINT_FAST32_MAX (18446744073709551615UL)
#else
-#define UINT_FAST16_MAX (4294967295U)
-#define UINT_FAST32_MAX (4294967295U)
+# define UINT_FAST16_MAX (4294967295U)
+# define UINT_FAST32_MAX (4294967295U)
#endif
#define UINT_FAST64_MAX (__UINT64_C(18446744073709551615))
/* Values to test for integral types holding `void *' pointer. */
#if __WORDSIZE == 64
-#define INTPTR_MIN (-9223372036854775807L - 1)
-#define INTPTR_MAX (9223372036854775807L)
-#define UINTPTR_MAX (18446744073709551615UL)
+# define INTPTR_MIN (-9223372036854775807L - 1)
+# define INTPTR_MAX (9223372036854775807L)
+# define UINTPTR_MAX (18446744073709551615UL)
#else
-#define INTPTR_MIN (-2147483647 - 1)
-#define INTPTR_MAX (2147483647)
-#define UINTPTR_MAX (4294967295U)
+# define INTPTR_MIN (-2147483647 - 1)
+# define INTPTR_MAX (2147483647)
+# define UINTPTR_MAX (4294967295U)
#endif
/* Minimum for largest signed integral type. */
-#define INTMAX_MIN (-__INT64_C(9223372036854775807) - 1)
+#define INTMAX_MIN (-__INT64_C(9223372036854775807) - 1)
/* Maximum for largest signed integral type. */
-#define INTMAX_MAX (__INT64_C(9223372036854775807))
+#define INTMAX_MAX (__INT64_C(9223372036854775807))
/* Maximum for largest unsigned integral type. */
#define UINTMAX_MAX (__UINT64_C(18446744073709551615))
@@ -225,11 +236,11 @@ __extension__ typedef unsigned long long int uintmax_t;
/* Limits of `ptrdiff_t' type. */
#if __WORDSIZE == 64
-#define PTRDIFF_MIN (-9223372036854775807L - 1)
-#define PTRDIFF_MAX (9223372036854775807L)
+# define PTRDIFF_MIN (-9223372036854775807L - 1)
+# define PTRDIFF_MAX (9223372036854775807L)
#else
-#define PTRDIFF_MIN (-2147483647 - 1)
-#define PTRDIFF_MAX (2147483647)
+# define PTRDIFF_MIN (-2147483647 - 1)
+# define PTRDIFF_MAX (2147483647)
#endif
/* Limits of `sig_atomic_t'. */
@@ -238,57 +249,57 @@ __extension__ typedef unsigned long long int uintmax_t;
/* Limit of `size_t' type. */
#if __WORDSIZE == 64
-#define SIZE_MAX (18446744073709551615UL)
+# define SIZE_MAX (18446744073709551615UL)
#else
-#ifdef __WORDSIZE32_SIZE_ULONG
-#define SIZE_MAX (4294967295UL)
-#else
-#define SIZE_MAX (4294967295U)
-#endif
+# ifdef __WORDSIZE32_SIZE_ULONG
+# define SIZE_MAX (4294967295UL)
+# else
+# define SIZE_MAX (4294967295U)
+# endif
#endif
/* Limits of `wchar_t'. */
#ifndef WCHAR_MIN
/* These constants might also be defined in . */
-#define WCHAR_MIN __WCHAR_MIN
-#define WCHAR_MAX __WCHAR_MAX
+# define WCHAR_MIN __WCHAR_MIN
+# define WCHAR_MAX __WCHAR_MAX
#endif
/* Limits of `wint_t'. */
-#define WINT_MIN (0u)
-#define WINT_MAX (4294967295u)
+#define WINT_MIN (0u)
+#define WINT_MAX (4294967295u)
/* Signed. */
-#define INT8_C(c) c
-#define INT16_C(c) c
-#define INT32_C(c) c
+#define INT8_C(_c) _c
+#define INT16_C(_c) _c
+#define INT32_C(_c) _c
#if __WORDSIZE == 64
-#define INT64_C(c) c##L
+# define INT64_C(_c) _c##L
#else
-#define INT64_C(c) c##LL
+# define INT64_C(_c) _c##LL
#endif
/* Unsigned. */
-#define UINT8_C(c) c
-#define UINT16_C(c) c
-#define UINT32_C(c) c##U
+#define UINT8_C(_c) _c
+#define UINT16_C(_c) _c
+#define UINT32_C(_c) _c##U
#if __WORDSIZE == 64
-#define UINT64_C(c) c##UL
+# define UINT64_C(_c) _c##UL
#else
-#define UINT64_C(c) c##ULL
+# define UINT64_C(_c) _c##ULL
#endif
/* Maximal type. */
#if __WORDSIZE == 64
-#define INTMAX_C(c) c##L
-#define UINTMAX_C(c) c##UL
+# define INTMAX_C(_c) _c##L
+# define UINTMAX_C(_c) _c##UL
#else
-#define INTMAX_C(c) c##LL
-#define UINTMAX_C(c) c##ULL
+# define INTMAX_C(_c) _c##LL
+# define UINTMAX_C(_c) _c##ULL
#endif
#ifdef __cplusplus
}
#endif
-#endif /* _STDINT_H_ */
+#endif /* SIMPLEKERNEL_STDINT_H */
diff --git a/src/libc/include/stdio.h b/src/libc/include/stdio.h
index a52d368bc..1b51ae3a2 100644
--- a/src/libc/include/stdio.h
+++ b/src/libc/include/stdio.h
@@ -1,19 +1,30 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-// Based on https://github.com/mpaland/printf
-// stdio.h for Simple-XX/SimpleKernel.
+/**
+ * @file stdio.h
+ * @brief stdio 定义
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * Based on https://github.com/mpaland/printf
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
-#ifndef _STDIO_H_
-#define _STDIO_H_
+#ifndef SIMPLEKERNEL_STDIO_H
+#define SIMPLEKERNEL_STDIO_H
#ifdef __cplusplus
extern "C" {
#endif
-#include "stdint.h"
-#include "stddef.h"
#include "stdarg.h"
+#include "stddef.h"
+#include "stdint.h"
/**
* Tiny sprintf implementation
@@ -25,7 +36,7 @@ extern "C" {
* null character
*/
#define sprintf sprintf_
-int sprintf_(char *buffer, const char *format, ...);
+int sprintf_(char* _buffer, const char* _format, ...);
/**
* Tiny snprintf/vsnprintf implementation
@@ -38,23 +49,23 @@ int sprintf_(char *buffer, const char *format, ...);
* than count indicates truncation. Only when the returned value is non-negative
* and less than count, the string has been completely written.
*/
-#define snprintf snprintf_
+#define snprintf snprintf_
#define vsnprintf vsnprintf_
-int snprintf_(char *buffer, size_t count, const char *format, ...);
-int vsnprintf_(char *buffer, size_t count, const char *format, va_list va);
-int _vsnprintf(char *buffer, const size_t maxlen, const char *format,
- va_list va);
+int snprintf_(char* _buffer, size_t _count, const char* _format, ...);
+int vsnprintf_(char* _buffer, size_t _count, const char* _format, va_list _va);
+int _vsnprintf(char* _buffer, const size_t _maxlen, const char* _format,
+ va_list _va);
-int printf(const char *fmt, ...);
+int32_t printf(const char* _fmt, ...);
-int info(const char *fmt, ...);
+int32_t info(const char* _fmt, ...);
-int warn(const char *fmt, ...);
+int32_t warn(const char* _fmt, ...);
-int err(const char *fmt, ...);
+int32_t err(const char* _fmt, ...);
#ifdef __cplusplus
}
#endif
-#endif /* _STDIO_H_ */
+#endif /* SIMPLEKERNEL_STDIO_H */
diff --git a/src/libc/include/stdlib.h b/src/libc/include/stdlib.h
index 369a96747..726ca670b 100644
--- a/src/libc/include/stdlib.h
+++ b/src/libc/include/stdlib.h
@@ -1,33 +1,47 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-//
-// stdlib.h for Simple-XX/SimpleKernel.
-
-#ifndef _STDLIB_H_
-#define _STDLIB_H_
+/**
+ * @file stdlib.h
+ * @brief stdlib 定义
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
+
+#ifndef SIMPLEKERNEL_STDLIB_H
+#define SIMPLEKERNEL_STDLIB_H
#ifdef __cplusplus
extern "C" {
#endif
-#include "stdint.h"
#include "stddef.h"
+#include "stdint.h"
int abs(int);
-int atoi(const char *);
-long atol(const char *);
-long long atoll(const char *);
-int itoa(int num, char *str, int len, int base);
-long strtol(const char *nptr, char **endptr, int base);
-long long strtoll(const char *nptr, char **endptr, int base);
+int atoi(const char*);
+long atol(const char*);
+long long atoll(const char*);
+int itoa(int _num, char* _str, int _len, int _base);
+long strtol(const char* _nptr, char** _endptr, int _base);
+long long strtoll(const char* _nptr, char** _endptr, int _base);
+
+void* malloc(size_t size);
+
+void free(void* ptr);
-void *malloc(size_t size);
+void* kmalloc(size_t size);
-void free(void *ptr);
+void kfree(void* ptr);
#ifdef __cplusplus
}
#endif
-#endif /* _STDLIB_H_ */
+#endif /* SIMPLEKERNEL_STDLIB_H */
diff --git a/src/libc/include/string.h b/src/libc/include/string.h
index 904c44be6..5881a4742 100644
--- a/src/libc/include/string.h
+++ b/src/libc/include/string.h
@@ -1,41 +1,51 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-//
-// string.h for Simple-XX/SimpleKernel.
+/**
+ * @file string.h
+ * @brief string 定义
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
-#ifndef _STRING_H_
-#define _STRING_H_
+#ifndef SIMPLEKERNEL_STRING_H
+#define SIMPLEKERNEL_STRING_H
#ifdef __cplusplus
extern "C" {
#endif
-#include "stdint.h"
#include "stddef.h"
+#include "stdint.h"
-extern void *memcpy(void *dest, const void *src, size_t len);
-extern void *memset(void *dest, int val, size_t len);
-extern int memcmp(const void *str1, const void *str2, size_t count);
-extern void *memmove(void *dest, const void *src, size_t len);
-extern void bzero(void *dest, uint32_t len);
+extern void* memcpy(void* _dest, const void* _src, size_t _len);
+extern void* memset(void* _dest, int val, size_t _len);
+extern int memcmp(const void* _str1, const void* _str2, size_t _count);
+extern void* memmove(void* _dest, const void* _src, size_t _len);
+extern void bzero(void* _dest, uint32_t _len);
// 字符串比较
-extern int strcmp(const char *src, const char *dest);
-extern int strncmp(const char *s1, const char *s2, size_t n);
-extern char *strcpy(char *dest, const char *src);
-extern char *strncpy(char *s1, const char *s2, size_t n);
+extern int strcmp(const char* _src, const char* _dest);
+extern int strncmp(const char* _s1, const char* _s2, size_t _n);
+extern char* strcpy(char* _dest, const char* _src);
+extern char* strncpy(char* _s1, const char* _s2, size_t _n);
// 字符串合并
-extern char *strcat(char *dest, const char *src);
-extern char *strchr(const char *s, int c);
+extern char* strcat(char* _dest, const char* _src);
+extern char* strchr(const char* _s, int _c);
// length of string
-extern size_t strlen(const char *src);
-extern size_t strnlen(const char *str, size_t maxlen);
-extern void backspace(char *src);
-extern void append(char *src, char dest);
-extern void strrev(char *str);
+extern size_t strlen(const char* _src);
+extern size_t strnlen(const char* _str, size_t _maxlen);
+extern void backspace(char* _src);
+extern void append(char* _src, char _dest);
+extern void strrev(char* _str);
#ifdef __cplusplus
}
#endif
-#endif /* _STRING_H_ */
+#endif /* SIMPLEKERNEL_STRING_H */
diff --git a/src/libc/src/math/math.c b/src/libc/src/math/math.c
index 0ecae481b..0a26daa61 100644
--- a/src/libc/src/math/math.c
+++ b/src/libc/src/math/math.c
@@ -1,8 +1,19 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-// Based on libgcc
-// math.c for Simple-XX/SimpleKernel.
+/**
+ * @file math.c
+ * @brief math 定义
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * Based on libgcc
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
#ifdef __cplusplus
extern "C" {
@@ -10,67 +21,69 @@ extern "C" {
#include "math.h"
-long long divmoddi4(long long num, long long den, long long *rem_p) {
+long long divmoddi4(long long _num, long long _den, long long* _rem_p) {
int minus = 0;
long long v;
- if (num < 0) {
- num = -num;
+ if (_num < 0) {
+ _num = -_num;
minus = 1;
}
- if (den < 0) {
- den = -den;
+ if (_den < 0) {
+ _den = -_den;
minus ^= 1;
}
- v = udivmoddi4(num, den, (unsigned long long *)rem_p);
+ v = udivmoddi4(_num, _den, (unsigned long long*)_rem_p);
if (minus) {
v = -v;
- if (rem_p)
- *rem_p = -(*rem_p);
+ if (_rem_p) {
+ *_rem_p = -(*_rem_p);
+ }
}
return v;
}
// BUG: 在 x86_64 下观察到了精度损失
-unsigned long long udivmoddi4(unsigned long long num, unsigned long long den,
- unsigned long long *rem_p) {
+unsigned long long udivmoddi4(unsigned long long _num, unsigned long long _den,
+ unsigned long long* _rem_p) {
unsigned long long quot = 0, qbit = 1;
- if (den == 0) {
- return 1 / ((unsigned)den); /* Intentional divide by zero, without
+ if (_den == 0) {
+ return 1 / ((unsigned)_den); /* Intentional divide by zero, without
triggering a compiler warning which
would abort the build */
}
/* Left-justify denominator and count shift */
- while ((long long)den >= 0) {
- den <<= 1;
+ while ((long long)_den >= 0) {
+ _den <<= 1;
qbit <<= 1;
}
while (qbit) {
- if (den <= num) {
- num -= den;
+ if (_den <= _num) {
+ _num -= _den;
quot += qbit;
}
- den >>= 1;
+ _den >>= 1;
qbit >>= 1;
}
- if (rem_p)
- *rem_p = num;
+ if (_rem_p) {
+ *_rem_p = _num;
+ }
return quot;
}
-unsigned long long udivdi3(unsigned long long num, unsigned long long den) {
- return udivmoddi4(num, den, 0);
+unsigned long long udivdi3(unsigned long long _num, unsigned long long _den) {
+ return udivmoddi4(_num, _den, 0);
}
-unsigned long long umoddi3(unsigned long long num, unsigned long long den) {
+unsigned long long umoddi3(unsigned long long _num, unsigned long long _den) {
unsigned long long v;
- (void)udivmoddi4(num, den, &v);
+ (void)udivmoddi4(_num, _den, &v);
return v;
}
diff --git a/src/libc/src/stdio/vsprintf.c b/src/libc/src/stdio/vsprintf.c
index ca2e56db3..8420ac755 100644
--- a/src/libc/src/stdio/vsprintf.c
+++ b/src/libc/src/stdio/vsprintf.c
@@ -1,369 +1,385 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-// Based on https://github.com/mpaland/printf
-// vsprintf.c for Simple-XX/SimpleKernel.
+/**
+ * @file vsprintf.c
+ * @brief vsprintf 定义
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * Based on https://github.com/mpaland/printf
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
#ifdef __cplusplus
extern "C" {
#endif
-#include "stdbool.h"
-#include "stdint.h"
+#include "math.h"
#include "stdarg.h"
+#include "stdbool.h"
#include "stddef.h"
-#include "math.h"
+#include "stdint.h"
#include "stdio.h"
// 'ntoa' conversion buffer size, this must be big enough to hold one converted
// numeric number including padded zeros (dynamically created on stack)
// default: 32 byte
#ifndef PRINTF_NTOA_BUFFER_SIZE
-#define PRINTF_NTOA_BUFFER_SIZE 32U
+# define PRINTF_NTOA_BUFFER_SIZE 32U
#endif
// 'ftoa' conversion buffer size, this must be big enough to hold one converted
// float number including padded zeros (dynamically created on stack)
// default: 32 byte
#ifndef PRINTF_FTOA_BUFFER_SIZE
-#define PRINTF_FTOA_BUFFER_SIZE 32U
+# define PRINTF_FTOA_BUFFER_SIZE 32U
#endif
// support for the floating point type (%f)
// default: activated
#define PRINTF_DISABLE_SUPPORT_FLOAT
#ifndef PRINTF_DISABLE_SUPPORT_FLOAT
-#define PRINTF_SUPPORT_FLOAT
+# define PRINTF_SUPPORT_FLOAT
#endif
// support for exponential floating point notation (%e/%g)
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL
-#define PRINTF_SUPPORT_EXPONENTIAL
+# define PRINTF_SUPPORT_EXPONENTIAL
#endif
// define the default floating point precision
// default: 6 digits
#ifndef PRINTF_DEFAULT_FLOAT_PRECISION
-#define PRINTF_DEFAULT_FLOAT_PRECISION 6U
+# define PRINTF_DEFAULT_FLOAT_PRECISION 6U
#endif
// define the largest float suitable to print with %f
// default: 1e9
#ifndef PRINTF_MAX_FLOAT
-#define PRINTF_MAX_FLOAT 1e9
+# define PRINTF_MAX_FLOAT 1e9
#endif
// support for the long long types (%llu or %p)
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG
-#define PRINTF_SUPPORT_LONG_LONG
+# define PRINTF_SUPPORT_LONG_LONG
#endif
// support for the ptrdiff_t type (%t)
// ptrdiff_t is normally defined in as long or long long type
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T
-#define PRINTF_SUPPORT_PTRDIFF_T
+# define PRINTF_SUPPORT_PTRDIFF_T
#endif
///////////////////////////////////////////////////////////////////////////////
// internal flag definitions
-#define FLAGS_ZEROPAD (1U << 0U)
-#define FLAGS_LEFT (1U << 1U)
-#define FLAGS_PLUS (1U << 2U)
-#define FLAGS_SPACE (1U << 3U)
-#define FLAGS_HASH (1U << 4U)
+#define FLAGS_ZEROPAD (1U << 0U)
+#define FLAGS_LEFT (1U << 1U)
+#define FLAGS_PLUS (1U << 2U)
+#define FLAGS_SPACE (1U << 3U)
+#define FLAGS_HASH (1U << 4U)
#define FLAGS_UPPERCASE (1U << 5U)
-#define FLAGS_CHAR (1U << 6U)
-#define FLAGS_SHORT (1U << 7U)
-#define FLAGS_LONG (1U << 8U)
+#define FLAGS_CHAR (1U << 6U)
+#define FLAGS_SHORT (1U << 7U)
+#define FLAGS_LONG (1U << 8U)
#define FLAGS_LONG_LONG (1U << 9U)
#define FLAGS_PRECISION (1U << 10U)
#define FLAGS_ADAPT_EXP (1U << 11U)
// import float.h for DBL_MAX
#if defined(PRINTF_SUPPORT_FLOAT)
-#include "float.h"
+# include "float.h"
#endif
// output function type
-typedef void (*out_fct_type)(char character, void *buffer, size_t idx,
- size_t maxlen);
+typedef void (*out_fct_type)(char _character, void* _buffer, size_t _idx,
+ size_t _maxlen);
// wrapper (used as buffer) for output function type
typedef struct {
- void (*fct)(char character, void *arg);
- void *arg;
+ void (*fct)(char _character, void* arg);
+ void* arg;
} out_fct_wrap_type;
// internal buffer output
-static inline void _out_buffer(char character, void *buffer, size_t idx,
- size_t maxlen) {
- if (idx < maxlen) {
- ((char *)buffer)[idx] = character;
+inline static void
+_out_buffer(char _character, void* _buffer, size_t _idx, size_t _maxlen) {
+ if (_idx < _maxlen) {
+ ((char*)_buffer)[_idx] = _character;
}
}
// internal null output
-static inline void _out_null(char character, void *buffer, size_t idx,
- size_t maxlen) {
- (void)character;
- (void)buffer;
- (void)idx;
- (void)maxlen;
+inline static void
+_out_null(char _character, void* _buffer, size_t _idx, size_t _maxlen) {
+ (void)_character;
+ (void)_buffer;
+ (void)_idx;
+ (void)_maxlen;
}
// internal secure strlen
// \return The length of the string (excluding the terminating 0) limited by
// 'maxsize'
-static inline unsigned int _strnlen_s(const char *str, size_t maxsize) {
- const char *s;
- for (s = str; *s && maxsize--; ++s)
+inline static unsigned int _strnlen_s(const char* _str, size_t _maxsize) {
+ const char* s;
+ for (s = _str; *s && _maxsize--; ++s)
;
- return (unsigned int)(s - str);
+ return (unsigned int)(s - _str);
}
// internal test if char is a digit (0-9)
// \return true if char is a digit
-static inline bool _is_digit(char ch) {
- return (ch >= '0') && (ch <= '9');
+inline static bool _is_digit(char _ch) {
+ return (_ch >= '0') && (_ch <= '9');
}
// internal ASCII string to unsigned int conversion
-static unsigned int _atoi(const char **str) {
+static unsigned int _atoi(const char** _str) {
unsigned int i = 0U;
- while (_is_digit(**str)) {
- i = i * 10U + (unsigned int)(*((*str)++) - '0');
+ while (_is_digit(**_str)) {
+ i = i * 10U + (unsigned int)(*((*_str)++) - '0');
}
return i;
}
// output the specified string in reverse, taking care of any zero-padding
-static size_t _out_rev(out_fct_type out, char *buffer, size_t idx,
- size_t maxlen, const char *buf, size_t len,
- unsigned int width, unsigned int flags) {
- const size_t start_idx = idx;
+static size_t _out_rev(out_fct_type _out, char* _buffer, size_t _idx,
+ size_t _maxlen, const char* _buf, size_t _len,
+ unsigned int _width, unsigned int _flags) {
+ const size_t start_idx = _idx;
- // pad spaces up to given width
- if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) {
- for (size_t i = len; i < width; i++) {
- out(' ', buffer, idx++, maxlen);
+ // pad spaces up to given _width
+ if (!(_flags & FLAGS_LEFT) && !(_flags & FLAGS_ZEROPAD)) {
+ for (size_t i = _len; i < _width; i++) {
+ _out(' ', _buffer, _idx++, _maxlen);
}
}
// reverse string
- while (len) {
- out(buf[--len], buffer, idx++, maxlen);
+ while (_len) {
+ _out(_buf[--_len], _buffer, _idx++, _maxlen);
}
// append pad spaces up to given width
- if (flags & FLAGS_LEFT) {
- while (idx - start_idx < width) {
- out(' ', buffer, idx++, maxlen);
+ if (_flags & FLAGS_LEFT) {
+ while (_idx - start_idx < _width) {
+ _out(' ', _buffer, _idx++, _maxlen);
}
}
- return idx;
+ return _idx;
}
// internal itoa format
-static size_t _ntoa_format(out_fct_type out, char *buffer, size_t idx,
- size_t maxlen, char *buf, size_t len, bool negative,
- unsigned int base, unsigned int prec,
- unsigned int width, unsigned int flags) {
+static size_t
+_ntoa_format(out_fct_type _out, char* _buffer, size_t _idx, size_t _maxlen,
+ char* _buf, size_t _len, bool _negative, unsigned int _base,
+ unsigned int _prec, unsigned int _width, unsigned int _flags) {
// pad leading zeros
- if (!(flags & FLAGS_LEFT)) {
- if (width && (flags & FLAGS_ZEROPAD) &&
- (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
- width--;
+ if (!(_flags & FLAGS_LEFT)) {
+ if (_width && (_flags & FLAGS_ZEROPAD)
+ && (_negative || (_flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
+ _width--;
}
- while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
- buf[len++] = '0';
+ while ((_len < _prec) && (_len < PRINTF_NTOA_BUFFER_SIZE)) {
+ _buf[_len++] = '0';
}
- while ((flags & FLAGS_ZEROPAD) && (len < width) &&
- (len < PRINTF_NTOA_BUFFER_SIZE)) {
- buf[len++] = '0';
+ while ((_flags & FLAGS_ZEROPAD) && (_len < _width)
+ && (_len < PRINTF_NTOA_BUFFER_SIZE)) {
+ _buf[_len++] = '0';
}
}
// handle hash
- if (flags & FLAGS_HASH) {
- if (!(flags & FLAGS_PRECISION) && len &&
- ((len == prec) || (len == width))) {
- len--;
- if (len && (base == 16U)) {
- len--;
+ if (_flags & FLAGS_HASH) {
+ if (!(_flags & FLAGS_PRECISION) && _len
+ && ((_len == _prec) || (_len == _width))) {
+ _len--;
+ if (_len && (_base == 16U)) {
+ _len--;
}
}
- if ((base == 16U) && !(flags & FLAGS_UPPERCASE) &&
- (len < PRINTF_NTOA_BUFFER_SIZE)) {
- buf[len++] = 'x';
+ if ((_base == 16U) && !(_flags & FLAGS_UPPERCASE)
+ && (_len < PRINTF_NTOA_BUFFER_SIZE)) {
+ _buf[_len++] = 'x';
}
- else if ((base == 16U) && (flags & FLAGS_UPPERCASE) &&
- (len < PRINTF_NTOA_BUFFER_SIZE)) {
- buf[len++] = 'X';
+ else if ((_base == 16U) && (_flags & FLAGS_UPPERCASE)
+ && (_len < PRINTF_NTOA_BUFFER_SIZE)) {
+ _buf[_len++] = 'X';
}
- else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
- buf[len++] = 'b';
+ else if ((_base == 2U) && (_len < PRINTF_NTOA_BUFFER_SIZE)) {
+ _buf[_len++] = 'b';
}
- if (len < PRINTF_NTOA_BUFFER_SIZE) {
- buf[len++] = '0';
+ if (_len < PRINTF_NTOA_BUFFER_SIZE) {
+ _buf[_len++] = '0';
}
}
- if (len < PRINTF_NTOA_BUFFER_SIZE) {
- if (negative) {
- buf[len++] = '-';
+ if (_len < PRINTF_NTOA_BUFFER_SIZE) {
+ if (_negative) {
+ _buf[_len++] = '-';
}
- else if (flags & FLAGS_PLUS) {
- buf[len++] = '+'; // ignore the space if the '+' exists
+ else if (_flags & FLAGS_PLUS) {
+ _buf[_len++] = '+'; // ignore the space if the '+' exists
}
- else if (flags & FLAGS_SPACE) {
- buf[len++] = ' ';
+ else if (_flags & FLAGS_SPACE) {
+ _buf[_len++] = ' ';
}
}
- return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
+ return _out_rev(_out, _buffer, _idx, _maxlen, _buf, _len, _width, _flags);
}
// internal itoa for 'long' type
-static size_t _ntoa_long(out_fct_type out, char *buffer, size_t idx,
- size_t maxlen, unsigned long value, bool negative,
- unsigned long base, unsigned int prec,
- unsigned int width, unsigned int flags) {
+static size_t
+_ntoa_long(out_fct_type _out, char* _buffer, size_t _idx, size_t _maxlen,
+ unsigned long _value, bool _negative, unsigned long _base,
+ unsigned int _prec, unsigned int _width, unsigned int _flags) {
char buf[PRINTF_NTOA_BUFFER_SIZE];
size_t len = 0U;
// no hash for 0 values
- if (!value) {
- flags &= ~FLAGS_HASH;
+ if (!_value) {
+ _flags &= ~FLAGS_HASH;
}
- // write if precision != 0 and value is != 0
- if (!(flags & FLAGS_PRECISION) || value) {
+ // write if precision != 0 and _value is != 0
+ if (!(_flags & FLAGS_PRECISION) || _value) {
do {
- const char digit = (char)(value % base);
- buf[len++] =
- digit < 10 ? '0' + digit
- : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
- value /= base;
- } while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
+ const char digit = (char)(_value % _base);
+ buf[len++] = digit < 10
+ ? '0' + digit
+ : (_flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
+ _value /= _base;
+ } while (_value && (len < PRINTF_NTOA_BUFFER_SIZE));
}
- return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative,
- (unsigned int)base, prec, width, flags);
+ return _ntoa_format(_out, _buffer, _idx, _maxlen, buf, len, _negative,
+ (unsigned int)_base, _prec, _width, _flags);
}
// internal itoa for 'long long' type
#if defined(PRINTF_SUPPORT_LONG_LONG)
-static size_t _ntoa_long_long(out_fct_type out, char *buffer, size_t idx,
- size_t maxlen, unsigned long long value,
- bool negative, unsigned long long base,
- unsigned int prec, unsigned int width,
- unsigned int flags) {
+static size_t
+_ntoa_long_long(out_fct_type _out, char* _buffer, size_t _idx, size_t _maxlen,
+ unsigned long long _value, bool _negative,
+ unsigned long long _base, unsigned int _prec,
+ unsigned int _width, unsigned int _flags) {
char buf[PRINTF_NTOA_BUFFER_SIZE];
size_t len = 0U;
// no hash for 0 values
- if (!value) {
- flags &= ~FLAGS_HASH;
+ if (!_value) {
+ _flags &= ~FLAGS_HASH;
}
-#if defined(__i386__)
- // write if precision != 0 and value is != 0
- if (!(flags & FLAGS_PRECISION) || value) {
+# if defined(__i386__)
+ // write if precision != 0 and _value is != 0
+ if (!(_flags & FLAGS_PRECISION) || _value) {
do {
unsigned long long no;
- unsigned long long t = udivmoddi4(value, base, &no);
+ unsigned long long t = udivmoddi4(_value, _base, &no);
const char digit = (char)t;
- buf[len++] =
- digit < 10 ? '0' + digit
- : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
- value = udivdi3(value, base);
- } while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
+ buf[len++] = digit < 10
+ ? '0' + digit
+ : (_flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
+ _value = udivdi3(_value, _base);
+ } while (_value && (len < PRINTF_NTOA_BUFFER_SIZE));
}
-#else
+# else
// write if precision != 0 and value is != 0
- if (!(flags & FLAGS_PRECISION) || value) {
+ if (!(_flags & FLAGS_PRECISION) || _value) {
do {
- const char digit = (char)(value % base);
- buf[len++] =
- digit < 10 ? '0' + digit
- : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
- value /= base;
- } while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
- }
-#endif
- return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative,
- (unsigned int)base, prec, width, flags);
+ const char digit = (char)(_value % _base);
+ buf[len++] = digit < 10
+ ? '0' + digit
+ : (_flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
+ _value /= _base;
+ } while (_value && (len < PRINTF_NTOA_BUFFER_SIZE));
+ }
+# endif
+ return _ntoa_format(_out, _buffer, _idx, _maxlen, buf, len, _negative,
+ (unsigned int)_base, _prec, _width, _flags);
}
-#endif // PRINTF_SUPPORT_LONG_LONG
+#endif // PRINTF_SUPPORT_LONG_LONG
#if defined(PRINTF_SUPPORT_FLOAT)
-#if defined(PRINTF_SUPPORT_EXPONENTIAL)
+# if defined(PRINTF_SUPPORT_EXPONENTIAL)
// forward declaration so that _ftoa can switch to exp notation for values >
// PRINTF_MAX_FLOAT
-static size_t _etoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen,
- double value, unsigned int prec, unsigned int width,
- unsigned int flags);
-#endif
+static size_t _etoa(out_fct_type _out, char* _buffer, size_t _idx,
+ size_t _maxlen, double _value, unsigned int _prec,
+ unsigned int _width, unsigned int _flags);
+# endif
// internal ftoa for fixed decimal floating point
-static size_t _ftoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen,
- double value, unsigned int prec, unsigned int width,
- unsigned int flags) {
- char buf[PRINTF_FTOA_BUFFER_SIZE];
- size_t len = 0U;
- double diff = 0.0;
+static size_t _ftoa(out_fct_type _out, char* _buffer, size_t _idx,
+ size_t _maxlen, double _value, unsigned int _prec,
+ unsigned int _width, unsigned int _flags) {
+ char buf[PRINTF_FTOA_BUFFER_SIZE];
+ size_t len = 0U;
+ double diff = 0.0;
// powers of 10
- static const double pow10[] = {1, 10, 100, 1000,
- 10000, 100000, 1000000, 10000000,
- 100000000, 1000000000};
+ static const double pow10[]
+ = { 1, 10, 100, 1000, 10000,
+ 100000, 1000000, 10000000, 100000000, 1000000000 };
// test for special values
- if (value != value)
- return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags);
- if (value < -DBL_MAX)
- return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags);
- if (value > DBL_MAX)
- return _out_rev(out, buffer, idx, maxlen,
- (flags & FLAGS_PLUS) ? "fni+" : "fni",
- (flags & FLAGS_PLUS) ? 4U : 3U, width, flags);
+ if (_value != _value) {
+ return _out_rev(_out, _buffer, _idx, _maxlen, "nan", 3, _width, _flags);
+ }
+ if (_value < -DBL_MAX) {
+ return _out_rev(_out, _buffer, _idx, _maxlen, "fni-", 4, _width,
+ _flags);
+ }
+ if (_value > DBL_MAX) {
+ return _out_rev(_out, _buffer, _idx, _maxlen,
+ (_flags & FLAGS_PLUS) ? "fni+" : "fni",
+ (_flags & FLAGS_PLUS) ? 4U : 3U, _width, _flags);
+ }
// test for very large values
// standard printf behavior is to print EVERY whole number digit -- which
// could be 100s of characters overflowing your buffers == bad
- if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) {
-#if defined(PRINTF_SUPPORT_EXPONENTIAL)
- return _etoa(out, buffer, idx, maxlen, value, prec, width, flags);
-#else
+ if ((_value > PRINTF_MAX_FLOAT) || (_value < -PRINTF_MAX_FLOAT)) {
+# if defined(PRINTF_SUPPORT_EXPONENTIAL)
+ return _etoa(_out, _buffer, _idx, _maxlen, _value, _prec, _width,
+ _flags);
+# else
return 0U;
-#endif
+# endif
}
// test for negative
bool negative = false;
- if (value < 0) {
+ if (_value < 0) {
negative = true;
- value = 0 - value;
+ _value = 0 - _value;
}
// set default precision, if not set explicitly
- if (!(flags & FLAGS_PRECISION)) {
- prec = PRINTF_DEFAULT_FLOAT_PRECISION;
+ if (!(_flags & FLAGS_PRECISION)) {
+ _prec = PRINTF_DEFAULT_FLOAT_PRECISION;
}
// limit precision to 9, cause a prec >= 10 can lead to overflow errors
- while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) {
+ while ((len < PRINTF_FTOA_BUFFER_SIZE) && (_prec > 9U)) {
buf[len++] = '0';
- prec--;
+ _prec--;
}
- int whole = (int)value;
- double tmp = (value - whole) * pow10[prec];
+ int whole = (int)_value;
+ double tmp = (_value - whole) * pow10[_prec];
unsigned long frac = (unsigned long)tmp;
diff = tmp - frac;
@@ -383,7 +399,7 @@ static size_t _ftoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen,
}
if (prec == 0U) {
- diff = value - (double)whole;
+ diff = _value - (double)whole;
if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) {
// exactly 0.5 and ODD, then round up
// 1.5 -> 2, but 2.5 -> 2
@@ -419,11 +435,11 @@ static size_t _ftoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen,
}
// pad leading zeros
- if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) {
- if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
- width--;
+ if (!(_flags & FLAGS_LEFT) && (_flags & FLAGS_ZEROPAD)) {
+ if (_width && (negative || (_flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
+ _width--;
}
- while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) {
+ while ((len < _width) && (len < PRINTF_FTOA_BUFFER_SIZE)) {
buf[len++] = '0';
}
}
@@ -432,37 +448,38 @@ static size_t _ftoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen,
if (negative) {
buf[len++] = '-';
}
- else if (flags & FLAGS_PLUS) {
- buf[len++] = '+'; // ignore the space if the '+' exists
+ else if (_flags & FLAGS_PLUS) {
+ buf[len++] = '+'; // ignore the space if the '+' exists
}
- else if (flags & FLAGS_SPACE) {
+ else if (_flags & FLAGS_SPACE) {
buf[len++] = ' ';
}
}
- return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
+ return _out_rev(_out, _buffer, _idx, _maxlen, buf, len, _width, _flags);
}
-#if defined(PRINTF_SUPPORT_EXPONENTIAL)
+# if defined(PRINTF_SUPPORT_EXPONENTIAL)
// internal ftoa variant for exponential floating-point type, contributed by
// Martijn Jasperse
-static size_t _etoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen,
- double value, unsigned int prec, unsigned int width,
- unsigned int flags) {
+static size_t _etoa(out_fct_type _out, char* _buffer, size_t _idx,
+ size_t _maxlen, double _value, unsigned int _prec,
+ unsigned int _width, unsigned int _flags) {
// check for NaN and special values
- if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) {
- return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags);
+ if ((_value != _value) || (_value > DBL_MAX) || (_value < -DBL_MAX)) {
+ return _ftoa(_out, _buffer, _idx, _maxlen, _value, _prec, _width,
+ _flags);
}
// determine the sign
- const bool negative = value < 0;
+ const bool negative = _value < 0;
if (negative) {
- value = -value;
+ _value = -_value;
}
// default precision
- if (!(flags & FLAGS_PRECISION)) {
- prec = PRINTF_DEFAULT_FLOAT_PRECISION;
+ if (!(_flags & FLAGS_PRECISION)) {
+ _prec = PRINTF_DEFAULT_FLOAT_PRECISION;
}
// determine the decimal exponent
@@ -473,24 +490,24 @@ static size_t _etoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen,
double F;
} conv;
- conv.F = value;
- int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2
- conv.U = (conv.U & ((1ULL << 52U) - 1U)) |
- (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2)
+ conv.F = _value;
+ int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2
+ conv.U = (conv.U & ((1ULL << 52U) - 1U))
+ | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2)
// now approximate log10 from the log2 integer part and an expansion of ln
// around 1.5
- int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 +
- (conv.F - 1.5) * 0.289529654602168);
+ int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981
+ + (conv.F - 1.5) * 0.289529654602168);
// now we want to compute 10^expval but we want to be sure it won't overflow
- exp2 = (int)(expval * 3.321928094887362 + 0.5);
- const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453;
- const double z2 = z * z;
- conv.U = (uint64_t)(exp2 + 1023) << 52U;
+ exp2 = (int)(expval * 3.321928094887362 + 0.5);
+ const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453;
+ const double z2 = z * z;
+ conv.U = (uint64_t)(exp2 + 1023) << 52U;
// compute exp(z) using continued fractions, see
// https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex
- conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
+ conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
// correct for rounding errors
- if (value < conv.F) {
+ if (_value < conv.F) {
expval--;
conv.F /= 10;
}
@@ -500,31 +517,31 @@ static size_t _etoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen,
unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U;
// in "%g" mode, "prec" is the number of *significant figures* not decimals
- if (flags & FLAGS_ADAPT_EXP) {
+ if (_flags & FLAGS_ADAPT_EXP) {
// do we want to fall-back to "%f" mode?
- if ((value >= 1e-4) && (value < 1e6)) {
- if ((int)prec > expval) {
- prec = (unsigned)((int)prec - expval - 1);
+ if ((_value >= 1e-4) && (_value < 1e6)) {
+ if ((int)_prec > expval) {
+ _prec = (unsigned)((int)_prec - expval - 1);
}
else {
- prec = 0;
+ _prec = 0;
}
- flags |= FLAGS_PRECISION; // make sure _ftoa respects precision
+ _flags |= FLAGS_PRECISION; // make sure _ftoa respects precision
// no characters in exponent
minwidth = 0U;
expval = 0;
}
else {
// we use one sigfig for the whole part
- if ((prec > 0) && (flags & FLAGS_PRECISION)) {
- --prec;
+ if ((_prec > 0) && (_flags & FLAGS_PRECISION)) {
+ --_prec;
}
}
}
// will everything fit?
- unsigned int fwidth = width;
- if (width > minwidth) {
+ unsigned int fwidth = _width;
+ if (_width > minwidth) {
// we didn't fall-back so subtract the characters required for the
// exponent
fwidth -= minwidth;
@@ -533,93 +550,94 @@ static size_t _etoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen,
// not enough characters, so go back to default sizing
fwidth = 0U;
}
- if ((flags & FLAGS_LEFT) && minwidth) {
+ if ((_flags & FLAGS_LEFT) && minwidth) {
// if we're padding on the right, DON'T pad the floating part
fwidth = 0U;
}
// rescale the float value
if (expval) {
- value /= conv.F;
+ _value /= conv.F;
}
// output the floating part
- const size_t start_idx = idx;
- idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec,
- fwidth, flags & ~FLAGS_ADAPT_EXP);
+ const size_t start_idx = _idx;
+ _idx = _ftoa(_out, _buffer, _idx, _maxlen, negative ? -_value : _value,
+ _prec, fwidth, _flags & ~FLAGS_ADAPT_EXP);
// output the exponent part
if (minwidth) {
// output the exponential symbol
- out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen);
+ _out((_flags & FLAGS_UPPERCASE) ? 'E' : 'e', _buffer, _idx++, _maxlen);
// output the exponent value
- idx = _ntoa_long(out, buffer, idx, maxlen,
- (expval < 0) ? -expval : expval, expval < 0, 10, 0,
- minwidth - 1, FLAGS_ZEROPAD | FLAGS_PLUS);
+ _idx = _ntoa_long(_out, _buffer, _idx, _maxlen,
+ (expval < 0) ? -expval : expval, expval < 0, 10, 0,
+ minwidth - 1, FLAGS_ZEROPAD | FLAGS_PLUS);
// might need to right-pad spaces
- if (flags & FLAGS_LEFT) {
- while (idx - start_idx < width)
- out(' ', buffer, idx++, maxlen);
+ if (_flags & FLAGS_LEFT) {
+ while (_idx - start_idx < _width) {
+ _out(' ', _buffer, _idx++, _maxlen);
+ }
}
}
- return idx;
+ return _idx;
}
-#endif /* PRINTF_SUPPORT_EXPONENTIAL */
-#endif /* PRINTF_SUPPORT_FLOAT */
+# endif /* PRINTF_SUPPORT_EXPONENTIAL */
+#endif /* PRINTF_SUPPORT_FLOAT */
// internal vsnprintf
-int _vsnprintf(char *buffer, const size_t maxlen, const char *format,
- va_list va) {
+int _vsnprintf(char* _buffer, const size_t _maxlen, const char* _format,
+ va_list _va) {
out_fct_type out = _out_buffer;
unsigned int flags, width, precision, n;
size_t idx = 0U;
- if (!buffer) {
+ if (!_buffer) {
// use null output function
out = _out_null;
}
- while (*format) {
- // format specifier? %[flags][width][.precision][length]
- if (*format != '%') {
+ while (*_format) {
+ // _format specifier? %[flags][width][.precision][length]
+ if (*_format != '%') {
// no
- out(*format, buffer, idx++, maxlen);
- format++;
+ out(*_format, _buffer, idx++, _maxlen);
+ _format++;
continue;
}
else {
// yes, evaluate it
- format++;
+ _format++;
}
// evaluate flags
flags = 0U;
do {
- switch (*format) {
+ switch (*_format) {
case '0':
flags |= FLAGS_ZEROPAD;
- format++;
+ _format++;
n = 1U;
break;
case '-':
flags |= FLAGS_LEFT;
- format++;
+ _format++;
n = 1U;
break;
case '+':
flags |= FLAGS_PLUS;
- format++;
+ _format++;
n = 1U;
break;
case ' ':
flags |= FLAGS_SPACE;
- format++;
+ _format++;
n = 1U;
break;
case '#':
flags |= FLAGS_HASH;
- format++;
+ _format++;
n = 1U;
break;
default:
@@ -630,77 +648,77 @@ int _vsnprintf(char *buffer, const size_t maxlen, const char *format,
// evaluate width field
width = 0U;
- if (_is_digit(*format)) {
- width = _atoi(&format);
+ if (_is_digit(*_format)) {
+ width = _atoi(&_format);
}
- else if (*format == '*') {
- const int w = va_arg(va, int);
+ else if (*_format == '*') {
+ const int w = va_arg(_va, int);
if (w < 0) {
- flags |= FLAGS_LEFT; // reverse padding
- width = (unsigned int)-w;
+ flags |= FLAGS_LEFT; // reverse padding
+ width = (unsigned int)-w;
}
else {
width = (unsigned int)w;
}
- format++;
+ _format++;
}
// evaluate precision field
precision = 0U;
- if (*format == '.') {
+ if (*_format == '.') {
flags |= FLAGS_PRECISION;
- format++;
- if (_is_digit(*format)) {
- precision = _atoi(&format);
+ _format++;
+ if (_is_digit(*_format)) {
+ precision = _atoi(&_format);
}
- else if (*format == '*') {
- const int prec = (int)va_arg(va, int);
+ else if (*_format == '*') {
+ const int prec = (int)va_arg(_va, int);
precision = prec > 0 ? (unsigned int)prec : 0U;
- format++;
+ _format++;
}
}
// evaluate length field
- switch (*format) {
+ switch (*_format) {
case 'l':
flags |= FLAGS_LONG;
- format++;
- if (*format == 'l') {
+ _format++;
+ if (*_format == 'l') {
flags |= FLAGS_LONG_LONG;
- format++;
+ _format++;
}
break;
case 'h':
flags |= FLAGS_SHORT;
- format++;
- if (*format == 'h') {
+ _format++;
+ if (*_format == 'h') {
flags |= FLAGS_CHAR;
- format++;
+ _format++;
}
break;
#if defined(PRINTF_SUPPORT_PTRDIFF_T)
case 't':
flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG
: FLAGS_LONG_LONG);
- format++;
+ _format++;
break;
#endif
case 'j':
flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG
: FLAGS_LONG_LONG);
- format++;
+ _format++;
break;
case 'z':
flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG
: FLAGS_LONG_LONG);
- format++;
+ _format++;
break;
default:
break;
}
// evaluate specifier
- switch (*format) {
+ switch (*_format) {
case 'd':
case 'i':
case 'u':
@@ -710,26 +728,26 @@ int _vsnprintf(char *buffer, const size_t maxlen, const char *format,
case 'b': {
// set the base
unsigned int base;
- if (*format == 'x' || *format == 'X') {
+ if (*_format == 'x' || *_format == 'X') {
base = 16U;
}
- else if (*format == 'o') {
+ else if (*_format == 'o') {
base = 8U;
}
- else if (*format == 'b') {
+ else if (*_format == 'b') {
base = 2U;
}
else {
- base = 10U;
- flags &= ~FLAGS_HASH; // no hash for dec format
+ base = 10U;
+ flags &= ~FLAGS_HASH; // no hash for dec _format
}
// uppercase
- if (*format == 'X') {
+ if (*_format == 'X') {
flags |= FLAGS_UPPERCASE;
}
// no plus or space flag for u, x, X, o, b
- if ((*format != 'i') && (*format != 'd')) {
+ if ((*_format != 'i') && (*_format != 'd')) {
flags &= ~(FLAGS_PLUS | FLAGS_SPACE);
}
@@ -739,197 +757,202 @@ int _vsnprintf(char *buffer, const size_t maxlen, const char *format,
}
// convert the integer
- if ((*format == 'i') || (*format == 'd')) {
+ if ((*_format == 'i') || (*_format == 'd')) {
// signed
if (flags & FLAGS_LONG_LONG) {
#if defined(PRINTF_SUPPORT_LONG_LONG)
- const long long value = va_arg(va, long long);
+ const long long value = va_arg(_va, long long);
idx = _ntoa_long_long(
- out, buffer, idx, maxlen,
- (unsigned long long)(value > 0 ? value : 0 - value),
- value < 0, base, precision, width, flags);
+ out, _buffer, idx, _maxlen,
+ (unsigned long long)(value > 0 ? value : 0 - value),
+ value < 0, base, precision, width, flags);
#endif
}
else if (flags & FLAGS_LONG) {
- const long value = va_arg(va, long);
- idx = _ntoa_long(
- out, buffer, idx, maxlen,
- (unsigned long)(value > 0 ? value : 0 - value),
- value < 0, base, precision, width, flags);
+ const long value = va_arg(_va, long);
+ idx = _ntoa_long(out, _buffer, idx, _maxlen,
+ (unsigned long)(value > 0 ? value
+ : 0 - value),
+ value < 0, base, precision, width,
+ flags);
}
else {
- const int value =
- (flags & FLAGS_CHAR) ? (char)va_arg(va, int)
- : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int)
- : va_arg(va, int);
- idx = _ntoa_long(
- out, buffer, idx, maxlen,
- (unsigned int)(value > 0 ? value : 0 - value),
- value < 0, base, precision, width, flags);
+ const int value
+ = (flags & FLAGS_CHAR) ? (char)va_arg(_va, int)
+ : (flags & FLAGS_SHORT) ? (short int)va_arg(_va, int)
+ : va_arg(_va, int);
+ idx = _ntoa_long(out, _buffer, idx, _maxlen,
+ (unsigned int)(value > 0 ? value
+ : 0 - value),
+ value < 0, base, precision, width,
+ flags);
}
}
else {
// unsigned
if (flags & FLAGS_LONG_LONG) {
#if defined(PRINTF_SUPPORT_LONG_LONG)
- idx = _ntoa_long_long(out, buffer, idx, maxlen,
- va_arg(va, unsigned long long),
+ idx = _ntoa_long_long(out, _buffer, idx, _maxlen,
+ va_arg(_va, unsigned long long),
false, base, precision, width,
flags);
#endif
}
else if (flags & FLAGS_LONG) {
- idx = _ntoa_long(out, buffer, idx, maxlen,
- va_arg(va, unsigned long), false, base,
- precision, width, flags);
+ idx = _ntoa_long(out, _buffer, idx, _maxlen,
+ va_arg(_va, unsigned long), false,
+ base, precision, width, flags);
}
else {
- const unsigned int value =
- (flags & FLAGS_CHAR)
- ? (unsigned char)va_arg(va, unsigned int)
- : (flags & FLAGS_SHORT)
- ? (unsigned short int)va_arg(va, unsigned int)
- : va_arg(va, unsigned int);
- idx = _ntoa_long(out, buffer, idx, maxlen, value, false,
- base, precision, width, flags);
+ const unsigned int value
+ = (flags & FLAGS_CHAR)
+ ? (unsigned char)va_arg(_va, unsigned int)
+ : (flags & FLAGS_SHORT)
+ ? (unsigned short int)va_arg(_va, unsigned int)
+ : va_arg(_va, unsigned int);
+ idx = _ntoa_long(out, _buffer, idx, _maxlen, value,
+ false, base, precision, width, flags);
}
}
- format++;
+ _format++;
break;
}
#if defined(PRINTF_SUPPORT_FLOAT)
case 'f':
case 'F':
- if (*format == 'F')
+ if (*_format == 'F') {
flags |= FLAGS_UPPERCASE;
- idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double),
+ }
+ idx = _ftoa(out, _buffer, idx, _maxlen, va_arg(_va, double),
precision, width, flags);
- format++;
+ _format++;
break;
-#if defined(PRINTF_SUPPORT_EXPONENTIAL)
+# if defined(PRINTF_SUPPORT_EXPONENTIAL)
case 'e':
case 'E':
case 'g':
case 'G':
- if ((*format == 'g') || (*format == 'G'))
+ if ((*_format == 'g') || (*_format == 'G')) {
flags |= FLAGS_ADAPT_EXP;
- if ((*format == 'E') || (*format == 'G'))
+ }
+ if ((*_format == 'E') || (*_format == 'G')) {
flags |= FLAGS_UPPERCASE;
- idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double),
+ }
+ idx = _etoa(out, _buffer, idx, _maxlen, va_arg(_va, double),
precision, width, flags);
- format++;
+ _format++;
break;
-#endif // PRINTF_SUPPORT_EXPONENTIAL
-#endif // PRINTF_SUPPORT_FLOAT
+# endif // PRINTF_SUPPORT_EXPONENTIAL
+#endif // PRINTF_SUPPORT_FLOAT
case 'c': {
unsigned int l = 1U;
// pre padding
if (!(flags & FLAGS_LEFT)) {
while (l++ < width) {
- out(' ', buffer, idx++, maxlen);
+ out(' ', _buffer, idx++, _maxlen);
}
}
// char output
- out((char)va_arg(va, int), buffer, idx++, maxlen);
+ out((char)va_arg(_va, int), _buffer, idx++, _maxlen);
// post padding
if (flags & FLAGS_LEFT) {
while (l++ < width) {
- out(' ', buffer, idx++, maxlen);
+ out(' ', _buffer, idx++, _maxlen);
}
}
- format++;
+ _format++;
break;
}
case 's': {
- const char * p = va_arg(va, char *);
- unsigned int l =
- _strnlen_s(p, precision ? precision : (size_t)-1);
+ const char* p = va_arg(_va, char*);
+ unsigned int l
+ = _strnlen_s(p, precision ? precision : (size_t)-1);
// pre padding
if (flags & FLAGS_PRECISION) {
l = (l < precision ? l : precision);
}
if (!(flags & FLAGS_LEFT)) {
while (l++ < width) {
- out(' ', buffer, idx++, maxlen);
+ out(' ', _buffer, idx++, _maxlen);
}
}
// string output
- while ((*p != 0) &&
- (!(flags & FLAGS_PRECISION) || precision--)) {
- out(*(p++), buffer, idx++, maxlen);
+ while ((*p != 0)
+ && (!(flags & FLAGS_PRECISION) || precision--)) {
+ out(*(p++), _buffer, idx++, _maxlen);
}
// post padding
if (flags & FLAGS_LEFT) {
while (l++ < width) {
- out(' ', buffer, idx++, maxlen);
+ out(' ', _buffer, idx++, _maxlen);
}
}
- format++;
+ _format++;
break;
}
case 'p': {
- width = sizeof(void *) * 2U;
+ width = sizeof(void*) * 2U;
flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE;
#if defined(PRINTF_SUPPORT_LONG_LONG)
const bool is_ll = sizeof(uintptr_t) == sizeof(long long);
if (is_ll) {
- idx = _ntoa_long_long(out, buffer, idx, maxlen,
- (unsigned long)va_arg(va, void *),
+ idx = _ntoa_long_long(out, _buffer, idx, _maxlen,
+ (unsigned long)va_arg(_va, void*),
false, 16U, precision, width, flags);
}
else {
#endif
idx = _ntoa_long(
- out, buffer, idx, maxlen,
- (unsigned long)((unsigned long)va_arg(va, void *)),
- false, 16U, precision, width, flags);
+ out, _buffer, idx, _maxlen,
+ (unsigned long)((unsigned long)va_arg(_va, void*)), false,
+ 16U, precision, width, flags);
#if defined(PRINTF_SUPPORT_LONG_LONG)
}
#endif
- format++;
+ _format++;
break;
}
case '%':
- out('%', buffer, idx++, maxlen);
- format++;
+ out('%', _buffer, idx++, _maxlen);
+ _format++;
break;
default:
- out(*format, buffer, idx++, maxlen);
- format++;
+ out(*_format, _buffer, idx++, _maxlen);
+ _format++;
break;
}
}
// termination
- out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);
+ out((char)0, _buffer, idx < _maxlen ? idx : _maxlen - 1U, _maxlen);
// return written chars without terminating \0
return (int)idx;
}
-int sprintf_(char *buffer, const char *format, ...) {
+int sprintf_(char* _buffer, const char* _format, ...) {
va_list va;
- va_start(va, format);
- // const int ret = _vsnprintf(buffer, (size_t)-1, format, va);
- const int ret = _vsnprintf(buffer, (size_t)-1, "TEST:%d\n", va);
+ va_start(va, _format);
+ // const int ret = _vsnprintf(_buffer, (size_t)-1, _format, va);
+ const int ret = _vsnprintf(_buffer, (size_t)-1, "TEST:%d\n", va);
va_end(va);
return ret;
}
-int snprintf_(char *buffer, size_t count, const char *format, ...) {
+int snprintf_(char* _buffer, size_t _count, const char* _format, ...) {
va_list va;
- va_start(va, format);
- const int ret = _vsnprintf(buffer, count, format, va);
+ va_start(va, _format);
+ const int ret = _vsnprintf(_buffer, _count, _format, va);
va_end(va);
return ret;
}
-int vsnprintf_(char *buffer, size_t count, const char *format, va_list va) {
- return _vsnprintf(buffer, count, format, va);
+int vsnprintf_(char* _buffer, size_t _count, const char* _format, va_list _va) {
+ return _vsnprintf(_buffer, _count, _format, _va);
}
#ifdef __cplusplus
diff --git a/src/libc/src/stdlib/atoi.c b/src/libc/src/stdlib/atoi.c
index 3e46a36c5..1c97acaa2 100644
--- a/src/libc/src/stdlib/atoi.c
+++ b/src/libc/src/stdlib/atoi.c
@@ -1,8 +1,18 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-//
-// atoi.c for Simple-XX/SimpleKernel.
+/**
+ * @file atoi.c
+ * @brief atoi 定义
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
#include "stddef.h"
#include "stdlib.h"
@@ -11,14 +21,14 @@ int abs(int _i) {
return _i < 0 ? -_i : _i;
}
-int atoi(const char *_str) {
- return (int)strtol(_str, (char **)NULL, 10);
+int atoi(const char* _str) {
+ return (int)strtol(_str, (char**)NULL, 10);
}
-long atol(const char *_str) {
- return (long)strtoll(_str, (char **)NULL, 10);
+long atol(const char* _str) {
+ return (long)strtoll(_str, (char**)NULL, 10);
}
-long long atoll(const char *_str) {
- return (long long)strtoll(_str, (char **)NULL, 10);
+long long atoll(const char* _str) {
+ return (long long)strtoll(_str, (char**)NULL, 10);
}
diff --git a/src/libc/src/stdlib/itoa.c b/src/libc/src/stdlib/itoa.c
index 5c2717246..8d3517e43 100644
--- a/src/libc/src/stdlib/itoa.c
+++ b/src/libc/src/stdlib/itoa.c
@@ -1,33 +1,43 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-//
-// itoa.c for Simple-XX/SimpleKernel.
+/**
+ * @file itoa.c
+ * @brief itoa 定义
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
#include "stdlib.h"
#include "string.h"
-int itoa(int num, char *str, int len, int base) {
- int sum = num;
+int itoa(int _num, char* _str, int _len, int _base) {
+ int sum = _num;
int i = 0;
int digit;
- if (len == 0) {
+ if (_len == 0) {
return -1;
}
do {
- digit = sum % base;
+ digit = sum % _base;
if (digit < 0xA) {
- str[i++] = '0' + digit;
+ _str[i++] = '0' + digit;
}
else {
- str[i++] = 'A' + digit - 0xA;
+ _str[i++] = 'A' + digit - 0xA;
}
- sum /= base;
- } while (sum && (i < (len - 1)));
- if (i == (len - 1) && sum) {
+ sum /= _base;
+ } while (sum && (i < (_len - 1)));
+ if (i == (_len - 1) && sum) {
return -1;
}
- str[i] = '\0';
- strrev(str);
+ _str[i] = '\0';
+ strrev(_str);
return 0;
}
diff --git a/src/libc/src/stdlib/strtol.c b/src/libc/src/stdlib/strtol.c
index dacaa82ab..d73a20c71 100644
--- a/src/libc/src/stdlib/strtol.c
+++ b/src/libc/src/stdlib/strtol.c
@@ -1,13 +1,24 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-// Based on libgcc
-// strtol.c for Simple-XX/SimpleKernel.
+/**
+ * @file strtol.c
+ * @brief strtol 定义
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * Based on libgcc
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
-#include "stdlib.h"
#include "ctype.h"
#include "limits.h"
#include "math.h"
+#include "stdlib.h"
/*
* Convert a string to a long integer.
@@ -15,8 +26,8 @@
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
-long strtol(const char *nptr, char **endptr, int base) {
- const char * s = nptr;
+long strtol(const char* _nptr, char** _endptr, int _base) {
+ const char* s = _nptr;
unsigned long acc;
int c;
unsigned long cutoff;
@@ -34,15 +45,17 @@ long strtol(const char *nptr, char **endptr, int base) {
neg = 1;
c = *s++;
}
- else if (c == '+')
+ else if (c == '+') {
c = *s++;
- if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) {
- c = s[1];
- s += 2;
- base = 16;
}
- if (base == 0)
- base = c == '0' ? 8 : 10;
+ if ((_base == 0 || _base == 16) && c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ _base = 16;
+ }
+ if (_base == 0) {
+ _base = c == '0' ? 8 : 10;
+ }
/*
* Compute the cutoff value between legal numbers and illegal
@@ -61,33 +74,40 @@ long strtol(const char *nptr, char **endptr, int base) {
* Set any if any `digits' consumed; make it negative to indicate
* overflow.
*/
- cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
- cutlim = cutoff % (unsigned long)base;
- cutoff /= (unsigned long)base;
+ cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
+ cutlim = cutoff % (unsigned long)_base;
+ cutoff /= (unsigned long)_base;
for (acc = 0, any = 0;; c = *s++) {
- if (isdigit(c))
+ if (isdigit(c)) {
c -= '0';
- else if (isalpha(c))
+ }
+ else if (isalpha(c)) {
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
- else
+ }
+ else {
break;
- if (c >= base)
+ }
+ if (c >= _base) {
break;
- if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ }
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
any = -1;
+ }
else {
- any = 1;
- acc *= base;
+ any = 1;
+ acc *= _base;
acc += c;
}
}
if (any < 0) {
acc = neg ? LONG_MIN : LONG_MAX;
}
- else if (neg)
+ else if (neg) {
acc = -acc;
- if (endptr != 0)
- *endptr = (char *)(any ? s - 1 : nptr);
+ }
+ if (_endptr != 0) {
+ *_endptr = (char*)(any ? s - 1 : _nptr);
+ }
return (acc);
}
@@ -97,8 +117,8 @@ long strtol(const char *nptr, char **endptr, int base) {
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
-long long strtoll(const char *nptr, char **endptr, int base) {
- const char *s = nptr;
+long long strtoll(const char* _nptr, char** _endptr, int _base) {
+ const char* s = _nptr;
long long acc;
int c;
long long cutoff;
@@ -115,15 +135,17 @@ long long strtoll(const char *nptr, char **endptr, int base) {
neg = 1;
c = *s++;
}
- else if (c == '+')
+ else if (c == '+') {
c = *s++;
- if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) {
- c = s[1];
- s += 2;
- base = 16;
}
- if (base == 0)
- base = c == '0' ? 8 : 10;
+ if ((_base == 0 || _base == 16) && c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ _base = 16;
+ }
+ if (_base == 0) {
+ _base = c == '0' ? 8 : 10;
+ }
/*
* Compute the cutoff value between legal numbers and illegal
* numbers. That is the largest legal value, divided by the
@@ -145,34 +167,41 @@ long long strtoll(const char *nptr, char **endptr, int base) {
: LLONG_MAX;
#if defined(__i386__)
- cutoff = udivmoddi4(cutoff, base, (unsigned long long *)&cutlim);
+ cutoff = udivmoddi4(cutoff, _base, (unsigned long long*)&cutlim);
#else
- cutlim = cutoff % (long long)base;
- cutoff /= (long long)base;
+ cutlim = cutoff % (long long)_base;
+ cutoff /= (long long)_base;
#endif
for (acc = 0, any = 0;; c = *s++) {
- if (isdigit(c))
+ if (isdigit(c)) {
c -= '0';
- else if (isalpha(c))
+ }
+ else if (isalpha(c)) {
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
- else
+ }
+ else {
break;
- if (c >= base)
+ }
+ if (c >= _base) {
break;
- if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ }
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
any = -1;
+ }
else {
- any = 1;
- acc *= base;
+ any = 1;
+ acc *= _base;
acc += c;
}
}
if (any < 0) {
acc = neg ? LLONG_MIN : LLONG_MAX;
}
- else if (neg)
+ else if (neg) {
acc = -acc;
- if (endptr != 0)
- *endptr = (char *)(any ? s - 1 : nptr);
+ }
+ if (_endptr != 0) {
+ *_endptr = (char*)(any ? s - 1 : _nptr);
+ }
return (acc);
}
diff --git a/src/libc/src/string/string.c b/src/libc/src/string/string.c
index 22a49bd98..aa60e4db0 100644
--- a/src/libc/src/string/string.c
+++ b/src/libc/src/string/string.c
@@ -1,55 +1,69 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-//
-// string.c for Simple-XX/SimpleKernel.
+/**
+ * @file string.c
+ * @brief string 定义
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-03-31
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-03-31 Zone.N 迁移到 doxygen
+ *
+ */
#ifdef __cplusplus
extern "C" {
#endif
-#include "stddef.h"
#include "string.h"
#include "assert.h"
+#include "stddef.h"
#define __glibc_unlikely(cond) __builtin_expect((cond), 0)
-#define __glibc_likely(cond) __builtin_expect((cond), 1)
+#define __glibc_likely(cond) __builtin_expect((cond), 1)
// 获取字符串长度
-size_t strlen(const char *str) {
+size_t strlen(const char* _str) {
size_t len = 0;
- while (str[len]) {
+ while (_str[len]) {
len++;
}
return len;
}
-size_t strnlen(const char *str, size_t maxlen) {
- const char * char_ptr, *end_ptr = str + maxlen;
- const unsigned long int *longword_ptr;
+size_t strnlen(const char* _str, size_t _maxlen) {
+ const char * char_ptr, *end_ptr = _str + _maxlen;
+ const unsigned long int* longword_ptr;
unsigned long int longword, himagic, lomagic;
- if (maxlen == 0)
+ if (_maxlen == 0) {
return 0;
+ }
- if (__glibc_unlikely(end_ptr < str))
- end_ptr = (const char *)~0UL;
+ if (__glibc_unlikely(end_ptr < _str)) {
+ end_ptr = (const char*)~0UL;
+ }
/* Handle the first few characters by reading one character at a time.
Do this until CHAR_PTR is aligned on a longword boundary. */
- for (char_ptr = str;
+ for (char_ptr = _str;
((unsigned long int)char_ptr & (sizeof(longword) - 1)) != 0;
- ++char_ptr)
+ ++char_ptr) {
if (*char_ptr == '\0') {
- if (char_ptr > end_ptr)
+ if (char_ptr > end_ptr) {
char_ptr = end_ptr;
- return char_ptr - str;
+ }
+ return char_ptr - _str;
}
+ }
/* All these elucidatory comments refer to 4-byte longwords,
but the theory applies equally well to 8-byte longwords. */
- longword_ptr = (unsigned long int *)char_ptr;
+ longword_ptr = (unsigned long int*)char_ptr;
/* Bits 31, 24, 16, and 8 of this number are zero. Call these bits
the "holes." Note that there is a hole just to the left of
@@ -60,8 +74,8 @@ size_t strnlen(const char *str, size_t maxlen) {
The 1-bits make sure that carries propagate to the next 0-bit.
The 0-bits provide holes for carries to fall into. */
- himagic = 0x80808080L;
- lomagic = 0x01010101L;
+ himagic = 0x80808080L;
+ lomagic = 0x01010101L;
if (sizeof(longword) > 4) {
/* 64-bit version of the magic. */
/* Do the shift in two steps to avoid a warning if long has 32 bits. */
@@ -76,177 +90,196 @@ size_t strnlen(const char *str, size_t maxlen) {
/* Instead of the traditional loop which tests each character,
we will test a longword at a time. The tricky part is testing
if *any of the four* bytes in the longword in question are zero. */
- while (longword_ptr < (unsigned long int *)end_ptr) {
+ while (longword_ptr < (unsigned long int*)end_ptr) {
longword = *longword_ptr++;
if ((longword - lomagic) & himagic) {
/* Which of the bytes was the zero? If none of them were, it was
a misfire; continue the search. */
- const char *cp = (const char *)(longword_ptr - 1);
+ const char* cp = (const char*)(longword_ptr - 1);
- char_ptr = cp;
- if (cp[0] == 0)
+ char_ptr = cp;
+ if (cp[0] == 0) {
break;
+ }
char_ptr = cp + 1;
- if (cp[1] == 0)
+ if (cp[1] == 0) {
break;
+ }
char_ptr = cp + 2;
- if (cp[2] == 0)
+ if (cp[2] == 0) {
break;
+ }
char_ptr = cp + 3;
- if (cp[3] == 0)
+ if (cp[3] == 0) {
break;
+ }
if (sizeof(longword) > 4) {
char_ptr = cp + 4;
- if (cp[4] == 0)
+ if (cp[4] == 0) {
break;
+ }
char_ptr = cp + 5;
- if (cp[5] == 0)
+ if (cp[5] == 0) {
break;
+ }
char_ptr = cp + 6;
- if (cp[6] == 0)
+ if (cp[6] == 0) {
break;
+ }
char_ptr = cp + 7;
- if (cp[7] == 0)
+ if (cp[7] == 0) {
break;
+ }
}
}
char_ptr = end_ptr;
}
- if (char_ptr > end_ptr)
+ if (char_ptr > end_ptr) {
char_ptr = end_ptr;
- return char_ptr - str;
+ }
+ return char_ptr - _str;
}
// 如果 src > dest, 则返回值大于 0,如果 src = dest, 则返回值等于 0,
// 如果 srd < dest ,则返回值小于 0。
-int strcmp(const char *src, const char *dest) {
- while (*src && *dest && (*src == *dest)) {
- src++;
- dest++;
+int strcmp(const char* _src, const char* _dest) {
+ while (*_src && *_dest && (*_src == *_dest)) {
+ _src++;
+ _dest++;
}
- return *src - *dest;
+ return *_src - *_dest;
}
-int strncmp(const char *s1, const char *s2, size_t n) {
-
- if (n == 0)
+int strncmp(const char* _s1, const char* _s2, size_t _n) {
+ if (_n == 0) {
return 0;
+ }
do {
- if (*s1 != *s2++)
- return (*(const unsigned char *)s1 -
- *(const unsigned char *)(s2 - 1));
- if (*s1++ == '\0')
+ if (*_s1 != *_s2++) {
+ return (*(const unsigned char*)_s1
+ - *(const unsigned char*)(_s2 - 1));
+ }
+ if (*_s1++ == '\0') {
break;
- } while (--n != 0);
+ }
+ } while (--_n != 0);
return 0;
}
-char *strcpy(char *dest, const char *src) {
- char *address = dest;
- while ((*dest++ = *src++) != '\0') {
+char* strcpy(char* _dest, const char* _src) {
+ char* address = _dest;
+ while ((*_dest++ = *_src++) != '\0') {
;
}
return address;
}
-char *strncpy(char *s1, const char *s2, size_t n) {
- size_t size = strnlen(s2, n);
- if (size != n)
- memset(s1 + size, '\0', n - size);
- return memcpy(s1, s2, size);
+char* strncpy(char* _s1, const char* _s2, size_t _n) {
+ size_t size = strnlen(_s2, _n);
+ if (size != _n) {
+ memset(_s1 + size, '\0', _n - size);
+ }
+ return memcpy(_s1, _s2, size);
}
-void backspace(char *src) {
- size_t len = strlen(src);
- src[len - 1] = '\0';
+void backspace(char* _src) {
+ size_t len = strlen(_src);
+ _src[len - 1] = '\0';
}
-void append(char *src, char dest) {
- size_t len = strlen(src);
- src[len] = dest;
- src[len + 1] = '\0';
+void append(char* _src, char _dest) {
+ size_t len = strlen(_src);
+ _src[len] = _dest;
+ _src[len + 1] = '\0';
}
-char *strcat(char *dest, const char *src) {
- uint8_t *add_d = (uint8_t *)dest;
- if (dest != 0 && src != 0) {
+char* strcat(char* _dest, const char* _src) {
+ uint8_t* add_d = (uint8_t*)_dest;
+ if (_dest != 0 && _src != 0) {
while (*add_d) {
add_d++;
}
- while (*src) {
- *add_d++ = *src++;
+ while (*_src) {
+ *add_d++ = *_src++;
}
}
- return dest;
+ return _dest;
}
-char *strchr(register const char *s, int c) {
+char* strchr(register const char* _s, int _c) {
do {
- if (*s == c) {
- return (char *)s;
+ if (*_s == _c) {
+ return (char*)_s;
}
- } while (*s++);
- return (0);
+ } while (*_s++);
+ return NULL;
}
-void *memcpy(void *dest, const void *src, size_t len) {
- char * d = dest;
- const char *s = src;
- while (len--)
+void* memcpy(void* _dest, const void* _src, size_t _len) {
+ char* d = _dest;
+ const char* s = _src;
+ while (_len--) {
*d++ = *s++;
- return dest;
+ }
+ return _dest;
}
-void *memset(void *dest, int val, size_t len) {
- unsigned char *ptr = dest;
- while (len-- > 0)
- *ptr++ = val;
- return dest;
+void* memset(void* _dest, int _val, size_t _len) {
+ unsigned char* ptr = _dest;
+ while (_len-- > 0) {
+ *ptr++ = _val;
+ }
+ return _dest;
}
-void bzero(void *dest, uint32_t len) {
- memset(dest, 0, len);
+void bzero(void* _dest, uint32_t _len) {
+ memset(_dest, 0, _len);
}
-int memcmp(const void *str1, const void *str2, size_t count) {
- register const unsigned char *s1 = (const unsigned char *)str1;
- register const unsigned char *s2 = (const unsigned char *)str2;
+int memcmp(const void* _str1, const void* _str2, size_t _count) {
+ register const unsigned char* s1 = (const unsigned char*)_str1;
+ register const unsigned char* s2 = (const unsigned char*)_str2;
- while (count-- > 0) {
- if (*s1++ != *s2++)
+ while (_count-- > 0) {
+ if (*s1++ != *s2++) {
return s1[-1] < s2[-1] ? -1 : 1;
+ }
}
return 0;
}
-void *memmove(void *dest, const void *src, size_t len) {
- char * d = dest;
- const char *s = src;
- if (d < s)
- while (len--)
+void* memmove(void* _dest, const void* _src, size_t _len) {
+ char* d = _dest;
+ const char* s = _src;
+ if (d < s) {
+ while (_len--) {
*d++ = *s++;
+ }
+ }
else {
- const char *lasts = s + (len - 1);
- char * lastd = d + (len - 1);
- while (len--)
+ const char* lasts = s + (_len - 1);
+ char* lastd = d + (_len - 1);
+ while (_len--) {
*lastd-- = *lasts--;
+ }
}
- return dest;
+ return _dest;
}
-void strrev(char *str) {
+void strrev(char* _str) {
int i;
int j;
unsigned char a;
- unsigned len = strlen((const char *)str);
+ unsigned len = strlen((const char*)_str);
for (i = 0, j = len - 1; i < j; i++, j--) {
- a = str[i];
- str[i] = str[j];
- str[j] = a;
+ a = _str[i];
+ _str[i] = _str[j];
+ _str[j] = a;
}
+ return;
}
#ifdef __cplusplus
diff --git a/src/libcxx/CMakeLists.txt b/src/libcxx/CMakeLists.txt
index cc94239e9..bf3c61791 100644
--- a/src/libcxx/CMakeLists.txt
+++ b/src/libcxx/CMakeLists.txt
@@ -1,5 +1,6 @@
-# This file is a part of Simple-XX/SimpleKernel (https://github.com/Simple-XX/SimpleKernel).
+# This file is a part of Simple-XX/SimpleKernel
+# (https://github.com/Simple-XX/SimpleKernel).
#
# CMakeLists.txt for Simple-XX/SimpleKernel.
diff --git a/src/libcxx/include/algo b/src/libcxx/include/algo
index 633b0a101..f625c4d2f 100644
--- a/src/libcxx/include/algo
+++ b/src/libcxx/include/algo
@@ -1,1809 +1,1944 @@
-// This file is a part of Simple-XX/SimpleKernel
-// (https://github.com/Simple-XX/SimpleKernel).
-// Based on https://github.com/Alinshans/MyTinySTL
-// algo for Simple-XX/SimpleKernel.
-
-#ifndef _ALGO_
-#define _ALGO_
+/**
+ * @file algo
+ * @brief stl algo 支持
+ * @author Zone.N (Zone.Niuzh@hotmail.com)
+ * @version 1.0
+ * @date 2023-04-05
+ * @copyright MIT LICENSE
+ * https://github.com/Simple-XX/SimpleKernel
+ * Based on https://github.com/Alinshans/MyTinySTL
+ * @par change log:
+ *
+ * Date Author Description
+ * 2023-04-05 Zone.N 迁移到 doxygen
+ *
+ */
+
+#ifndef SIMPLEKERNEL_ALGO
+#define SIMPLEKERNEL_ALGO
// 这个头文件包含了 std 的一系列算法
-#include "stddef.h"
-#include "time.h"
#include "algobase"
-#include "memory"
-#include "heap_algo"
#include "functional"
+#include "heap_algo"
+#include "memory"
+#include "stddef.h"
+#include "time.h"
namespace mystl {
- /*****************************************************************************************/
- // all_of
- // 检查[first, last)内是否全部元素都满足一元操作 unary_pred 为 true
- // 的情况,满足则返回 true
- /*****************************************************************************************/
- template
- bool all_of(InputIter first, InputIter last, UnaryPredicate unary_pred) {
- for (; first != last; ++first) {
- if (!unary_pred(*first))
- return false;
+/*****************************************************************************************/
+// all_of
+// 检查[first, last)内是否全部元素都满足一元操作 unary_pred 为 true
+// 的情况,满足则返回 true
+/*****************************************************************************************/
+template
+bool all_of(InputIter first, InputIter last, UnaryPredicate unary_pred) {
+ for (; first != last; ++first) {
+ if (!unary_pred(*first)) {
+ return false;
}
- return true;
}
+ return true;
+}
- /*****************************************************************************************/
- // any_of
- // 检查[first, last)内是否存在某个元素满足一元操作 unary_pred 为 true
- // 的情况,满足则返回 true
- /*****************************************************************************************/
- template
- bool any_of(InputIter first, InputIter last, UnaryPredicate unary_pred) {
- for (; first != last; ++first) {
- if (unary_pred(*first))
- return true;
+/*****************************************************************************************/
+// any_of
+// 检查[first, last)内是否存在某个元素满足一元操作 unary_pred 为 true
+// 的情况,满足则返回 true
+/*****************************************************************************************/
+template
+bool any_of(InputIter first, InputIter last, UnaryPredicate unary_pred) {
+ for (; first != last; ++first) {
+ if (unary_pred(*first)) {
+ return true;
}
- return false;
}
+ return false;
+}
- /*****************************************************************************************/
- // none_of
- // 检查[first, last)内是否全部元素都不满足一元操作 unary_pred 为 true
- // 的情况,满足则返回 true
- /*****************************************************************************************/
- template
- bool none_of(InputIter first, InputIter last, UnaryPredicate unary_pred) {
- for (; first != last; ++first) {
- if (unary_pred(*first))
- return false;
+/*****************************************************************************************/
+// none_of
+// 检查[first, last)内是否全部元素都不满足一元操作 unary_pred 为 true
+// 的情况,满足则返回 true
+/*****************************************************************************************/
+template
+bool none_of(InputIter first, InputIter last, UnaryPredicate unary_pred) {
+ for (; first != last; ++first) {
+ if (unary_pred(*first)) {
+ return false;
}
- return true;
}
-
- /*****************************************************************************************/
- // count
- // 对[first, last)区间内的元素与给定值进行比较,缺省使用
- // operator==,返回元素相等的个数
- /*****************************************************************************************/
- template
- size_t count(InputIter first, InputIter last, const T &value) {
- size_t n = 0;
- for (; first != last; ++first) {
- if (*first == value)
- ++n;
- }
- return n;
- }
-
- /*****************************************************************************************/
- // count_if
- // 对[first, last)区间内的每个元素都进行一元 unary_pred 操作,返回结果为
- // true 的个数
- /*****************************************************************************************/
- template
- size_t count_if(InputIter first, InputIter last,
- UnaryPredicate unary_pred) {
- size_t n = 0;
- for (; first != last; ++first) {
- if (unary_pred(*first))
- ++n;
- }
- return n;
- }
-
- /*****************************************************************************************/
- // find
- // 在[first, last)区间内找到等于 value 的元素,返回指向该元素的迭代器
- /*****************************************************************************************/
- template
- InputIter find(InputIter first, InputIter last, const T &value) {
- while (first != last && *first != value)
- ++first;
- return first;
+ return true;
+}
+
+/*****************************************************************************************/
+// count
+// 对[first, last)区间内的元素与给定值进行比较,缺省使用
+// operator==,返回元素相等的个数
+/*****************************************************************************************/
+template
+size_t count(InputIter first, InputIter last, const T& value) {
+ size_t n = 0;
+ for (; first != last; ++first) {
+ if (*first == value) {
+ ++n;
+ }
+ }
+ return n;
+}
+
+/*****************************************************************************************/
+// count_if
+// 对[first, last)区间内的每个元素都进行一元 unary_pred 操作,返回结果为
+// true 的个数
+/*****************************************************************************************/
+template
+size_t count_if(InputIter first, InputIter last, UnaryPredicate unary_pred) {
+ size_t n = 0;
+ for (; first != last; ++first) {
+ if (unary_pred(*first)) {
+ ++n;
+ }
+ }
+ return n;
+}
+
+/*****************************************************************************************/
+// find
+// 在[first, last)区间内找到等于 value 的元素,返回指向该元素的迭代器
+/*****************************************************************************************/
+template
+InputIter find(InputIter first, InputIter last, const T& value) {
+ while (first != last && *first != value) {
+ ++first;
+ }
+ return first;
+}
+
+/*****************************************************************************************/
+// find_if
+// 在[first, last)区间内找到第一个令一元操作 unary_pred 为 true
+// 的元素并返回指向该元素的迭代器
+/*****************************************************************************************/
+template
+InputIter find_if(InputIter first, InputIter last, UnaryPredicate unary_pred) {
+ while (first != last && !unary_pred(*first)) {
+ ++first;
+ }
+ return first;
+}
+
+/*****************************************************************************************/
+// find_if_not
+// 在[first, last)区间内找到第一个令一元操作 unary_pred 为 false
+// 的元素并返回指向该元素的迭代器
+/*****************************************************************************************/
+template
+InputIter
+find_if_not(InputIter first, InputIter last, UnaryPredicate unary_pred) {
+ while (first != last && unary_pred(*first)) {
+ ++first;
+ }
+ return first;
+}
+
+/*****************************************************************************************/
+// search
+// 在[first1, last1)中查找[first2, last2)的首次出现点
+/*****************************************************************************************/
+template
+ForwardIter1 search(ForwardIter1 first1, ForwardIter1 last1,
+ ForwardIter2 first2, ForwardIter2 last2) {
+ auto d1 = mystl::distance(first1, last1);
+ auto d2 = mystl::distance(first2, last2);
+ if (d1 < d2) {
+ return last1;
}
-
- /*****************************************************************************************/
- // find_if
- // 在[first, last)区间内找到第一个令一元操作 unary_pred 为 true
- // 的元素并返回指向该元素的迭代器
- /*****************************************************************************************/
- template
- InputIter find_if(InputIter first, InputIter last,
- UnaryPredicate unary_pred) {
- while (first != last && !unary_pred(*first))
- ++first;
- return first;
+ auto current1 = first1;
+ auto current2 = first2;
+ while (current2 != last2) {
+ if (*current1 == *current2) {
+ ++current1;
+ ++current2;
+ }
+ else {
+ if (d1 == d2) {
+ return last1;
+ }
+ else {
+ current1 = ++first1;
+ current2 = first2;
+ --d1;
+ }
+ }
}
+ return first1;
+}
- /*****************************************************************************************/
- // find_if_not
- // 在[first, last)区间内找到第一个令一元操作 unary_pred 为 false
- // 的元素并返回指向该元素的迭代器
- /*****************************************************************************************/
- template
- InputIter find_if_not(InputIter first, InputIter last,
- UnaryPredicate unary_pred) {
- while (first != last && unary_pred(*first))
- ++first;
- return first;
+// 重载版本使用函数对象 comp 代替比较操作
+template
+ForwardIter1 search(ForwardIter1 first1, ForwardIter1 last1,
+ ForwardIter2 first2, ForwardIter2 last2, Compared comp) {
+ auto d1 = mystl::distance(first1, last1);
+ auto d2 = mystl::distance(first2, last2);
+ if (d1 < d2) {
+ return last1;
}
-
- /*****************************************************************************************/
- // search
- // 在[first1, last1)中查找[first2, last2)的首次出现点
- /*****************************************************************************************/
- template
- ForwardIter1 search(ForwardIter1 first1, ForwardIter1 last1,
- ForwardIter2 first2, ForwardIter2 last2) {
- auto d1 = mystl::distance(first1, last1);
- auto d2 = mystl::distance(first2, last2);
- if (d1 < d2)
- return last1;
- auto current1 = first1;
- auto current2 = first2;
- while (current2 != last2) {
- if (*current1 == *current2) {
- ++current1;
- ++current2;
+ auto current1 = first1;
+ auto current2 = first2;
+ while (current2 != last2) {
+ if (comp(*current1, *current2)) {
+ ++current1;
+ ++current2;
+ }
+ else {
+ if (d1 == d2) {
+ return last1;
}
else {
- if (d1 == d2) {
- return last1;
- }
- else {
- current1 = ++first1;
- current2 = first2;
- --d1;
- }
+ current1 = ++first1;
+ current2 = first2;
+ --d1;
}
}
- return first1;
}
+ return first1;
+}
- // 重载版本使用函数对象 comp 代替比较操作
- template
- ForwardIter1 search(ForwardIter1 first1, ForwardIter1 last1,
- ForwardIter2 first2, ForwardIter2 last2,
- Compared comp) {
- auto d1 = mystl::distance(first1, last1);
- auto d2 = mystl::distance(first2, last2);
- if (d1 < d2)
- return last1;
- auto current1 = first1;
- auto current2 = first2;
- while (current2 != last2) {
- if (comp(*current1, *current2)) {
- ++current1;
- ++current2;
+/*****************************************************************************************/
+// search_n
+// 在[first, last)中查找连续 n 个 value
+// 所形成的子序列,返回一个迭代器指向该子序列的起始处
+/*****************************************************************************************/
+template
+ForwardIter
+search_n(ForwardIter first, ForwardIter last, Size n, const T& value) {
+ if (n <= 0) {
+ return first;
+ }
+ else {
+ first = mystl::find(first, last, value);
+ while (first != last) {
+ auto m = n - 1;
+ auto i = first;
+ ++i;
+ while (i != last && m != 0 && *i == value) {
+ ++i;
+ --m;
+ }
+ if (m == 0) {
+ return first;
}
else {
- if (d1 == d2) {
- return last1;
- }
- else {
- current1 = ++first1;
- current2 = first2;
- --d1;
- }
+ first = mystl::find(i, last, value);
}
}
- return first1;
+ return last;
}
+}
- /*****************************************************************************************/
- // search_n
- // 在[first, last)中查找连续 n 个 value
- // 所形成的子序列,返回一个迭代器指向该子序列的起始处
- /*****************************************************************************************/
- template
- ForwardIter search_n(ForwardIter first, ForwardIter last, Size n,
- const T &value) {
- if (n <= 0) {
- return first;
+// 重载版本使用函数对象 comp 代替比较操作
+template
+ForwardIter search_n(ForwardIter first, ForwardIter last, Size n,
+ const T& value, Compared comp) {
+ if (n <= 0) {
+ return first;
+ }
+ else {
+ while (first != last) {
+ if (comp(*first, value)) {
+ break;
+ }
+ ++first;
}
- else {
- first = mystl::find(first, last, value);
- while (first != last) {
- auto m = n - 1;
- auto i = first;
+ while (first != last) {
+ auto m = n - 1;
+ auto i = first;
+ ++i;
+ while (i != last && m != 0 && comp(*i, value)) {
++i;
- while (i != last && m != 0 && *i == value) {
+ --m;
+ }
+ if (m == 0) {
+ return first;
+ }
+ else {
+ while (i != last) {
+ if (comp(*i, value)) {
+ break;
+ }
++i;
- --m;
- }
- if (m == 0) {
- return first;
- }
- else {
- first = mystl::find(i, last, value);
}
+ first = i;
}
- return last;
}
+ return last;
}
-
- // 重载版本使用函数对象 comp 代替比较操作
- template
- ForwardIter search_n(ForwardIter first, ForwardIter last, Size n,
- const T &value, Compared comp) {
- if (n <= 0) {
- return first;
- }
- else {
- while (first != last) {
- if (comp(*first, value))
- break;
- ++first;
+}
+
+/*****************************************************************************************/
+// find_end
+// 在[first1, last1)区间中查找[first2,
+// last2)最后一次出现的地方,若不存在返回 last1
+/*****************************************************************************************/
+// find_end_dispatch 的 forward_iterator_tag 版本
+template
+ForwardIter1 find_end_dispatch(ForwardIter1 first1, ForwardIter1 last1,
+ ForwardIter2 first2, ForwardIter2 last2,
+ forward_iterator_tag, forward_iterator_tag) {
+ if (first2 == last2) {
+ return last1;
+ }
+ else {
+ auto result = last1;
+ while (true) {
+ // 利用 search 查找某个子序列的首次出现点,找不到则返回 last1
+ auto new_result = mystl::search(first1, last1, first2, last2);
+ if (new_result == last1) {
+ return result;
}
- while (first != last) {
- auto m = n - 1;
- auto i = first;
- ++i;
- while (i != last && m != 0 && comp(*i, value)) {
- ++i;
- --m;
- }
- if (m == 0) {
- return first;
- }
- else {
- while (i != last) {
- if (comp(*i, value))
- break;
- ++i;
- }
- first = i;
- }
+ else {
+ result = new_result;
+ first1 = new_result;
+ ++first1;
}
- return last;
}
}
+}
- /*****************************************************************************************/
- // find_end
- // 在[first1, last1)区间中查找[first2,
- // last2)最后一次出现的地方,若不存在返回 last1
- /*****************************************************************************************/
- // find_end_dispatch 的 forward_iterator_tag 版本
- template
- ForwardIter1 find_end_dispatch(ForwardIter1 first1, ForwardIter1 last1,
- ForwardIter2 first2, ForwardIter2 last2,
- forward_iterator_tag, forward_iterator_tag) {
- if (first2 == last2) {
- return last1;
- }
- else {
- auto result = last1;
- while (true) {
- // 利用 search 查找某个子序列的首次出现点,找不到则返回 last1
- auto new_result = mystl::search(first1, last1, first2, last2);
- if (new_result == last1) {
- return result;
- }
- else {
- result = new_result;
- first1 = new_result;
- ++first1;
- }
+// find_end_dispatch 的 bidirectional_iterator_tag 版本
+template
+BidirectionalIter1
+find_end_dispatch(BidirectionalIter1 first1, BidirectionalIter1 last1,
+ BidirectionalIter2 first2, BidirectionalIter2 last2,
+ bidirectional_iterator_tag, bidirectional_iterator_tag) {
+ typedef reverse_iterator reviter1;
+ typedef reverse_iterator reviter2;
+ reviter1 rlast1(first1);
+ reviter2 rlast2(first2);
+ reviter1 rresult
+ = mystl::search(reviter1(last1), rlast1, reviter2(last2), rlast2);
+ if (rresult == rlast1) {
+ return last1;
+ }
+ else {
+ auto result = rresult.base();
+ mystl::advance(result, -mystl::distance(first2, last2));
+ return result;
+ }
+}
+
+template
+ForwardIter1 find_end(ForwardIter1 first1, ForwardIter1 last1,
+ ForwardIter2 first2, ForwardIter2 last2) {
+ typedef typename iterator_traits::iterator_category Category1;
+ typedef typename iterator_traits::iterator_category Category2;
+ return mystl::find_end_dispatch(first1, last1, first2, last2, Category1(),
+ Category2());
+}
+
+// 重载版本使用函数对象 comp 代替比较操作
+// find_end_dispatch 的 forward_iterator_tag 版本
+template
+ForwardIter1
+find_end_dispatch(ForwardIter1 first1, ForwardIter1 last1, ForwardIter2 first2,
+ ForwardIter2 last2, forward_iterator_tag,
+ forward_iterator_tag, Compared comp) {
+ if (first2 == last2) {
+ return last1;
+ }
+ else {
+ auto result = last1;
+ while (true) {
+ // 利用 search 查找某个子序列的首次出现点,找不到则返回 last1
+ auto new_result = mystl::search(first1, last1, first2, last2, comp);
+ if (new_result == last1) {
+ return result;
+ }
+ else {
+ result = new_result;
+ first1 = new_result;
+ ++first1;
}
}
}
+}
- // find_end_dispatch 的 bidirectional_iterator_tag 版本
- template
- BidirectionalIter1
- find_end_dispatch(BidirectionalIter1 first1, BidirectionalIter1 last1,
- BidirectionalIter2 first2, BidirectionalIter2 last2,
- bidirectional_iterator_tag, bidirectional_iterator_tag) {
- typedef reverse_iterator reviter1;
- typedef reverse_iterator reviter2;
- reviter1 rlast1(first1);
- reviter2 rlast2(first2);
- reviter1 rresult =
- mystl::search(reviter1(last1), rlast1, reviter2(last2), rlast2);
- if (rresult == rlast1) {
- return last1;
- }
- else {
- auto result = rresult.base();
- mystl::advance(result, -mystl::distance(first2, last2));
- return result;
+// find_end_dispatch 的 bidirectional_iterator_tag 版本
+template
+BidirectionalIter1
+find_end_dispatch(BidirectionalIter1 first1, BidirectionalIter1 last1,
+ BidirectionalIter2 first2, BidirectionalIter2 last2,
+ bidirectional_iterator_tag, bidirectional_iterator_tag,
+ Compared comp) {
+ typedef reverse_iterator reviter1;
+ typedef reverse_iterator reviter2;
+ reviter1 rlast1(first1);
+ reviter2 rlast2(first2);
+ reviter1 rresult
+ = mystl::search(reviter1(last1), rlast1, reviter2(last2), rlast2, comp);
+ if (rresult == rlast1) {
+ return last1;
+ }
+ else {
+ auto result = rresult.base();
+ mystl::advance(result, -mystl::distance(first2, last2));
+ return result;
+ }
+}
+
+template
+ForwardIter1 find_end(ForwardIter1 first1, ForwardIter1 last1,
+ ForwardIter2 first2, ForwardIter2 last2, Compared comp) {
+ typedef typename iterator_traits::iterator_category Category1;
+ typedef typename iterator_traits::iterator_category Category2;
+ return mystl::find_end_dispatch(first1, last1, first2, last2, Category1(),
+ Category2(), comp);
+}
+
+/*****************************************************************************************/
+// find_first_of
+// 在[first1, last1)中查找[first2,
+// last2)中的某些元素,返回指向第一次出现的元素的迭代器
+/*****************************************************************************************/
+template
+InputIter find_first_of(InputIter first1, InputIter last1, ForwardIter first2,
+ ForwardIter last2) {
+ for (; first1 != last1; ++first1) {
+ for (auto iter = first2; iter != last2; ++iter) {
+ if (*first1 == *iter) {
+ return first1;
+ }
+ }
+ }
+ return last1;
+}
+
+// 重载版本使用函数对象 comp 代替比较操作
+template
+InputIter find_first_of(InputIter first1, InputIter last1, ForwardIter first2,
+ ForwardIter last2, Compared comp) {
+ for (; first1 != last1; ++first1) {
+ for (auto iter = first2; iter != last2; ++iter) {
+ if (comp(*first1, *iter)) {
+ return first1;
+ }
+ }
+ }
+ return last1;
+}
+
+/*****************************************************************************************/
+// for_each
+// 使用一个函数对象 f 对[first, last)区间内的每个元素执行一个 operator()
+// 操作,但不能改变元素内容 f() 可返回一个值,但该值会被忽略
+/*****************************************************************************************/
+template
+Function for_each(InputIter first, InputIter last, Function f) {
+ for (; first != last; ++first) {
+ f(*first);
+ }
+ return f;
+}
+
+/*****************************************************************************************/
+// adjacent_find
+// 找出第一对匹配的相邻元素,缺省使用 operator==
+// 比较,如果找到返回一个迭代器,指向这对元素的第一个元素
+/*****************************************************************************************/
+template
+ForwardIter adjacent_find(ForwardIter first, ForwardIter last) {
+ if (first == last) {
+ return last;
+ }
+ auto next = first;
+ while (++next != last) {
+ if (*first == *next) {
+ return first;
}
+ first = next;
}
+ return last;
+}
- template
- ForwardIter1 find_end(ForwardIter1 first1, ForwardIter1 last1,
- ForwardIter2 first2, ForwardIter2 last2) {
- typedef
- typename iterator_traits::iterator_category Category1;
- typedef
- typename iterator_traits::iterator_category Category2;
- return mystl::find_end_dispatch(first1, last1, first2, last2,
- Category1(), Category2());
+// 重载版本使用函数对象 comp 代替比较操作
+template
+ForwardIter adjacent_find(ForwardIter first, ForwardIter last, Compared comp) {
+ if (first == last) {
+ return last;
}
-
- // 重载版本使用函数对象 comp 代替比较操作
- // find_end_dispatch 的 forward_iterator_tag 版本
- template
- ForwardIter1 find_end_dispatch(ForwardIter1 first1, ForwardIter1 last1,
- ForwardIter2 first2, ForwardIter2 last2,
- forward_iterator_tag, forward_iterator_tag,
- Compared comp) {
- if (first2 == last2) {
- return last1;
+ auto next = first;
+ while (++next != last) {
+ if (comp(*first, *next)) {
+ return first;
}
- else {
- auto result = last1;
- while (true) {
- // 利用 search 查找某个子序列的首次出现点,找不到则返回 last1
- auto new_result =
- mystl::search(first1, last1, first2, last2, comp);
- if (new_result == last1) {
- return result;
- }
- else {
- result = new_result;
- first1 = new_result;
- ++first1;
- }
- }
+ first = next;
+ }
+ return last;
+}
+
+/*****************************************************************************************/
+// lower_bound
+// 在[first, last)中查找第一个不小于 value
+// 的元素,并返回指向它的迭代器,若没有则返回 last
+/*****************************************************************************************/
+// lbound_dispatch 的 forward_iterator_tag 版本
+template
+ForwardIter lbound_dispatch(ForwardIter first, ForwardIter last, const T& value,
+ forward_iterator_tag) {
+ auto len = mystl::distance(first, last);
+ auto half = len;
+ ForwardIter middle;
+ while (len > 0) {
+ half = len >> 1;
+ middle = first;
+ mystl::advance(middle, half);
+ if (*middle < value) {
+ first = middle;
+ ++first;
+ len = len - half - 1;
}
- }
-
- // find_end_dispatch 的 bidirectional_iterator_tag 版本
- template
- BidirectionalIter1
- find_end_dispatch(BidirectionalIter1 first1, BidirectionalIter1 last1,
- BidirectionalIter2 first2, BidirectionalIter2 last2,
- bidirectional_iterator_tag, bidirectional_iterator_tag,
- Compared comp) {
- typedef reverse_iterator reviter1;
- typedef reverse_iterator reviter2;
- reviter1 rlast1(first1);
- reviter2 rlast2(first2);
- reviter1 rresult = mystl::search(reviter1(last1), rlast1,
- reviter2(last2), rlast2, comp);
- if (rresult == rlast1) {
- return last1;
+ else {
+ len = half;
+ }
+ }
+ return first;
+}
+
+// lbound_dispatch 的 random_access_iterator_tag 版本
+template
+RandomIter lbound_dispatch(RandomIter first, RandomIter last, const T& value,
+ random_access_iterator_tag) {
+ auto len = last - first;
+ auto half = len;
+ RandomIter middle;
+ while (len > 0) {
+ half = len >> 1;
+ middle = first + half;
+ if (*middle < value) {
+ first = middle + 1;
+ len = len - half - 1;
}
else {
- auto result = rresult.base();
- mystl::advance(result, -mystl::distance(first2, last2));
- return result;
+ len = half;
+ }
+ }
+ return first;
+}
+
+template
+ForwardIter lower_bound(ForwardIter first, ForwardIter last, const T& value) {
+ return mystl::lbound_dispatch(first, last, value, iterator_category(first));
+}
+
+// 重载版本使用函数对象 comp 代替比较操作
+// lbound_dispatch 的 forward_iterator_tag 版本
+template
+ForwardIter lbound_dispatch(ForwardIter first, ForwardIter last, const T& value,
+ forward_iterator_tag, Compared comp) {
+ auto len = mystl::distance(first, last);
+ auto half = len;
+ ForwardIter middle;
+ while (len > 0) {
+ half = len >> 1;
+ middle = first;
+ mystl::advance(middle, half);
+ if (comp(*middle, value)) {
+ first = middle;
+ ++first;
+ len = len - half - 1;
}
- }
-
- template
- ForwardIter1 find_end(ForwardIter1 first1, ForwardIter1 last1,
- ForwardIter2 first2, ForwardIter2 last2,
- Compared comp) {
- typedef
- typename iterator_traits::iterator_category Category1;
- typedef
- typename iterator_traits::iterator_category Category2;
- return mystl::find_end_dispatch(first1, last1, first2, last2,
- Category1(), Category2(), comp);
- }
-
- /*****************************************************************************************/
- // find_first_of
- // 在[first1, last1)中查找[first2,
- // last2)中的某些元素,返回指向第一次出现的元素的迭代器
- /*****************************************************************************************/
- template
- InputIter find_first_of(InputIter first1, InputIter last1,
- ForwardIter first2, ForwardIter last2) {
- for (; first1 != last1; ++first1) {
- for (auto iter = first2; iter != last2; ++iter) {
- if (*first1 == *iter)
- return first1;
- }
+ else {
+ len = half;
+ }
+ }
+ return first;
+}
+
+// lbound_dispatch 的 random_access_iterator_tag 版本
+template
+RandomIter lbound_dispatch(RandomIter first, RandomIter last, const T& value,
+ random_access_iterator_tag, Compared comp) {
+ auto len = last - first;
+ auto half = len;
+ RandomIter middle;
+ while (len > 0) {
+ half = len >> 1;
+ middle = first + half;
+ if (comp(*middle, value)) {
+ first = middle + 1;
+ len = len - half - 1;
}
- return last1;
- }
-
- // 重载版本使用函数对象 comp 代替比较操作
- template
- InputIter find_first_of(InputIter first1, InputIter last1,
- ForwardIter first2, ForwardIter last2,
- Compared comp) {
- for (; first1 != last1; ++first1) {
- for (auto iter = first2; iter != last2; ++iter) {
- if (comp(*first1, *iter))
- return first1;
- }
+ else {
+ len = half;
}
- return last1;
}
+ return first;
+}
- /*****************************************************************************************/
- // for_each
- // 使用一个函数对象 f 对[first, last)区间内的每个元素执行一个 operator()
- // 操作,但不能改变元素内容 f() 可返回一个值,但该值会被忽略
- /*****************************************************************************************/
- template
- Function for_each(InputIter first, InputIter last, Function f) {
- for (; first != last; ++first) {
- f(*first);
- }
- return f;
- }
-
- /*****************************************************************************************/
- // adjacent_find
- // 找出第一对匹配的相邻元素,缺省使用 operator==
- // 比较,如果找到返回一个迭代器,指向这对元素的第一个元素
- /*****************************************************************************************/
- template
- ForwardIter adjacent_find(ForwardIter first, ForwardIter last) {
- if (first == last)
- return last;
- auto next = first;
- while (++next != last) {
- if (*first == *next)
- return first;
- first = next;
+template
+ForwardIter lower_bound(ForwardIter first, ForwardIter last, const T& value,
+ Compared comp) {
+ return mystl::lbound_dispatch(first, last, value, iterator_category(first),
+ comp);
+}
+
+/*****************************************************************************************/
+// upper_bound
+// 在[first, last)中查找第一个大于value
+// 的元素,并返回指向它的迭代器,若没有则返回 last
+/*****************************************************************************************/
+// ubound_dispatch 的 forward_iterator_tag 版本
+template
+ForwardIter ubound_dispatch(ForwardIter first, ForwardIter last, const T& value,
+ forward_iterator_tag) {
+ auto len = mystl::distance(first, last);
+ auto half = len;
+ ForwardIter middle;
+ while (len > 0) {
+ half = len >> 1;
+ middle = first;
+ mystl::advance(middle, half);
+ if (value < *middle) {
+ len = half;
}
- return last;
- }
-
- // 重载版本使用函数对象 comp 代替比较操作
- template
- ForwardIter adjacent_find(ForwardIter first, ForwardIter last,
- Compared comp) {
- if (first == last)
- return last;
- auto next = first;
- while (++next != last) {
- if (comp(*first, *next))
- return first;
- first = next;
+ else {
+ first = middle;
+ ++first;
+ len = len - half - 1;
}
- return last;
}
+ return first;
+}
- /*****************************************************************************************/
- // lower_bound
- // 在[first, last)中查找第一个不小于 value
- // 的元素,并返回指向它的迭代器,若没有则返回 last
- /*****************************************************************************************/
- // lbound_dispatch 的 forward_iterator_tag 版本
- template
- ForwardIter lbound_dispatch(ForwardIter first, ForwardIter last,
- const T &value, forward_iterator_tag) {
- auto len = mystl::distance(first, last);
- auto half = len;
- ForwardIter middle;
- while (len > 0) {
- half = len >> 1;
- middle = first;
- mystl::advance(middle, half);
- if (*middle < value) {
- first = middle;
- ++first;
- len = len - half - 1;
- }
- else {
- len = half;
- }
+// ubound_dispatch 的 random_access_iterator_tag 版本
+template
+RandomIter ubound_dispatch(RandomIter first, RandomIter last, const T& value,
+ random_access_iterator_tag) {
+ auto len = last - first;
+ auto half = len;
+ RandomIter middle;
+ while (len > 0) {
+ half = len >> 1;
+ middle = first + half;
+ if (value < *middle) {
+ len = half;
}
- return first;
- }
-
- // lbound_dispatch 的 random_access_iterator_tag 版本
- template
- RandomIter lbound_dispatch(RandomIter first, RandomIter last,
- const T &value, random_access_iterator_tag) {
- auto len = last - first;
- auto half = len;
- RandomIter middle;
- while (len > 0) {
- half = len >> 1;
- middle = first + half;
- if (*middle < value) {
- first = middle + 1;
- len = len - half - 1;
- }
- else {
- len = half;
- }
+ else {
+ first = middle + 1;
+ len = len - half - 1;
+ }
+ }
+ return first;
+}
+
+template
+ForwardIter upper_bound(ForwardIter first, ForwardIter last, const T& value) {
+ return mystl::ubound_dispatch(first, last, value, iterator_category(first));
+}
+
+// 重载版本使用函数对象 comp 代替比较操作
+// ubound_dispatch 的 forward_iterator_tag 版本
+template
+ForwardIter ubound_dispatch(ForwardIter first, ForwardIter last, const T& value,
+ forward_iterator_tag, Compared comp) {
+ auto len = mystl::distance(first, last);
+ auto half = len;
+ ForwardIter middle;
+ while (len > 0) {
+ half = len >> 1;
+ middle = first;
+ mystl::advance(middle, half);
+ if (comp(value, *middle)) {
+ len = half;
}
- return first;
- }
-
- template
- ForwardIter lower_bound(ForwardIter first, ForwardIter last,
- const T &value) {
- return mystl::lbound_dispatch(first, last, value,
- iterator_category(first));
- }
-
- // 重载版本使用函数对象 comp 代替比较操作
- // lbound_dispatch 的 forward_iterator_tag 版本
- template
- ForwardIter lbound_dispatch(ForwardIter first, ForwardIter last,
- const T &value, forward_iterator_tag,
- Compared comp) {
- auto len = mystl::distance(first, last);
- auto half = len;
- ForwardIter middle;
- while (len > 0) {
- half = len >> 1;
- middle = first;
- mystl::advance(middle, half);
- if (comp(*middle, value)) {
- first = middle;
- ++first;
- len = len - half - 1;
- }
- else {
- len = half;
- }
+ else {
+ first = middle;
+ ++first;
+ len = len - half - 1;
}
- return first;
}
+ return first;
+}
- // lbound_dispatch 的 random_access_iterator_tag 版本
- template
- RandomIter lbound_dispatch(RandomIter first, RandomIter last,
- const T &value, random_access_iterator_tag,
- Compared comp) {
- auto len = last - first;
- auto half = len;
- RandomIter middle;
- while (len > 0) {
- half = len >> 1;
- middle = first + half;
- if (comp(*middle, value)) {
- first = middle + 1;
- len = len - half - 1;
- }
- else {
- len = half;
- }
+// ubound_dispatch 的 random_access_iterator_tag 版本
+template
+RandomIter ubound_dispatch(RandomIter first, RandomIter last, const T& value,
+ random_access_iterator_tag, Compared comp) {
+ auto len = last - first;
+ auto half = len;
+ RandomIter middle;
+ while (len > 0) {
+ half = len >> 1;
+ middle = first + half;
+ if (comp(value, *middle)) {
+ len = half;
}
- return first;
- }
-
- template
- ForwardIter lower_bound(ForwardIter first, ForwardIter last, const T &value,
- Compared comp) {
- return mystl::lbound_dispatch(first, last, value,
- iterator_category(first), comp);
- }
-
- /*****************************************************************************************/
- // upper_bound
- // 在[first, last)中查找第一个大于value
- // 的元素,并返回指向它的迭代器,若没有则返回 last
- /*****************************************************************************************/
- // ubound_dispatch 的 forward_iterator_tag 版本
- template
- ForwardIter ubound_dispatch(ForwardIter first, ForwardIter last,
- const T &value, forward_iterator_tag) {
- auto len = mystl::distance(first, last);
- auto half = len;
- ForwardIter middle;
- while (len > 0) {
- half = len >> 1;
- middle = first;
- mystl::advance(middle, half);
- if (value < *middle) {
- len = half;
- }
- else {
- first = middle;
- ++first;
- len = len - half - 1;
- }
+ else {
+ first = middle + 1;
+ len = len - half - 1;
}
- return first;
}
+ return first;
+}
- // ubound_dispatch 的 random_access_iterator_tag 版本
- template
- RandomIter ubound_dispatch(RandomIter first, RandomIter last,
- const T &value, random_access_iterator_tag) {
- auto len = last - first;
- auto half = len;
- RandomIter middle;
- while (len > 0) {
- half = len >> 1;
- middle = first + half;
- if (value < *middle) {
- len = half;
- }
- else {
- first = middle + 1;
- len = len - half - 1;
- }
+template
+ForwardIter upper_bound(ForwardIter first, ForwardIter last, const T& value,
+ Compared comp) {
+ return mystl::ubound_dispatch(first, last, value, iterator_category(first),
+ comp);
+}
+
+/*****************************************************************************************/
+// binary_search
+// 二分查找,如果在[first, last)内有等同于 value 的元素,返回 true,否则返回
+// false
+/*****************************************************************************************/
+template
+bool binary_search(ForwardIter first, ForwardIter last, const T& value) {
+ auto i = mystl::lower_bound(first, last, value);
+ return i != last && !(value < *i);
+}
+
+// 重载版本使用函数对象 comp 代替比较操作
+template
+bool binary_search(ForwardIter first, ForwardIter last, const T& value,
+ Compared comp) {
+ auto i = mystl::lower_bound(first, last, value);
+ return i != last && !comp(value, *i);
+}
+
+/*****************************************************************************************/
+// equal_range
+// 查找[first,last)区间中与 value
+// 相等的元素所形成的区间,返回一对迭代器指向区间首尾
+// 第一个迭代器指向第一个不小于 value 的元素,第二个迭代器指向第一个大于
+// value 的元素
+/*****************************************************************************************/
+// erange_dispatch 的 forward_iterator_tag 版本
+template
+mystl::pair
+erange_dispatch(ForwardIter first, ForwardIter last, const T& value,
+ forward_iterator_tag) {
+ auto len = mystl::distance(first, last);
+ auto half = len;
+ ForwardIter middle, left, right;
+ while (len > 0) {
+ half = len >> 1;
+ middle = first;
+ mystl::advance(middle, half);
+ if (*middle < value) {
+ first = middle;
+ ++first;
+ len = len - half - 1;
}
- return first;
- }
-
- template
- ForwardIter upper_bound(ForwardIter first, ForwardIter last,
- const T &value) {
- return mystl::ubound_dispatch(first, last, value,
- iterator_category(first));
- }
-
- // 重载版本使用函数对象 comp 代替比较操作
- // ubound_dispatch 的 forward_iterator_tag 版本
- template
- ForwardIter ubound_dispatch(ForwardIter first, ForwardIter last,
- const T &value, forward_iterator_tag,
- Compared comp) {
- auto len = mystl::distance(first, last);
- auto half = len;
- ForwardIter middle;
- while (len > 0) {
- half = len >> 1;
- middle = first;
- mystl::advance(middle, half);
- if (comp(value, *middle)) {
- len = half;
- }
- else {
- first = middle;
- ++first;
- len = len - half - 1;
- }
+ else if (value < *middle) {
+ len = half;
}
- return first;
- }
-
- // ubound_dispatch 的 random_access_iterator_tag 版本
- template
- RandomIter ubound_dispatch(RandomIter first, RandomIter last,
- const T &value, random_access_iterator_tag,
- Compared comp) {
- auto len = last - first;
- auto half = len;
- RandomIter middle;
- while (len > 0) {
- half = len >> 1;
- middle = first + half;
- if (comp(value, *middle)) {
- len = half;
- }
- else {
- first = middle + 1;
- len = len - half - 1;
- }
+ else {
+ left = mystl::lower_bound(first, last, value);
+ mystl::advance(first, len);
+ right = mystl::upper_bound(++middle, first, value);
+ return mystl::pair(left, right);
+ }
+ }
+ return mystl::pair(last, last);
+}
+
+// erange_dispatch 的 random_access_iterator_tag 版本
+template
+mystl::pair
+erange_dispatch(RandomIter first, RandomIter last, const T& value,
+ random_access_iterator_tag) {
+ auto len = last - first;
+ auto half = len;
+ RandomIter middle, left, right;
+ while (len > 0) {
+ half = len >> 1;
+ middle = first + half;
+ if (*middle < value) {
+ first = middle + 1;
+ len = len - half - 1;
+ }
+ else if (value < *middle) {
+ len = half;
}
- return first;
- }
-
- template
- ForwardIter upper_bound(ForwardIter first, ForwardIter last, const T &value,
- Compared comp) {
- return mystl::ubound_dispatch(first, last, value,
- iterator_category(first), comp);
- }
-
- /*****************************************************************************************/
- // binary_search
- // 二分查找,如果在[first, last)内有等同于 value 的元素,返回 true,否则返回
- // false
- /*****************************************************************************************/
- template
- bool binary_search(ForwardIter first, ForwardIter last, const T &value) {
- auto i = mystl::lower_bound(first, last, value);
- return i != last && !(value < *i);
- }
-
- // 重载版本使用函数对象 comp 代替比较操作
- template
- bool binary_search(ForwardIter first, ForwardIter last, const T &value,
- Compared comp) {
- auto i = mystl::lower_bound(first, last, value);
- return i != last && !comp(value, *i);
- }
-
- /*****************************************************************************************/
- // equal_range
- // 查找[first,last)区间中与 value
- // 相等的元素所形成的区间,返回一对迭代器指向区间首尾
- // 第一个迭代器指向第一个不小于 value 的元素,第二个迭代器指向第一个大于
- // value 的元素
- /*****************************************************************************************/
- // erange_dispatch 的 forward_iterator_tag 版本
- template
- mystl::pair
- erange_dispatch(ForwardIter first, ForwardIter last, const T &value,
- forward_iterator_tag) {
- auto len = mystl::distance(first, last);
- auto half = len;
- ForwardIter middle, left, right;
- while (len > 0) {
- half = len >> 1;
- middle = first;
- mystl::advance(middle, half);
- if (*middle < value) {
- first = middle;
- ++first;
- len = len - half - 1;
- }
- else if (value < *middle) {
- len = half;
- }
- else {
- left = mystl::lower_bound(first, last, value);
- mystl::advance(first, len);
- right = mystl::upper_bound(++middle, first, value);
- return mystl::pair(left, right);
- }
+ else {
+ left = mystl::lower_bound(first, middle, value);
+ right = mystl::upper_bound(++middle, first + len, value);
+ return mystl::pair(left, right);
+ }
+ }
+ return mystl::pair(last, last);
+}
+
+template
+mystl::pair
+equal_range(ForwardIter first, ForwardIter last, const T& value) {
+ return mystl::erange_dispatch(first, last, value, iterator_category(first));
+}
+
+// 重载版本使用函数对象 comp 代替比较操作
+// erange_dispatch 的 forward iterator 版本
+template
+mystl::pair
+erange_dispatch(ForwardIter first, ForwardIter last, const T& value,
+ forward_iterator_tag, Compared comp) {
+ auto len = mystl::distance(first, last);
+ auto half = len;
+ ForwardIter middle, left, right;
+ while (len > 0) {
+ half = len >> 1;
+ middle = first;
+ mystl::advance(middle, half);
+ if (comp(*middle, value)) {
+ first = middle;
+ ++first;
+ len = len - half - 1;
}
- return mystl::pair(last, last);
- }
-
- // erange_dispatch 的 random_access_iterator_tag 版本
- template
- mystl::pair
- erange_dispatch(RandomIter first, RandomIter last, const T &value,
- random_access_iterator_tag) {
- auto len = last - first;
- auto half = len;
- RandomIter middle, left, right;
- while (len > 0) {
- half = len >> 1;
- middle = first + half;
- if (*middle < value) {
- first = middle + 1;
- len = len - half - 1;
- }
- else if (value < *middle) {
- len = half;
- }
- else {
- left = mystl::lower_bound(first, middle, value);
- right = mystl::upper_bound(++middle, first + len, value);
- return mystl::pair(left, right);
- }
+ else if (comp(value, *middle)) {
+ len = half;
}
- return mystl::pair(last, last);
- }
-
- template
- mystl::pair
- equal_range(ForwardIter first, ForwardIter last, const T &value) {
- return mystl::erange_dispatch(first, last, value,
- iterator_category(first));
- }
-
- // 重载版本使用函数对象 comp 代替比较操作
- // erange_dispatch 的 forward iterator 版本
- template
- mystl::pair
- erange_dispatch(ForwardIter first, ForwardIter last, const T &value,
- forward_iterator_tag, Compared comp) {
- auto len = mystl::distance(first, last);
- auto half = len;
- ForwardIter middle, left, right;
- while (len > 0) {
- half = len >> 1;
- middle = first;
- mystl::advance(middle, half);
- if (comp(*middle, value)) {
- first = middle;
- ++first;
- len = len - half - 1;
- }
- else if (comp(value, *middle)) {
- len = half;
- }
- else {
- left = mystl::lower_bound(first, last, value, comp);
- mystl::advance(first, len);
- right = mystl::upper_bound(++middle, first, value, comp);
- return mystl::pair(left, right);
- }
+ else {
+ left = mystl::lower_bound(first, last, value, comp);
+ mystl::advance(first, len);
+ right = mystl::upper_bound(++middle, first, value, comp);
+ return mystl::pair(left, right);
+ }
+ }
+ return mystl::pair(last, last);
+}
+
+// erange_dispatch 的 random access iterator 版本
+template
+mystl::pair
+erange_dispatch(RandomIter first, RandomIter last, const T& value,
+ random_access_iterator_tag, Compared comp) {
+ auto len = last - first;
+ auto half = len;
+ RandomIter middle, left, right;
+ while (len > 0) {
+ half = len >> 1;
+ middle = first + half;
+ if (comp(*middle, value)) {
+ first = middle + 1;
+ len = len - half - 1;
+ }
+ else if (comp(value, *middle)) {
+ len = half;
}
- return mystl::pair(last, last);
- }
-
- // erange_dispatch 的 random access iterator 版本
- template
- mystl::pair
- erange_dispatch(RandomIter first, RandomIter last, const T &value,
- random_access_iterator_tag, Compared comp) {
- auto len = last - first;
- auto half = len;
- RandomIter middle, left, right;
- while (len > 0) {
- half = len >> 1;
- middle = first + half;
- if (comp(*middle, value)) {
- first = middle + 1;
- len = len - half - 1;
- }
- else if (comp(value, *middle)) {
- len = half;
- }
- else {
- left = mystl::lower_bound(first, middle, value, comp);
- right = mystl::upper_bound(++middle, first + len, value, comp);
- return mystl::pair(left, right);
- }
+ else {
+ left = mystl::lower_bound(first, middle, value, comp);
+ right = mystl::upper_bound(++middle, first + len, value, comp);
+ return mystl::pair(left, right);
}
- return mystl::pair(last, last);
- }
-
- template
- mystl::pair
- equal_range(ForwardIter first, ForwardIter last, const T &value,
- Compared comp) {
- return mystl::erange_dispatch(first, last, value,
- iterator_category(first), comp);
}
+ return mystl::pair(last, last);
+}
- /*****************************************************************************************/
- // generate
- // 将函数对象 gen 的运算结果对[first, last)内的每个元素赋值
- /*****************************************************************************************/
- template
- void generate(ForwardIter first, ForwardIter last, Generator gen) {
- for (; first != last; ++first) {
- *first = gen();
+template
+mystl::pair
+equal_range(ForwardIter first, ForwardIter last, const T& value,
+ Compared comp) {
+ return mystl::erange_dispatch(first, last, value, iterator_category(first),
+ comp);
+}
+
+/*****************************************************************************************/
+// generate
+// 将函数对象 gen 的运算结果对[first, last)内的每个元素赋值
+/*****************************************************************************************/
+template
+void generate(ForwardIter first, ForwardIter last, Generator gen) {
+ for (; first != last; ++first) {
+ *first = gen();
+ }
+}
+
+/*****************************************************************************************/
+// generate_n
+// 用函数对象 gen 连续对 n 个元素赋值
+/*****************************************************************************************/
+template
+void generate_n(ForwardIter first, Size n, Generator gen) {
+ for (; n > 0; --n, ++first) {
+ *first = gen();
+ }
+}
+
+/*****************************************************************************************/
+// includes
+// 判断序列一S1 是否包含序列二S2
+/*****************************************************************************************/
+template
+bool includes(InputIter1 first1, InputIter1 last1, InputIter2 first2,
+ InputIter2 last2) {
+ while (first1 != last1 && first2 != last2) {
+ if (*first2 < *first1) {
+ return false;
}
- }
-
- /*****************************************************************************************/
- // generate_n
- // 用函数对象 gen 连续对 n 个元素赋值
- /*****************************************************************************************/
- template
- void generate_n(ForwardIter first, Size n, Generator gen) {
- for (; n > 0; --n, ++first) {
- *first = gen();
+ else if (*first1 < *first2) {
+ ++first1;
+ }
+ else {
+ ++first1, ++first2;
}
}
+ return first2 == last2;
+}
- /*****************************************************************************************/
- // includes
- // 判断序列一S1 是否包含序列二S2
- /*****************************************************************************************/
- template
- bool includes(InputIter1 first1, InputIter1 last1, InputIter2 first2,
- InputIter2 last2) {
- while (first1 != last1 && first2 != last2) {
- if (*first2 < *first1) {
- return false;
- }
- else if (*first1 < *first2) {
- ++first1;
- }
- else {
- ++first1, ++first2;
- }
+// 重载版本使用函数对象 comp 代替比较操作
+template
+bool includes(InputIter1 first1, InputIter1 last1, InputIter2 first2,
+ InputIter2 last2, Compared comp) {
+ while (first1 != last1 && first2 != last2) {
+ if (comp(*first2, *first1)) {
+ return false;
+ }
+ else if (comp(*first1, *first2)) {
+ ++first1;
+ }
+ else {
+ ++first1, ++first2;
+ }
+ }
+ return first2 == last2;
+}
+
+/*****************************************************************************************/
+// is_heap
+// 检查[first, last)内的元素是否为一个堆,如果是,则返回 true
+/*****************************************************************************************/
+template
+bool is_heap(RandomIter first, RandomIter last) {
+ auto n = mystl::distance(first, last);
+ auto parent = 0;
+ for (auto child = 1; child < n; ++child) {
+ if (first[parent] < first[child]) {
+ return false;
+ }
+ if ((child & 1) == 0) {
+ ++parent;
}
- return first2 == last2;
}
+ return true;
+}
- // 重载版本使用函数对象 comp 代替比较操作
- template
- bool includes(InputIter1 first1, InputIter1 last1, InputIter2 first2,
- InputIter2 last2, Compared comp) {
- while (first1 != last1 && first2 != last2) {
- if (comp(*first2, *first1)) {
- return false;
- }
- else if (comp(*first1, *first2)) {
- ++first1;
- }
- else {
- ++first1, ++first2;
- }
+// 重载版本使用函数对象 comp 代替比较操作
+template
+bool is_heap(RandomIter first, RandomIter last, Compared comp) {
+ auto n = mystl::distance(first, last);
+ auto parent = 0;
+ for (auto child = 1; child < n; ++child) {
+ if (comp(first[parent], first[child])) {
+ return false;
+ }
+ if ((child & 1) == 0) {
+ ++parent;
}
- return first2 == last2;
}
+ return true;
+}
- /*****************************************************************************************/
- // is_heap
- // 检查[first, last)内的元素是否为一个堆,如果是,则返回 true
- /*****************************************************************************************/
- template
- bool is_heap(RandomIter first, RandomIter last) {
- auto n = mystl::distance(first, last);
- auto parent = 0;
- for (auto child = 1; child < n; ++child) {
- if (first[parent] < first[child])
- return false;
- if ((child & 1) == 0)
- ++parent;
- }
+/*****************************************************************************************/
+// is_sorted
+// 检查[first, last)内的元素是否升序,如果是升序,则返回 true
+/*****************************************************************************************/
+template
+bool is_sorted(ForwardIter first, ForwardIter last) {
+ if (first == last) {
return true;
}
-
- // 重载版本使用函数对象 comp 代替比较操作
- template
- bool is_heap(RandomIter first, RandomIter last, Compared comp) {
- auto n = mystl::distance(first, last);
- auto parent = 0;
- for (auto child = 1; child < n; ++child) {
- if (comp(first[parent], first[child]))
- return false;
- if ((child & 1) == 0)
- ++parent;
+ auto next = first;
+ ++next;
+ for (; next != last; first = next, ++next) {
+ if (*next < *first) {
+ return false;
}
- return true;
}
+ return true;
+}
- /*****************************************************************************************/
- // is_sorted
- // 检查[first, last)内的元素是否升序,如果是升序,则返回 true
- /*****************************************************************************************/
- template
- bool is_sorted(ForwardIter first, ForwardIter last) {
- if (first == last)
- return true;
- auto next = first;
- ++next;
- for (; next != last; first = next, ++next) {
- if (*next < *first)
- return false;
- }
+// 重载版本使用函数对象 comp 代替比较操作
+template
+bool is_sorted(ForwardIter first, ForwardIter last, Compared comp) {
+ if (first == last) {
return true;
}
-
- // 重载版本使用函数对象 comp 代替比较操作
- template
- bool is_sorted(ForwardIter first, ForwardIter last, Compared comp) {
- if (first == last)
- return true;
- auto next = first;
- ++next;
- for (; next != last; first = next, ++next) {
- if (comp(*next, *first))
- return false;
+ auto next = first;
+ ++next;
+ for (; next != last; first = next, ++next) {
+ if (comp(*next, *first)) {
+ return false;
}
- return true;
}
+ return true;
+}
- /*****************************************************************************************/
- // median
- // 找出三个值的中间值
- /*****************************************************************************************/
- template
- const T &median(const T &left, const T &mid, const T &right) {
- if (left < mid)
- if (mid < right) // left < mid < right
- return mid;
- else if (left < right) // left < right <= mid
- return right;
- else // right <= left < mid
- return left;
- else if (left < right) // mid <= left < right
- return left;
- else if (mid < right) // mid < right <= left
- return right;
- else // right <= mid <= left
+/*****************************************************************************************/
+// median
+// 找出三个值的中间值
+/*****************************************************************************************/
+template
+const T& median(const T& left, const T& mid, const T& right) {
+ if (left < mid) {
+ if (mid < right) { // left < mid < right
return mid;
- }
-
- // 重载版本使用函数对象 comp 代替比较操作
- template
- const T &median(const T &left, const T &mid, const T &right,
- Compared comp) {
- if (comp(left, mid))
- if (comp(mid, right))
- return mid;
- else if (comp(left, right))
- return right;
- else
- return left;
- else if (comp(left, right))
- return left;
- else if (comp(mid, right))
+ }
+ else if (left < right) { // left < right <= mid
return right;
- else
- return mid;
- }
-
- /*****************************************************************************************/
- // max_element
- // 返回一个迭代器,指向序列中最大的元素
- /*****************************************************************************************/
- template
- ForwardIter max_element(ForwardIter first, ForwardIter last) {
- if (first == last)
- return first;
- auto result = first;
- while (++first != last) {
- if (*result < *first)
- result = first;
}
- return result;
- }
-
- // 重载版本使用函数对象 comp 代替比较操作
- template
- ForwardIter max_element(ForwardIter first, ForwardIter last,
- Compared comp) {
- if (first == last)
- return first;
- auto result = first;
- while (++first != last) {
- if (comp(*result, *first))
- result = first;
+ else { // right <= left < mid
+ return left;
}
- return result;
}
-
- /*****************************************************************************************/
- // min_element
- // 返回一个迭代器,指向序列中最小的元素
- /*****************************************************************************************/
- template
- ForwardIter min_elememt(ForwardIter first, ForwardIter last) {
- if (first == last)
- return first;
- auto result = first;
- while (++first != last) {
- if (*first < *result)
- result = first;
- }
- return result;
+ else if (left < right) { // mid <= left < right
+ return left;
}
-
- // 重载版本使用函数对象 comp 代替比较操作
- template
- ForwardIter min_elememt(ForwardIter first, ForwardIter last,
- Compared comp) {
- if (first == last)
- return first;
- auto result = first;
- while (++first != last) {
- if (comp(*first, *result))
- result = first;
- }
- return result;
+ else if (mid < right) { // mid < right <= left
+ return right;
}
-
- /*****************************************************************************************/
- // swap_ranges
- // 将[first1, last1)从 first2 开始,交换相同个数元素
- // 交换的区间长度必须相同,两个序列不能互相重叠,返回一个迭代器指向序列二最后一个被交换元素的下一位置
- /*****************************************************************************************/
- template
- ForwardIter2 swap_ranges(ForwardIter1 first1, ForwardIter1 last1,
- ForwardIter2 first2) {
- for (; first1 != last1; ++first1, ++first2) {
- mystl::iter_swap(first1, first2);
- }
- return first2;
- }
-
- /*****************************************************************************************/
- // transform
- // 第一个版本以函数对象 unary_op 作用于[first,
- // last)中的每个元素并将结果保存至 result 中 第二个版本以函数对象 binary_op
- // 作用于两个序列[first1, last1)、[first2, last2)的相同位置
- /*****************************************************************************************/
- template
- OutputIter transform(InputIter first, InputIter last, OutputIter result,
- UnaryOperation unary_op) {
- for (; first != last; ++first, ++result) {
- *result = unary_op(*first);
- }
- return result;
+ else { // right <= mid <= left
+ return mid;
}
+}
- template
- OutputIter transform(InputIter1 first1, InputIter1 last1, InputIter2 first2,
- OutputIter result, BinaryOperation binary_op) {
- for (; first1 != last1; ++first1, ++first2, ++result) {
- *result = binary_op(*first1, *first2);
+// 重载版本使用函数对象 comp 代替比较操作
+template
+const T& median(const T& left, const T& mid, const T& right, Compared comp) {
+ if (comp(left, mid)) {
+ if (comp(mid, right)) {
+ return mid;
}
- return result;
- }
-
- /*****************************************************************************************/
- // remove_copy
- // 移除区间内与指定 value 相等的元素,并将结果复制到以 result
- // 标示起始位置的容器上
- /*****************************************************************************************/
- template
- OutputIter remove_copy(InputIter first, InputIter last, OutputIter result,
- const T &value) {
- for (; first != last; ++first) {
- if (*first != value) {
- *result++ = *first;
- }
+ else if (comp(left, right)) {
+ return right;
}
- return result;
- }
-
- /*****************************************************************************************/
- // remove
- // 移除所有与指定 value 相等的元素
- // 并不从容器中删除这些元素,所以 remove 和 remove_if 不适用于 array
- /*****************************************************************************************/
- template
- ForwardIter remove(ForwardIter first, ForwardIter last, const T &value) {
- first =
- mystl::find(first, last, value); // 利用 find 找出第一个匹配的地方
- auto next = first;
- return first == last ? first
- : mystl::remove_copy(++next, last, first, value);
- }
-
- /*****************************************************************************************/
- // remove_copy_if
- // 移除区间内所有令一元操作 unary_pred 为 true 的元素,并将结果复制到以
- // result 为起始位置的容器上
- /*****************************************************************************************/
- template
- OutputIter remove_copy_if(InputIter first, InputIter last,
- OutputIter result, UnaryPredicate unary_pred) {
- for (; first != last; ++first) {
- if (!unary_pred(*first)) {
- *result = *first;
- ++result;
- }
+ else {
+ return left;
}
- return result;
}
-
- /*****************************************************************************************/
- // remove_if
- // 移除区间内所有令一元操作 unary_pred 为 true 的元素
- /*****************************************************************************************/
- template
- ForwardIter remove_if(ForwardIter first, ForwardIter last,
- UnaryPredicate unary_pred) {
- first = mystl::find_if(first, last,
- unary_pred); // 利用 find_if 找出第一个匹配的地方
- auto next = first;
- return first == last
- ? first
- : mystl::remove_copy_if(++next, last, first, unary_pred);
- }
-
- /*****************************************************************************************/
- // replace
- // 将区间内所有的 old_value 都以 new_value 替代
- /*****************************************************************************************/
- template
- void replace(ForwardIter first, ForwardIter last, const T &old_value,
- const T &new_value) {
- for (; first != last; ++first) {
- if (*first == old_value)
- *first = new_value;
- }
- }
-
- /*****************************************************************************************/
- // replace_copy
- // 行为与 replace 类似,不同的是将结果复制到 result
- // 所指的容器中,原序列没有改变
- /*****************************************************************************************/
- template
- OutputIter replace_copy(InputIter first, InputIter last, OutputIter result,
- const T &old_value, const T &new_value) {
- for (; first != last; ++first, ++result) {
- *result = *first == old_value ? new_value : *first;
- }
- return result;
+ else if (comp(left, right)) {
+ return left;
}
-
- /*****************************************************************************************/
- // replace_copy_if
- // 行为与 replace_if 类似,不同的是将结果复制到 result
- // 所指的容器中,原序列没有改变
- /*****************************************************************************************/
- template
- OutputIter replace_copy_if(InputIter first, InputIter last,
- OutputIter result, UnaryPredicate unary_pred,
- const T &new_value) {
- for (; first != last; ++first, ++result) {
- *result = unary_pred(*first) ? new_value : *first;
- }
- return result;
+ else if (comp(mid, right)) {
+ return right;
}
+ else {
+ return mid;
+ }
+}
- /*****************************************************************************************/
- // replace_if
- // 将区间内所有令一元操作 unary_pred 为 true 的元素都用 new_value 替代
- /*****************************************************************************************/
- template
- void replace_if(ForwardIter first, ForwardIter last,
- UnaryPredicate unary_pred, const T &new_value) {
- for (; first != last; ++first) {
- if (unary_pred(*first))
- *first = new_value;
+/*****************************************************************************************/
+// max_element
+// 返回一个迭代器,指向序列中最大的元素
+/*****************************************************************************************/
+template
+ForwardIter max_element(ForwardIter first, ForwardIter last) {
+ if (first == last) {
+ return first;
+ }
+ auto result = first;
+ while (++first != last) {
+ if (*result < *first) {
+ result = first;
}
}
+ return result;
+}
- /*****************************************************************************************/
- // reverse
- // 将[first, last)区间内的元素反转
- /*****************************************************************************************/
- // reverse_dispatch 的 bidirectional_iterator_tag 版本
- template
- void reverse_dispatch(BidirectionalIter first, BidirectionalIter last,
- bidirectional_iterator_tag) {
- while (true) {
- if (first == last || first == --last)
- return;
- mystl::iter_swap(first++, last);
+// 重载版本使用函数对象 comp 代替比较操作
+template
+ForwardIter max_element(ForwardIter first, ForwardIter last, Compared comp) {
+ if (first == last) {
+ return first;
+ }
+ auto result = first;
+ while (++first != last) {
+ if (comp(*result, *first)) {
+ result = first;
}
}
+ return result;
+}
- // reverse_dispatch 的 random_access_iterator_tag 版本
- template
- void reverse_dispatch(RandomIter first, RandomIter last,
- random_access_iterator_tag) {
- while (first < last)
- mystl::iter_swap(first++, --last);
+/*****************************************************************************************/
+// min_element
+// 返回一个迭代器,指向序列中最小的元素
+/*****************************************************************************************/
+template
+ForwardIter min_elememt(ForwardIter first, ForwardIter last) {
+ if (first == last) {
+ return first;
+ }
+ auto result = first;
+ while (++first != last) {
+ if (*first < *result) {
+ result = first;
+ }
}
+ return result;
+}
- template
- void reverse(BidirectionalIter first, BidirectionalIter last) {
- mystl::reverse_dispatch(first, last, iterator_category(first));
+// 重载版本使用函数对象 comp 代替比较操作
+template
+ForwardIter min_elememt(ForwardIter first, ForwardIter last, Compared comp) {
+ if (first == last) {
+ return first;
}
-
- /*****************************************************************************************/
- // reverse_copy
- // 行为与 reverse 类似,不同的是将结果复制到 result 所指容器中
- /*****************************************************************************************/
- template
- OutputIter reverse_copy(BidirectionalIter first, BidirectionalIter last,
- OutputIter result) {
- while (first != last) {
- --last;
- *result = *last;
+ auto result = first;
+ while (++first != last) {
+ if (comp(*first, *result)) {
+ result = first;
+ }
+ }
+ return result;
+}
+
+/*****************************************************************************************/
+// swap_ranges
+// 将[first1, last1)从 first2 开始,交换相同个数元素
+// 交换的区间长度必须相同,两个序列不能互相重叠,返回一个迭代器指向序列二最后一个被交换元素的下一位置
+/*****************************************************************************************/
+template
+ForwardIter2
+swap_ranges(ForwardIter1 first1, ForwardIter1 last1, ForwardIter2 first2) {
+ for (; first1 != last1; ++first1, ++first2) {
+ mystl::iter_swap(first1, first2);
+ }
+ return first2;
+}
+
+/*****************************************************************************************/
+// transform
+// 第一个版本以函数对象 unary_op 作用于[first,
+// last)中的每个元素并将结果保存至 result 中 第二个版本以函数对象 binary_op
+// 作用于两个序列[first1, last1)、[first2, last2)的相同位置
+/*****************************************************************************************/
+template
+OutputIter transform(InputIter first, InputIter last, OutputIter result,
+ UnaryOperation unary_op) {
+ for (; first != last; ++first, ++result) {
+ *result = unary_op(*first);
+ }
+ return result;
+}
+
+template
+OutputIter transform(InputIter1 first1, InputIter1 last1, InputIter2 first2,
+ OutputIter result, BinaryOperation binary_op) {
+ for (; first1 != last1; ++first1, ++first2, ++result) {
+ *result = binary_op(*first1, *first2);
+ }
+ return result;
+}
+
+/*****************************************************************************************/
+// remove_copy
+// 移除区间内与指定 value 相等的元素,并将结果复制到以 result
+// 标示起始位置的容器上
+/*****************************************************************************************/
+template
+OutputIter remove_copy(InputIter first, InputIter last, OutputIter result,
+ const T& value) {
+ for (; first != last; ++first) {
+ if (*first != value) {
+ *result++ = *first;
+ }
+ }
+ return result;
+}
+
+/*****************************************************************************************/
+// remove
+// 移除所有与指定 value 相等的元素
+// 并不从容器中删除这些元素,所以 remove 和 remove_if 不适用于 array
+/*****************************************************************************************/
+template
+ForwardIter remove(ForwardIter first, ForwardIter last, const T& value) {
+ first
+ = mystl::find(first, last, value); // 利用 find 找出第一个匹配的地方
+ auto next = first;
+ return first == last ? first
+ : mystl::remove_copy(++next, last, first, value);
+}
+
+/*****************************************************************************************/
+// remove_copy_if
+// 移除区间内所有令一元操作 unary_pred 为 true 的元素,并将结果复制到以
+// result 为起始位置的容器上
+/*****************************************************************************************/
+template
+OutputIter remove_copy_if(InputIter first, InputIter last, OutputIter result,
+ UnaryPredicate unary_pred) {
+ for (; first != last; ++first) {
+ if (!unary_pred(*first)) {
+ *result = *first;
++result;
}
- return result;
}
-
- /*****************************************************************************************/
- // random_shuffle
- // 将[first, last)内的元素次序随机重排
- // 重载版本使用一个产生随机数的函数对象 rand
- /*****************************************************************************************/
- template
- void random_shuffle(RandomIter first, RandomIter last) {
- if (first == last)
+ return result;
+}
+
+/*****************************************************************************************/
+// remove_if
+// 移除区间内所有令一元操作 unary_pred 为 true 的元素
+/*****************************************************************************************/
+template
+ForwardIter
+remove_if(ForwardIter first, ForwardIter last, UnaryPredicate unary_pred) {
+ first = mystl::find_if(first, last,
+ unary_pred); // 利用 find_if 找出第一个匹配的地方
+ auto next = first;
+ return first == last
+ ? first
+ : mystl::remove_copy_if(++next, last, first, unary_pred);
+}
+
+/*****************************************************************************************/
+// replace
+// 将区间内所有的 old_value 都以 new_value 替代
+/*****************************************************************************************/
+template
+void replace(ForwardIter first, ForwardIter last, const T& old_value,
+ const T& new_value) {
+ for (; first != last; ++first) {
+ if (*first == old_value) {
+ *first = new_value;
+ }
+ }
+}
+
+/*****************************************************************************************/
+// replace_copy
+// 行为与 replace 类似,不同的是将结果复制到 result
+// 所指的容器中,原序列没有改变
+/*****************************************************************************************/
+template
+OutputIter replace_copy(InputIter first, InputIter last, OutputIter result,
+ const T& old_value, const T& new_value) {
+ for (; first != last; ++first, ++result) {
+ *result = *first == old_value ? new_value : *first;
+ }
+ return result;
+}
+
+/*****************************************************************************************/
+// replace_copy_if
+// 行为与 replace_if 类似,不同的是将结果复制到 result
+// 所指的容器中,原序列没有改变
+/*****************************************************************************************/
+template
+OutputIter replace_copy_if(InputIter first, InputIter last, OutputIter result,
+ UnaryPredicate unary_pred, const T& new_value) {
+ for (; first != last; ++first, ++result) {
+ *result = unary_pred(*first) ? new_value : *first;
+ }
+ return result;
+}
+
+/*****************************************************************************************/
+// replace_if
+// 将区间内所有令一元操作 unary_pred 为 true 的元素都用 new_value 替代
+/*****************************************************************************************/
+template
+void replace_if(ForwardIter first, ForwardIter last, UnaryPredicate unary_pred,
+ const T& new_value) {
+ for (; first != last; ++first) {
+ if (unary_pred(*first)) {
+ *first = new_value;
+ }
+ }
+}
+
+/*****************************************************************************************/
+// reverse
+// 将[first, last)区间内的元素反转
+/*****************************************************************************************/
+// reverse_dispatch 的 bidirectional_iterator_tag 版本
+template
+void reverse_dispatch(BidirectionalIter first, BidirectionalIter last,
+ bidirectional_iterator_tag) {
+ while (true) {
+ if (first == last || first == --last) {
return;
- srand((unsigned)time(0));
- for (auto i = first + 1; i != last; ++i) {
- mystl::iter_swap(i, first + (rand() % (i - first + 1)));
}
- }
-
- // 重载版本使用一个产生随机数的函数对象 rand
- template
- void random_shuffle(RandomIter first, RandomIter last,
- RandomNumberGenerator &rand) {
- if (first == last)
- return;
- auto len = mystl::distance(first, last);
- for (auto i = first + 1; i != last; ++i) {
- mystl::iter_swap(i, first + (rand(i - first + 1) % len));
- }
- }
-
- /*****************************************************************************************/
- // rotate
- // 将[first, middle)内的元素和 [middle,
- // last)内的元素互换,可以交换两个长度不同的区间 返回交换后 middle 的位置
- /*****************************************************************************************/
- // rotate_dispatch 的 forward_iterator_tag 版本
- template
- ForwardIter rotate_dispatch(ForwardIter first, ForwardIter middle,
- ForwardIter last, forward_iterator_tag) {
- auto first2 = middle;
- do {
- mystl::swap(*first++, *first2++);
- if (first == middle)
- middle = first2;
- } while (first2 != last); // 后半段移到前面
-
- auto new_middle = first; // 迭代器返回的位置
- first2 = middle;
- while (first2 != last) { // 调整剩余元素
- mystl::swap(*first++, *first2++);
- if (first == middle) {
- middle = first2;
- }
- else if (first2 == last) {
- first2 = middle;
- }
+ mystl::iter_swap(first++, last);
+ }
+}
+
+// reverse_dispatch 的 random_access_iterator_tag 版本
+template
+void reverse_dispatch(RandomIter first, RandomIter last,
+ random_access_iterator_tag) {
+ while (first < last) {
+ mystl::iter_swap(first++, --last);
+ }
+}
+
+template
+void reverse(BidirectionalIter first, BidirectionalIter last) {
+ mystl::reverse_dispatch(first, last, iterator_category(first));
+}
+
+/*****************************************************************************************/
+// reverse_copy
+// 行为与 reverse 类似,不同的是将结果复制到 result 所指容器中
+/*****************************************************************************************/
+template
+OutputIter reverse_copy(BidirectionalIter first, BidirectionalIter last,
+ OutputIter result) {
+ while (first != last) {
+ --last;
+ *result = *last;
+ ++result;
+ }
+ return result;
+}
+
+/*****************************************************************************************/
+// random_shuffle
+// 将[first, last)内的元素次序随机重排
+// 重载版本使用一个产生随机数的函数对象 rand
+/*****************************************************************************************/
+template
+void random_shuffle(RandomIter first, RandomIter last) {
+ if (first == last) {
+ return;
+ }
+ srand((unsigned)time(0));
+ for (auto i = first + 1; i != last; ++i) {
+ mystl::iter_swap(i, first + (rand() % (i - first + 1)));
+ }
+}
+
+// 重载版本使用一个产生随机数的函数对象 rand
+template
+void random_shuffle(RandomIter first, RandomIter last,
+ RandomNumberGenerator& rand) {
+ if (first == last) {
+ return;
+ }
+ auto len = mystl::distance(first, last);
+ for (auto i = first + 1; i != last; ++i) {
+ mystl::iter_swap(i, first + (rand(i - first + 1) % len));
+ }
+}
+
+/*****************************************************************************************/
+// rotate
+// 将[first, middle)内的元素和 [middle,
+// last)内的元素互换,可以交换两个长度不同的区间 返回交换后 middle 的位置
+/*****************************************************************************************/
+// rotate_dispatch 的 forward_iterator_tag 版本
+template
+ForwardIter rotate_dispatch(ForwardIter first, ForwardIter middle,
+ ForwardIter last, forward_iterator_tag) {
+ auto first2 = middle;
+ do {
+ mystl::swap(*first++, *first2++);
+ if (first == middle) {
+ middle = first2;
}
- return new_middle;
- }
+ } while (first2 != last); // 后半段移到前面
- // rotate_dispatch 的 bidirectional_iterator_tag 版本
- template
- BidirectionalIter
- rotate_dispatch(BidirectionalIter first, BidirectionalIter middle,
- BidirectionalIter last, bidirectional_iterator_tag) {
- mystl::reverse_dispatch(first, middle, bidirectional_iterator_tag());
- mystl::reverse_dispatch(middle, last, bidirectional_iterator_tag());
- while (first != middle && middle != last)
- mystl::swap(*first++, *--last);
+ auto new_middle = first; // 迭代器返回的位置
+ first2 = middle;
+ while (first2 != last) { // 调整剩余元素
+ mystl::swap(*first++, *first2++);
if (first == middle) {
- mystl::reverse_dispatch(middle, last, bidirectional_iterator_tag());
- return last;
+ middle = first2;
}
- else {
- mystl::reverse_dispatch(first, middle,
- bidirectional_iterator_tag());
- return first;
+ else if (first2 == last) {
+ first2 = middle;
}
}
+ return new_middle;
+}
- // 求最大公因子
- template
- EuclideanRingElement rgcd(EuclideanRingElement m, EuclideanRingElement n) {
- while (n != 0) {
- auto t = m % n;
- m = n;
- n = t;
- }
- return m;
- }
-
- // rotate_dispatch 的 random_access_iterator_tag 版本
- template
- RandomIter rotate_dispatch(RandomIter first, RandomIter middle,
- RandomIter last, random_access_iterator_tag) {
- // 因为是 random access iterator,我们可以确定每个元素的位置
- auto n = last - first;
- auto l = middle - first;
- auto r = n - l;
- auto result = first + (last - middle);
- if (l == r) {
- mystl::swap_ranges(first, middle, middle);
- return result;
- }
- auto cycle_times = rgcd(n, l);
- for (auto i = 0; i < cycle_times; ++i) {
- auto tmp = *first;
- auto p = first;
- if (l < r) {
- for (auto j = 0; j < r / cycle_times; ++j) {
- if (p > first + r) {
- *p = *(p - r);
- p -= r;
- }
- *p = *(p + l);
- p += l;
+// rotate_dispatch 的 bidirectional_iterator_tag 版本
+template
+BidirectionalIter
+rotate_dispatch(BidirectionalIter first, BidirectionalIter middle,
+ BidirectionalIter last, bidirectional_iterator_tag) {
+ mystl::reverse_dispatch(first, middle, bidirectional_iterator_tag());
+ mystl::reverse_dispatch(middle, last, bidirectional_iterator_tag());
+ while (first != middle && middle != last) {
+ mystl::swap(*first++, *--last);
+ }
+ if (first == middle) {
+ mystl::reverse_dispatch(middle, last, bidirectional_iterator_tag());
+ return last;
+ }
+ else {
+ mystl::reverse_dispatch(first, middle, bidirectional_iterator_tag());
+ return first;
+ }
+}
+
+// 求最大公因子
+template
+EuclideanRingElement rgcd(EuclideanRingElement m, EuclideanRingElement n) {
+ while (n != 0) {
+ auto t = m % n;
+ m = n;
+ n = t;
+ }
+ return m;
+}
+
+// rotate_dispatch 的 random_access_iterator_tag 版本
+template
+RandomIter rotate_dispatch(RandomIter first, RandomIter middle, RandomIter last,
+ random_access_iterator_tag) {
+ // 因为是 random access iterator,我们可以确定每个元素的位置
+ auto n = last - first;
+ auto l = middle - first;
+ auto r = n - l;
+ auto result = first + (last - middle);
+ if (l == r) {
+ mystl::swap_ranges(first, middle, middle);
+ return result;
+ }
+ auto cycle_times = rgcd(n, l);
+ for (auto i = 0; i < cycle_times; ++i) {
+ auto tmp = *first;
+ auto p = first;
+ if (l < r) {
+ for (auto j = 0; j < r / cycle_times; ++j) {
+ if (p > first + r) {
+ *p = *(p - r);
+ p -= r;
}
+ *p = *(p + l);
+ p += l;
}
- else {
- for (auto j = 0; j < l / cycle_times - 1; ++j) {
- if (p < last - l) {
- *p = *(p + l);
- p += l;
- }
- *p = *(p - r);
- p -= r;
+ }
+ else {
+ for (auto j = 0; j < l / cycle_times - 1; ++j) {
+ if (p < last - l) {
+ *p = *(p + l);
+ p += l;
}
+ *p = *(p - r);
+ p -= r;
}
- *p = tmp;
- ++first;
}
- return result;
+ *p = tmp;
+ ++first;
}
+ return result;
+}
- template
- ForwardIter rotate(ForwardIter first, ForwardIter middle,
- ForwardIter last) {
- if (first == middle)
- return last;
- if (middle == last)
- return first;
- return mystl::rotate_dispatch(first, middle, last,
- iterator_category(first));
- }
-
- /*****************************************************************************************/
- // rotate_copy
- // 行为与 rotate 类似,不同的是将结果复制到 result 所指的容器中
- /*****************************************************************************************/
- template
- ForwardIter rotate_copy(ForwardIter first, ForwardIter middle,
- ForwardIter last, OutputIter result) {
- return mystl::copy(first, middle, mystl::copy(middle, last, result));
- }
-
- /*****************************************************************************************/
- // is_permutation
- // 判断[first1,last1)是否为[first2, last2)的排列组合
- /*****************************************************************************************/
- template
- bool is_permutation_aux(ForwardIter1 first1, ForwardIter1 last1,
- ForwardIter2 first2, ForwardIter2 last2,
- BinaryPred pred) {
- constexpr bool is_ra_it =
- mystl::is_random_access_iterator::value &&
- mystl::is_random_access_iterator::value;
- if (is_ra_it) {
- auto len1 = last1 - first1;
- auto len2 = last2 - first2;
- if (len1 != len2)
- return false;
+template
+ForwardIter rotate(ForwardIter first, ForwardIter middle, ForwardIter last) {
+ if (first == middle) {
+ return last;
+ }
+ if (middle == last) {
+ return first;
+ }
+ return mystl::rotate_dispatch(first, middle, last,
+ iterator_category(first));
+}
+
+/*****************************************************************************************/
+// rotate_copy
+// 行为与 rotate 类似,不同的是将结果复制到 result 所指的容器中
+/*****************************************************************************************/
+template
+ForwardIter rotate_copy(ForwardIter first, ForwardIter middle, ForwardIter last,
+ OutputIter result) {
+ return mystl::copy(first, middle, mystl::copy(middle, last, result));
+}
+
+/*****************************************************************************************/
+// is_permutation
+// 判断[first1,last1)是否为[first2, last2)的排列组合
+/*****************************************************************************************/
+template
+bool is_permutation_aux(ForwardIter1 first1, ForwardIter1 last1,
+ ForwardIter2 first2, ForwardIter2 last2,
+ BinaryPred pred) {
+ constexpr bool is_ra_it
+ = mystl::is_random_access_iterator::value
+ && mystl::is_random_access_iterator::value;
+ if (is_ra_it) {
+ auto len1 = last1 - first1;
+ auto len2 = last2 - first2;
+ if (len1 != len2) {
+ return false;
}
+ }
- // 先找出相同的前缀段
- for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
- if (!pred(*first1, *first2))
- break;
+ // 先找出相同的前缀段
+ for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
+ if (!pred(*first1, *first2)) {
+ break;
}
- if (is_ra_it) {
- if (first1 == last1)
- return true;
+ }
+ if (is_ra_it) {
+ if (first1 == last1) {
+ return true;
}
- else {
- auto len1 = mystl::distance(first1, last1);
- auto len2 = mystl::distance(first2, last2);
- if (len1 == 0 && len2 == 0)
- return true;
- if (len1 != len2)
- return false;
+ }
+ else {
+ auto len1 = mystl::distance(first1, last1);
+ auto len2 = mystl::distance(first2, last2);
+ if (len1 == 0 && len2 == 0) {
+ return true;
+ }
+ if (len1 != len2) {
+ return false;
}
+ }
- // 判断剩余部分
- for (auto i = first1; i != last1; ++i) {
- bool is_repeated = false;
- for (auto j = first1; j != i; ++j) {
- if (pred(*j, *i)) {
- is_repeated = true;
- break;
- }
+ // 判断剩余部分
+ for (auto i = first1; i != last1; ++i) {
+ bool is_repeated = false;
+ for (auto j = first1; j != i; ++j) {
+ if (pred(*j, *i)) {
+ is_repeated = true;
+ break;
}
+ }
- if (!is_repeated) {
- // 计算 *i 在 [first2, last2) 的数目
- auto c2 = 0;
- for (auto j = first2; j != last2; ++j) {
- if (pred(*i, *j))
- ++c2;
- }
- if (c2 == 0)
- return false;
-
- // 计算 *i 在 [first1, last1) 的数目
- auto c1 = 1;
- auto j = i;
- for (++j; j != last1; ++j) {
- if (pred(*i, *j))
- ++c1;
+ if (!is_repeated) {
+ // 计算 *i 在 [first2, last2) 的数目
+ auto c2 = 0;
+ for (auto j = first2; j != last2; ++j) {
+ if (pred(*i, *j)) {
+ ++c2;
}
- if (c1 != c2)
- return false;
}
- }
- return true;
- }
+ if (c2 == 0) {
+ return false;
+ }
- template
- bool is_permutation(ForwardIter1 first1, ForwardIter1 last1,
- ForwardIter2 first2, ForwardIter2 last2,
- BinaryPred pred) {
- return is_permutation_aux(first1, last1, first2, last2, pred);
- }
-
- template
- bool is_permutation(ForwardIter1 first1, ForwardIter1 last1,
- ForwardIter2 first2, ForwardIter2 last2) {
- typedef typename iterator_traits::value_type v1;
- typedef typename iterator_traits::value_type v2;
- static_assert(std::is_same::value,
- "the type should be same in mystl::is_permutation");
- return is_permutation_aux(first1, last1, first2, last2,
- mystl::equal_to());
- }
-
- /*****************************************************************************************/
- // next_permutation
- // 取得[first, last)所标示序列的下一个排列组合,如果没有下一个排序组合,返回
- // false,否则返回 true
- /*****************************************************************************************/
- template
- bool next_permutation(BidirectionalIter first, BidirectionalIter last) {
- auto i = last;
- if (first == last || first == --i)
- return false;
- for (;;) {
- auto ii = i;
- if (*--i < *ii) { // 找到第一对小于关系的元素
- auto j = last;
- while (!(*i < *--j)) {}
- mystl::iter_swap(i, j); // 交换 i,j 所指元素
- mystl::reverse(ii, last); // 将 ii 之后的所有元素反转
- return true;
+ // 计算 *i 在 [first1, last1) 的数目
+ auto c1 = 1;
+ auto j = i;
+ for (++j; j != last1; ++j) {
+ if (pred(*i, *j)) {
+ ++c1;
+ }
}
- if (i == first) {
- mystl::reverse(first, last);
+ if (c1 != c2) {
return false;
}
}
}
-
- // 重载版本使用函数对象 comp 代替比较操作
- template
- bool next_permutation(BidirectionalIter first, BidirectionalIter last,
- Compared comp) {
- auto i = last;
- if (first == last || first == --i)
- return false;
- for (;;) {
- auto ii = i;
- if (comp(*--i, *ii)) {
- auto j = last;
- while (!comp(*i, *--j)) {}
- mystl::iter_swap(i, j); // 交换 i,j 所指元素
- mystl::reverse(ii, last); // 将 ii 之后的所有元素反转
- return true;
- }
- if (i == first) {
- mystl::reverse(first, last);
- return false;
+ return true;
+}
+
+template
+bool is_permutation(ForwardIter1 first1, ForwardIter1 last1,
+ ForwardIter2 first2, ForwardIter2 last2, BinaryPred pred) {
+ return is_permutation_aux(first1, last1, first2, last2, pred);
+}
+
+template
+bool is_permutation(ForwardIter1 first1, ForwardIter1 last1,
+ ForwardIter2 first2, ForwardIter2 last2) {
+ typedef typename iterator_traits::value_type v1;
+ typedef typename iterator_traits::value_type v2;
+ static_assert(std::is_same::value,
+ "the type should be same in mystl::is_permutation");
+ return is_permutation_aux(first1, last1, first2, last2,
+ mystl::equal_to());
+}
+
+/*****************************************************************************************/
+// next_permutation
+// 取得[first, last)所标示序列的下一个排列组合,如果没有下一个排序组合,返回
+// false,否则返回 true
+/*****************************************************************************************/
+template
+bool next_permutation(BidirectionalIter first, BidirectionalIter last) {
+ auto i = last;
+ if (first == last || first == --i) {
+ return false;
+ }
+ for (;;) {
+ auto ii = i;
+ if (*--i < *ii) { // 找到第一对小于关系的元素
+ auto j = last;
+ while (!(*i < *--j)) {
}
+ mystl::iter_swap(i, j); // 交换 i,j 所指元素
+ mystl::reverse(ii, last); // 将 ii 之后的所有元素反转
+ return true;
+ }
+ if (i == first) {
+ mystl::reverse(first, last);
+ return false;
}
}
+}
- /*****************************************************************************************/
- // prev_permutation
- // 取得[first, last)所标示序列的上一个排列组合,如果没有上一个排序组合,返回
- // false,否则返回 true
- /*****************************************************************************************/
- template