QEMU代码分析(1)中说了,QEMU中有很多构造函数都定义为module_init()。
但是在在main执行之前,都主要执行了哪些构造函数?都做了哪些初始化操作呢?
今天主要讲和CPU相关的type_init(x86_cpu_register_types). (target-i386/cpu.c)
1.调用关系
2.代码分析
2.1 type_register_internal(info)
static TypeImpl *type_register_internal(const TypeInfo *info)
{
TypeImpl *ti;
ti = type_new(info); //根据info信息,创建一个TypeImpl对象
type_table_add(ti); //将TypeTmpl插入一个hash表中(第一次调用会新建hash表)。这个表中就存储了各种不同类型cpu的信息:name, parent,class_init,instance_init...
return ti;
}
2.2 x86_cpu_register_types()
static void x86_cpu_register_types(void)
{
int i;
type_register_static(&x86_cpu_type_info); //注册第一类cpu,TYPE_X86_CPU,定义cpu的name、parent等信息,挂接instance_init函数为x86_cpu_initfn, class_init挂接为x86_cpu_common_class_init. 把TYPE_X86_CPU的这些信息,作为一个节点放入hash表中。比如后面执行这类cpu的instance_init这些函数时,就会调用x86_cpu_initfn.
for (i = 0; i < ARRAY_SIZE(builtin_x86_defs); i++) {
x86_register_cpudef_type(&builtin_x86_defs[i]); //函数功能与type_resiter_static基本相同,不过这里是注册tuiltin_x86_defs[]数组中的各个cpu类型,注册也就是把cpu信息放入上面那个hash表中。
}
#ifdef CONFIG_KVM
type_register_static(&host_x86_cpu_type_info);
#endif
}
x86_cpu_type_info定义如下:
static const TypeInfo x86_cpu_type_info = {
.name = TYPE_X86_CPU,
.parent = TYPE_CPU,
.instance_size = sizeof(X86CPU),
.instance_init = x86_cpu_initfn,
.abstract = true,
.class_size = sizeof(X86CPUClass),
.class_init = x86_cpu_common_class_init,
};
builtin_x86_type_info定义如下:(有qemu64的,phenom的,core2duo的....)
static X86CPUDefinition builtin_x86_defs[] = {
{
.name = "qemu64",
.level = 4,
.vendor = CPUID_VENDOR_AMD,
.family = 6,
.model = 6,
.stepping = 3,
.features[FEAT_1_EDX] =
PPRO_FEATURES |
CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
CPUID_PSE36,
.features[FEAT_1_ECX] =
CPUID_EXT_SSE3 | CPUID_EXT_CX16 | CPUID_EXT_POPCNT,
.features[FEAT_8000_0001_EDX] =
(PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
.features[FEAT_8000_0001_ECX] =
CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
.xlevel = 0x8000000A,
},
{
.name = "phenom",
.level = 5,
.vendor = CPUID_VENDOR_AMD,
.family = 16,
.model = 2,
.stepping = 3,
.features[FEAT_1_EDX] =
PPRO_FEATURES |
CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
CPUID_PSE36 | CPUID_VME | CPUID_HT,
.features[FEAT_1_ECX] =
CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_CX16 |
CPUID_EXT_POPCNT,
.features[FEAT_8000_0001_EDX] =
(PPRO_FEATURES & CPUID_EXT2_AMD_ALIASES) |
CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX |
CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT | CPUID_EXT2_MMXEXT |
CPUID_EXT2_FFXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP,
/* Missing: CPUID_EXT3_CMP_LEG, CPUID_EXT3_EXTAPIC,
CPUID_EXT3_CR8LEG,
CPUID_EXT3_MISALIGNSSE, CPUID_EXT3_3DNOWPREFETCH,
CPUID_EXT3_OSVW, CPUID_EXT3_IBS */
.features[FEAT_8000_0001_ECX] =
CPUID_EXT3_LAHF_LM | CPUID_EXT3_SVM |
CPUID_EXT3_ABM | CPUID_EXT3_SSE4A,
.features[FEAT_SVM] =
CPUID_SVM_NPT | CPUID_SVM_LBRV,
.xlevel = 0x8000001A,
.model_id = "AMD Phenom(tm) 9550 Quad-Core Processor"
},
{
.name = "core2duo",
.level = 10,
.vendor = CPUID_VENDOR_INTEL,
...
...
3.总结
综上x86_cpu_register_types功能是:
将各种类型的cpu的信息存入一个hash表中。表中的每个元素是一种cpu类型,每个元素指定了cpu的name,parent等信息,以及instanc_init, class_init 与具体的函数进行挂接。
后面通过查找这个hash表,就可以找到某个类型cpu的所有描述信息,并且可以找到这类cpu的初始化函数并执行。
本文深入探讨QEMU中的type_init(x86_cpu_register_types)构造函数,解析其调用流程和作用。该函数主要负责将不同类型的CPU信息注册到哈希表中,包括名称、父类型及初始化函数等,为后续CPU类型的查找和初始化提供支持。
3235

被折叠的 条评论
为什么被折叠?



