没有合适的资源?快使用搜索试试~ 我知道了~
Qemu&Kvm虚拟计算机系统启动流程图
5星 · 超过95%的资源 需积分: 50 73 下载量 3 浏览量
2013-10-27
15:13:42
上传
评论 4
收藏 641KB PDF 举报
温馨提示
试读
1页
详细地跟踪分析了Qemu&Kvm虚拟计算机系统构建实例化与启动流程
资源推荐
资源详情
资源评论
atexit(qemu_run_exit_notifiers)(注册Qemu-Kvm退出的通知回调函数链)
error_set_progname(设置全局程序名变量)
init_clocks创建三个定时器并根据参数进行初始设置,用于提供激励
qemu_cache_utils_init好像没有什么特别需要关注的
QLIST_INIT (&vm_change_state_head)(初始化全局虚拟机状态改变链表头
vm_change_state_head)
os_setup_early_signal_handling设置管道错信号缺省处理方式为忽略不退出
module_call_init注册生成编译配置时的机器类型(将相关的机器类型注册到一
个全局链表当中,后面藉此进行查找识别缺省虚拟机类型用于实例化)
find_default_machine找到上一步注册的缺省的虚拟机类型
全局变量缺省值设置并进行配置参数缺省值预处理,生成一组虚拟设备参数配
置变量,如qemu_drive_opts等(qemu-options.def其由qemu-options.hx产生)
cpudef_init处理器描述定义链表初始化(注册cpu描述定义信息)
loc_set_none位置设置(暂时看来不重要)
计算设置一些全局变量(数据目录,最多cpu数,根据机器配置确定是否使用一
些缺省设备)
socket_init Linux环境下为空
chardev_init_func(根据字符设备配置选项,初始化字符设备实例化链表)
fsdev_init_func(这是什么功能)
os_daemonize(缺省为0,暂不分析)
qemu_create_pidfile(根据配置选项确认是否创建进程pid文件,貌似是一种锁
机制)
kvm_init(建立与/dev/kvm的连接,初始化设置全局变量,分配虚拟机状态管
理数据结构)
qemu_init_main_loop(创建事件文件描述符句柄,用于事件通知,io完成后将通知qemu_event_read进行读
取)分具有独立I/O线程和非独立I/O线程,独立I/O线程需要初始化一下全局条件量以及锁用于同步
os_set_line_buffering(暂时不看)
init_timer_alarm(创建初始化开启所有相关告警定时器,使它们开始工作,这些定时器事件出现
后会触发调用qemu_notify_event,其产生事件通知qemu_kvm_notify_work)
configure_icount
net_init_clients(根据网络设施配置选项,根据配置链表进行初始化)
bt_parse蓝牙分析 init the bluetooth world
cpu_exec_init_all(是否可以去除)init the dynamic translator
bdrv_init_with_whitelist(注册所有块设备的驱动函数处理结构到链表
bdrv_drivers当中)
blk_mig_init(注册迁移初始化处理例程到savevm_handlers链表中)
drive_add增加CDROM和FLOPPY、SDCARD(qemu_drive_opts)
drive_enable_snapshot(开启快照特性支持)
drive_init_func(貌似创建块设备)
register_savevm_live(注册虚拟机休眠处理例程到savevm_handlers链表中)
numa(暂时不关注)
mon_init_func
serial_parse
parallel_parse
virtcon_parse
debugcon_parse
module_call_init(注册所有设备,以便后面的实例化作准备)
device_help_func
select_watchdog(选择看门狗设施)
qdev_prop_register_global_list(注册全局属性变量)
qemu_add_globals
machine->init(进行实例化创建,包括虚拟VCPU创建,内存系统创建,设备
创建)
cpu_synchronize_all_post_init(初始化VCPU上下文现场信息)
os_setup_signal_handling(设置SIGINT,SIGHUP,SIGTERM以及SIGCHLD信号处
理函数)
set_numa_modes
usb_parse(可热拔插设备)init USB devices
device_init_func设备初始化(根据之前注册的信息查找驱动,总线然后藉此进
行实例化创建)init generic devices
net_check_clients(比较复杂)
get_displaystate
计算并根据情况选择display_init如 sdl_display_init
dpy_resize
qemu_mod_timer(创建定时器)
text_consoles_set_display
gdbserver_start(调试相关暂时不分析)
qdev_machine_creation_done(只能增加可热拔插设备)
rom_load_all
qemu_system_reset(调用各虚拟设备的初始化例程,需要看哪些地方会注册复位回调函数,是
不是每个虚拟化设备都有这样的机制,向Qemu Monitor发reset,所有vcpu状态同步复位)
如果是loadvm则执行load_vmstate
qemu_start_incoming_migration
(暂时不走这个流程)
vm_start(主要流程)
os_setup_post(daemonize待进一步分析,暂时不看)
改变根目录及进程用户id
main_loop
quit_timers(设置alarm_timer为空并停止之前的alarm_timer,因为定时器在系
统中存在,故需要停止以免影响系统,并没有删除)
net_cleanup(vlans,non_vlan_clients)
第二遍命令行配置参数选项处理,最终完成定制化处理
init the memory内存大小初始化设置128MB
typedef struct KVMSlot {
target_phys_addr_t start_addr;
ram_addr_t memory_size;
ram_addr_t phys_offset;
int slot;
int flags;
} KVMSlot;
struct kvm_context {
void *opaque;
/// is dirty pages logging enabled for all regions or not
int dirty_pages_log_all;
/// do not create in-kernel irqchip if set
int no_irqchip_creation;
/// in-kernel irqchip status
int irqchip_in_kernel;
/// ioctl to use to inject interrupts
int irqchip_inject_ioctl;
/// do not create in-kernel pit if set
int no_pit_creation;
#ifdef KVM_CAP_IRQ_ROUTING
struct kvm_irq_routing *irq_routes;
int nr_allocated_irq_routes;
#endif
void *used_gsi_bitmap;
int max_gsi;
};
typedef struct kvm_context *kvm_context_t;
typedef struct CPUX86State {
/* standard registers */
target_ulong regs[CPU_NB_REGS];
target_ulong eip;
target_ulong eflags; /* eflags register. During CPU emulation, CC
flags and DF are set to zero because they are
stored elsewhere */
/* emulator internal eflags handling */
target_ulong cc_src;
target_ulong cc_dst;
uint32_t cc_op;
int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */
uint32_t hflags; /* TB flags, see HF_xxx constants. These flags
are known at translation time. */
uint32_t hflags2; /* various other flags, see HF2_xxx constants. */
/* segments */
SegmentCache segs[6]; /* selector values */
SegmentCache ldt;
SegmentCache tr;
SegmentCache gdt; /* only base and limit are used */
SegmentCache idt; /* only base and limit are used */
target_ulong cr[5]; /* NOTE: cr1 is unused */
int32_t a20_mask;
/* FPU state */
unsigned int fpstt; /* top of stack index */
uint16_t fpus;
uint16_t fpuc;
uint8_t fptags[8]; /* 0 = valid, 1 = empty */
FPReg fpregs[8];
/* emulator internal variables */
float_status fp_status;
CPU86_LDouble ft0;
float_status mmx_status; /* for 3DNow! float ops */
float_status sse_status;
uint32_t mxcsr;
XMMReg xmm_regs[CPU_NB_REGS];
XMMReg xmm_t0;
MMXReg mmx_t0;
target_ulong cc_tmp; /* temporary for rcr/rcl */
/* sysenter registers */
uint32_t sysenter_cs;
target_ulong sysenter_esp;
target_ulong sysenter_eip;
uint64_t efer;
uint64_t star;
uint64_t vm_hsave;
uint64_t vm_vmcb;
uint64_t tsc_offset;
uint64_t intercept;
uint16_t intercept_cr_read;
uint16_t intercept_cr_write;
uint16_t intercept_dr_read;
uint16_t intercept_dr_write;
uint32_t intercept_exceptions;
uint8_t v_tpr;
#ifdef TARGET_X86_64
target_ulong lstar;
target_ulong cstar;
target_ulong fmask;
target_ulong kernelgsbase;
#endif
uint64_t system_time_msr;
uint64_t wall_clock_msr;
uint64_t tsc;
uint64_t pat;
/* exception/interrupt handling */
int error_code;
int exception_is_int;
target_ulong exception_next_eip;
target_ulong dr[8]; /* debug registers */
union {
CPUBreakpoint *cpu_breakpoint[4];
CPUWatchpoint *cpu_watchpoint[4];
}; /* break/watchpoints for dr[0..3] */
uint32_t smbase;
int old_exception; /* exception in flight */
CPU_COMMON
/* processor features (e.g. for CPUID insn) */
uint32_t cpuid_level;
uint32_t cpuid_vendor1;
uint32_t cpuid_vendor2;
uint32_t cpuid_vendor3;
uint32_t cpuid_version;
uint32_t cpuid_features;
uint32_t cpuid_ext_features;
uint32_t cpuid_xlevel;
uint32_t cpuid_model[12];
uint32_t cpuid_ext2_features;
uint32_t cpuid_ext3_features;
uint32_t cpuid_apic_id;
int cpuid_vendor_override;
/* MTRRs */
uint64_t mtrr_fixed[11];
uint64_t mtrr_deftype;
MTRRVar mtrr_var[8];
/* For KVM */
uint32_t mp_state;
int32_t exception_injected;
int32_t interrupt_injected;
uint8_t soft_interrupt;
uint8_t nmi_injected;
uint8_t nmi_pending;
uint8_t has_error_code;
uint32_t sipi_vector;
uint32_t cpuid_kvm_features;
/* in order to simplify APIC support, we leave this pointer to the
user */
struct DeviceState *apic_state;
uint64 mcg_cap;
uint64 mcg_status;
uint64 mcg_ctl;
uint64 mce_banks[MCE_BANKS_DEF*4];
uint64_t tsc_aux;
/* vmstate */
uint16_t fpus_vmstate;
uint16_t fptag_vmstate;
uint16_t fpregs_format_vmstate;
int kvm_vcpu_update_vapic;
uint64_t xstate_bv;
XMMReg ymmh_regs[CPU_NB_REGS];
uint64_t xcr0;
} CPUX86State;
kvm_disable_irqchip_creation(kvm_context);
kvm_disable_pit_creation(kvm_context);
kvm_create(kvm_context, 0, NULL)
kvm_arch_qemu_create_context();
kvm_arch_init_irq_routing()
kvm_init_ap();
qemu_kvm_has_gsi_routing()
qemu_kvm_has_pit_state2()
kvm_create_vm(在KVM中创建一个Qemu&Kvm虚
拟机实例)
用户态使用的内存槽布局描述数据结构初始化(初始
化索引)
kvm_create_default_phys_mem
kvm_create_irqchip
kvm_arch_create
kvm_init_tss
kvm_init_identity_map_page
kvm_create_pit
kvm_init_coalesced_mmio
main
当进行编译选择时会在对应的代码节植入机器类型的初始化入口地
址,这里实际上查找已经注册的机器类型并调用其入口进行初始化
选择默认的机器类型作为实例化的模板
data_dir,max_cpus,qemu_device_opts,qemu_global_opts,default_seri
al,default_parallel,default_virtcon,default_vga,default_floppy,default
_cdrom,default_sdcard,display_type,default_monitor,vga_interface_t
ype……
main_loop
cpu_enable_ticks
vm_state_notify
resume_all_vcpus(对于
非独立io线程为空,否则
不空)
monitor_protocol_event
tcp_start_incoming_migration
exec_start_incoming_migration
unix_start_incoming_migration
fd_start_incoming_migration
static void sigchld_handler(int signal)
{
waitpid(-1, NULL, WNOHANG);
}
void os_setup_signal_handling(void)
{
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = termsig_handler;
sigaction(SIGINT, &act, NULL);
sigaction(SIGHUP, &act, NULL);
sigaction(SIGTERM, &act, NULL);
act.sa_handler = sigchld_handler;
act.sa_flags = SA_NOCLDSTOP;
sigaction(SIGCHLD, &act, NULL);
}
kvm_main_loop
cpu_disable_ticks(关闭
vm_start中的定时器tick)
init_get_clock
qemu_new_clock(QEMU_CLOCK_REALTIME)
qemu_new_clock(QEMU_CLOCK_VIRTUAL);
host_clock = qemu_new_clock(QEMU_CLOCK_HOST);
rtc_clock = host_clock;
static int chardev_init_func(QemuOpts *opts, void *opaque)
{
CharDriverState *chr;
chr = qemu_chr_open_opts(opts, NULL);
if (!chr)
return -1;
return 0;
}
static int fsdev_init_func(QemuOpts *opts, void *opaque)
{
int ret;
ret = qemu_fsdev_add(opts);
return ret;
}
load the kernel header
kernel protocol version
highest address for loading the initrd
handle vga= parameter
loader type
heap
load initrd
load kernel and setup
register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
rtc_init
kvm_pit_init
pit_init
pcspk_init
serial_isa_init
parallel_init
vmmouse_init
DMA_init
fdctrl_init_isa
pthread_create(..., ap_main_loop,…)
kvm_init_vcpu
等待ap_main_loop创建完成
kvm_create_vcpu
/* signal VCPU creation */使父进程可以继
续下去
/* and wait for machine initialization */
qemu_cond_wait(&qemu_system_cond);
/* re-initialize cpu_single_env after re-
acquiring qemu_mutex */
kvm_main_loop_cpu(CPU执行循环)
kvm_cpu_exec
kvm_vm_ioctl(kvm_state, KVM_CREATE_VCPU, id)
env->kvm_fd = r;
env->kvm_state = kvm_state;
mmap_size = kvm_ioctl(kvm_state, KVM_GET_VCPU_MMAP_SIZE, 0);
env->kvm_run =mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, env->kvm_fd, 0);
kvm_arch_init_vcpu
kvm_arch_vcpu_create
kvm_arch_vcpu_setup
create_vcpu_fd
allocate_vpid
kvm_vcpu_init
alloc_vmcs
vmcs_init
vmx_vcpu_load
vmx_vcpu_setup
……
vcpu_load
kvm_arch_vcpu_reset
kvm_mmu_setup
……
_kvm_arch_init_vcpu kvm_arch_reset_vcpu
kvm_reset_mpstate
……
kvm_run
pre_kvm_run
ioctl(fd, KVM_RUN, 0)
post_kvm_run
VM Exit 退出处理
kvm_vcpu_ioctl
kvm_arch_vcpu_ioctl_run
__vcpu_run
vapic_enter
vcpu_enter_guest
vapic_exit
kvm_check_async_pf_completion
各类请求处理
kvm_mmu_reload
vmx_vcpu_run
kvm_guest_enter
vmx_handle_exit
如果返回值为0则
需要到用户态执行
Guest OS
vmx_vcpu_load
env->exception_injected = -1;
env->interrupt_injected = -1;
env->nmi_injected = 0;
env->nmi_pending = 0;
env->xcr0 = 1;
if (kvm_irqchip_in_kernel()) {
env->mp_state = cpu_is_bsp(env) ? KVM_MP_STATE_RUNNABLE :
KVM_MP_STATE_UNINITIALIZED;
} else {
env->mp_state = KVM_MP_STATE_RUNNABLE;
}
mutex_init(&vcpu->mutex);
vcpu->cpu = -1;//还没分配调度物理CPU
vcpu->kvm = kvm;
vcpu->vcpu_id = id;
init_waitqueue_head(&vcpu->wq);
kvm_async_pf_vcpu_init(vcpu);
vcpu->run = page_address(page)
kvm_arch_vcpu_init
/* I/O */
/* Control */
……
vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS); /* 22.2.4 */
vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
vmcs_write16(HOST_ES_SELECTOR, __KERNEL_DS); /* 22.2.4 */
vmcs_write16(HOST_FS_SELECTOR, 0); /* 22.2.4 */
vmcs_write16(HOST_GS_SELECTOR, 0); /* 22.2.4 */
vmcs_write16(HOST_SS_SELECTOR, __KERNEL_DS); /* 22.2.4 */
……
vmcs_writel(CR4_GUEST_HOST_MASK, ~vmx-
>vcpu.arch.cr4_guest_owned_bits);
kvm_write_tsc(&vmx->vcpu, 0);
vcpu->arch.nmi_pending = false;
vcpu->arch.nmi_injected = false;
vcpu->arch.switch_db_regs = 0;
memset(vcpu->arch.db, 0, sizeof(vcpu->arch.db));
vcpu->arch.dr6 = DR6_FIXED_1;
vcpu->arch.dr7 = DR7_FIXED_1;
kvm_make_request(KVM_REQ_EVENT, vcpu);
vcpu->arch.apf.msr_val = 0;
kvm_clear_async_pf_completion_queue(vcpu);
kvm_async_pf_hash_reset(vcpu);
vcpu->arch.apf.halted = false;
vmx_vcpu_reset
init_kvm_nested_mmu
init_kvm_softmmu init_kvm_tdp_mmu
init_kvm_mmu
创建vcpu线程
Qemu-Kvm 主线程
在vcpu从线程当中
VCPU线程处于待命状态执行循环
main
main_loop
kvm_main_loop
pthread_cond_broadcast(
&qemu_system_cond)
初始化设置仿真操作设施
初始化设置内存管理设施
设置初始化多处理器相关设施
分配设置pio共享内存区域
创建虚拟MMU
创建lapic
……
pc_init_pciàpc_init1
pc_cpus_init(根据系统配置的个数依次构建实例化虚拟
VCPU)
vmport_init(虚拟机端口注册初始化)
pc_memory_init(内存子系统实例化)
pc_allocate_cpu_irq
kvm_i8259_init|i8259_init
pc_register_ferr_irq
pc_allocate_cpu_irq
pc_vga_init
pc_basic_device_init
pc_init_ne2k_isa|pci_nic_init_nofail
pci_piix3_ide_init|isa_ide_init
pc_audio_init(调用所有注册过的音频设备初始化例程)
pc_cmos_init
usb_uhci_piix3_init(创建并初始化USB的uhci)
piix4_pm_init(创建并初始化PM电源管理设备)
i440fx_init_memory_mappings
pc_pci_device_init
分配pc.ram并进行注册联接(与内核中的槽进行关联)
加载BIOS文件并进行注册pc.bios的ROM空间
注册pc.rom空间
bochs_bios_init
如果引导Linux则在此通过load_linux
加载Linux内核
rom_add_option
io_thread = pthread_self()
Qemu&Kvm主线程转化成I/O线程
qemu_system_ready = 1(qemu系统准备就绪,通知虚
拟CPU线程往下执行)
设置信号量文件描述符sigfd
pthread_cond_broadcast(&qemu_system_cond);
io_thread_sigfd = sigfd;
cpu_single_env = NULL;
main_loop_wait
qemu_shutdown_requested
qemu_powerdown_requested
qemu_reset_requested
kvm_debug_cpu_requested
pause_all_threads
pthread_mutex_unlock(&qemu_mutex)
monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
if (qemu_no_shutdown()) {
vm_stop(0);
} else
break;
monitor_protocol_event(QEVENT_POWERDOWN, NULL);
qemu_irq_raise(qemu_system_powerdown);
qemu_kvm_system_reset();
open("/dev/kvm", O_RDWR)(建立与KVM Virtualization Extension的
连接,从而可以获取硬件虚拟化的扩展支持功能)
KVM API版本一致性检查,确保Qemu-Kvm与KVM的接口一致
kvm_abi = r;
kvm_page_size = getpagesize();
kvm_state = qemu_mallocz(sizeof(*kvm_state));
kvm_context = &kvm_state->kvm_context;
kvm_state->fd = fd;
kvm_state->vmfd = -1;
kvm_context->opaque = cpu_single_env;
kvm_context->dirty_pages_log_all = 0;
kvm_context->no_irqchip_creation = 0;
kvm_context->no_pit_creation = 0;
……
kvm_cpu_register_phys_memory_client(注册内存布局映射处理用的回
调函数)
pthread_mutex_lock(&qemu_mutex)
kvm_create_context(创建Qemu-Kvm用户态虚拟机上下文环境)
struct KVMState {
KVMSlot slots[32];
int fd;
int vmfd;
int coalesced_mmio;
#ifdef KVM_CAP_COALESCED_MMIO
struct kvm_coalesced_mmio_ring *coalesced_mmio_ring;
#endif
int broken_set_mem_region;
int migration_log;
int vcpu_events;
int robust_singlestep;
int debugregs;
#ifdef KVM_CAP_SET_GUEST_DEBUG
QTAILQ_HEAD(, kvm_sw_breakpoint) kvm_sw_breakpoints;
#endif
int irqchip_in_kernel;
int pit_in_kernel;
struct kvm_context kvm_context;
};
extern struct KVMState *kvm_state;
static CPUPhysMemoryClient kvm_cpu_phys_memory_client = {
.set_memory = kvm_client_set_memory,
.sync_dirty_bitmap = kvm_client_sync_dirty_bitmap,
.migration_log = kvm_client_migration_log,
};
void kvm_cpu_register_phys_memory_client(void)
{
cpu_register_phys_memory_client(&kvm_cpu_phys_memory_client);
}
static void kvm_client_set_memory(struct CPUPhysMemoryClient
*client,
target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset)
{
kvm_set_phys_mem(start_addr, size, phys_offset);
}
kvm->irq_routes = qemu_mallocz(sizeof(*kvm-
>irq_routes));
kvm->nr_allocated_irq_routes = 0;
fd = kvm_ioctl(kvm_state, KVM_CREATE_VM, 0);
kvm_state->vmfd = fd;
lm_capable_kernel是否是支持长模式的内核
kvm_get_msr_list获取msr寄存器列表
kvm_check_extension(kvm_state,
KVM_CAP_ADJUST_CLOCK)
kvm_set_boot_cpu_id
kvm_set_shadow_pages设置影子页表使用的缓存页
数
qemu_add_vm_change_state_handler
kvm_add_irq_route(kvm_context, i, KVM_IRQCHIP_IOAPIC,
2);/kvm_add_irq_route(kvm_context, i, KVM_IRQCHIP_IOAPIC, i);
kvm_commit_irq_routes(kvm_context);
signal(SIG_IPI, sig_ipi_handler);
void kvm_create_irqchip(kvm_context_t kvm)
{
int r;
kvm->irqchip_in_kernel = 0;
if (!kvm->no_irqchip_creation) {
r = kvm_ioctl(kvm_state, KVM_CHECK_EXTENSION, KVM_CAP_IRQCHIP);
if (r > 0) { /* kernel irqchip supported */
r = kvm_vm_ioctl(kvm_state, KVM_CREATE_IRQCHIP);
if (r >= 0) {
kvm->irqchip_inject_ioctl = KVM_IRQ_LINE;
r = kvm_ioctl(kvm_state, KVM_CHECK_EXTENSION,
KVM_CAP_IRQ_INJECT_STATUS);
if (r > 0)
kvm->irqchip_inject_ioctl = KVM_IRQ_LINE_STATUS;
kvm->irqchip_in_kernel = 1;
} else
fprintf(stderr, "Create kernel PIC irqchip failed");
}
}
kvm_state->irqchip_in_kernel = kvm->irqchip_in_kernel;
}
kvm_ioctl(kvm_state, KVM_CHECK_EXTENSION,
KVM_CAP_USER_MEMORY);
kvm_create_vm(在KVM中创建一个虚
拟机实例)
kvm_coalesced_mmio_init(初始化
KVM虚拟机的MMIO设施)
kvm_anon_inode_getfd(为Qemu-Kvm
创建操作KVM虚拟机的文件描述符)
kvm_arch_alloc_vm(分配KVM虚拟机实例管理结
构)
kvm_arch_init_vm(初始化KVM虚拟机实例管理结
构)
hardware_enable_all(最重要的是
kvm_cpu_vmxon)
kvm->coalesced_mmio_ring = page_address(page);
kvm_iodevice_init(&dev->dev,
&coalesced_mmio_ops);
kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS,
&dev->dev);
INIT_HLIST_HEAD(&kvm->mask_notifier_list);
INIT_HLIST_HEAD(&kvm->irq_ack_notifier_list);
kvm_init_mmu_notifier
list_add(&kvm->vm_list, &vm_list);(加入KVM虚拟
机链表)
kvm->mm = current->mm;
mmget(&kvm->mm->mm_count);
spin_lock_init(&kvm->mmu_lock);
raw_spin_lock_init(&kvm->requests_lock);
kvm_eventfd_init
mutex_init(&kvm->lock);
mutex_init(&kvm->irq_lock);
mutex_init(&kvm->slots_lock);
atomic_set(&kvm->users_count, 1);
虚拟设备实例化
内存系统实例化
虚拟CPU实例化
利用qemu_eventfd创建事件文件描述符并初始化
将其与io线程文件描述符io_thread_fd关联,其它地方可
以通过写这个文件描述符来实现事件通知
os_host_main_loop_wait
poll any events/XXX: separate device handlers from
system ones
依次调用io处理例程io_handles
qemu_run_all_timers(处理定时器函数)
初始化rfds,wfds,xfds并将io_handles中需要poll的加
入其中
qemu_mutex_unlock_iothread(解锁io线程)
select
qemu_mutex_lock_iothread(锁住io线程)
qemu_bh_poll
process_irqchip_events
是否在运行
kvm_main_loop_wait
kvm_cpu_exec
post_kvm_run_save
fpu功能初始化
信号量相关设置处理
多处理器相关处理设置
中断处理
pio与mmio仿真模拟
多处理器初始化
kvm_lapic_reset/kvm_arch_vcpu_
reset
kvm_inject_pending_timer_irqs
dm_request_for_irq_injection
signal_pending
kvm_resched
KVM_EXIT_UNKN
OWN
KVM_EXIT_FAIL_
ENTRY
KVM_EXIT_EXCE
PTION
KVM_EXIT_IO
KVM_EXIT_DEBU
G
KVM_EXIT_MMI
O
KVM_EXIT_HLT
KVM_EXIT_IRQ_
WINDOW_OPEN
KVM_EXIT_SHUT
DOWN
KVM_EXIT_INTE
RNAL_ERROR
DEFAULTS
handle_unhandled
handle_failed_vment
ry
kvm_show_regs
kvm_show_code
kvm_handle_io handle_debug handle_mmio kvm_arch_halt handle_shutdown handle_shutdown
kvm_handle_internal
_error
kvm_arch_run
kvm_show_regs
不需要退出
0
非0
kvm_guest_exit
返回0
是否是可识别的
EXIT_REASON_E
XCEPTION_NMI
EXIT_REASON_E
XTERNAL_INTER
RUPT
EXIT_REASON_T
RIPLE_FAULT
EXIT_REASON_N
MI_WINDOW
EXIT_REASON_IO
_INSTRUCTION
EXIT_REASON_C
R_ACCESS
EXIT_REASON_D
R_ACCESS
EXIT_REASON_C
PUID
EXIT_REASON_M
SR_READ
EXIT_REASON_M
SR_WRITE
EXIT_REASON_
PENDING_INTE
RRUPT
handle_exception
handle_external_inte
rrupt
handle_triple_fault handle_nmi_window handle_io handle_cr handle_dr handle_cpuid handle_rdmsr handle_wrmsr
handle_interrupt_wi
ndow
EXIT_REASON_H
LT
EXIT_REASON_IN
VD
EXIT_REASON_IN
VLPG
EXIT_REASON_V
MCALL
EXIT_REASON_V
MCLEAR
EXIT_REASON_V
MPTRLD
EXIT_REASON_V
MPTRST
EXIT_REASON_V
MREAD
EXIT_REASON_V
MRESUME
EXIT_REASON_V
MWRITE
EXIT_REASON_
VMOFF
handle_halt handle_invd handle_invlpg handle_vmcall handle_vmx_insn handle_vmx_insn handle_vmx_insn handle_vmx_insn handle_vmx_insn handle_vmx_insn handle_vmx_insn
EXIT_REASON_V
MON
EXIT_REASON_TP
R_BELOW_THRES
HOLD
EXIT_REASON_A
PIC_ACCESS
EXIT_REASON_W
BINVD
EXIT_REASON_XS
ETBV
EXIT_REASON_T
ASK_SWITCH
EXIT_REASON_M
CE_DURING_VME
NTRY
EXIT_REASON_EP
T_VIOLATION
EXIT_REASON_E
PT_MISCONFIG
EXIT_REASON_P
AUSE_INSTRUCTI
ON
EXIT_REASON_
MWAIT_INSTR
UCTION
handle_vmx_insn
handle_tpr_below_th
reshold
handle_apic_access handle_wbinvd handle_xsetbv handle_task_switch
handle_machine_che
ck
handle_ept_violation
handle_ept_misconfi
g
handle_pause handle_invalid_op
EXIT_REASON_
MONITOR_INS
TRUCTION
handle_invalid_op
/* memory size */
/* set the number of CPU */
/* set boot devices, and disable floppy signature check if
requested */
/* floppy type */
/* hard drives */
qemu_register_reset(pc_cmos_init_late, &arg);
清理撤销vlans,
non_vlan_clients中的每个元素
timers_state.cpu_ticks_offset =
cpu_get_ticks();
timers_state.cpu_clock_offset =
cpu_get_clock();
timers_state.cpu_ticks_enabled
= 0;
timers_state.cpu_ticks_en
abled
vm_running
vm_running=1
kvm_add_irq_route(kvm_context, i,
KVM_IRQCHIP_PIC_MASTER, i);
sigaction(SIGBUS, &action,
NULL);àsigbus_handler
……
kvm_add_irq_route(kvm_context, i,
KVM_IRQCHIP_PIC_SLAVE, i - 8);
分配kvm->memslots内存槽管理区域
init_srcu_struct(&kvm->srcu)
分配kvm->buses[i]管理数据结构
spin_lock_init(&kvm->irqfds.lock);
INIT_LIST_HEAD(&kvm->irqfds.items);
INIT_LIST_HEAD(&kvm->ioeventfds);
cpu_set_debug_excp_handler(cpu_debug_ha
ndler);
qemu_event_init
qemu_cond_init(&qemu_pause_cond);
qemu_cond_init(&qemu_system_cond);
qemu_mutex_init(&qemu_fair_mutex);
qemu_mutex_init(&qemu_global_mutex);
qemu_mutex_lock(&qemu_global_mutex);
unblock_io_signals();
qemu_thread_self(&io_thread);
是否采用单独的I/O
thread 线程
cpu_set_debug_excp_handler(cpu_debug_ha
ndler);
qemu_event_init
err = qemu_eventfd(fds);
err = fcntl_setfl(fds[0],
O_NONBLOCK);
err = fcntl_setfl(fds[1],
O_NONBLOCK);
qemu_set_fd_handler2(fds[0],
NULL, qemu_event_read,
NULL,
(void *)(unsigned long)fds[0]);
io_thread_fd = fds[1];
static void pc_init_pci(ram_addr_t ram_size,
const char *boot_device,
const char *kernel_filename,
const char *kernel_cmdline,
const char *initrd_filename,
const char *cpu_model)
cpu_init(cpu_model)
env->cpuid_apic_id = env->cpu_index;
env->apic_state = apic_init(env, env-
>cpuid_apic_id);
qemu_register_reset(pc_cpu_reset, env);
pc_cpu_reset(env);
是否apic
在Qemu-Kvm中分配一个管理VCPU的数
据结构并继续初始化cpu_exec_init
optimize_flags_init
cpu_x86_register根据cpu模型qemu32去查找
CPU描述信息,填充VCPU管理数据结构字段
mce_init(env);
qemu_init_vcpu
env->nr_cores = smp_cores;
env->nr_threads = smp_threads;
kvm_init_vcpu(env);
是否采用单独的I/O
thread 线程
env->nr_cores = smp_cores;
env->nr_threads = smp_threads;
kvm_start_vcpu(env);
否
否
env->thread = qemu_mallocz(sizeof(QemuThread));
env->halt_cond = qemu_mallocz(sizeof(QemuCond));
qemu_cond_init(env->halt_cond);
qemu_thread_create(env->thread, kvm_cpu_thread_fn, env);
qemu_cond_timedwait(&qemu_cpu_cond,
&qemu_global_mutex, 100);
qemu_mutex_lock(&qemu_global_mutex);
qemu_thread_self(env->thread);
kvm_init_vcpu
kvm_init_ipi
/* signal CPU creation */
env->created = 1;
qemu_cond_signal(&qemu_cpu_cond);
/* and wait for machine initialization */
while (!qemu_system_ready)
qemu_cond_timedwait(&qemu_system_cond,
&qemu_global_mutex, 100);
qemu_kvm_wait_io_event
cpu_can_run
qemu_cpu_exec
不返回
I/O Thread
VCPU Thread
Qemu-Kvm Main Thread
RAMRAM
0x00000000
0x000a0000
0x000d0000
I/O BIOS
0x000e0000
0x000c0000
RO
M
RAM PC.BIOS(128KB)
0x00100000
PC.ROM(128KB)Hole RAM
熊海泉 xionghaiquan@sina.com.cn
xhqzju
- 粉丝: 1
- 资源: 6
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 航天器遥测数据故障检测系统python源码+文档说明+数据库(课程设计)
- 北京航空航天大学操作系统课设+ppt+实验报告
- 基于Vue+Echarts实现风力发电机中传感器的数据展示监控可视化系统+源代码+文档说明(高分课程设计)
- 基于单片机的风力发电机转速控制源码
- 基于C++实现的风力发电气动平衡监测系统+源代码+测量数据(高分课程设计)
- 毕业设计- 基于STM32F103C8T6 单片机,物联网技术的太阳能发电装置+源代码+文档说明+架构图+界面截图
- 基于 LSTM(长短期记忆)(即改进的循环神经网络)预测风力发电厂中风力涡轮机产生的功率+源代码+文档说明
- 基于stm32f103+空心杯电机+oled按键+运动算法
- 《CKA/CKAD应试指南/从docker到kubernetes 完全攻略》学习笔记 第1章docker基础(1.1-1.4)
- 基于python实现的水下压缩空气储能互补系统建模仿真与经济效益分析+源代码+论文
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
- 1
- 2
前往页