英语

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 树进行路由,它将在到达主 KVM 树之前应用于 fixes 分支。

请注意,预计此过渡期将持续相当长的时间,即在可预见的未来将是现状。

5.3.1. 分支

KVM x86 树被组织成多个主题分支。使用更细粒度的主题分支的目的是更容易跟踪开发领域,并限制人为错误和/或错误提交的附带损害,例如,删除主题分支的 HEAD 提交不会对其他正在进行的提交的 SHA1 哈希产生影响,并且由于错误而拒绝拉取请求只会延迟该主题分支。

nextfixes 之外的所有主题分支都通过 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 树)进行的补丁和/或具有其他 acks/reviews 的补丁也在一定程度上跳过队列。

请注意,绝大多数审查是在 rc1 和 rc6 之间完成的,上下浮动。 rc6 和下一个 rc1 之间的时间段用于赶上其他任务,即在此期间保持沉默并不罕见。

欢迎使用 Pings 获取状态更新,但请记住当前版本的发布周期,并抱有现实的期望。如果您正在 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 树)不是严格要求的,尽管仍然是首选。

除了少数特殊的 snowflakes 外,不要对函数使用 kernel-doc 注释。绝大多数“公共”KVM 函数并不是真正的公共函数,因为它们仅供 KVM 内部使用(有计划使 KVM 的头文件和导出私有化以强制执行此操作)。

5.4.3. 注释

使用祈使语气编写注释并避免使用代词。使用注释来提供代码的高级概述,和/或解释代码执行的原因。不要重复代码字面意义上的作用;让代码自己说话。如果代码本身难以理解,注释将无济于事。

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. Shortlog

首选的前缀格式是 KVM: <topic>:,其中 <topic> 是以下之一

- x86
- x86/mmu
- x86/pmu
- x86/xen
- selftests
- SVM
- nSVM
- VMX
- nVMX

不要使用 x86/kvm! x86/kvm 专门用于 Linux-as-a-KVM-guest 更改,即用于 arch/x86/kernel/kvm.c。不要使用文件名或完整文件路径作为主题/shortlog 前缀。

请注意,这些与主题分支不一致(主题分支更关心代码冲突)。

所有名称都区分大小写! 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. Changelog

最重要的是,使用祈使语气编写变更日志并避免使用代词。

有关更多信息,请参见 描述您的更改,但有一项修改:首先简要介绍一下实际更改,然后跟进背景信息。注意!此顺序与 tip 树的首选方法直接冲突!在发送主要针对 _NOT_ KVM 代码的 arch/x86 代码的补丁时,请遵循 tip 树的首选样式。

KVM x86 首选在深入研究细节之前说明补丁的作用,原因有几个。首先,实际更改的代码可以说是最重要的信息,因此应该很容易找到该信息。在 3 个或更多段落的背景信息之后,在单行代码中埋没“实际更改的内容”的变更日志使得很难找到该信息。

对于初始审查,有人可能会争辩说“什么坏了”更重要,但是对于浏览日志和 git 考古学,血淋淋的细节越来越不重要。例如,在进行一系列“git blame”时,沿途每次更改的细节都毫无用处,细节仅对罪魁祸首很重要。提供“更改了什么”使快速确定提交是否可能感兴趣变得容易。

首先说明“更改了什么”的另一个好处是,几乎总是有可能用一个句子说明“更改了什么”。相反,除了最简单的错误外,所有错误都需要多个句子或段落才能完全描述问题。如果“更改了什么”和“错误是什么”都非常短,那么顺序无关紧要。但是,如果一个较短(几乎总是“更改了什么”),那么首先介绍较短的一个是有利的,因为对于具有严格排序偏好的读者/审阅者来说,这不太方便。例如,跳过一个句子来获取上下文比跳过三个段落来获取“更改了什么”的痛苦要小。

5.4.7. Fixes

如果更改修复了 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 上都进行测试。鼓励启动实际 VM,但不是强制性的。

对于触及 KVM 的影子分页代码的更改,必须禁用 TDP(EPT/NPT)运行。对于影响常见 KVM MMU 代码的更改,强烈建议禁用 TDP 运行。对于所有其他更改,如果被修改的代码依赖于和/或与模块参数交互,则必须使用相关设置进行测试。

