一、 qemu侧irqchip的实现
Qemu在main函数之前,已经创建了TYPE_I8259、ioapic、TYPE_APIC三个类型,用于创建这三个设备,实现在qemu侧的irqchip。 如果irqchip在hypervisor中实现,则需要创建三个新的设备,相比前面提到的三个设备要简单很多,主要是用来实现中断从qemu到hypervisor的分发过程。Irqchip实现在hypervisor的好处是,guest的所有中断都在驱动中进行处理,减少了hypervisor到qemu的陷出过程。(本文后续hypervisor以HAXM为例分析)
二、中断数据结构
-
GSIState:记录了中断状态,对应PIC和IOAPIC的各个管脚,ISA_NUM_IRQS为16,IOAPIC_NUM_PINS,对应PIC和IOAPIC的管脚数。
-
qemu_irq是一个指向IRQState结构的指针,可以表示一个中断引脚,handler表示执行的函数,n表示管脚号:
三、设备创建
Qemu中对应HAXM新创建了三个设备,包括i8259、hax-ioapic、hax-apic,其中hax-apic在中断分发中没有起到什么作用,只有一些辅助的功能。
1.设备创建的流程
1)type_init进行类型的初始化 设备文件的最后一行会调用type_init,对设备的TypeInfo类型进行处理。type_init宏对应module_init宏,其对应的函数添加了attribute((constructor))属性,因此会在main函数执行之前调用register_module_init:
该函数会动态分配一个指向ModuleEntry类型的节点,将i8259、ioapic、apic类型的init函数赋给ModuleEntry的init的函数,并插入到ModuleTypeList类型的链表里面: 2)module_call_init main函数会调用module_call_init函数,对之前插入到链表中的所有TypeInfo调用init回调函数,对应的为hax_pic_register_types、hax_apic_register_types、hax_ioapic_register_types,这些回调函数将完成设备TypeInfo类型到TypeImpl类型的转换,并以name为键值插入到hash表中完成类型的注册,至此完成了QOM中的类型注册过程。 TypeInfo类型和TypeImpl类型大部分成员相同,最大的不同是TypeImpl中加入了parent_type和class成员。 3)qdev_create 目前qemu(2.12)创建的是i440FX+piix3的主板,在主板模拟时,会调用qdev_create函数根据之前得到的TypeImpl结构创建pic和ioapic设备。Qdev_create只是初始化了设备的状态,允许设备属性的设置,对设备的真正初始化还需要调用设备的realize函数。 qdev_create调用了qdev_try_create,进一步调用object_new,object_new会根据之前类型中注册的name,找到对应的TypeImpl结构,调用object_new_eith_type。 object_new_eith_type函数调用type_initialize。type_initialize首先设置了一些field,并为clazz成员分配了一个ObjectClass,然后初始化了所有的父类和祖类类型,包括实际类型和抽象类型,最后依次调用了父类和祖类的class_base_init函数与自己的class_init函数。 之后object_new_with_type首先分配了对象的实际空间,然后调用object_initialize_with_type函数,根据TypeImpl结构对该对象进行了初始化。至此完成了类对象的构造部分,现在设备已经创建好,但是里面的数据还没有填充,因此设备仍然处于不可用的状态。 4)qdev_init_nofail