qemu系统总线——sysbus
在实际的物理机器上,CPU与外接连接的总线被称之为Host Bus。即系统总线,SysBus。在qemu中,对sysbus总线进行了模拟,实现在hw/core/sysbus.c文件中。
type_init(sysbus_register_types);
static void sysbus_register_types(void)
{
type_register_static(&system_bus_info);
type_register_static(&sysbus_device_type_info);
}
通过对type_init的分析可以知道,上边的代码是将struct TypeImpl结构体对象system_bus_info以及sysbus_device_type_info注册到全局哈希表中。两种结构体对象的具体内容如下:
static const TypeInfo system_bus_info = {
.name = TYPE_SYSTEM_BUS,
.parent = TYPE_BUS,
.instance_size = sizeof(BusState),
.class_init = system_bus_class_init,
}
static const TypeInfo sysbus_device_type_info = {
.name = TYPE_SYS_BUS_DEVICE,
.parent = TYPE_DEVICE,
.instance_size = sizeof(SysBusDevice),
.abstract = true,
.class_size = sizeof(SysBusDeviceClass),
.class_init = sysbus_device_class_init,
};
在qemu中,系统总线由全局变量main_system_bus来表示。main_system_bus的创建由main_system_bus_create函数来完成。如下:
static BusState *main_system_bus;
#define TYPE_SYSTEM_BUS "System"
static void main_system_bus_create(void)
{
main_system_bus = g_malloc0(system_bus_info.instance_size);
qbus_create_inplace(main_system_bus, system_bus_info.instance_size, TYPE_SYSTEM_BUS, NULL, "main-system-bus");
OBJECT(main_system_bus)->free = g_free;
}
上边的代码中,总线的表示由BusState结构体来抽象,如下:
struct BusState {
Object obj;
DeviceState *parent;
char *name;
HotPlugHandler *hotplug_handler;
int max_index;
bool realized;
int num_children;
QTAILQ_HEAD(, BusChild) children;
QLIST_ENTRY(BusState) sibling;
ResettableState reset;
};
typedef struct BusState BusState;
创建总线的主要函数为qbus_create_inplace,如下:
void qbus_create_inplace(void *bus, size_t size, const char *typename, DeviceState *parent, const char *name)
{
object_initialize(bus, size, typename);
qbus_init(bus, parent, name);
}
上边代码主要完成了两部分的工作,一部分为main_system_bus所对应的BusClass的初始化过程;另外一部分为main_system_bus所对应的BusState的初始化过程。
void object_initialize(void *data, size_t size, const char *typename)
{
TypeImpl *type = type_get_by_name(typename);
//获取名为System的TypeImpl,即上边所定义的system_bus_info结构体对象
if (!type) {
error_report("missing object type '%s'", typename);
abort();
}
object_initialize_with_type(data, size, type);
//根据system_bus_info结构体对象来初始化main_system_bus中的成员信息
}
static void object_initialize_with_type(Object *obj, size_t size, TypeImpl *type)
{
type_initialize(type);
//该函数主要用来创建Object所需的 ObjectClass结构体对象,并调用type对象中所指向的class_init指针函数来对ObjectClass对象进行初始化。
g_assert(type->instance_size >= sizeof(Object));
g_assert(type->abstract == false);
g_assert(size >= type->instance_size);
memset(obj, 0, type->instance_size);
obj->class = type->class;
object_ref(obj);
object_class_property_init_all(obj);
obj->properties = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, object_property_free);
object_init_with_type(obj, type);
object_post_init_with_type(obj, type);
}
BusClass的初始化中,主要对BusClass中print_dev以及get_fw_dev_path变量的赋值。注意,Object对象中的properties属性为哈希表指针,关于Object对象的所有属性都会以键值对的形式存放在该哈希表中。
static void qbus_init(BusState *bus, DeviceState *parent, const char *name)
{
const char *typename = object_get_typename(OBJECT(bus));
//return Object->ObjectClass->TypeImpl->name;
BusClass *bc;
int i, bus_id;
bus->parent = parent;
if (name) {
bus->name = g_strdup(name);
} else if (bus->parent && bus->parent->id) {
bus_id = bus->parent->num_child_bus;
bus->name = g_strdup_printf("%s.%d", bus->parent->id, bus_id);
} else {
bc = BUS_GET_CLASS(bus);
bus_id = bc->automic_ids++;
bus->name = g_strdup_printf("%s.%d", typename, bus_id);
for (i = 0; bus->name[i]; i++) {
bus->name[i] = qemu_tolower(bus->name[i]);
}
}
if (bus->parent) {
QLIST_INSERT_HEAD(&bus->parent->child_bus, bus, sibling);
bus->parent->num_child_bus++;
object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus));
object_unref(OBJECT(bus));
} else {
assert(bus == sysbus_get_default());
}
}
BusState的初始化,主要完成对变量name的赋值,以及将当前总线插入上级总线的子集链表中。
qemu用ObjectProperty结构体来保存Object结构体对象的属性。
ObjectProperty *object_property_add_child(Object *obj, const char *name, Object *child)
{
return object_property_try_add_child(obj, name, child, &error_abort);
}
ObjectProperty *object_property_try_add_child(Object *obj, const char *name, Object *child, Error *errp)
{
g_autofree char *type = NULL;
ObjectProperty *op;
assert(!child->parent);
type = g_strdup_printf("child<%s>", object_get_typename(child));
op = object_property_try_add(obj, name, type, object_get_child_property, NULL, object_finalize_child_property, child, errp);
//创建ObjectProperty结构体对象并存储信息
if (!op) {
return NULL;
}
op->resolve = object_resolve_child_property;
object_ref(child);
child->parent = obj;
//设置子节点的父节点
return op;
}
ObjectProperty *object_property_try_add(Object *obj, const char *name, const char *type, ObjectPropertyAccessor *get, ObjectPropertyAccessor *set, ObjectPropertyRelease *release, void *opaque, Error **errp)
{
//假设当前添加的属性名为“sysbus”
ObjectProperty *prop;
size_t name_len = strlen(name);
//name_len的长度此时为6。
if (name_len >= 3 && !memcmp(name + name_len - 3, "[*]", 4)) {
//此时的判断条件是不成立的,因此并不会进入该条件中执行操作
int i;
ObjectProperty *ret;
char *name_no_array = g_strdup(name);
name_no_array[name_len - 3] = '\0';
for (i = 0; ; i++) {
char *full_name = g_strdup_printf("%s[%d]", name_no_array, i);
ret = object_property_try_add(obj, full_name, type, get, set, release, opaque, NULL);
g_free(full_name);
if (ret) {
break;
}
}
g_free(name_no_array);
return ret;
}
if (object_property_find(obj, name, NULL) != NULL) {
//从Object对象中查找与name对应的属性
error_setg(errp, "attempt to add suplicate property '%s' to object (type '%s')", name, object_get_typename(obj));
return NULL;
}
prop = g_malloc0(sizeof(*prop));
//申请ObjectProperty结构体空间
prop->name = g_strdup(name);
prop->type = g_strdup(type);
prop->get = get;
prop->set = set;
prop->release = release;
prop->opaque = opaque;
//对该结构体进行赋值操作,前两步为字符操作,后三步为指针函数操作
g_hash_table_insert(obj->properties, prop->name, prop);
//将该结构体对象插入obj->properties哈希表中
return prop;
}
ObjectProperty *object_property_find(Object *obj, const char *name, Error *errp)
{
ObjectProperty *prop;
ObjectClass *klass = object_get_class(obj);
//获取object对应的objectclass
prop = object_class_property_find(klass, name, NULL);
//获取ObjectProperty结构体对象
if (prop) {
return prop;
}
prop = g_hash_table_lookup(obj->properties, name);
//查找name所对应的ObjectProperty结构体对象
if (prop) {
return prop;
}
error_setg(errp, "Property '.%s' not found", name);
return NULL;
}
注意,上边的两次查找是不同的,第一次是从ObjectClass中查找,第二次是从Object中查找
ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name, Error **errp)
{
ObjectProperty *prop;
ObjectClass *parent_klass;
parent_klass = object_class_get_parent(klass);
if (parent_klass) {
prop = object_class_property_find(parent_klass, name, NULL);
if (prop) {
return prop;
}
}
prop = g_hash_table_lookup(klass->properties, name);
//从ObjectClass中properties变量指向的哈希表中获取name所对应的ObjectProperty结构体对象
if (!prop) {
error_setg(errp, "Property '.%s' not found", name);
}
return prop;
}
qemu-sysbus
最新推荐文章于 2025-02-14 16:57:41 发布