CPU特性是一个CPU可以选择是否支持的特性。在QEMU中,CPU特性相关的CPU属性为bool型,即使能时表明该特性被实现,禁用时表明没有实现。ARM CPU特性的例子是PMU。CPU类型如cortex-A15和cortex-A57,它们分别实现了ARMv7-A和ARMv8-A的ARM架构,两者选择性的实现PMU,比如,如果用户使用cortex-A15但不使用PMU,命令行-cpu参数应该包含pmu=off,”-cpu cortex-a15,pmu=off”。
因为并不是所有CPU类型都支持所有可选的CPU特性,是否一个CPU属性存在依赖于CPU类型。比如,实现了ARMv8架构的CPU可选择性的支持AArch32 CPU特性,这可以禁用aarch64 CPU属性来使能。CPU类型如cortex-A15,没有实现ARMv8-A,将不会有aarch64 CPU属性。
QEMU对一些CPU特性的支持是有限的,仅部分支持该特性或在某些环境下支持该特性。比如,aarch64 CPU特性,当不使能时,将使能aarch32 CPU特性,当使用KVM加速器并当运行在host CPU类型时,aarch64 CPU类型被使能。当前aarch64仅与KVM工作,它也与TCG一起工作。与KVM相关的CPU特性存在前缀”kvm-”并被描述为”KVM VCPU特性”。
1 CPU特性probe
可以通过QMP命令”query-cpu-model-expansion”决定哪个CPU特性有效和给定CPU类型是否功能正常。下面为使用”script/qmp/qmp-shell”发送QMP命令的一些例子。
(1)对于max CPU类型决定是否哪个CPU类型有效(注意,开始QEMU使用qemu-system-aarch64,因此max在这个例子中实现了ARMv8-A):
(QEMU) query-cpu-model-expansion type=full model={"name":"max"}
{ "return": {
"model": { "name": "max", "props": {
"sve1664": true, "pmu": true, "sve1792": true, "sve1920": true,
"sve128": true, "aarch64": true, "sve1024": true, "sve": true,
"sve640": true, "sve768": true, "sve1408": true, "sve256": true,
"sve1152": true, "sve512": true, "sve384": true, "sve1536": true,
"sve896": true, "sve1280": true, "sve2048": true
}}}}
我们可以看到max CPU类型存在pmu/aarch64/sve<N> CPU特性。我们也看到所有CPU特性都使能,因为它们全都为true。(sve<N> CPU特性都可选SVE向量长度。当所有的SVE向量长度都支持TCG,当使用KVM时更可能只支持一部分长度)。
(2)让我们禁用PMU特性
(QEMU) query-cpu-model-expansion type=full model={"name":"max","props":{"pmu":false}}
{ "return": {
"model": { "name": "max", "props": {
"sve1664": true, "pmu": false, "sve1792": true, "sve1920": true,
"sve128": true, "aarch64": true, "sve1024": true, "sve": true,
"sve640": true, "sve768": true, "sve1408": true, "sve256": true,
"sve1152": true, "sve512": true, "sve384": true, "sve1536": true,
"sve896": true, "sve1280": true, "sve2048": true
}}}}
我们可以看到它没有工作,因为pmu被设置为false。
(3)让我们禁用aarch64,它将使能aarch32 CPU特性
(QEMU) query-cpu-model-expansion type=full model={"name":"max","props":{"aarch64":false}}
{"error": {
"class": "GenericError", "desc":
"'aarch64' feature cannot be disabled unless KVM is enabled and 32-bit EL1 is supported"
}}
它看上去该特性仅限制在我们没有的配置。
(4)让我们禁用sve并会对可选的SVE向量长度发生什么。
(QEMU) query-cpu-model-expansion type=full model={"name":"max","props":{"sve":false}}
{ "return": {
"model": { "name": "max", "props": {
"sve1664": false, "pmu": true, "sve1792": false, "sve1920": false,
"sve128": false, "aarch64": true, "sve1024": false, "sve": false,
"sve640": false, "sve768": false, "sve1408": false, "sve256": false,
"sve1152": false, "sve512": false, "sve384": false, "sve1536": false,
"sve896": false, "sve1280": false, "sve2048": false
}}}}
- (5)让我们尝试probe Cortex-A15 CPU类型的CPU特性。
- CPU特性依赖的注意事项
存在有的特性依赖与其他特性的可能。比如有可能在某一次修改一个特性没有发生错误,但当尝试修改其他所有特性时发生错误,这依赖于它们处理的顺序。也有可能丢该所有特性都没有产生错误,但相同的特性不能单独的被修改。因为这些原因调用者应该尝试一次性做所有的修改保证修改有效。
1.3 CPU模型和KVM的注意事项
CPU模型通常不会与KVM工作。也有一些情况会工作,比如使用cortex-A57 CPU模型与KVM在host上,但大多数情况如果KVM使能,host CPU类型必须被使用。这意味着guest提供所有相同的CPU特性与host CPU类型一样。因为这个原因,host CPU类型应该使能host默认一样的CPU特性。也有些奇怪当使用Host CPU类型时禁用CPU特性,但缺少CPU模型时,如果我想启guest而不想有所有host CPU特性,最好我们也能做。
使能KVM也影响QMP命令”query-cpu-model-expansion”。影响也不仅限于相关特性,也影响到哪个CPU类型被扩展。当KVM使能时,仅max/host和当前CPU类型可以被扩展。这个限制是必须因为并不是所有CPU类型可以与KVM工作,但也可能导致遇到一些非预期的错误。比如cortex-A57 CPU类型仅当KVM使能时才有效。
因此用户可能使用host CPU类型,但尝试查询cortex-A57,但该查询可能由于我们的限制而失败。这也不算问题,因为管理层和用户喜欢使用host CPU类型。另外,如果KVM使能QEMU例子运行在Host上,使用cortex-A57 CPU类型,然后查询cortex-A57将能工作。
2 使用CPU特性
在决定了哪些CPU特性有效以及支持之后,然后可以选择性的在命令行中使能或禁用CPU类型:
Qemu-system-aarch64 -M virt -cpu max,pmu=off, sve=on, sve128=on,sve256=on
上面例子禁用PMU并使能了max CPU类型前面两个SVE向量长度。注意sve=on并不是必须的,因为当我们看到max CPU类型的probe时,sve已经默认使能了。另外,基于默认的probe,我们似乎需要禁用很多SVE向量长度,而不是仅禁用我们想要的两个。这个不是这种情况,因为禁用很多SVE向量长度将很冗长,sve<N> CPU属性有特殊的语义。
3 KVM VCPU特性
VCPU特性为与KVM相关的CPU特性,比如半虚拟化特性或使能CPU虚拟化扩展的特性。该特性的CPU属性仅当KVM使能时有效并以前缀”kvm-”命令。KVM VCPU特性可能被probe,使能并禁用与其他CPU特性一样。下面为KVM VCPU特性和它们的描述。
Kvm-no-adjvtime: 默认kvm-no-adjvtime被禁用。这意味着默认虚拟时钟调整被使能。
Kvm-steal-time: 从v5.2开始,kvm-steal-time默认被使能当KVM使能时,特性被支持,guest为64位。
当kvm-steal-time使能时,一个64位guest可以解释由于host没有调度相关的VCPU线程CPU不能运行的时间。数据可能影响guest调度器的行为并导出到guest用户空间。
4 TCG VCPU特性
TCG VCPU特性位TCG相关的CPU特性。下面为TCG VCPU支持的特性和描述:
Pauth: 使能或禁用”FEAT_Pauth”,指针权限。默认,该特性被-cpu max使能。
Pauth-impdef: 当”FEAT_Pauth”使能时,或*impdef*算法被使能或*architected*QARMA算法被使能。默认impdef算法被禁用,QARMA被使能。
QARMA算法有一个好的压缩算法,但模拟起来比较慢。QEMU使用的impdef算法非压缩图像的但明显更快。
5 SVE CPU属性
这里有两种SVE CPU属性:sve和sve<N>。第一个用于使能或禁用整个SVE特性,就如同pmu CPU属性一样完全的禁用或使能PMU。第二个用于使能或禁用某个相关的vector长度,N为位长度。”sve<N>” CPU属性有一些依赖和限制。另外,因为我们想默认将所有支持的vector长度被使能,避免使用冗长的命令,我们提供解析语义。
5.1 SVE CPU属性依赖和限制
(1)当sve被使能时至少一个向量长度必须被使能;
(2)如果N向量长度被使能,当KVM被使能,所有更小的host支持的向量长度必须被使能。如果KVM没有使能,仅所有更小的2^N向量长度必须被使能。比如如果hostz支持所有的长度,使能KVM,达到512位(128,256,384,512),如果sve512使能,其他的向量长度也必须被使能。没有KVM,384位向量长度不会被要求。
(3)如果KVM被使能仅host CPU支持的向量长度被使能。如果host不支持SVE,不会有sve*属性被使能。
5.2 SVE CPU属性解析语义
(1)若SVE被禁用sve=off,哪个SVE向量长度被使能或禁用都与guest无关,因为整个SVE特性被禁用,这会禁用guest上所有的向量长度。但是QEMU仍跟踪任何sve<N> 用户提供的CPU属性。如果后面sve=on,guest将获得使能的长度。若没有sve=on,然后某个精确的向量长度被使能,产生一个错误。
(2)若SVE被使能sve=on,但没有提供其他sve<N> CPU属性,然后所有支持的向量长度都被使能,当KVM没有使用时,支持的向量长度意味这非2^N长度;当KVM被使用时,host处理器支持的所有向量长度。
(3)若SVE被使能,当尝试禁用最后使能的向量长度,一个错误产生。
(4)若一个或多个向量长度被精确使能并至少一个最大使能的长度被精确禁用,错误产生;
(5)当KVM使能时,若host不支持SVE,当尝试使能任何sve*属性时,错误产生;
(6)当KVM使能时,若host支持SVE,当尝试使能host不支持的向量长度,错误产生;
(7)若一个或多个sve<N> CPU属性被设置为off,但没有sve<N>,CPU属性被设置为on,指定的向量长度被禁用但默认的没有指定的长度仍使能。当KVM没有使能时,禁用2^n向量长度也禁用所有的大于2^n向量长度。当KVM被使能时,禁用任何支持的向量长度也会禁用所有更大的向量长度;
(8)若一个或多个sve<N> CPU属性被设置为on,它们被使能且所有没有指定的长度被默认为禁用;
(9)若SVE被禁用sve=off,允许所有的向量长度被明确禁用,若sve=on后,错误产生。为避免该错误,必须使能支持一个向量长度优于使能SVE。
5.3 SVE CPU属性例子
(1)禁用SVE
$ qemu-system-aarch64 -M virt -cpu max,sve=off
(2)对max CPU类型隐晦的使能所有向量长度
$ qemu-system-aarch64 -M virt -cpu max
(3)当KVM使能时,对Host CPU类型隐晦的使能所有host CPU支持的向量长度
$ qemu-system-aarch64 -M virt,accel=kvm -cpu host
(4)仅使能128位向量长度
$ qemu-system-aarch64 -M virt -cpu max,sve128=on
(5)禁用512位向量长度和所有更大的向量长度,因为512位2^n。这会导致所有更小的未初始化的长度如128、256、384默认为使能的
$ qemu-system-aarch64 -M virt -cpu max,sve512=off
(6)使能128位,256位,512位向量长度
$ qemu-system-aarch64 -M virt -cpu max,sve128=on,sve256=on,sve512=on
(7)如(6)相同,但因为128位和512位被512位向量长度所要求,允许它们位自动使能
$ qemu-system-aarch64 -M virt -cpu max,sve512=on
(8)如(7)相同,但先禁用SVE然后再使能它
$ qemu-system-aarch64 -M virt -cpu max,sve=off,sve512=on,sve=on
(9)关于最后向量长度,强制错误
$ qemu-system-aarch64 -M virt -cpu max,sve128=off
$ qemu-system-aarch64 -M virt -cpu max,sve=off,sve128=off,sve=on
5.4 SVE用户模式默认向量长度属性
对于qemu-aarch64,cpu属性sve-default-vector-length=N定义为Linux内核参数文件/proc/sys/abi/sve_default_vector_length。默认的长度N,必须为16和8192之间的数目。
若没有指定,默认向量长度为64。
若默认长度大于使能的最大向量长度,实际的向量长度被减少。注意QEMU最大的长度为64。
若属性被设置为-1,默认向量长度被设置为最大可能的长度。
翻译来自:
cpu-features.rst - docs/system/arm/cpu-features.rst - Qemu source code (v6.2.0) - Bootlin