qemu-sysbus

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值