请注意,KVM 自检和 KVM 单元测试确实存在已知故障。如果您怀疑故障不是由于您的更改造成的,请验证在有和没有您的更改的情况下是否发生完全相同的故障。

触及 reStructured Text 文档(即 .rst 文件)的更改必须清理构建 htmldocs,即没有新的警告或错误。

如果您无法完全测试更改(例如,由于缺少硬件),请清楚地说明您能够进行的测试级别,例如,在求职信中。

5.5.1. 新功能

除了一个例外,新功能必须带有测试覆盖率。并非严格要求 KVM 特定测试,例如,如果通过运行足够启用的 guest VM 或在 VM 中运行相关的内核自检来提供覆盖率,但是在所有情况下都首选专用 KVM 测试。特别是对于启用新硬件功能,必须进行否定测试用例,因为很少通过简单地运行 VM 来执行错误和异常流。

此规则的唯一例外是 KVM 只是通过 KVM_GET_SUPPORTED_CPUID 宣传对某个功能的支持,即对于 KVM 无法阻止 guest 使用的指令/功能,并且没有真正的启用。

请注意,“新功能”不仅仅是指“新硬件功能”!无法使用现有 KVM 自检和/或 KVM 单元测试很好地验证的新功能必须带有测试。

欢迎发布没有测试的新功能开发以获取早期反馈,但是此类提交应标记为 RFC,并且求职信应清楚说明请求/期望的反馈类型。不要滥用 RFC 流程; RFC 通常不会收到深入审查。

5.5.2. Bug 修复

除了“明显”的检查发现的错误外,修复必须附带要修复的错误的重现程序。在许多情况下,重现程序是隐式的,例如对于构建错误和测试失败,但是读者仍然应该清楚什么是坏的以及如何验证修复。对于通过非公共工作负载/测试发现的错误,可以给予一定的回旋余地,但是强烈建议为此类错误提供回归测试。

一般来说,对于任何不容易发生的错误,都首选回归测试。例如,即使该错误最初是由诸如 syzkaller 之类的模糊测试器发现的,但如果该错误需要达到百万分之一的类型竞争条件,则可能有必要进行有针对性的回归测试。

请注意,KVM 错误很少紧急难以重现。在没有重现程序的情况下发布修复之前,请问问自己一个错误是否真的真正是世界末日。

5.6. 发布

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 自检(例如,针对 bug 修复的回归测试)应与 KVM 更改一起作为单个系列发布。标准的内核对分规则适用,即导致测试失败的 KVM 更改应在自检更新之后排序,反之亦然,由于 KVM bug 而失败的新测试应在 KVM 修复之后排序。

KVM 单元测试应始终单独发布。工具(例如 b4 am)不知道 KVM 单元测试是一个单独的存储库,并且当系列中的补丁应用于不同的树时会感到困惑。要将 KVM 单元测试补丁链接回 KVM 补丁,请首先发布 KVM 更改,然后在 KVM 单元测试补丁中提供 KVM 补丁/系列的 lore Link:。

5.7. 通知

当补丁/系列被正式接受时,将发送一封通知电子邮件以回复原始帖子(多补丁系列的求职信)。通知将包括树和主题分支,以及已应用补丁的提交的 SHA1。

如果应用了补丁的子集,将在通知中明确说明这一点。除非另有说明,否则暗示系列中未接受的任何补丁都需要更多工作,应在新版本中提交。

如果由于某种原因在正式接受后删除了补丁,将发送一封回复通知电子邮件,解释删除补丁的原因以及后续步骤。

5.7.1. SHA1 稳定性

在 SHA1 进入 Linus 的树之前,不能 100% 保证 SHA1 的稳定!在发送通知后,SHA1 通常是稳定的,但是会发生一些事情。在大多数情况下,如果应用的补丁的 SHA1 发生更改,将提供通知电子邮件的更新。但是,在某些情况下,例如,如果需要重新构建所有 KVM x86 分支,则不会给出单独的通知。

5.8. 漏洞

guest 可以利用来攻击主机(内核或用户空间)的错误,或者嵌套 VM 可以利用来攻击主机(L2 攻击 L1)的错误,是 KVM 特别感兴趣的。如果您怀疑某个错误可能导致转义、数据泄漏等,请遵循 安全错误 的协议。