中断虚拟化代码分析

上传人:wt****50 文档编号:37626762 上传时间:2018-04-20 格式:PDF 页数:21 大小:467.91KB
返回 下载 相关 举报
中断虚拟化代码分析_第1页
第1页 / 共21页
中断虚拟化代码分析_第2页
第2页 / 共21页
中断虚拟化代码分析_第3页
第3页 / 共21页
中断虚拟化代码分析_第4页
第4页 / 共21页
中断虚拟化代码分析_第5页
第5页 / 共21页
点击查看更多>>
资源描述

《中断虚拟化代码分析》由会员分享,可在线阅读,更多相关《中断虚拟化代码分析(21页珍藏版)》请在金锄头文库上搜索。

1、qemu-kvm 中断虚拟化代码分析硬件中断发生(qemu 模拟设备) 1.硬件产生中断的接口 void qemu_set_irq(qemu_irq irq, int level);2.中断过程 void qemu_set_irq(qemu_irq irq, int level) if (!irq) return;irq-handler(irq-opaque, irq-n, level); 设置中断控制器 hander,大致分为三种情况 1.cpu_irq 的 hander= pic_irq_request 2.内核模拟中断控制器的 hander=kvm_i8259_set_irq 3.用户模

2、拟中断控制器的 hander=i8259_set_irq/* PC hardware initialisation */ static void pc_init1() cpu_irq = qemu_allocate_irqs(pic_irq_request, NULL, 1); #ifdef KVM_CAP_IRQCHIP if (kvm_enabled() isa_irq = i8259 = kvm_i8259_init(cpu_irq0); else #endif i8259 = i8259_init(cpu_irq0); isa_irq_state = qemu_mallocz(size

