设为首页 收藏本站
查看: 1225|回复: 0

[经验分享] KVM Hypercall第一弹

[复制链接]
累计签到:77 天
连续签到:1 天
发表于 2014-5-27 10:36:22 | 显示全部楼层 |阅读模式
个人其实非常看好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

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-19755-1-1.html 上篇帖子: 如何在 KVM 虚拟机上运行 KVM 暨 如何让虚拟机支持虚拟化 下篇帖子: Ubuntu 12.04 安装KVM 管理虚拟机
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表