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

[经验分享] xen的超级调用

[复制链接]

尚未签到

发表于 2015-10-12 08:32:25 | 显示全部楼层 |阅读模式
  超级调用是特权操作,有xen来实现.采用的是软中断的方式.它是整个xen的基础.
  具体的实现是首先我们有一些超级调用的处理函数,和他们对应的超级调用号,有一个索引文件来记录他们的对应关系.
  超级调用发生在guest的内核层,某一个函数如果需要使用超级调用,则会先跳转到超级调用页的相应地方,通过int82h 内陷进入xen中,搜索索引来跳转到超级调用的处理程序.
  如果是guest的用户态,必须先进入内核态,通过调用内核态的函数来调用超级调用.
  通过xen4.4的代码来分析一下这个过程:
  在Hypercall-x86_64.h中记录了guest中内核超级调用函数
  static inline int
HYPERVISOR_set_trap_table(
trap_info_t *table)
{
return _hypercall1(int, set_trap_table, table);
}


这个超级调用调用了_hypercall1   (和上面文件的地方相同)
  #define _hypercall1(type, name, a1)\
({\
long __res, __ign1;\
asm volatile (\
"call hypercall_page + ("STR(__HYPERVISOR_##name)" * 32)"\
: "=a" (__res), "=D" (__ign1)\
: "1" ((long)(a1))\
: "memory" );\
(type)__res;\
})

_hypercallN其实都是跳转到超级调用对应的
  超级调用页的初始化(xen/arch/x86/x86_64/traps.c)void hypercall_page_initialise(struct domain *d, void *hypercall_page)
{
memset(hypercall_page, 0xCC, PAGE_SIZE);
if ( has_hvm_container_domain(d) )
hvm_hypercall_page_initialise(d, hypercall_page);
else if ( !is_pv_32bit_domain(d) )
hypercall_page_initialise_ring3_kernel(hypercall_page);
else
hypercall_page_initialise_ring1_kernel(hypercall_page);
}超级调用页中写的一些什么呢,我们看其中一个
  static void hypercall_page_initialise_ring3_kernel(void *hypercall_page)
{
char *p;
int i;
/* Fill in all the transfer points with template machine code. */
for ( i = 0; i < (PAGE_SIZE / 32); i++ )
{
if ( i == __HYPERVISOR_iret )
continue;
p = (char *)(hypercall_page + (i * 32));
*(u8  *)(p+ 0) = 0x51;    /* push %rcx */
*(u16 *)(p+ 1) = 0x5341;  /* push %r11 */
*(u8  *)(p+ 3) = 0xb8;    /* mov  $<i>,%eax */
*(u32 *)(p+ 4) = i;
*(u16 *)(p+ 8) = 0x050f;  /* syscall */
*(u16 *)(p+10) = 0x5b41;  /* pop  %r11 */
*(u8  *)(p+12) = 0x59;    /* pop  %rcx */
*(u8  *)(p+13) = 0xc3;    /* ret */
}
/*
* HYPERVISOR_iret is special because it doesn't return and expects a
* special stack frame. Guests jump at this transfer point instead of
* calling it.
*/
p = (char *)(hypercall_page + (__HYPERVISOR_iret * 32));
*(u8  *)(p+ 0) = 0x51;    /* push %rcx */
*(u16 *)(p+ 1) = 0x5341;  /* push %r11 */
*(u8  *)(p+ 3) = 0x50;    /* push %rax */
*(u8  *)(p+ 4) = 0xb8;    /* mov  $__HYPERVISOR_iret,%eax */
*(u32 *)(p+ 5) = __HYPERVISOR_iret;
*(u16 *)(p+ 9) = 0x050f;  /* syscall */
}

直接用机器码写的指令,然后其中会用syscall(和int82h可以认为是一样)来进入xen中.这样才可以执行这些特权指令.这是规范,出于安全的考虑.
  xen先保存内核的状态,然后根据索引来跳转到的不同的超级调用的处理函数.
  索引文件 xen/arch/x86/x86_64/entry.SENTRY(hypercall_table)
.quad do_set_trap_table     /*  0 */
.quad do_mmu_update
.quad do_set_gdt
.quad do_stack_switch
.quad do_set_callbacks
.quad do_fpu_taskswitch     /*  5 */
.quad do_sched_op_compat
.quad do_platform_op
.quad do_set_debugreg
.quad do_get_debugreg
.quad do_update_descriptor  /* 10 */
.quad do_ni_hypercall
.quad do_memory_op
.quad do_multicall
.quad do_update_va_mapping
.quad do_set_timer_op       /* 15 */
.quad do_event_channel_op_compat


  具体的处理函数在xen/arch/x86/traps.c中
  long do_set_trap_table(XEN_GUEST_HANDLE_PARAM(const_trap_info_t) traps)
{
struct trap_info cur;
struct vcpu *curr = current;
struct trap_info *dst = curr->arch.pv_vcpu.trap_ctxt;
long rc = 0;
/* If no table is presented then clear the entire virtual IDT. */
if ( guest_handle_is_null(traps) )
{
memset(dst, 0, NR_VECTORS * sizeof(*dst));
init_int80_direct_trap(curr);
return 0;
}
for ( ; ; )
{
if ( hypercall_preempt_check() )
{
rc = hypercall_create_continuation(
__HYPERVISOR_set_trap_table, &quot;h&quot;, traps);
break;
}
if ( copy_from_guest(&cur, traps, 1) )
{
rc = -EFAULT;
break;
}
if ( cur.address == 0 )
break;
if ( !is_canonical_address(cur.address) )
return -EINVAL;
fixup_guest_code_selector(curr->domain, cur.cs);
memcpy(&dst[cur.vector], &cur, sizeof(cur));
if ( cur.vector == 0x80 )
init_int80_direct_trap(curr);
guest_handle_add_offset(traps, 1);
}
return rc;
}

这是超级调用的整个过程,整个过程中唯一一点不清楚的是syscall进入xen中的汇编语言xen/arch/x86/x86_64/entry.S(姑且认为就是保存了内核状态,并跳转)
  这些知识只是在更改超级调用的时候才会用到,超级调用已经成为了xen的一种机制,提供特权操作的机制.我们可以再别的地方任意使用,不考虑其中的细节.

版权声明:本文为博主原创文章,未经博主允许不得转载。

运维网声明 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-125612-1-1.html 上篇帖子: centos安装xen 下篇帖子: xen,xenserver,xcp的区别
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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