3、of(*isa_irq_state); isa_irq_state-i8259 = i8259; isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24); 先研究用户空间中断控制器的中断发生过程 static void i8259_set_irq(void *opaque, int irq, int level) PicState2 *s = opaque; pic_set_irq1( pic_update_irq(s); 中断触发方式分为电平触发和边沿触发,isa 设备大多数采用边沿触发,pci 设备采用电平 触发。

4、假如采用边沿触发, 如果 leveld 等于 1, 并且没有等待的中断请求 (没有 pending 中断请求) , 设置中断请求寄存器为 1,另外设置 pending 中断请求为 1. 如果有 pending 中断请求,并不设置中断请求寄存器,可见允许中断丢失。 /* set irq level. If an edge is detected, then the IRR is set to 1 */ static inline void pic_set_irq1(PicState *s, int irq, int level) int mask; mask = 1 elcr s-last_ir

5、r |= mask; else s-irr s-last_irr else /* edge triggered */ if (level) if (s-last_irr s-last_irr |= mask; else s-last_irr 每次有中断请求,必须调用该函数。该函数调用造成中断嵌套。另外必须话必须注入中断。 什么情况下是必须呢?具体可参照 pic_get_irq()函数。 这个函数对产生中断优先级和正在处理中断优先级进行比较,如果大于话,注入请求中断。 注入中断时机由 qemu_irq_raise 触发的,下面列出该函数。 /* raise irq to CPU if neces

6、sary. must be called every time the active irq may change */ void pic_update_irq(PicState2 *s) /* look at requested irq */ irq = pic_get_irq( if (irq = 0) qemu_irq_raise(s-parent_irq); 不要认为,好像又循环到中断入口了,实际没有,关键在于参数 s-parent_irq,该参数实 际调用 cpu_irq 的 hander= pic_irq_request static inline void qemu_irq_ra

7、ise(qemu_irq irq) qemu_set_irq(irq, 1); 目前只研究用户态模拟中断控制器 i8259(剔除 KVM 模拟和 apic 中断控制器), cpu_interrupt 函数实际中断目前虚拟处理器运行,为硬件中断注入做好准备,目前就是中 断注入时机。如何中断(暂停)虚拟处理器运行呢,通过该函数 pthread_kill(env-kvm_cpu_state.thread, SIG_IPI)中断处理器运行; static void pic_irq_request(void *opaque, int irq, int level) CPUState *env = fir

8、st_cpu; if (level) cpu_interrupt(env, CPU_INTERRUPT_HARD); else cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); 中断注入 中断注入负责将虚拟中断控制器采集的中断请求注入到虚拟处理器。 需要处理两个问题, 什 么时候注入,如何注入? static int kvm_main_loop_cpu(CPUState *env) while (1) int run_cpu = !is_cpu_stopped(env); if (run_cpu run_cpu = !env-halted; if (r

9、un_cpu) kvm_cpu_exec(env); kvm_main_loop_wait(env, 0); else kvm_main_loop_wait(env, 1000); pthread_mutex_unlock( return 0; 如果中断控制器不是内核空间模拟(用户空间模拟),进行中断注入。 kvm_main_loop_cpukvm_cpu_execkvm_run int kvm_run(CPUState *env)#if !defined(_s390_) if (!kvm-irqchip_in_kernel) run-request_interrupt_window = kv

10、m_arch_try_push_interrupts(env); #endif 1.首先满足三个条件 1)内核 kvm 准备好了接受中断注入 2)有中断请求并且为硬件中断请求 3)虚拟处理器运行中断(开中断) 2.获取中断请求号 3.kvm 注入中断请求 int kvm_arch_try_push_interrupts(void *opaque) CPUState *env = cpu_single_env; int r, irq;if (kvm_is_ready_for_interrupt_injection(env) irq = cpu_get_pic_interrupt(env); if

11、 (irq = 0) r = kvm_inject_irq(env, irq); if (r cpu_index, irq); return (env-interrupt_request /内核空间中断采集 中断控制器由两种 8259 和 apic,这两个设备在用户空间模拟过程,在上面已分析。接下来 看一下在内核态模拟,我们暂且称之为内核空间中断采集。 static void kvm_i8259_set_irq(void *opaque, int irq, int level) int pic_ret; if (kvm_set_irq(irq, level, return; 进入通过/dev/

12、kvm 接口,进入内核。 long kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg) case KVM_IRQ_LINE_STATUS: case KVM_IRQ_LINE: struct kvm_irq_level irq_event;r = -EFAULT; if (copy_from_user( if (irqchip_in_kernel(kvm) _s32 status; status = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, ir

13、q_event.irq, irq_event.level); if (ioctl = KVM_IRQ_LINE_STATUS) irq_event.status = status; if (copy_to_user(argp, r = 0; break; 硬件中断进入 8259 和 apic 中断控制器 int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level) struct kvm_kernel_irq_routing_entry *e, irq_setKVM_NR_IRQCHIPS; int ret = -

14、1, i = 0; struct kvm_irq_routing_table *irq_rt; struct hlist_node *n;trace_kvm_set_irq(irq, level, irq_source_id);/* Not possible to detect if the guest uses the PIC or the * IOAPIC. So set the bit in both. The guest will ignore * writes to the unused one. */ rcu_read_lock(); irq_rt = rcu_dereferenc

15、e(kvm-irq_routing);if (irq nr_rt_entries) hlist_for_each_entry(e, n, rcu_read_unlock();while(i-) int r; r = irq_seti.set( if (r irq_statese-irqchip.pin, irq_source_id, level); return kvm_pic_set_irq(pic, e-irqchip.pin, level); #else return -1; #endif 这里 8259 中断控制器代码,如用户态过程类似,可参考上面分析 int kvm_pic_set_irq(void *opaque, int irq, int level) struct kvm_pic *s = opaque; int ret = -1;pic_lock(s); if (irq = 0 pic_update_irq(s); trace_kvm_pic_set_irq(irq 3, irq pic_unlock(s);return ret; 如果收到中断响应 /* * callback when PIC0 irq status changed */ static voi

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 建筑/环境 > 建筑机械

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号