admin管理员组文章数量:1130349
文章目录
- 硬件基础
-
- vendor
- signature
- feature
- 数据结构
-
- 物理抽象
-
- virCPUx86CPUID
- virCPUx86DataItem
- virCPUx86Data
- 配置信息
-
- virCPUx86Vendor
- virCPUx86Feature
- virCPUx86Model
- virCPUx86Map
- 概念抽象
-
- virCPUFeatureDef
- virCPUDef
- 工具函数
-
- 数据加载
-
- virCPUx86LoadMap
- 基本操作
-
- virCPUx86DataItemCmp
- virCPUx86DataNext
- virCPUx86DataGet
- virCPUx86DataItemAndBits
- virCPUx86DataItemClearBits
- 集合操作
-
- x86DataAdd
- x86DataSubtract
- x86DataIntersect
- 信息提取
-
- x86DataToCPUFeatures
- x86DataToVendor
- virsh 工具
-
- capabilities
- cpu-baseline
- cpu-compare
硬件基础
- 虚拟机的迁移需要保证两端的主机能够暴露给虚机的cpu feature相同,如果不相同无法保证迁移后虚机能够正常运行,因此迁移前会判断两端虚机特性,不同会报错,终止迁移。为了让资源池中新加入一台服务器并能够顺利将虚机迁移过去,需要计算源和目的两端服务器的cpu feature交集,然后暴露给虚机,保证迁移顺利,这是虚拟化组件需要解决的事情。本节主要介绍其硬件基础。
- Intel通过cpuid指令查询cpu的signature和feature,signature标识着cpu的版本信息,feature包含了cpu的支持的硬件特性,比如虚拟化相关的vmx(Virtual Machine Extensions)特性,内存管理相关的pae(Physical Address Extension)特性,或者MSR(Model Specific Registers)等。通过cpuid指令可以查到两类信息,一类是cpu基本(Basic)信息,一类是cpu扩展(Extended)信息。
- cpuid指令虽然没有操作数,但它的输出较其它有操作数的指令更为复杂,它将寄存器(EAX,ECX)作为输入,将寄存器(EAX,EBX,ECX,EDX)作为输出。输入的不同,执行cpuid指令得到的输出信息不同。比如,在EAX=0,ECX=0的情况下,如果执行cpuid指令,得到的是cpu的vendor信息和输入EAX的最大值;在EAX=1,ECX=0的情况下,如果执行cpuid指令,得到的是cpu的signature和feature。CPU feature相关的cpuid指令就是上面这两个,下面具体介绍它们的输出格式,以及如何获取vendor、signature和feature信息。关于cpu指令的详细介绍,参考intel手册的vol 2A-3.3-CPU Identification小节的介绍。demo可参考:cpuid demo
vendor
- 当EAX被设置成0,作为输入时,执行cpuid指令,它的输出分别是EAX,保存EAX作为输入的最大值和vendor信息。Intel手册中关于vendor信息的获取说明如下:
- 假设最大输入值为Maximum,那么EAX作为输入的取值范围就是[0, Maximum]。当EAX在这区间范围内作为输入时,执行cpuid指令输出的信息为Basic类信息。vendor为厂商信息,由EBX/ECX/ECX三个寄存器共同提供。对于x86架构有三个厂商信息,分别是:GenuineIntel(Intel)、AuthenticAMD(AMD)和HygonGenuine(Hygon)
signature
- 当EAX被设置成1,作为输入时,执行cpuid指令,它的输出寄存器中,EAX保存cpu的signature的信息。ECX和EDX保存cpu的feature信息,Intel手册说明如下:
- EAX的signature信息格式如下:
feature
- feature信息和signature一样,通过设置EAX为1执行cpuid指令得到。它的信息保存在两个寄存器ECX、EDX中,寄存器的每个bit标识着一个cpu的特性,如果该bit被置位,表示cpu支持该特性,反之,如果该bit被清零,标志cpu不支持该特性。
- ECX和ECX表示的feature格式如下:
数据结构
- Libvirt提供了探测主机cpu feature的工具、计算指定cpu feature集合与主机cpu feature集合关系的工具,以及计算不同cpu feature交集的工具。通过这些工具,上层应用可以计算出两个cpu之间feature的交集,从而决定如何暴露给虚拟机,顺利实现虚机的迁移。本节主要介绍Libvirt中与cpu feature相关的数据结构。
物理抽象
virCPUx86CPUID
- virCPUx86CPUID用于描述执行一条cpuid指令前后的输入和输出。
typedef struct _virCPUx86CPUID virCPUx86CPUID;
typedef virCPUx86CPUID *virCPUx86CPUIDPtr;
struct _virCPUx86CPUID {
uint32_t eax_in; /* 输入:寄存器EAX的值 */
uint32_t ecx_in; /* 输入:寄存器ECX的值 */
uint32_t eax; /* 输出:寄存器EAX的值 */
uint32_t ebx; /* 同上 */
uint32_t ecx;
uint32_t edx;
};
- 在Libvirt中,使用嵌入式汇编调用cpuid指令,在执行过程中用到了virCPUx86CPUID结构,如下:
cpuidCall(virCPUx86CPUID *cpuid)
{
asm("xor %%ebx, %%ebx;" /* clear the other registers as some cpuid */
"xor %%edx, %%edx;" /* functions may use them as additional arguments */
"cpuid;"
: "=a" (cpuid->eax), /* 将eax的值作为输出保存到cpuid->eax中*/
"=b" (cpuid->ebx), /* 原理同上 */
"=c" (cpuid->ecx),
"=d" (cpuid->edx)
: "a" (cpuid->eax_in), /* 指定寄存器eax的值从cpuid->eax_in中读取 */
"c" (cpuid->ecx_in)); /* 指定寄存器ecx的值从cpuid->ecx_in中读取 */
}
virCPUx86DataItem
- virCPUx86DataItem在type为VIR_CPU_X86_DATA_CPUID时,保存的是一条cpuid指令输入输出。
typedef struct _virCPUx86DataItem virCPUx86DataItem;
typedef virCPUx86DataItem *virCPUx86DataItemPtr;
struct _virCPUx86DataItem {
virCPUx86DataType type; /* 当type=VIR_CPU_X86_DATA_CPUID时,data的cpuid值有效 */
union {
virCPUx86CPUID cpuid; /* 保存一条cpuid的输入输出*/
virCPUx86MSR msr;
} data;
};
virCPUx86Data
- 对于一个cpu来说,当使用cpuid指令查询它的相关信息时,它会有很多的输出,每改变一次输入的值,执行cpuid查到的输出值意义就不一样,因此cpuid的输入输出组成的条目非常多,Libvirt通过virCPUx86Data来描述执行cpuid的所有输入输出组成的数组。virCPUx86Data可以认为保存的是cpuid指令查询后,得到的原始数据。
typedef struct _virCPUx86Data virCPUx86Data;
struct _virCPUx86Data {
size_t len; /* 数组的大小,数组的每个元素表示cpuid指令的一个输入输出 */
virCPUx86DataItem *items; /* 数组的基地址 */
};
配置信息
- Libvirt为了管理cpu feature,将支持的所有架构的所有feature组织成xml文件,持久化到磁盘上,同时将支持的所有model和vendor也组织成xml文件,持久化到磁盘上。在libvirt获取host capabilities或者计算feature交集时,会首先将支持的所有feature,vendor,model都加载到内存中,用于feature集合的计算。xml所在目录为/usr/share/libvirt/cpu_map/,下面主要介绍这些xml格式在内存中的数据结构。
virCPUx86Vendor
- vendor信息可以通过cpuid指令查询得到,virCPUx86Vendor结构用于存放查询vendor的cpuid指令的输入输出,组成的一个item。
typedef struct _virCPUx86Vendor virCPUx86Vendor;
typedef virCPUx86Vendor *virCPUx86VendorPtr;
struct _virCPUx86Vendor {
char *name; /* 厂商名称,对于x86架构,可能的名称就是Intel、AMD和Hygon */
virCPUx86DataItem data; /* cpuid查询得到的条目,它的输出EBX、ECX和EDX就是厂商名称的accii码值 */
};
- Libvirt保存了支持的vendor信息到xml中,当virsh工具需要处理vendor相关信息时,Libvirt从xml中读取支持的vendor信息,加载到内存,对应的数据结构就是virCPUx86Vendor。Libvirt的vendor信息保存在/usr/share/libvirt/cpu_map/x86_vendors.xml 中,如下:
<cpus>
<vendor name='Intel' string='GenuineIntel'/> /* 厂商名: Intel; 输出EBX/ECX/EDX组成的字符串为'GenuineIntel' */
<vendor name='AMD' string='AuthenticAMD'/>
<vendor name='Hygon' string='HygonGenuine'/>
</cpus>
virCPUx86Feature
- cpu的feature信息也通过cpuid指令查询得到,virCPUx86Feature的data域存放的数组通常只有一个元素,代表一个bit对应的feature。
typedef struct _virCPUx86Feature virCPUx86Feature;
typedef virCPUx86Feature *virCPUx86FeaturePtr;
struct _virCPUx86Feature {
/* feature名 */
char *name;
/* feature对应的寄存器值,对应寄存器中的一个bit
* 这里看上去data包含的是一个item数组
* 但实际上通常情况下只有一个元素 */
virCPUx86Data data;
/* 如果该feature不影响迁移(可迁移)
* 设置为true,反之,设置为false */
bool migratable;
};
- libvirt将所有feature以一定格式组织起来,存放到/usr/share/libvirt/cpu_map/x86_features.xml中,这个xml描述了x86架构下所有厂商的feature属性,包括该通过什么输入得到,输出的feature值对应寄存器的哪一位;该feature是否可以迁移等。每当Libvirt需要计算feature时,将这些feature加载到内存,进行操作。xml中一个典型的feature描述如下:
<feature name='vmx'> /* feature名字: vmx*/
<cpuid eax_in='0x01' ecx='0x00000020'/> /* 获取feature时输入EAX的值为0x01,该feature对应输出ECX的第5bit */
</feature>
virCPUx86Model
- cpu的model信息通过cpuid指令查到,得到的原始数据被保存到一个virCPUx86Data数据结构中。同时,virCPUx86Model结构中还将原数据解析出来,分别存放到vendor和signature中。
typedef struct _virCPUx86Model virCPUx86Model;
typedef virCPUx86Model *virCPUx86ModelPtr;
struct _virCPUx86Model {
char *name; /* Model名 */
virCPUx86VendorPtr vendor;文章目录
- 硬件基础
-
- vendor
- signature
- feature
- 数据结构
-
- 物理抽象
-
- virCPUx86CPUID
- virCPUx86DataItem
- virCPUx86Data
- 配置信息
-
- virCPUx86Vendor
- virCPUx86Feature
- virCPUx86Model
- virCPUx86Map
- 概念抽象
-
- virCPUFeatureDef
- virCPUDef
- 工具函数
-
- 数据加载
-
- virCPUx86LoadMap
- 基本操作
-
- virCPUx86DataItemCmp
- virCPUx86DataNext
- virCPUx86DataGet
- virCPUx86DataItemAndBits
- virCPUx86DataItemClearBits
- 集合操作
-
- x86DataAdd
- x86DataSubtract
- x86DataIntersect
- 信息提取
-
- x86DataToCPUFeatures
- x86DataToVendor
- virsh 工具
-
- capabilities
- cpu-baseline
- cpu-compare
硬件基础
- 虚拟机的迁移需要保证两端的主机能够暴露给虚机的cpu feature相同,如果不相同无法保证迁移后虚机能够正常运行,因此迁移前会判断两端虚机特性,不同会报错,终止迁移。为了让资源池中新加入一台服务器并能够顺利将虚机迁移过去,需要计算源和目的两端服务器的cpu feature交集,然后暴露给虚机,保证迁移顺利,这是虚拟化组件需要解决的事情。本节主要介绍其硬件基础。
- Intel通过cpuid指令查询cpu的signature和feature,signature标识着cpu的版本信息,feature包含了cpu的支持的硬件特性,比如虚拟化相关的vmx(Virtual Machine Extensions)特性,内存管理相关的pae(Physical Address Extension)特性,或者MSR(Model Specific Registers)等。通过cpuid指令可以查到两类信息,一类是cpu基本(Basic)信息,一类是cpu扩展(Extended)信息。
- cpuid指令虽然没有操作数,但它的输出较其它有操作数的指令更为复杂,它将寄存器(EAX,ECX)作为输入,将寄存器(EAX,EBX,ECX,EDX)作为输出。输入的不同,执行cpuid指令得到的输出信息不同。比如,在EAX=0,ECX=0的情况下,如果执行cpuid指令,得到的是cpu的vendor信息和输入EAX的最大值;在EAX=1,ECX=0的情况下,如果执行cpuid指令,得到的是cpu的signature和feature。CPU feature相关的cpuid指令就是上面这两个,下面具体介绍它们的输出格式,以及如何获取vendor、signature和feature信息。关于cpu指令的详细介绍,参考intel手册的vol 2A-3.3-CPU Identification小节的介绍。demo可参考:cpuid demo
vendor
- 当EAX被设置成0,作为输入时,执行cpuid指令,它的输出分别是EAX,保存EAX作为输入的最大值和vendor信息。Intel手册中关于vendor信息的获取说明如下:
- 假设最大输入值为Maximum,那么EAX作为输入的取值范围就是[0, Maximum]。当EAX在这区间范围内作为输入时,执行cpuid指令输出的信息为Basic类信息。vendor为厂商信息,由EBX/ECX/ECX三个寄存器共同提供。对于x86架构有三个厂商信息,分别是:GenuineIntel(Intel)、AuthenticAMD(AMD)和HygonGenuine(Hygon)
signature
- 当EAX被设置成1,作为输入时,执行cpuid指令,它的输出寄存器中,EAX保存cpu的signature的信息。ECX和EDX保存cpu的feature信息,Intel手册说明如下:
- EAX的signature信息格式如下:
feature
- feature信息和signature一样,通过设置EAX为1执行cpuid指令得到。它的信息保存在两个寄存器ECX、EDX中,寄存器的每个bit标识着一个cpu的特性,如果该bit被置位,表示cpu支持该特性,反之,如果该bit被清零,标志cpu不支持该特性。
- ECX和ECX表示的feature格式如下:
数据结构
- Libvirt提供了探测主机cpu feature的工具、计算指定cpu feature集合与主机cpu feature集合关系的工具,以及计算不同cpu feature交集的工具。通过这些工具,上层应用可以计算出两个cpu之间feature的交集,从而决定如何暴露给虚拟机,顺利实现虚机的迁移。本节主要介绍Libvirt中与cpu feature相关的数据结构。
物理抽象
virCPUx86CPUID
- virCPUx86CPUID用于描述执行一条cpuid指令前后的输入和输出。
typedef struct _virCPUx86CPUID virCPUx86CPUID;
typedef virCPUx86CPUID *virCPUx86CPUIDPtr;
struct _virCPUx86CPUID {
uint32_t eax_in; /* 输入:寄存器EAX的值 */
uint32_t ecx_in; /* 输入:寄存器ECX的值 */
uint32_t eax; /* 输出:寄存器EAX的值 */
uint32_t ebx; /* 同上 */
uint32_t ecx;
uint32_t edx;
};
- 在Libvirt中,使用嵌入式汇编调用cpuid指令,在执行过程中用到了virCPUx86CPUID结构,如下:
cpuidCall(virCPUx86CPUID *cpuid)
{
asm("xor %%ebx, %%ebx;" /* clear the other registers as some cpuid */
"xor %%edx, %%edx;" /* functions may use them as additional arguments */
"cpuid;"
: "=a" (cpuid->eax), /* 将eax的值作为输出保存到cpuid->eax中*/
"=b" (cpuid->ebx), /* 原理同上 */
"=c" (cpuid->ecx),
"=d" (cpuid->edx)
: "a" (cpuid->eax_in), /* 指定寄存器eax的值从cpuid->eax_in中读取 */
"c" (cpuid->ecx_in)); /* 指定寄存器ecx的值从cpuid->ecx_in中读取 */
}
virCPUx86DataItem
- virCPUx86DataItem在type为VIR_CPU_X86_DATA_CPUID时,保存的是一条cpuid指令输入输出。
typedef struct _virCPUx86DataItem virCPUx86DataItem;
typedef virCPUx86DataItem *virCPUx86DataItemPtr;
struct _virCPUx86DataItem {
virCPUx86DataType type; /* 当type=VIR_CPU_X86_DATA_CPUID时,data的cpuid值有效 */
union {
virCPUx86CPUID cpuid; /* 保存一条cpuid的输入输出*/
virCPUx86MSR msr;
} data;
};
virCPUx86Data
- 对于一个cpu来说,当使用cpuid指令查询它的相关信息时,它会有很多的输出,每改变一次输入的值,执行cpuid查到的输出值意义就不一样,因此cpuid的输入输出组成的条目非常多,Libvirt通过virCPUx86Data来描述执行cpuid的所有输入输出组成的数组。virCPUx86Data可以认为保存的是cpuid指令查询后,得到的原始数据。
typedef struct _virCPUx86Data virCPUx86Data;
struct _virCPUx86Data {
size_t len; /* 数组的大小,数组的每个元素表示cpuid指令的一个输入输出 */
virCPUx86DataItem *items; /* 数组的基地址 */
};
配置信息
- Libvirt为了管理cpu feature,将支持的所有架构的所有feature组织成xml文件,持久化到磁盘上,同时将支持的所有model和vendor也组织成xml文件,持久化到磁盘上。在libvirt获取host capabilities或者计算feature交集时,会首先将支持的所有feature,vendor,model都加载到内存中,用于feature集合的计算。xml所在目录为/usr/share/libvirt/cpu_map/,下面主要介绍这些xml格式在内存中的数据结构。
virCPUx86Vendor
- vendor信息可以通过cpuid指令查询得到,virCPUx86Vendor结构用于存放查询vendor的cpuid指令的输入输出,组成的一个item。
typedef struct _virCPUx86Vendor virCPUx86Vendor;
typedef virCPUx86Vendor *virCPUx86VendorPtr;
struct _virCPUx86Vendor {
char *name; /* 厂商名称,对于x86架构,可能的名称就是Intel、AMD和Hygon */
virCPUx86DataItem data; /* cpuid查询得到的条目,它的输出EBX、ECX和EDX就是厂商名称的accii码值 */
};
- Libvirt保存了支持的vendor信息到xml中,当virsh工具需要处理vendor相关信息时,Libvirt从xml中读取支持的vendor信息,加载到内存,对应的数据结构就是virCPUx86Vendor。Libvirt的vendor信息保存在/usr/share/libvirt/cpu_map/x86_vendors.xml 中,如下:
<cpus>
<vendor name='Intel' string='GenuineIntel'/> /* 厂商名: Intel; 输出EBX/ECX/EDX组成的字符串为'GenuineIntel' */
<vendor name='AMD' string='AuthenticAMD'/>
<vendor name='Hygon' string='HygonGenuine'/>
</cpus>
virCPUx86Feature
- cpu的feature信息也通过cpuid指令查询得到,virCPUx86Feature的data域存放的数组通常只有一个元素,代表一个bit对应的feature。
typedef struct _virCPUx86Feature virCPUx86Feature;
typedef virCPUx86Feature *virCPUx86FeaturePtr;
struct _virCPUx86Feature {
/* feature名 */
char *name;
/* feature对应的寄存器值,对应寄存器中的一个bit
* 这里看上去data包含的是一个item数组
* 但实际上通常情况下只有一个元素 */
virCPUx86Data data;
/* 如果该feature不影响迁移(可迁移)
* 设置为true,反之,设置为false */
bool migratable;
};
- libvirt将所有feature以一定格式组织起来,存放到/usr/share/libvirt/cpu_map/x86_features.xml中,这个xml描述了x86架构下所有厂商的feature属性,包括该通过什么输入得到,输出的feature值对应寄存器的哪一位;该feature是否可以迁移等。每当Libvirt需要计算feature时,将这些feature加载到内存,进行操作。xml中一个典型的feature描述如下:
<feature name='vmx'> /* feature名字: vmx*/
<cpuid eax_in='0x01' ecx='0x00000020'/> /* 获取feature时输入EAX的值为0x01,该feature对应输出ECX的第5bit */
</feature>
virCPUx86Model
- cpu的model信息通过cpuid指令查到,得到的原始数据被保存到一个virCPUx86Data数据结构中。同时,virCPUx86Model结构中还将原数据解析出来,分别存放到vendor和signature中。
typedef struct _virCPUx86Model virCPUx86Model;
typedef virCPUx86Model *virCPUx86ModelPtr;
struct _virCPUx86Model {
char *name; /* Model名 */
virCPUx86VendorPtr vendor;版权声明:本文标题:Libvirt CPU Feature 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://it.en369.cn/jiaocheng/1763609425a2947900.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。


发表评论