ARMv7 KVM 在 linux中的实现
2021/9/26 7:14:43
本文主要是介绍ARMv7 KVM 在 linux中的实现,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
linux-5.6
函数角度
架构无关部分 在 virt 架构相关部分 在 arch/arm/kvm
- arch/arm/kvm 的出口函数
__init_stage2_translation // 没被 virt 调用 __kvm_arm_vcpu_get_events __kvm_arm_vcpu_set_events __kvm_flush_vm_context __kvm_hyp_init __kvm_tlb_flush_local_vmid __kvm_tlb_flush_vmid __kvm_tlb_flush_vmid_ipa __kvm_vcpu_run_nvhe __vcpu_spsr // 没被 virt 调用 handle_exit kvm_arch_vcpu_ioctl_get_fpu kvm_arch_vcpu_ioctl_get_regs kvm_arch_vcpu_ioctl_get_sregs kvm_arch_vcpu_ioctl_set_fpu kvm_arch_vcpu_ioctl_set_guest_debug kvm_arch_vcpu_ioctl_set_regs kvm_arch_vcpu_ioctl_set_sregs kvm_arch_vcpu_ioctl_translate kvm_arm_copy_reg_indices kvm_arm_get_reg kvm_arm_num_regs kvm_arm_set_reg kvm_arm_vcpu_arch_get_attr kvm_arm_vcpu_arch_has_attr kvm_arm_vcpu_arch_set_attr kvm_coproc_table_init kvm_inject_vabt kvm_reset_vcpu kvm_target_cpu kvm_vcpu_preferred_target vgic_v3_cpu_sysregs_uaccess vgic_v3_has_cpu_sysregs_attr
初始化角度
virt/kvm/arm/arm.c module_init(arm_init); kvm_init ...
运行时角度
- VM entry
// arm 的 kvm 代码(包括架构和非架构相关) 运行在 两个mode // 有 __hyp_text 标识的 运行在 hyp mode vcpu 对应一个 fd ,对应一个 file_operations , 为 kvm_vcpu_fops static struct file_operations kvm_vcpu_fops = { .release = kvm_vcpu_release, .unlocked_ioctl = kvm_vcpu_ioctl, .mmap = kvm_vcpu_mmap, .llseek = noop_llseek, KVM_COMPAT(kvm_vcpu_compat_ioctl), }; kvm_vcpu_ioctl // virt/kvm/kvm_main.c switch (ioctl) { case KVM_RUN: { oldpid = rcu_access_pointer(vcpu->pid); kvm_arch_vcpu_ioctl_run(vcpu, vcpu->run); // virt/kvm/arm/arm.c kvm_vcpu_first_run_init kvm_arm_vcpu_is_finalized kvm_timer_enable kvm_arm_pmu_v3_enable while (ret > 0) { ... /************************************************************** * Enter the guest * / trace_kvm_entry(*vcpu_pc(vcpu)); guest_enter_irqoff(); if (has_vhe()) {ret = kvm_vcpu_run_vhe(vcpu);} else {ret = kvm_call_hyp_ret(__kvm_vcpu_run_nvhe, vcpu);} vcpu->mode = OUTSIDE_GUEST_MODE; vcpu->stat.exits++; /* * Back from guest *************************************************************/ ... guest_exit handle_exit } } } __kvm_vcpu_run_nvhe // __hyp_text /* Jump in the fire! */ again: exit_code = __guest_enter(vcpu, host_ctxt); // 该行执行后,进入虚拟机, 下一行就是返回. /* And we're baaack! */ // arch/arm/kvm/hyp/entry.S /* int __guest_enter(struct kvm_vcpu *vcpu, struct kvm_cpu_context *host) */ ENTRY(__guest_enter) @ Save host registers add r1, r1, #(USR_REGS_OFFSET + S_R4) stm r1!, {r4-r12} str lr, [r1, #4] @ Skip SP_usr (already saved) @ Restore guest registers add r0, r0, #(VCPU_GUEST_CTXT + USR_REGS_OFFSET + S_R0) ldr lr, [r0, #S_LR] ldm r0, {r0-r12} clrex eret // 该指令后进入 虚拟机 ENDPROC(__guest_enter)
- VM exit
我们知道返回时的第一条指令 __guest_enter 会进入,那什么时候返回呢?不知道
ENTRY(__guest_exit) /* * return convention: * guest r0, r1, r2 saved on the stack * r0: vcpu pointer * r1: exception code */ add r2, r0, #(VCPU_GUEST_CTXT + USR_REGS_OFFSET + S_R3) stm r2!, {r3-r12} str lr, [r2, #4] add r2, r0, #(VCPU_GUEST_CTXT + USR_REGS_OFFSET + S_R0) pop {r3, r4, r5} @ r0, r1, r2 stm r2, {r3-r5} ldr r0, [r0, #VCPU_HOST_CTXT] add r0, r0, #(USR_REGS_OFFSET + S_R4) ldm r0!, {r4-r12} ldr lr, [r0, #4] mov r0, r1 mrs r1, SPSR mrs r2, ELR_hyp mrc p15, 4, r3, c5, c2, 0 @ HSR /* * Force loads and stores to complete before unmasking aborts * and forcing the delivery of the exception. This gives us a * single instruction window, which the handler will try to * match. */ dsb sy cpsie a .global abort_guest_exit_start abort_guest_exit_start: isb .global abort_guest_exit_end abort_guest_exit_end: /* * If we took an abort, r0[31] will be set, and cmp will set * the N bit in PSTATE. */ cmp r0, #0 msrmi SPSR_cxsf, r1 msrmi ELR_hyp, r2 mcrmi p15, 4, r3, c5, c2, 0 @ HSR bx lr ENDPROC(__guest_exit)
arch/arm/kvm/hyp/hyp-entry.S guest_trap: // hyp_hvc load_vcpu r0 @ Load VCPU pointer to r0 #ifdef CONFIG_VFPv3 @ Check for a VFP access lsr r1, r1, #HSR_EC_SHIFT cmp r1, #HSR_EC_CP_0_13 beq __vfp_guest_restore #endif mov r1, #ARM_EXCEPTION_HVC b __guest_exit hyp_irq: push {r0, r1, r2} mov r1, #ARM_EXCEPTION_IRQ load_vcpu r0 @ Load VCPU pointer to r0 b __guest_exit
arch/arm/kvm/hyp/hyp-entry.S .align 5 __kvm_hyp_vector: .global __kvm_hyp_vector @ Hyp-mode exception vector W(b) hyp_reset W(b) hyp_undef W(b) hyp_svc W(b) hyp_pabt W(b) hyp_dabt W(b) hyp_hvc W(b) hyp_irq W(b) hyp_fiq .macro vect_br val, targ ARM( eor sp, sp, #\val ) ARM( tst sp, #7 ) ARM( eorne sp, sp, #\val ) THUMB( cmp r1, #\val ) THUMB( popeq {r1, r2} ) beq \targ .endm vect_br 0, hyp_fiq vect_br 1, hyp_irq vect_br 2, hyp_hvc vect_br 3, hyp_dabt vect_br 4, hyp_pabt vect_br 5, hyp_svc vect_br 6, hyp_undef vect_br 7, hyp_reset #endif .macro invalid_vector label, cause .align \label: mov r0, #\cause b __hyp_panic .endm invalid_vector hyp_reset ARM_EXCEPTION_RESET invalid_vector hyp_undef ARM_EXCEPTION_UNDEFINED invalid_vector hyp_svc ARM_EXCEPTION_SOFTWARE invalid_vector hyp_pabt ARM_EXCEPTION_PREF_ABORT invalid_vector hyp_fiq ARM_EXCEPTION_FIQ 实现了以下三个,其他五个没实现 hyp_dabt hyp_hvc hyp_irq
这篇关于ARMv7 KVM 在 linux中的实现的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-12如何创建可引导的 ESXi USB 安装介质 (macOS, Linux, Windows)
- 2024-11-08linux的 vi编辑器中搜索关键字有哪些常用的命令和技巧?-icode9专业技术文章分享
- 2024-11-08在 Linux 的 vi 或 vim 编辑器中什么命令可以直接跳到文件的结尾?-icode9专业技术文章分享
- 2024-10-22原生鸿蒙操作系统HarmonyOS NEXT(HarmonyOS 5)正式发布
- 2024-10-18操作系统入门教程:新手必看的基本操作指南
- 2024-10-18初学者必看:操作系统入门全攻略
- 2024-10-17操作系统入门教程:轻松掌握操作系统基础知识
- 2024-09-11Linux部署Scrapy学习:入门级指南
- 2024-09-11Linux部署Scrapy:入门级指南
- 2024-08-21【Linux】分区向左扩容的方法