kvm启动虚拟机流程

启动虚拟机

virDomainCreate

#0  virDomainCreate (domain=0x697990) at libvirt.c:8133
#1  0x000000000042261f in cmdStart (ctl=0x7fffffffe230, cmd=0x696890)
    at virsh.c:3150
#2  0x000000000041cd1e in vshCommandRun (ctl=0x7fffffffe230, cmd=0x696890)
    at virsh.c:18449
#3  0x000000000042e2d6 in main (argc=3, argv=0x7fffffffe488) at virsh.c:20052


remote_driver.c
remoteDomainCreate
 call-> callWithFD-> virNetClientProgramCall-> virNetClientSendWithReply->
    virNetClientSendInternal-> virNetClientIO

qemu_driver.c
qemuDomainStart -> qemuDomainStartWithFlags -> qemuDomainObjStart
-> qemuProcessStart-> virCommandRun

剩余工作由qemu来完成,如分配内存qemu初始化时会调用pc_memory_init来分配内存。

qemu_domain.c中
qemuDomainObjBeginJobWithDriver

qemu_process.c中
qemuProcessStart

#0  qemuDomainStart (dom=0x7f34b4001090) at qemu/qemu_driver.c:4862
#1  0x00007f34defc1bef in virDomainCreate (domain=0x7f34b4001090)
    at libvirt.c:8153
#2  0x000000000043de40 in remoteDispatchDomainCreate (args=<optimized out>,
    rerr=<optimized out>, msg=<optimized out>, client=<optimized out>,
    server=<optimized out>) at remote_dispatch.h:852
#3  remoteDispatchDomainCreateHelper (server=<optimized out>,
    client=<optimized out>, msg=<optimized out>, rerr=0x7f34d9ed3c80,
    args=<optimized out>, ret=<optimized out>) at remote_dispatch.h:830
#4  0x00007f34df00ca61 in virNetServerProgramDispatchCall (
    msg=<optimized out>, client=<optimized out>, server=<optimized out>,
    prog=<optimized out>) at rpc/virnetserverprogram.c:416
#5  virNetServerProgramDispatch (prog=0x7956d0, server=0x78a4e0,
    client=0x790ec0, msg=0x7d58f0) at rpc/virnetserverprogram.c:289
#6  0x00007f34df007e51 in virNetServerHandleJob (jobOpaque=<optimized out>,
    opaque=0x78a4e0) at rpc/virnetserver.c:168
#7  0x00007f34def36f66 in virThreadPoolWorker (opaque=<optimized out>)
    at util/threadpool.c:144
#8  0x00007f34def36617 in virThreadHelper (data=<optimized out>)
    at util/threads-pthread.c:161
#9  0x00007f34dc635f05 in start_thread () from /lib64/libpthread.so.0
#10 0x00007f34dbf7153d in clone () from /lib64/libc.so.6

qemu-kvm -m 1024 -smp 2 -hda /home/sdb/kvm_windows7.img -vnc :11

#0  pc_memory_init (system_memory=0x555556401880, kernel_filename=0x0,
    kernel_cmdline=0x555555866d97 "", initrd_filename=0x0,
    below_4g_mem_size=1073741824, above_4g_mem_size=0,
    rom_memory=0x5555564325e0, ram_memory=0x7fffffffde80)
    at /home/sdc/wyf/kvm/qemu-kvm-1.0.1/hw/pc.c:977
#1  0x00005555557ec12f in pc_init1 (system_memory=0x555556401880,
    system_io=0x555556401980, ram_size=1073741824,
    boot_device=0x7fffffffe310 "cad", kernel_filename=0x0,
    kernel_cmdline=0x555555866d97 "", initrd_filename=0x0, cpu_model=0x0,
    pci_enabled=1, kvmclock_enabled=1)
    at /home/sdc/wyf/kvm/qemu-kvm-1.0.1/hw/pc_piix.c:134
#2  0x00005555557ec7ed in pc_init_pci (ram_size=1073741824,
    boot_device=0x7fffffffe310 "cad", kernel_filename=0x0,
    kernel_cmdline=0x555555866d97 "", initrd_filename=0x0, cpu_model=0x0)
    at /home/sdc/wyf/kvm/qemu-kvm-1.0.1/hw/pc_piix.c:257
