首先第一步便是给Xen中添加新的Hypercall, Hypercall、Hypervisor与GuestVM的关系与Systemcall、OS与Process的关系类似,如果GuestVM想要执行一些特权行为(如请求硬件)那么就要使用hypercall,控制权会转交给hypervisor,当hypervisor完成相关操作时会将控制权再交回GuestVM。
Debug 系列:
- Add New Hypercall to Xen
- Debug Xen on Physical Machine
- Xentrace
- Debug Key
可以参考Chang Hyun Park的此文中添加Hypercall到hvm的描述。
修改Xen文件
假定XEN为xen源码的顶级目录,我的是xen-4.4.3
修改hvm.c
在 XEN/xen/arch/x86/hvm/hvm.c中 查找hvm_hypercall64_table, hvm_hypercall32_table, 并添加自己的hypercall:
我添加了两个,本例以alice_op为例。 添加HYPERCALL(your hypercall name),使用的hvm-ubuntu是32位的,不过为了64位的也能使用,两个表都添加上了。修改entry.S
在XEN/xen/arch/x86/x86_64/entry.S中查找 ENTRY(hypercall_table),并添加自己的hypercall.(均以do开头)
39号本身是给用户预留的,如果要添加多个顺次增加。
之后,在下面的hypercall_args_table
添加参数项
其中.byte后的数字表示有几个参数。为了简便,do_alice_op我们就不使用参数。
PS:如果Xen是在32位机子上的,则修改的是XEN/xen/arch/x86/x86_32/entry.S
修改hypercall.h
在XEN/xen/include/xen/hypercall.h or XEN/xen/include/asm/hypercall.h(如果有架构依赖)中添加自己的hypercall声明:
(我放到asm/hypercall.h中了)添加hypercall number到xen.h
在XEN/xen/include/public/xen.h中添加自己的hypercall 号:
注释掉xc_reserved_op添加hypercall实现
hypercall如果是共用的功能,实现可以放到XEN/xen/common/kernel.c,与某些功能相关的话可以放到任何在XEN/xen/arch/x86/目录下的文件中,因为我之后要进行memory相关的学习,所以就放到XEN/arch/x86/mm.c里面了
#重新编译xen
make xen -j8
并安装 make install-xen -j8
,之后重启后,现在就可以调用hypercall了
由于hypercall只能在内核态进行调用,所以可以放到systemcall中或者编译为kernel module在进行加载时调用;xen本身也提供了使用privcmd的工具能够来调用hypercall。下面使用hypercall和kernel module两种方式进行实现。
#Privcmd
1 |
|
使用gcc -o test test.c进行编译后sudo ./test
使用sudo xl dm
查看日志后,也可以看到hypercall被调用的日志
#Kernel Module
###在Debian中使用Kernel Module方式
现在的Linux中已经有对于Xen的支持,所以在源码文件中是有xen.h这一文件的。这次我们修改Kernel Header文件来简化Kernel Module的编写。
在linux-src-dir/xen/interface/xen.h中添加自己的hypercall声明
linux-src-dir在debian上是在/usr/src中,其他的系统自己可以找一下。
之后在 linux-src-dir/arch/x86/include/asm/xen/hypercall.h中添加我们hypercall的声明。
(别人的图,忘截了)接下来就可以着手编写kernel module啦:
1 |
|
需要注意的是,需要在最后加上MODULE_LICENSE(“GPL”),否则有些lib不能使用就会报错。
相应的makefile:
1
2
3
4
5
6obj-m += hypercall_ko_debian.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
现在就可以调用hypercall了~
Note
- 如果使用System Call来实现的话,需要修改内核源码。
- Kernel Module的编程可以参考《Linux Kernel Module Programming Guide》 Peter Jay Salzman, Michael Burian, Ori Pomerantz
Change Log
- Add Debug series (2017-05-11)
- Delete ubuntu-example (2016-12-26)
Ubuntu 的那个Kernel Module是用别人的,写的不是很简洁,而且不推荐在Module内再自己重新写Hypercall的相关操作等,所以就去掉了。