QEMU代码分析(2) - 构造函数type_init(x86_cpu_register_types)

本文深入探讨QEMU中的type_init(x86_cpu_register_types)构造函数,解析其调用流程和作用。该函数主要负责将不同类型的CPU信息注册到哈希表中,包括名称、父类型及初始化函数等,为后续CPU类型的查找和初始化提供支持。

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的初始化函数并执行。

在CentOS 7上安装QEMU后,执行`qemu-system-x86_64 --version`时出现“未找到指令”的错误通常意味着QEMU未正确安装或未安装包含`qemu-system-x86_64`的软件包。以下是解决该问题的方法。 ### 检查QEMU安装包是否正确安装 在CentOS 7中,`qemu-system-x86_64`属于`qemu-kvm`软件包的一部分。如果仅安装了`qemu-img`或`qemu`基础包,而没有安装包含系统仿真支持的包,则会出现此错误。需要安装`qemu-kvm`来确保包含`qemu-system-x86_64`可执行文件: ```bash sudo yum install qemu-kvm ``` 该命令将安装QEMU的核心KVM支持模块,同时也包含了`qemu-system-x86_64`命令行工具[^2]。 ### 验证PATH环境变量 如果`qemu-system-x86_64`已经安装但仍然提示“未找到指令”,则可能是执行路径未包含QEMU的安装目录。默认情况下,QEMU的可执行文件会安装在`/usr/bin/`或`/usr/local/bin/`目录下。检查该路径是否包含在`$PATH`环境变量中: ```bash echo $PATH ``` 如果路径中没有包含QEMU的安装目录,可以通过修改环境变量来添加: ```bash export PATH=$PATH:/usr/local/bin ``` ### 从源码编译安装时的注意事项 如果从源码编译安装QEMU,并且没有将`qemu-system-x86_64`安装到系统路径中,也可能导致该命令无法找到。确保在执行`make install`时指定了正确的安装路径。例如: ```bash ./configure --target-list=x86_64-softmmu --prefix=/usr/local make sudo make install ``` 上述命令将QEMU安装到`/usr/local`目录下,生成的`qemu-system-x86_64`可执行文件位于`/usr/local/bin/qemu-system-x86_64`。如果希望直接使用`qemu-system-x86_64`命令,则需要确保`/usr/local/bin`已经在`$PATH`中[^1]。 ### 使用find命令查找qemu-system-x86_64路径 如果不确定`qemu-system-x86_64`是否安装成功,可以使用`find`命令查找该可执行文件的位置: ```bash sudo find / -name qemu-system-x86_64 ``` 如果找到了该文件,可以直接使用其完整路径运行,例如: ```bash /usr/local/bin/qemu-system-x86_64 --version ``` 如果未找到,则需要重新安装QEMU并确保包含x86_64系统仿真支持[^3]。 ### 安装完整的QEMU包 为了确保QEMU的所有组件都被正确安装,可以尝试安装完整的QEMU包: ```bash sudo yum install qemu-kvm qemu-img qemu-system-x86 qemu-system-s390x qemu-system-mips qemu-system-aarch64 ``` 此命令将安装包括`qemu-system-x86_64`在内的多个架构支持,确保x86_64平台的仿真功能可用[^5]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值