understanding_qemu
  • Introduction
  • 设备模型
    • 设备类型注册
    • 设备类型初始化
    • 设备实例化
    • DeviceClass实例化细节
    • 面向对象的设备模型
    • 接口
    • 类型、对象和接口之间的转换
    • PCDIMM
      • PCDIMM类型
      • PCDIMM实例
      • 插入系统
      • 创建ACPI表
      • NVDIMM
  • 地址空间
    • 从初始化开始
    • MemoryRegion
    • AddressSpace Part1
    • FlatView
    • RAMBlock
    • AddressSpace Part2
    • 眼见为实
    • 添加MemoryRegion
  • APIC
    • 纯Qemu模拟
    • Qemu/kernel混合模拟
    • APICV
  • Live Migration
    • 从用法说起
    • 整体架构
    • VMStateDescription
    • 内存热迁移
    • postcopy
  • FW_CFG
    • 规范解读
    • Linux Guest
    • SeaBios
  • Machine
    • MachineType
    • PCMachine
  • CPU
    • TYPE_CPU
    • X86_CPU
  • MemoryBackend
    • MemoryBackend类层次结构
    • MemoryBackend初始化流程
Powered by GitBook
On this page
  • 一一对应
  • 接口类

Was this helpful?

  1. 设备模型

设备类型初始化

一一对应

注册类型TypeImpl之后就需要初始化该类型,如果打开TypeImpl这个结构体,可以看到其中有个叫class的成员。初始化其实就是初始化的它。

    TypeImpl                               ObjectClass
    +----------------------+               +----------------------+
    |class                 |<------------->|type                  |
    |     (ObjectClass*)   |               |     (TypeImpl *)     |
    +----------------------+               +----------------------+

进行初始化的具体函数是 type_initialize()。

摘取其中主要的流程如下:

  type_initialize()
    ...
    parent = type_get_parent(ti);
    if (parent) {
      type_initialize(parent);
      ...
      for (i = 0; i < ti->num_interfaces; i++) {
        TypeImpl *t = type_get_by_name(ti->interfaces[i].typename);
        ...
        type_initialize_interface(ti, t, t);
      }
    }

    ...

    while (parent) {
      if (parent->class_base_init) {
        parent->class_base_init(ti->class, ti->class_data);
      }
      parent = type_get_parent(parent);
    }

    if (ti->class_init) {
      ti->class_init(ti->class, ti->class_data);
    }

其中主要做了几件事:

  • 设置类型的大小并创建该类型

  • 设置类型实例的大小,为实例化设备做准备

  • 初始化父设备类型,如果没有的话

  • 初始化接口类型

  • 调用父设备类型的class_base_init初始化自己

  • 调用class_init初始化自己

在这里看不出什么具体的东西,因为每种设备类型将执行不同的初始化函数。

但是有一点可以看出的是,qemu设备类型有一个树形结构。或者说是一种面向对象的编程模型,需要初始化父类后,再初始化自己。

接口类

在看了一段时间代码后,发现一个类型还能定义其相关的接口类型。

比如我们看e1000设备的定义可以看到在最后有定义一个interfaces成员。

#define TYPE_E1000_BASE "e1000-base"

static const TypeInfo e1000_base_info = {
    .name          = TYPE_E1000_BASE,
    .parent        = TYPE_PCI_DEVICE,
    ...
    .interfaces = (InterfaceInfo[]) {
        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
        { },
    },
};

那么我们来看看这个成员如何初始化,如何使用。

在 type_initialize()函数中有一段

for (i = 0; i < ti->num_interfaces; i++) {
  TypeImpl *t = type_get_by_name(ti->interfaces[i].typename);
  ...
  type_initialize_interface(ti, t, t);
}

这个就是在初始化ti这个类型的接口类。好在这个函数type_initialize_interface()不长,我们直接打开看看。

static void type_initialize_interface(TypeImpl *ti, TypeImpl *interface_type,
                                      TypeImpl *parent_type)
{
    InterfaceClass *new_iface;
    TypeInfo info = { };
    TypeImpl *iface_impl;

    info.parent = parent_type->name;
    info.name = g_strdup_printf("%s::%s", ti->name, interface_type->name);
    info.abstract = true;

    iface_impl = type_new(&info);
    iface_impl->parent_type = parent_type;
    type_initialize(iface_impl);
    g_free((char *)info.name);

    new_iface = (InterfaceClass *)iface_impl->class;
    new_iface->concrete_class = ti->class;
    new_iface->interface_type = interface_type;

    ti->class->interfaces = g_slist_append(ti->class->interfaces,
                                           iface_impl->class);
}

说实话,这个东西有点绕。因为在这个过程中又注册了一个新的类型并做了初始化。

                                                  TypeImpl
                                                  +------------------------------------+
                                                  |name                                |
                                                  |   "conventional-pci-device"        |
                                                  |class (struct InterfaceClass)       |
                                                  |                                    |
                                                  +------------------------------------+
                                                                      ^
                                                                      |
                                                                      |
    TypeImpl                                      TypeImpl            |
                                                  +------------------------------------+
    +--------------------------+                  |parent          ---+                |
    |name                      |                  |name                                |
    |   "e1000-base"           |                  |   "e1000::conventional-pci-device" |
    |class (E1000BaseClass)    |     +----------->|class (struct InterfaceClass)       |
    |   ^  interfaces     -----|-----+            |       concrete_class  ----+        |
    |   |                      |                  +------------------------------------+
    +--------------------------+                                              |
        |                                                                     |
        +---------------------------------------------------------------------+

最后的结果我尝试用图来展示。

  • 创建了一个INTERFACE_CONVENTIONAL_PCI_DEVICE类型的子类,也是一个接口类型

  • E1000BaseClass中的interfaces会指向新建的接口类

  • 而接口类中的concrete_class会指向E1000BaseClass

Previous设备类型注册Next设备实例化

Last updated 6 years ago

Was this helpful?