5. KVM x86¶
5.1. 前言¶
KVM 致力于成为一个热情友好的社区;欢迎并鼓励新手的贡献。请不要因为本文档的长度以及其中包含的许多规则/指南而感到气馁或害怕。每个人都会犯错,每个人都曾是新手。只要您真诚地努力遵循 KVM x86 的指南,乐于接受反馈,并从您所犯的任何错误中吸取教训,您就会受到热烈的欢迎,而不是受到火把和干草叉的攻击。
5.2. TL;DR¶
测试是强制性的。与既定的风格和模式保持一致。
5.3. 代码树¶
KVM x86 当前正处于从属于主 KVM 树过渡到“仅仅是另一个 KVM 架构”的时期。因此,KVM x86 分散在主 KVM 树 git.kernel.org/pub/scm/virt/kvm/kvm.git
和 KVM x86 特定的代码树 github.com/kvm-x86/linux.git
中。
一般来说,当前周期的修复直接应用于主 KVM 树,而下一个周期的所有开发都通过 KVM x86 代码树进行。在极不可能发生的情况下,当前周期的修复通过 KVM x86 代码树进行,它将先应用于 fixes
分支,然后再进入主 KVM 代码树。
请注意,此过渡期预计将持续相当长的时间,即在可预见的未来将保持现状。
5.3.1. 分支¶
KVM x86 代码树被组织成多个主题分支。使用更细粒度的主题分支的目的是为了更容易地跟踪开发领域,并限制人为错误和/或有缺陷的提交的附带损害,例如,删除主题分支的 HEAD 提交对其他正在进行的提交的 SHA1 哈希没有影响,并且由于错误而必须拒绝拉取请求只会延迟该主题分支。
除了 next
和 fixes
之外,所有主题分支都通过 Cthulhu 合并按需合并到 next
中,即当主题分支更新时。因此,强制推送到 next
是很常见的。
5.3.2. 生命周期¶
针对当前版本(即主线)的修复通常直接应用于主 KVM 代码树,即不通过 KVM x86 代码树。
针对下一个版本的更改通过 KVM x86 代码树进行。拉取请求(从 KVM x86 到主 KVM)是为每个 KVM x86 主题分支发送的,通常是在 Linus 打开合并窗口前一周,例如,对于“正常”版本,在 rc7 之后的一周。如果一切顺利,主题分支将被合并到 Linus 合并窗口期间发送的主 KVM 拉取请求中。
KVM x86 代码树没有自己的官方合并窗口,但新功能在 rc5 附近有一个软关闭,修复在 rc6 附近有一个软关闭(针对下一个版本;有关针对当前版本的修复,请参见上文)。
5.3.3. 时间线¶
提交通常按照先进先出的顺序进行审查和应用,对于一系列的大小、属于“缓存热点”的补丁等有一些回旋余地。修复,特别是针对当前版本和/或稳定版本树的修复,会跳过队列。将通过非 KVM 代码树(最常见的是通过 tip 代码树)并且/或具有其他 ack/review 的补丁也会在某种程度上跳过队列。
请注意,绝大多数审查都是在 rc1 到 rc6 之间完成的。rc6 和下一个 rc1 之间的这段时间用于处理其他任务,即在此期间的无线电静默并不罕见。
欢迎您 ping 来获取状态更新,但请记住当前发布周期的时间,并抱有合理的期望。如果您 ping 是为了接受,即不仅仅是为了反馈或更新,请在合理范围内尽一切努力确保您的补丁已准备好合并!对破坏构建或测试失败的系列进行 ping 会导致维护人员不高兴!
5.4. 开发¶
5.4.1. 基础代码树/分支¶
针对当前版本(即主线)的修复应基于 git://git.kernel.org/pub/scm/virt/kvm/kvm.git master
。请注意,修复不会自动保证包含在当前版本中。没有统一的规则,但通常只有针对紧急、关键和/或在当前版本中引入的错误的修复才应针对当前版本。
其他所有内容都应基于 kvm-x86/next
,即无需选择特定的主题分支作为基础。如果各个主题分支之间存在冲突和/或依赖关系,则维护人员有责任解决它们。
使用 kvm-x86/next
作为基础的唯一例外是,如果补丁/系列是多架构系列,即对公共 KVM 代码进行了非琐碎的修改和/或对其他架构的代码进行了不止表面上的更改。多架构补丁/系列应基于 KVM 历史中的一个共同的稳定点,例如 kvm-x86 next
基于的候选版本。如果您不确定补丁/系列是否真的是多架构的,请谨慎行事并将其视为多架构,即使用公共基础。
5.4.2. 编码风格¶
在风格、命名、模式等方面,一致性是 KVM x86 的首要任务。如果其他一切都失败了,请匹配已有的内容。
除了下面列出的少数注意事项外,请遵循 tip 树维护人员首选的 编码风格注释,因为补丁/系列经常同时触及 KVM 和非 KVM x86 文件,即引起 KVM 和 tip 树维护人员的注意。
对于变量声明,不严格要求使用反向冷杉树,也称为反向圣诞树或反向 XMAS 树,尽管仍然是首选。
除了少数特殊的雪花之外,不要对函数使用 kernel-doc 注释。绝大多数“公共” KVM 函数并不是真正的公共函数,因为它们仅供 KVM 内部使用(有计划将 KVM 的头文件和导出私有化以强制执行此操作)。
5.4.4. SDM 和 APM 参考¶
KVM 的大部分代码库都直接与 Intel 的软件开发手册 (SDM) 和 AMD 的架构程序员手册 (APM) 中定义的架构行为相关联。使用“Intel 的 SDM”和“AMD 的 APM”,甚至只是“SDM”或“APM”,而没有其他上下文,都是可以接受的。
不要按编号引用特定的节、表格、图等,尤其是在注释中。相反,如有必要(见下文),请复制粘贴相关的代码片段,并按名称引用节/表格/图。SDM 和 APM 的布局不断变化,因此数字/标签并不稳定。
一般来说,不要在注释中明确引用或复制粘贴 SDM 或 APM 的内容。除少数例外情况外,KVM 必须遵守架构行为,因此隐含 KVM 行为正在模拟 SDM 和/或 APM 行为。请注意,在更改日志中引用 SDM/APM 以证明更改的合理性并提供上下文是完全可以的,并且是鼓励的。
5.4.5. 短日志¶
首选前缀格式是 KVM: <topic>:
,其中 <topic>
是以下之一
- x86
- x86/mmu
- x86/pmu
- x86/xen
- selftests
- SVM
- nSVM
- VMX
- nVMX
不要使用 x86/kvm! x86/kvm
专门用于 Linux 作为 KVM 客户机更改,即用于 arch/x86/kernel/kvm.c。不要使用文件名或完整文件路径作为主题/短日志前缀。
请注意,这些与主题分支不一致(主题分支更关心代码冲突)。
所有名称都区分大小写! KVM: x86:
是好的,kvm: vmx:
不是。
将压缩补丁描述的第一个单词大写,但省略结尾的标点符号。例如
KVM: x86: Fix a null pointer dereference in function_xyz()
不是
kvm: x86: fix a null pointer dereference in function_xyz.
如果一个补丁涉及到多个主题,请向上遍历概念树,找到第一个共同的父节点(通常就是 x86
)。如有疑问,git log path/to/file
应该能提供合理的提示。
偶尔会出现新的主题,但如果您想提出引入新主题,请先在邮件列表中发起讨论,不要擅自行动。
有关更多信息,请参阅规范的补丁格式,但有一点修正:不要将 70-75 个字符的限制视为绝对的硬性限制。相反,将 75 个字符作为严格但不硬性的限制,将 80 个字符作为硬性限制。也就是说,如果有充分的理由,可以让 shortlog 超过标准限制几个字符。
5.4.6. 变更日志¶
最重要的是,使用祈使语气编写变更日志,并避免使用代词。
有关更多信息,请参阅描述您的更改,但有一点修正:先简要介绍实际的更改,然后再介绍背景和上下文。注意!此顺序与 tip tree 的首选方法直接冲突!在发送主要针对 _NOT_ KVM 代码的 arch/x86 代码的补丁时,请遵循 tip tree 的首选风格。
对于 KVM x86 来说,在深入细节之前说明补丁的作用是首选的做法,原因有几个。首先,也是最重要的,实际更改的代码是arguably最重要的信息,因此应该很容易找到该信息。变更日志如果将“实际更改的内容”埋藏在 3 个或更多段背景介绍之后的一句话中,则很难找到该信息。
对于初始审查,有人可能会认为“哪里坏了”更重要,但对于浏览日志和 git 考古来说,细节越来越不重要。例如,在执行一系列“git blame”时,沿途每次更改的细节都是无用的,细节仅对罪魁祸首重要。提供“更改的内容”可以很容易地快速确定提交是否可能值得关注。
首先说明“更改的内容”的另一个好处是,几乎总是可以用一句话来说明“更改的内容”。相反,除了最简单的错误之外,所有错误都需要多句话或多段才能完整描述问题。如果“更改的内容”和“错误是什么”都非常短,那么顺序并不重要。但如果一个更短(几乎总是“更改的内容”),那么首先介绍更短的那个是有利的,因为对于有严格排序偏好的读者/审查者来说,这不那么麻烦。例如,跳过一句话来获取上下文比跳过三段来获取“更改的内容”要轻松得多。
5.4.7. 修复¶
如果更改修复了 KVM/内核错误,即使该更改不需要向后移植到稳定内核,即使该更改修复了旧版本中的错误,也要添加 Fixes: 标签。
相反,如果修复确实需要向后移植,请使用“Cc: stable@vger.kernel”显式标记补丁(尽管电子邮件本身不需要 Cc: stable);KVM x86 默认选择不向后移植 Fixes:。一些自动选择的补丁确实会向后移植,但需要维护人员的明确批准(搜索 MANUALSEL)。
5.4.8. 函数引用¶
当在注释、变更日志或 shortlog 中(或任何地方)提及函数时,请使用 function_name()
格式。括号提供上下文并消除引用的歧义。
5.5. 测试¶
至少,一个系列中的所有补丁都必须在 KVM_INTEL=m KVM_AMD=m 和 KVM_WERROR=y 的情况下干净地构建。构建所有可能的 Kconfig 组合是不可行的,但越多越好。KVM_SMM、KVM_XEN、PROVE_LOCKING 和 X86_64 是特别值得关注的开关。
运行 KVM 自测和 KVM 单元测试也是强制性的(而且不言而喻,测试需要通过)。唯一的例外是那些影响运行时行为的概率可以忽略不计的更改,例如,仅修改注释的补丁。如果可能且相关,强烈建议在 Intel 和 AMD 上进行测试。鼓励启动实际的虚拟机,但不是强制性的。
对于涉及 KVM 影子分页代码的更改,强制要求在禁用 TDP (EPT/NPT) 的情况下运行。对于影响常见 KVM MMU 代码的更改,强烈建议在禁用 TDP 的情况下运行。对于所有其他更改,如果修改的代码依赖于模块参数和/或与之交互,则强制要求使用相关设置进行测试。
请注意,KVM 自测和 KVM 单元测试确实存在已知故障。如果您怀疑故障不是由您的更改引起的,请验证相同的故障是否在有和没有您的更改的情况下发生。
涉及 reStructured Text 文档(即 .rst 文件)的更改必须干净地构建 htmldocs,即没有新的警告或错误。
如果您无法完全测试更改,例如由于缺少硬件,请在 cover letter 中清楚说明您能够进行的测试级别。
5.5.1. 新功能¶
除了一种情况外,新功能必须附带测试覆盖率。并非严格要求 KVM 特定的测试,例如,如果通过运行足够启用的客户虚拟机或在虚拟机中运行相关的内核自测来提供覆盖率,但在所有情况下,首选专用的 KVM 测试。特别是负面测试用例对于启用新硬件功能是强制性的,因为错误和异常流程很少仅仅通过运行虚拟机来执行。
此规则的唯一例外是,如果 KVM 只是通过 KVM_GET_SUPPORTED_CPUID 来通告对某功能的支持,即对于 KVM 无法阻止客户机使用且没有真正启用的指令/功能。
请注意,“新功能”不仅仅意味着“新的硬件功能”!不能使用现有的 KVM 自测和/或 KVM 单元测试进行良好验证的新功能必须附带测试。
发布没有测试的新功能开发以获取早期反馈非常受欢迎,但此类提交应标记为 RFC,并且 cover letter 应清楚说明请求/期望的反馈类型。不要滥用 RFC 流程;RFC 通常不会收到深入的审查。
5.5.2. 错误修复¶
除了“显而易见”的通过检查发现的错误之外,修复必须附带要修复的错误的重现方法。在许多情况下,重现方法是隐式的,例如,对于构建错误和测试失败,但读者应该清楚地知道哪里坏了以及如何验证修复。对于通过非公共工作负载/测试发现的错误,会给予一定的回旋余地,但强烈建议为此类错误提供回归测试。
一般来说,对于任何不容易发现的错误,都首选回归测试。例如,即使该错误最初是通过 syzkaller 等模糊测试器发现的,如果该错误需要命中百万分之一的竞争条件类型,也可能需要有针对性的回归测试。
请注意,KVM 错误很少既紧急又难以重现。在发布没有重现方法的修复程序之前,请扪心自问,这个错误是否真的到了世界末日的地步。
5.6. 发布¶
5.6.1. 链接¶
不要通过 In-Reply-To:
标头显式引用错误报告、补丁/系列的先前版本等。对于大型系列和/或当版本计数很高时,使用 In-Reply-To:
会变成一场混乱,并且对于任何没有原始消息的人来说,In-Reply-To:
都是无用的,例如,如果有人没有抄送错误报告,或者如果收件人列表在版本之间发生变化。
要链接到错误报告、先前版本或任何感兴趣的内容,请使用 lore 链接。对于引用先前版本,一般来说,不要在变更日志中包含 Link:,因为不需要在 git 中记录历史记录,即将链接放在 cover letter 中或 git 忽略的部分中。请为导致补丁的错误报告和/或讨论提供正式的 Link:。更改的原因的上下文对于未来的读者非常有价值。
5.6.2. Git Base¶
如果您使用的是 git 2.9.0 或更高版本(Google 用户,你们都是!),请使用带有 --base
标志的 git format-patch
以自动在生成的补丁中包含基本树信息。
请注意,当且仅当分支的上游设置为基本主题分支时,--base=auto
才能按预期工作,例如,如果您的上游设置为您的个人存储库以进行备份,它将执行错误的操作。另一种“自动”解决方案是基于其 KVM x86 主题派生您的开发分支的名称,并将其馈送到 --base
中。例如 x86/pmu/my_branch_name
,然后编写一个小型包装器,从当前分支名称中提取 pmu
以生成 --base=x/pmu
,其中 x
是您的存储库用于跟踪 KVM x86 远程的任何名称。
5.6.3. 共同发布测试¶
与 KVM 更改关联的 KVM 自测(例如错误修复的回归测试)应与 KVM 更改一起作为单个系列发布。标准内核规则适用于二分法,即导致测试失败的 KVM 更改应在自测更新之后排序,反之亦然,由于 KVM 错误而失败的新测试应在 KVM 修复之后排序。
KVM 单元测试应始终单独发布。工具(例如 b4 am)不知道 KVM 单元测试是一个单独的存储库,并且当系列中的补丁应用于不同的树时会感到困惑。要将 KVM 单元测试补丁链接回 KVM 补丁,请首先发布 KVM 更改,然后在 KVM 单元测试补丁中提供指向 KVM 补丁/系列的 lore Link:。
5.7. 通知¶
当补丁/系列被正式接受时,将发送一封回复原始帖子(多补丁系列的 cover letter)的通知电子邮件。通知将包括树和主题分支,以及已应用的补丁的提交的 SHA1 值。
如果应用了补丁的子集,这将在通知中明确说明。除非另有说明,否则这意味着该系列中任何未被接受的补丁都需要更多工作,并且应在新版本中提交。
如果由于某种原因,补丁在正式被接受后被删除,则会发送一封回复通知电子邮件,解释补丁被删除的原因以及后续步骤。
5.7.1. SHA1 稳定性¶
在进入 Linus 的代码树之前,SHA1 值不能保证 100% 稳定!一旦发送了通知邮件,SHA1 值通常是稳定的,但有时也会发生变化。在大多数情况下,如果已应用补丁的 SHA1 值发生更改,将会提供通知邮件的更新。然而,在某些情况下,例如如果所有 KVM x86 分支都需要重新基于某个版本,将不会给出单独的通知。
5.8. 漏洞¶
KVM 特别关注那些可能被客户机利用来攻击宿主机(内核或用户空间),或者可能被嵌套虚拟机利用来攻击其宿主机(L2 攻击 L1)的错误。如果您怀疑某个错误可能导致逃逸、数据泄露等问题,请遵循 安全漏洞的协议。
5.4.3. 注释¶
使用祈使语气编写注释并避免使用代词。使用注释提供代码的高级概述,和/或解释代码执行操作的原因。不要重复代码的字面意思;让代码自己说明。如果代码本身难以理解,注释将无济于事。