xenのハイパーコールを呼んでみる
linuxのカーネルモジュールからxenのハイパーコールを呼んでみる。
とりあえず、実行中のドメインの情報をとってみる。
#include <linux/module.h> #include <asm/xen/hypercall.h> MODULE_LICENSE("GPL"); typedef uint8_t xen_domain_handle_t[16]; struct xen_domctl_getdomaininfo { domid_t domain; uint32_t flags; uint64_t tot_pages; uint64_t max_pages; uint64_t outstanding_pages; uint64_t shr_pages; uint64_t paged_pages; uint64_t shared_info_frame; uint64_t cpu_time; uint32_t nr_online_vcpus; uint32_t max_vcpu_id; uint32_t ssidref; xen_domain_handle_t handle; uint32_t cpupool; }; typedef struct xen_domctl_getdomaininfo xen_domctl_getdomaininfo_t; DEFINE_GUEST_HANDLE(xen_domctl_getdomaininfo_t); struct xen_sysctl_getdomaininfolist { domid_t first_domain; uint32_t max_domains; struct { xen_domctl_getdomaininfo_t *p; } buffer; uint32_t num_domains; }; typedef struct xen_sysctl_getdomaininfolist xen_sysctl_getdomaininfolist_t; DEFINE_GUEST_HANDLE(xen_sysctl_getdomaininfolist_t); #define XEN_SYSCTL_getdomaininfolist 6 #define XEN_SYSCTL_INTERFACE_VERSION 0x0000000A struct xen_sysctl { uint32_t cmd; uint32_t interface_version; union { struct xen_sysctl_getdomaininfolist getdomaininfolist; uint8_t pad[128]; } u; }; typedef struct xen_sysctl xen_sysctl_t; DEFINE_GUEST_HANDLE(xen_sysctl_t); #define __HYPERVISOR_sysctl 35 static long get_dominfolist(void) { long ret = 0; xen_sysctl_t sysctl; xen_domctl_getdomaininfo_t info[5]; int i; sysctl.cmd = XEN_SYSCTL_getdomaininfolist; sysctl.interface_version = XEN_SYSCTL_INTERFACE_VERSION; sysctl.u.getdomaininfolist.first_domain = 0; sysctl.u.getdomaininfolist.max_domains = 5; sysctl.u.getdomaininfolist.buffer.p = info; ret = _hypercall1(long, sysctl, &sysctl); if (ret) printk(KERN_EMERG "===== HYPERVISOR_sysctl failed. ret=%ld\n", ret); printk(KERN_EMERG "num=%u\n", sysctl.u.getdomaininfolist.num_domains); for (i = 0; i < sysctl.u.getdomaininfolist.num_domains; i++) printk(KERN_EMERG "===== domid=%u flag=%x cpu=%u\n", info[i].domain, info[i].flags, info[i].nr_online_vcpus); return ret; } static int __init dominfo_init(void) { long ret; printk(KERN_EMERG "===== dominfo init.\n"); ret = get_dominfolist(); return 0; } static void __exit dominfo_exit(void) { printk(KERN_EMERG "===== dominfo exit.\n"); } module_init(dominfo_init); module_exit(dominfo_exit);
最初の構造体とかマクロ定義とかはxenのコードにあったのをそのまま持ってきた。
hvm_opとかはHYPERVISOR_hvm_opとかいう関数があってそれをそのまま使えばよさそう。
sysctlはそれらしいのがなかったので_hypercall1を使った。
実行結果。
$ sudo insmod dominfo.ko $ sudo rmmod dominfo.ko $ dmesg | tail ... [ 1337.239688] ===== dominfo init. [ 1337.240255] num=2 [ 1337.240436] ===== domid=0 flag=ffff0020 cpu=4 [ 1337.240827] ===== domid=1 flag=ffff0012 cpu=2 [ 1342.504445] ===== dominfo exit. $ sudo xl list Name ID Mem VCPUs State Time(s) Domain-0 0 14477 4 r----- 25.3 u01 1 1023 2 -b---- 5.4
動いてるっぽい。