个人其实非常看好KVM,其实个人还非常看好Linux。请注意哥今天发这篇博文的背景:中国人民政府正式发出公告,政府部门采购一律不得用Windows 8, 还有一个新闻是美帝要对5名中国军官进行起诉,再一个是最近国内媒体有意无意提到马航370失联的相关报道,矛头隐隐指向美帝和波音,真假难辨。大意是这样。 然后前不久IBM发布了Power KVM, 而Redhat早就大力支持KVM了,个中滋味请同学们自己思考。。。另一个是:国内号称做OS的厂商几乎没有离开过Linux的,其实大家都懂的。
今天的废话就说了这么一点,不算多的,哈哈。下面进入正题,今天 咱们讲一下Linux下的Hypercall,幕后的黑手其实是某特尔处理器的VMCALL指令咯,手册里说得也不怎么详细,只给了op code:0F 01 C1 -- VMCALL Call to VM monitor by causing VM exit. 如此简洁颇具大家风范,嘿嘿
然后,然后注意Linux kernel source code下的这个文件,3.10的arch/x86/include/asm/kvm_para.h第19行:
/* This instruction is vmcall. On non-VT architectures, it will generate a
* trap that we will then rewrite to the appropriate instruction.
*/
#define KVM_HYPERCALL ".byte 0x0f,0x01,0xc1"
这条指令明显给Guest使用无疑,而且Guest一旦使用这个的话基本上意味着是所谓的半虚拟化了,其实我倒觉得你从哪个层面看了,如果你自己写一个内核模块在guest os里跑,然后你的内核模块中用到了VMCALL,那算不算半个虚拟化啊,有点抬杠了。。。
KVM_HYPERCALL其实跟SYSCALL非常相似,包括参数的传递。咱们先看只有一个参数的vmcall:
static inline long kvm_hypercall0 (unsigned int nr)
{
long ret;
asm volatile(KVM_HYPERCALL
: "=a"(ret)
: "a"(nr)
: "memory");
return ret;
}
熟悉inline汇编的同学一看就明白,nr可以认为是系统调用号,放在AX寄存器中,返回值也是放在AX中。当Guest OS中调用该函数时,导致VM-EXIT,于是KVM内核模块开始接收到控制权:
arch/x86/kvm/vmx.c:
handle_vmcall() --> kvm_emulate_hypercall ():
int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
{
unsigned long nr, a0, a1, a2, a3, ret;
int r = 1;
if (kvm_hv_hypercall_enabled(vcpu->kvm))
return kvm_hv_hypercall(vcpu);
nr = kvm_register_read(vcpu, VCPU_REGS_RAX);
a0 = kvm_register_read(vcpu, VCPU_REGS_RBX);
a1 = kvm_register_read(vcpu, VCPU_REGS_RCX);
a2 = kvm_register_read(vcpu, VCPU_REGS_RDX);
a3 = kvm_register_read(vcpu, VCPU_REGS_RSI);
trace_kvm_hypercall(nr, a0, a1, a2, a3);
if (!is_long_mode(vcpu)) {
nr &= 0xFFFFFFFF;
a0 &= 0xFFFFFFFF;
a1 &= 0xFFFFFFFF;
a2 &= 0xFFFFFFFF;
a3 &= 0xFFFFFFFF;
}
if (kvm_x86_ops->get_cpl(vcpu) != 0) {
ret = -KVM_EPERM;
goto out;
}
switch (nr) {
case KVM_HC_VAPIC_POLL_IRQ:
ret = 0;
break;
default:
ret = -KVM_ENOSYS;
break;
}
out:
kvm_register_write(vcpu, VCPU_REGS_RAX, ret) ;
++vcpu->stat.hypercalls;
return r;
}
EXPORT_SYMBOL_GPL(kvm_emulate_hypercall);
代码也很简单,根据Hypercall number(nr)进行处理,参数从(R)AX, BX, CX,DX,SI中得到。注意其中的kvm_register_write(vcpu, VCPU_REGS_RAX, ret),将hypercall处理结果返回给guest。如果此处ret = 0x55AA,那么guest中对kvm_hypercall0()的调用将返回0x55AA。
另一个要注意的是, Hypercall是同步执行的,如果HOST中不返回(比如睡眠10秒钟),那么guest中对kvm_hypercall0()的调用也不会返回,直到host里的睡眠结束。
运维网声明
1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网 享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com