#3  0x00005555556a7d49 in main (argc=9, argv=0x7fffffffe438,
    envp=0x7fffffffe488) at /home/sdc/wyf/kvm/qemu-kvm-1.0.1/vl.c:3389

qemu部分

运行状态初始化
    runstate_init();
时钟初始化
init_clocks();

(gdb) p *envp
$2 = 0x7fffffffe7e2 "LESSKEY=/etc/lesskey.bin"
qemu_cache_utils_init(envp);
链表初始化
QLIST_INIT (&vm_change_state_head);
信号初始化
os_setup_early_signal_handling();
模块调用初始化
module_call_init(MODULE_INIT_MACHINE);
pc_machine_init
fsdev_register_config
    找到默认qemu机器
machine = find_default_machine();

第一次对选项进行分词
    /* first pass of option parsing */
    optind = 1;
    while (optind < argc) {
        if (argv[optind][0] != '-') {
            /* disk image */
            optind++;
            continue;
        } else {
            const QEMUOption *popt;

            popt = lookup_opt(argc, argv, &optarg, &optind);
            switch (popt->index) {
            永远走不到,无定义参数lookup_opt中直接跳出。
            case QEMU_OPTION_nodefconfig:
                defconfig=0;
                break;
            }
        }
}
    if (defconfig) {
        int ret;
        qemu读取配置文件qemu.conf,没有该配置文件
        /usr//etc/qemu/qemu.conf
        ret = qemu_read_config_file(CONFIG_QEMU_CONFDIR "/qemu.conf");
        if (ret < 0 && ret != -ENOENT) {
            exit(1);
        }
        qemu读取配置文件target-x86_64.conf,
/usr//etc/qemu/target-x86_64.conf
        ret = qemu_read_config_file(arch_config_name);
        if (ret < 0 && ret != -ENOENT) {
            exit(1);
        }
}

cpu定义初始化
cpudef_init();

第二次对参数选项分词
……
将当前位置变到没啥特殊的地方”nowhere in particular”
loc_set_none();

    跟踪后端初始化
    if (!trace_backend_init(trace_events, trace_file)) {
        exit(1);
}

    定义数据目录
    /* If no data_dir is specified then try to find it relative to the
       executable path.  */
/usr/share/qemu
    if (!data_dir) {
        data_dir = os_find_datadir(argv[0]);
    }
    /* If all else fails use the install path specified when building. */
    if (!data_dir) {
        data_dir = CONFIG_QEMU_DATADIR;
}

对device、global选项进行默认驱动检查
    qemu_opts_foreach(qemu_find_opts("device"), default_driver_check, NULL, 0);
qemu_opts_foreach(qemu_find_opts("global"), default_driver_check, NULL, 0);

(gdb) p display_type
$11 = DT_DEFAULT

设定默认显示配置
   if (display_type == DT_NOGRAPHIC) {
        if (default_parallel)
            add_device_config(DEV_PARALLEL, "null");
        if (default_serial && default_monitor) {
            add_device_config(DEV_SERIAL, "mon:stdio");
        } else if (default_virtcon && default_monitor) {
            add_device_config(DEV_VIRTCON, "mon:stdio");
        } else {
            if (default_serial)
                add_device_config(DEV_SERIAL, "stdio");
            if (default_virtcon)
                add_device_config(DEV_VIRTCON, "stdio");
            if (default_monitor)
                monitor_parse("stdio", "readline");
        }
    } else {
        if (default_serial)
            add_device_config(DEV_SERIAL, "vc:80Cx24C");
        if (default_parallel)
            add_device_config(DEV_PARALLEL, "vc:80Cx24C");
        if (default_monitor)
            monitor_parse("vc:80Cx24C", "readline");
        if (default_virtcon)
            add_device_config(DEV_VIRTCON, "vc:80Cx24C");
    }

    if (default_vga)
        vga_interface_type = VGA_CIRRUS;
socket初始化,linux直接返回0
socket_init();
对字符设备初始化
    if (qemu_opts_foreach(qemu_find_opts("chardev"), chardev_init_func, NULL, 1) != 0)
        exit(1);
