Xen添加一個hypercall

Xen中,hypercall(超調用)是一個比較重要的概念;hypercall類似於system call,hypercall之於xen hypervisor就像系統調用之於Linux kernel.
x86平臺上,Xen中的hypercall是通過軟中端(中斷號0×82)來實現的。
在linux系統中添加新的系統調用,一般需要三個步驟:
1. 註冊新的系統調用號
2. 更新系統調用表
3. 添加新函數

xen中添加一個hypercall,也類似於在linux中添加一個系統調。下面簡單介紹一下,如何創建一個自己的hypercall。
(添加一個hypercall的完整的patch在這裏:add_hypercall.patch,可以用在最新的xen-unstable tree上。)

0.準備工作:獲取xen源代碼,以最新的upstreamxen爲例

1
2
hg clone http://xenbits.xen.org/xen-unstable.hg
cd xen-unstable.hg

也可以到如下網頁去下載Xen hypervisor的tarball文件:

http://www.xen.org/products/xen_source.html

1. 註冊一個hypercall調用號:xen/include/public/xen.h

1
2
3
 #define __HYPERVISOR_tmem_op 38
 #define __HYPERVISOR_xc_reserved_op 39 /* reserved for XenClient */
+#define __HYPERVISOR_hello_hypercall 39 /* add this temporarily; 39 is not used before */

2. 更新系統調用表:xen/arch/x86/x86_64/entry.S (若是32bit Intel平臺,則是x86_32/entry.S)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@@ -697,6 +697,7 @@
         .quad do_domctl
         .quad do_kexec_op
         .quad do_tmem_op
+ .quad do_hello_hypercall
         .rept __HYPERVISOR_arch_0-((.-hypercall_table)/8)
         .quad do_ni_hypercall
         .endr
@@ -745,6 +746,7 @@
         .byte 1 /* do_domctl */
         .byte 2 /* do_kexec */
         .byte 1 /* do_tmem_op */
+ .byte 1 /* do_hello_hypercall */
         .rept __HYPERVISOR_arch_0-(.-hypercall_args_table)
         .byte 0 /* do_ni_hypercall */
         .endr

3. 定義hypercall處理函數的頭文件:xen/include/asm-x86/hypercall.h

1
2
3
4
5
6
7
8
@@ -94,6 +94,10 @@
 do_kexec(
     unsigned long op, unsigned arg1, XEN_GUEST_HANDLE(void) uarg);
 
+extern int
+do_hello_hypercall(
+ char* str);
+

4. 定義函數在適當的地方(本例在:xen/arch/x86/traps.c中)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@@ -3850,6 +3850,20 @@
     return -EINVAL;
 }
 
+int do_hello_hypercall(char* str)
+{
+ printk("------------------------------\n");
+ printk("Begin: hello hypercall.\n");
+ if(str != NULL)
+ printk("Hello, %s.\n", str);
+ else
+ printk("Hello, the unkown.\n");
+ printk("End: hello hypercall.\n");
+ printk("----demoed by Jay.----\n");
+ printk("------------------------------\n");
+ return 0;
+}
+
 /*
  * Local variables:
  * mode: C

到這裏,添加hypercall的代碼就基本完成了,然後需要編譯xen hypervisor:
make xen
將生成的xen.gz更新到啓動時用的xen.gz,重啓系統。
下面寫一個測試這個hypercall的簡單代碼:
xen提供了/proc/xen/privcmd這個虛擬文件,從而在ring 3(用戶空間)可以利用ioctl來調用hypercall。
(注意:需要保證/usr/include/xen/xen.h中有你添加的__HYPERVISOR_hello_hypercall的宏定義,否則會編譯報錯,找不到新定義的hypercall符號。)
詳細代碼見:test_hypercall.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <stdio.h>  
#include <stdlib.h>  
#include <errno.h>  
#include <sys/ioctl.h>  
#include <linux/types.h>
#include <fcntl.h>  
#include <string.h>
#include <xenctrl.h>
#include <xen/sys/privcmd.h>
 
int main(int argc, char *argv[])  
{  
	int fd, ret;
	char * message;
	if (argc != 2) {
		printf("please input one parameter!\n");
		return -1;
	}
	message = (char *) malloc(sizeof(char) * (strlen(argv[1])+1));
	strcpy(message, argv[1]);
	privcmd_hypercall_t my_hypercall = {
		__HYPERVISOR_hello_hypercall,
		{(__u64)message, 0, 0, 0, 0}
	};
	fd = open("/proc/xen/privcmd", O_RDWR);
	if (fd < 0) {
		perror("can't open /proc/xen/privcmd");
		exit(1);
	} 
	else
		printf("privcmd's fd = %d\n", fd);
	ret = ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, &my_hypercall);
	printf("ret = %d\n", ret);  
}

注意測試代碼中,這裏有個強制類型轉換:(__u64)message,是爲了適應結構體privcmd_hypercall_t的定義,否則會出現編譯時warning:
test_hypercall.c:23: warning: initialization makes integer from pointer without a cast
因爲需要將指針變量轉化爲__u64整型的變量(__u64類型在linux/types.h中定義),應該顯式強制類型轉換,詳見:/usr/include/xen/sys/privcmd.h

1
2
3
4
5
6
7
8
9
10
11
#include <linux/types.h>
 
#ifndef __user
#define __user
#endif
 
typedef struct privcmd_hypercall
{
        __u64 op;
        __u64 arg[5];
} privcmd_hypercall_t;

編譯測試程序:gcc test_hypercall.c -o test_hypercall
運行測試程序:

1
2
3
[root@vt-snb7 jay]# ./test_hypercall world
privcmd's fd = 3
ret = 0

查看測試結果:xl dmesg | less

1
2
3
4
5
6
(XEN) ------------------------------
(XEN) Begin: hello hypercall.
(XEN) Hello, world.
(XEN) End: hello hypercall.
(XEN) ----demoed by Jay.----
(XEN) ------------------------------

參考資料:
在DomU中調用hypercall見:http://blog.csdn.net/sploving/article/details/5990507

http://wiki.xen.org/wiki/Hypercall

http://hi.baidu.com/mars208/blog/item/847dbc2200c628198b82a146.html

發佈了22 篇原創文章 · 獲贊 8 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章