关于raspi3的注册分析
1.raspi3_machine_init
1.1 binclude/hw/arm/raspi.c
static void raspi3_machine_init(MachineClass *mc)
{
mc->desc = "Raspberry Pi 3";
mc->init = raspi3_init;
mc->block_default_type = IF_SD;
mc->no_parallel = 1;
mc->no_floppy = 1;
mc->no_cdrom = 1;
mc->max_cpus = BCM283X_NCPUS;
mc->min_cpus = BCM283X_NCPUS;
mc->default_cpus = BCM283X_NCPUS;
mc->default_ram_size = 1 * GiB;
}
DEFINE_MACHINE("raspi3", raspi3_machine_init)
1.2 DEFINE_MACHINE
DEFINE_MACHINE
宏定义在include/hw/boards.h,效果等同于:
static void raspi3_machine_init_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = ((MachineClass *)object_class_dynamic_cast_assert(((ObjectClass *)((oc))), ("machine"), "/home/linux/qemu/hw/arm/raspi.c", 259, __func__));
raspi3_machine_init(mc);
}
static const TypeInfo raspi3_machine_init_typeinfo = {
.name = ("raspi3" "-machine"),
.parent = "machine",
.class_init = raspi3_machine_init_class_init,
};
static void raspi3_machine_init_register_types(void)
{
type_register_static(&raspi3_machine_init_typeinfo);
}
static void __attribute__((constructor)) do_qemu_init_raspi3_machine_init_register_types(void)
{
register_module_init(raspi3_machine_init_register_types, MODULE_INIT_QOM);
}
关于__attribute__((constructor))
:
The constructor attribute causes the function to be called automatically before execution enters main (). Similarly, the destructor attribute causes the function to be called automatically after main () completes or exit () is called. Functions with these attributes are useful for initializing data that is used implicitly during the execution of the program.
翻译
constructor属性使当前的函数在执行main函数前会自动的调用。类似的,destructor属性在main函数执行过后或者exit()被调用的时候进行调用。拥有这些属性的函数可以在执行程序过程中隐式地初始化数据。
可知在main函数初始化前,会调用do_qemu_init_raspi3_machine_init_register_types
,然后调用register_module_init
1.3 register_module_init
register_module_init
定义在/util/module.c
void register_module_init(void (*fn)(void), module_init_type type)
{
ModuleEntry *e;
ModuleTypeList *l;
e = g_malloc0(sizeof(*e));
e->init = fn;
e->type = type;
l = find_type(type);
QTAILQ_INSERT_TAIL(l, e, node);
}
//QTAILQ_INSERT_TAIL等价于
/*
do {
(e)->node.tqe_next = (void *)0;
(e)->node.tqe_circ.tql_prev = (l)->tqh_circ.tql_prev;
(l)->tqh_circ.tql_prev->tql_next = (e);
(l)->tqh_circ.tql_prev = &(e)->node.tqe_circ;
} while (/*CONSTCOND*/0)
*/
在本启动中,fn是raspi3_machine_init_register_types
的地址,这个地址赋值给e->init
,e->type
为QOM
关于struct ModuleEntry
typedef struct ModuleEntry
{
void (*init)(void);
QTAILQ_ENTRY(ModuleEntry) node;
module_init_type type;
} ModuleEntry;
关于module_init_type
typedef enum {
MODULE_INIT_BLOCK,
MODULE_INIT_OPTS,
MODULE_INIT_QOM,
MODULE_INIT_TRACE,
MODULE_INIT_XEN_BACKEND,
MODULE_INIT_LIBQOS,
MODULE_INIT_MAX
} module_init_type;
QTAILQ_ENTRY(ModuleEntry) node
等同于:
union {
struct ModuleEntry *tqe_next; /* next element */
QTailQLink tqe_circ; /* link for circular backwards list */
}
关于QOM
QEMU提供了一套面向对象编程的模型——QOM,即QEMU Object Module,几乎所有的设备如CPU、内存、总线等都是利用这一面向对象的模型来实现的。QOM模型的实现代码位于qom/文件夹下的文件中。
参考:https://blog.csdn.net/u011364612/article/details/53485856 (未细看)
find_type
解析:
static ModuleTypeList dso_init_list;
static ModuleTypeList init_type_list[MODULE_INIT_MAX];
typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList;
ModuleTypeList
等同于:
union {
struct ModuleEntry *tqh_first; /* first element */
QTailQLink tqh_circ; /* link for circular backwards list */
}
static ModuleTypeList *find_type(module_init_type type)
{
//
init_lists();
return &init_type_list[type];
}
static void init_lists(void)
{
static int inited;
int i;
if (inited) {
return;
}
for (i = 0; i < MODULE_INIT_MAX; i++) {
QTAILQ_INIT(&init_type_list[i]);
}
QTAILQ_INIT(&dso_init_list);
inited = 1;
}
QTAILQ_INIT(&init_type_list[i]);
等价于:
do {
(&init_type_list[i])->tqh_first = (void *)0;
(&init_type_list[i])->tqh_circ.tql_prev = &(&init_type_list[i])->tqh_circ;
} while (/*CONSTCOND*/0)
QTAILQ_INIT(&dso_init_list);
等价于
do {
(&dso_init_list)->tqh_first = (void *)0;
(&dso_init_list)->tqh_circ.tql_prev = &(&dso_init_list)->tqh_circ;
} while (/*CONSTCOND*/0)
1.4 总结
相当于在init_type_list[QOM]中注册了raspi3_machine_init_register_types
所在的地址