#ifdef CONFIG_VIRTFS
对文件系统设备进行初始化——没走进fsdev_init_func
    if (qemu_opts_foreach(qemu_find_opts("fsdev"), fsdev_init_func, NULL, 1) != 0) {
        exit(1);
    }
#endif

守护进程化
os_daemonize();
    配置加速器
configure_accelerator();
        for (i = 0; i < ARRAY_SIZE(accel_list); i++) {
            if (strcmp(accel_list[i].opt_name, buf) == 0) {
                *(accel_list[i].allowed) = 1;
                ret = accel_list[i].init();   kvm-all.c kvm_init
qemu初始化cpu循环
qemu_init_cpu_loop();
    qemu初始化主循环
    if (qemu_init_main_loop()) {
        fprintf(stderr, "qemu_init_main_loop failed\n");
        exit(1);
}
    os设定行缓存区
os_set_line_buffering();

    初始化时钟告警
    if (init_timer_alarm() < 0) {
        fprintf(stderr, "could not initialize alarm timer\n");
        exit(1);
}
配置icount,kvm或xen不允许配icount,直接返回。
configure_icount(icount_option);
    初始化网络客户端
    if (net_init_clients() < 0) {
        exit(1);
}

    初始化蓝牙世界
    /* init the bluetooth world */
    if (foreach_device_config(DEV_BT, bt_parse))
        exit(1);
   非xen的32位最多支持2GRAM的内存模拟。 
  if (!xen_enabled()) {
        /* On 32-bit hosts, QEMU is limited by virtual address space */
        if (ram_size > (2047 << 20) && HOST_LONG_BITS == 32) {
            fprintf(stderr, "qemu: at most 2047 MB RAM can be simulated\n");
            exit(1);
        }
}

cpu执行初始化(内存映射初始化、io内存初始化)
    cpu_exec_init_all();
    块设备初始化
    bdrv_init_with_whitelist();

blk_mig_init();

打开虚拟块设备
    /* open the virtual block devices */
    if (snapshot)
        qemu_opts_foreach(qemu_find_opts("drive"), drive_enable_snapshot, NULL, 0);
    if (qemu_opts_foreach(qemu_find_opts("drive"), drive_init_func, &machine->use_scsi, 1) != 0)
        exit(1);

    default_drive(default_cdrom, snapshot, machine->use_scsi,
                  IF_DEFAULT, 2, CDROM_OPTS);
    default_drive(default_floppy, snapshot, machine->use_scsi,
                  IF_FLOPPY, 0, FD_OPTS);
    default_drive(default_sdcard, snapshot, machine->use_scsi,
                  IF_SD, 0, SD_OPTS);

    register_savevm_live(NULL, "ram", 0, 4, NULL, ram_save_live, NULL,
                         ram_load, NULL);

    模块调用初始化(wdt_ib700_register_devices/ vmport_dev_register/ testdev_register_devices/ sga_register/ i440fx_register/ port92_register/ isa_qdev_register/ kvmclock_register_device/ kvm_tpr_opt_setup/ ivshmem_register_devices/ ioapic_register_devices/ pic_register/ pit_register/ pci_qdev_register/ debugcon_register_devices……
module_call_init(MODULE_INIT_DEVICE);


机器初始化(pc_init_pci-> pc_init1 PC硬件初始化)
    machine->init(ram_size, boot_devices,
                  kernel_filename, kernel_cmdline, initrd_filename, cpu_model);

pc的cpu初始化
    pc_cpus_init(cpu_model);
if (kvmclock_enabled) {
kvm时钟创建
        kvmclock_create();
}
pci内存初始化
    if (pci_enabled) {
        pci_memory = g_new(MemoryRegion, 1);
        memory_region_init(pci_memory, "pci", INT64_MAX);
        rom_memory = pci_memory;
    } else {
        pci_memory = NULL;
        rom_memory = system_memory;
}

分配内存、加载rom/bios
    /* allocate ram and load rom/bios */
    if (!xen_enabled()) {
        pc_memory_init(system_memory,
                       kernel_filename, kernel_cmdline, initrd_filename,
                       below_4g_mem_size, above_4g_mem_size,
                       pci_enabled ? rom_memory : system_memory, &ram_memory);
    }

gsi_state = g_malloc0(sizeof(*gsi_state));
qemu为gsi状态分配中断
gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);

为cpu中断分配内存
    if (!xen_enabled()) {
        cpu_irq = pc_allocate_cpu_irq();
        i8259 = i8259_init(cpu_irq[0]);
    } else {
        i8259 = xen_interrupt_controller_init();
}
ioapic初始化
    if (pci_enabled) {
        ioapic_init(gsi_state);
}
vga初始化
pc_vga_init(pci_enabled? pci_bus: NULL);

虚拟机基本设备初始化
    /* init basic PC hardware */
pc_basic_device_init(gsi, &rtc_state, &floppy, xen_enabled());
    for(i = 0; i < nb_nics; i++) {
        NICInfo *nd = &nd_table[i];

        if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0))
            pc_init_ne2k_isa(nd);
        else
           网卡初始化
            pci_nic_init_nofail(nd, "rtl8139", NULL);
}
    if (pci_enabled) {
        PCIDevice *dev;
        if (xen_enabled()) {
            dev = pci_piix3_xen_ide_init(pci_bus, hd, piix3_devfn + 1);
        } else {
            磁盘初始化
            dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
        }
    声卡初始化
audio_init(gsi, pci_enabled ? pci_bus : NULL);

cmos初始化
    pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
                 floppy, idebus[0], idebus[1], rtc_state);
    if (pci_enabled && acpi_enabled) {
        i2c_bus *smbus;

        if (!xen_enabled()) {
           分配中断
            cmos_s3 = qemu_allocate_irqs(pc_cmos_set_s3_resume, rtc_state, 1);
        } else {
            cmos_s3 = qemu_allocate_irqs(xen_cmos_set_s3_resume, rtc_state, 1);
        }
        piix4_pm初始化
        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
                              gsi[9], *cmos_s3, *smi_irq,
                              kvm_enabled());
        smbus_eeprom_init(smbus, 8, NULL, 0);
