QEMU-System mode emulation分析(2)

2. System mode下的机器(machine)管理

QEMU Sytem mode模拟的整个硬件平台,硬件平台最核心的是我们常说的板子,PC上常说是主板,其中包括了主要的元素如CPU、ROM空间、RAM空间等,而这里所说的machine就是对这个机器层次的模拟。

2.1 machine数据结构

qemu提供了通用的QEMUMachine结构用来描述machine,新增一个machine时只需在machine自己的文件中实例化该数据结构。实例化时最重要的是将自己的初始化函数注册在该数据结构中。

1) 通用接口

位置:hw/boards.h

typedef struct QEMUMachine {
    const char *name;
    const char *alias;
    const char *desc;            //description
    QEMUMachineInitFunc *init;   //machine init function,[board]_init
    int use_scsi;         //use scsi standard
    int max_cpus;
    unsigned int no_serial:1,
        no_parallel:1,
        use_virtcon:1,
        no_vga:1,
        no_floppy:1,
        no_cdrom:1,
        no_sdcard:1;
    int is_default;          //mark as default machine
    GlobalProperty *compat_props;
    struct QEMUMachine *next;  //指向machine列表中下一个machine
} QEMUMachine;

2) 接口实例化

例如arm的一板子做如下实例化:

static QEMUMachine integratorcp_machine = {
    .name = "integratorcp",
    .desc = "ARM Integrator/CP (ARM926EJ-S)",
    .init = integratorcp_init,
    .is_default = 1,
};

2.2 machine相关接口

1)需要实现的接口


QEMUMachine [board]_machine


描述machine的数据结构


宏machine_init([board]_machine_init)


main之前注册[board]_machine_init函数


[board]_machine_init


machine注册函数


[board]_init


machine初始化函数

2)调用的通用接口


int qemu_register_machine(QEMUMachine *m)


将当前machine注册到machine列表中


cpu_init (const char *cpu_model)


cpu初始化


am_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size)


申请ram空间


staticinline void cpu_register_physical_memory(target_phys_addr_tstart_addr, ram_addr_tsize,  ram_addr_t phys_offset


对申请的内存空间分页


DeviceState *qdev_create(BusState *bus, const char *name)


创建设备


void qdev_init_nofail(DeviceState *dev)


设备初始化通过hw_error()结束程序


int qdev_init(DeviceState *dev)


设备初始化,被qdev_init_nofail调用


void qdev_prop_set(DeviceState *dev, const char *name, void *src, enum PropertyType type)


设备属性设置


void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr)


io地址映射


DeviceState *sysbus_create_varargs(const char *name, target_phys_addr_t addr, ...)


在总线上挂接设备,并完成设备的创建,初始化,地址映射以及中断初始化等操作


static inline DeviceState *sysbus_create_simple(const char *name,  target_phys_addr_taddr,

qemu_irq irq)


sysbus_create_varargs的快捷方式,当设备只有一个对应的中断号调用此函数


qemu_irq qdev_get_gpio_in(DeviceState *dev, int n)

2.3 machine注册

由上图可知,在qemu中,与machine相关的有两个链表,分别为init_type_list[MODULE_INIT_MACHINE]和machine链表。

1)  由init_type_list[MODULE_INIT_MACHINE]指示的链表记录了machine的注册函数,其数据结构如下:

文件:module.c

static ModuleTypeList init_type_list[MODULE_INIT_MAX];

typedef struct ModuleEntry
{
    module_init_type type;    //链表类型
    void (*init)(void);   //machine的注册函数
    QTAILQ_ENTRY(ModuleEntry) node;
} ModuleEntry;

module.h
typedef enum {
    MODULE_INIT_BLOCK,
    MODULE_INIT_DEVICE,
    MODULE_INIT_MACHINE,
    MODULE_INIT_MAX
} module_init_type;

链表形成后如图所示:

2) machine链表

machine链表结构如上图所示,节点数据结构为QEMUMachine,其中的init成员记录了machine的初始化函数,next成员指向下一个machine。

下面分别介绍两个链表的创建过程。

2.3.1 init_type_list[MODULE_INIT_MACHINE]生成

machine中需要实现宏接口machine_init(func),func为machine的注册函数。machine_init(func)的处理流程如下:

编译器对所有的machine_init进行处理,便生成了由init_type_list[MODULE_INIT_MACHINE]指示的链表。

2.3.2 machine链表生成