if (pci_enabled) {
    pci设备初始化
        pc_pci_device_init(pci_bus);
    }

    cpu同步初始化
    cpu_synchronize_all_post_init();
    设定numa模式
set_numa_modes();
初始化usb设备
    /* init USB devices */
    if (usb_enabled) {
        if (foreach_device_config(DEV_USB, usb_parse) < 0)
            exit(1);
    }
    初始化通用设备
    /* init generic devices */
    if (qemu_opts_foreach(qemu_find_opts("device"), device_init_func, NULL, 1) != 0)
        exit(1);
    网络客户端检查
net_check_clients();

 

建立信号处理
os_setup_signal_handling();
#ifdef CONFIG_VNC
vnc显示初始化
    /* init remote displays */
    if (vnc_display) {
        vnc_display_init(ds);
        if (vnc_display_open(ds, vnc_display) < 0)
            exit(1);

        if (show_vnc_port) {
            printf("VNC server running on `%s'\n", vnc_display_local_addr(ds));
        }
    }
#endif

显示配置
    /* display setup */
    dpy_resize(ds);
    dcl = ds->listeners;
    while (dcl != NULL) {
        if (dcl->dpy_refresh != NULL) {
            ds->gui_timer = qemu_new_timer_ms(rt_clock, gui_update, ds);
            qemu_mod_timer(ds->gui_timer, qemu_get_clock_ms(rt_clock));
            break;
        }
        dcl = dcl->next;
    }
文本控制台设定显示
    text_consoles_set_display(ds);
初始化虚拟机设定完成
qdev_machine_creation_done();
只读内存加载
    if (rom_load_all() != 0) {
        fprintf(stderr, "rom loading failed\n");
        exit(1);
}
寄存器重置
qemu_register_reset(qbus_reset_all_fn, sysbus_get_default());

qemu_run_machine_init_done_notifiers();
qemu系统重置
qemu_system_reset(VMRESET_SILENT);

} else if (autostart) {
虚拟机启动
        vm_start();
}
操作系统设定路标
os_setup_post();
恢复所有vcpu
resume_all_vcpus();
进入主循环
main_loop();
关闭块设备
bdrv_close_all();
暂停所有vcpu
pause_all_vcpus();
清理网络
net_cleanup();
寄存器释放
    res_free();

2013年5月24日

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
08-03 862
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值