main函数通过module_call_init(MODULE_INIT_MACHINE)来调用init_type_list[MODULE_INIT_MACHINE]中每个节点的初始化函数[board]_machine_init来注册每个节点对应的machine的数据结构到machine队列中。其过程如下图所示。

通过上图所示过程,qemu中便生成了machine链表,记录了每个machine的基本信息。

拥有了每个machine的基本信息,在运行时就可根据-machine参数找到指定的machine进行初始化。不存在-machine参数时,将默认machine作为要运行的开发板。之后再调用选定machine的初始化函数。machine的初始化过程在下节中介绍。

2.4 machine初始化

此处以arm的integrator/CP开发板为例介绍machine的初始化过程。

不论是总线还是中断控制器都可看做设备,设备创建过程以及设备如何连接总线将在设备机制中介绍。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-23 11:52:01

QEMU-System mode emulation分析(2)的相关文章

Qemu: User mode emulation and Full system emulation

转载: https://wiki.edubuntu.org/UbuntuDevelopment/Ports QEMU QEMU is a processor emulator and supports emulation of ARM, PowerPC, SPARC, x86, x86-64 and more. QEMU has two operating modes: User mode emulation: QEMU can launch Linux processes compiled f

libvirtError: no connection driver available for qemu:///system 解决办法

今天部署了一套K版的OpenStack环境后,启动nova-compute后,日志里狂报如下错误(因为其内部有定时任务需要去连libvirtd进程): 2015-08-14 10:01:00.061 28580 TRACE nova.virt.libvirt.host File "/usr/lib64/python2.7/site-packages/libvirt.py", line 105, in openAuth 2015-08-14 10:01:00.061 28580 TRAC

System.arraycopy()的分析

System.arraycopy()的分析 一.深度复制和浅度复制的区别 原文地址:https://www.cnblogs.com/lsswudi/p/11331133.html

android Qemu GPS 模块简明分析

Android 的 gps module 是  gps.default.so 在system/lib/hw/ 目录上, 一般提供gps功能的手机应该实现这个module和真实gps硬件交互 Qemu中gps就是要构造一个gps.default.so,  但这个so并不和真的硬件打交道,只是个模拟接口,其代码在sdk/emulator/gps/gps_qemu.c中 Qemu 容器外部实现了一个gps设备,但这个设备和 Android 交互只能通过管道,所以gps_qemu.c的功能就是同管道打交

QEMU-System mode emulation分析(1)

1. 执行主流程简单分析 在该模式下,qemu除了模拟cpu执行,还要管理.模拟外围设备,因此系统模式模拟比用户模式模拟多出很多需要我们关心的地方,比如,机器管理,设备管理,总线模拟,中断模拟,mmu模拟,以及它们是如何协同工作的等等.本节主要简单分析下qemu系统模式的执行主流程.如下图所示: 上图主要描述整个模拟器执行过程的大体框架,由图可知,main_loop是模拟器运行时的主循环,cpu_exec_all()函数是用来执行cpu指令,main_loop_wait是用来执行外围设备模拟代码

QEMU 中的QOM分析

QOM (QEMU Object Model) 类对象的意义: 1:每个类型在系统中都只有且只有一个类对象 2:当系统中的某个类型的实例对象都被销毁了,那么系统就会销毁该类对象了 3:类对象的作用:负责虚函数表的存储,如果没有类对象,每个实例对象都要存储一份一模一样的虚函数表,这完全是对存储空间的浪费

LUCI system reboot 范例分析

系统重启: \lua\luci\controller\admin\system.lua entry({"admin", "system", "reboot"}, call("action_reboot"), _("Reboot"), 90) 直接调用action_reboot接口: function action_reboot() local reboot = luci.http.formvalue(&qu

几篇QEMU/KVM代码分析文章

QEMU/KVM结合起来分析的几篇文章,代码跟最新的版本有些差异,但大体逻辑一样,写得通俗易懂.我把链接放这里主要是为自己需要查看时调转过去方便,感谢作者的付出! QEMU Source Code Study - 1 QEMU Source Code Study (2) - KVM_init QEMU Source Code Study (3) - KVM_CREATE_VCPU QEMU Source Code Study - KVM_RUN

Qemu 有用的链接

Qemu下载和编译 Download https://en.wikibooks.org/wiki/QEMU/Linux https://en.wikibooks.org/wiki/QEMU/Installing_QEMU QEMU Internals Manual http://qemu.weilnetz.de/qemu-tech.html#Introduction QEMU/Debugging with QEMU QEMU Emulator User Documentation KQemu Q