はわわーっ

はわわわわっ

libxenctrlのメモ #2

xc_domain_getinfolistを見てみる。
xl listとかしたときに呼ばれるやつっぽい。

int xc_domain_getinfolist(xc_interface *xch,
                          uint32_t first_domain,
                          unsigned int max_domains,
                          xc_domaininfo_t *info)
{
    int ret = 0;
    DECLARE_SYSCTL;
    DECLARE_HYPERCALL_BOUNCE(info, max_domains*sizeof(*info), XC_HYPERCALL_BUFFER_BOUNCE_OUT);

    if ( xc_hypercall_bounce_pre(xch, info) )
        return -1;

    sysctl.cmd = XEN_SYSCTL_getdomaininfolist;
    sysctl.u.getdomaininfolist.first_domain = first_domain;
    sysctl.u.getdomaininfolist.max_domains  = max_domains;
    set_xen_guest_handle(sysctl.u.getdomaininfolist.buffer, info);

    if ( xc_sysctl(xch, &sysctl) < 0 )
        ret = -1;
    else
        ret = sysctl.u.getdomaininfolist.num_domains;

    xc_hypercall_bounce_post(xch, info);

    return ret;
}

最初の変数定義とか。

#define DECLARE_SYSCTL struct xen_sysctl sysctl

#define DECLARE_HYPERCALL_BOUNCE(_ubuf, _sz, _dir) DECLARE_NAMED_HYPERCALL_BOUNCE(_ubuf, _ubuf, _sz, _dir)

#define DECLARE_NAMED_HYPERCALL_BOUNCE(_name, _ubuf, _sz, _dir) \
    xc_hypercall_buffer_t XC__HYPERCALL_BUFFER_NAME(_name) = {  \
        .hbuf = NULL,                                           \
        .param_shadow = NULL,                                   \
        .sz = _sz, .dir = _dir, .ubuf = _ubuf,                  \
    }

#define XC__HYPERCALL_BUFFER_NAME(_name) xc__hypercall_buffer_##_name

ここで、struct xen_sysctl型のsysctlとxc_hypercall_buffer_t型のxc__hypercall_buffer_infoという変数が定義される。
構造体の定義は

struct xen_sysctl {
    uint32_t cmd;
#define XEN_SYSCTL_readconsole                    1
#define XEN_SYSCTL_tbuf_op                        2
#define XEN_SYSCTL_physinfo                       3
#define XEN_SYSCTL_sched_id                       4
#define XEN_SYSCTL_perfc_op                       5
#define XEN_SYSCTL_getdomaininfolist              6
#define XEN_SYSCTL_debug_keys                     7
#define XEN_SYSCTL_getcpuinfo                     8
#define XEN_SYSCTL_availheap                      9
#define XEN_SYSCTL_get_pmstat                    10
#define XEN_SYSCTL_cpu_hotplug                   11
#define XEN_SYSCTL_pm_op                         12
#define XEN_SYSCTL_page_offline_op               14
#define XEN_SYSCTL_lockprof_op                   15
#define XEN_SYSCTL_topologyinfo                  16 
#define XEN_SYSCTL_numainfo                      17
#define XEN_SYSCTL_cpupool_op                    18
#define XEN_SYSCTL_scheduler_op                  19
#define XEN_SYSCTL_coverage_op                   20
    uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */
    union {
        struct xen_sysctl_readconsole       readconsole;
        struct xen_sysctl_tbuf_op           tbuf_op;
        struct xen_sysctl_physinfo          physinfo;
        struct xen_sysctl_topologyinfo      topologyinfo;
        struct xen_sysctl_numainfo          numainfo;
        struct xen_sysctl_sched_id          sched_id;
        struct xen_sysctl_perfc_op          perfc_op;
        struct xen_sysctl_getdomaininfolist getdomaininfolist;
        struct xen_sysctl_debug_keys        debug_keys;
        struct xen_sysctl_getcpuinfo        getcpuinfo;
        struct xen_sysctl_availheap         availheap;
        struct xen_sysctl_get_pmstat        get_pmstat;
        struct xen_sysctl_cpu_hotplug       cpu_hotplug;
        struct xen_sysctl_pm_op             pm_op;
        struct xen_sysctl_page_offline_op   page_offline;
        struct xen_sysctl_lockprof_op       lockprof_op;
        struct xen_sysctl_cpupool_op        cpupool_op;
        struct xen_sysctl_scheduler_op      scheduler_op;
        struct xen_sysctl_coverage_op       coverage_op;
        uint8_t                             pad[128];
    } u;
};
typedef struct xen_sysctl xen_sysctl_t;
DEFINE_XEN_GUEST_HANDLE(xen_sysctl_t);

struct xen_sysctl_getdomaininfolist {       
    /* IN variables. */
    domid_t               first_domain;     
    uint32_t              max_domains;      
    XEN_GUEST_HANDLE_64(xen_domctl_getdomaininfo_t) buffer;
    /* OUT variables. */
    uint32_t              num_domains;      
};      
typedef struct xen_sysctl_getdomaininfolist xen_sysctl_getdomaininfolist_t;
DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getdomaininfolist_t);

XEN_GUEST_HANDLE_64のところは

#define XEN_GUEST_HANDLE_64(name) XEN_GUEST_HANDLE(name)

#define XEN_GUEST_HANDLE(name)          __XEN_GUEST_HANDLE(name)

#define __XEN_GUEST_HANDLE(name)        __guest_handle_ ## name

ってあったから、たぶん__guest_handle_xen_domctl_getdomaininfo_tっていう型がある?
grepしても見つからなかったけど

#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
    typedef struct { type *p; } __guest_handle_ ## name

こんなのがあったから、__guest_handle_xen_domctl_getdomaininfo_tってのは
たぶんpっていうポインタ変数を持つ構造体なんだろうきっと。

struct xc_hypercall_buffer {
    /* Hypercall safe memory buffer. */
    void *hbuf;

    /*
     * Reference to xc_hypercall_buffer passed as argument to the
     * current function.
     */
    struct xc_hypercall_buffer *param_shadow;

    /*
     * Direction of copy for bounce buffering.
     */
    int dir;

    /* Used iff dir != 0. */
    void *ubuf;
    size_t sz;
};
typedef struct xc_hypercall_buffer xc_hypercall_buffer_t;

enum {  
    XC_HYPERCALL_BUFFER_BOUNCE_NONE = 0,
    XC_HYPERCALL_BUFFER_BOUNCE_IN   = 1,
    XC_HYPERCALL_BUFFER_BOUNCE_OUT  = 2,
    XC_HYPERCALL_BUFFER_BOUNCE_BOTH = 3
};

で、sysctl変数に値を設定していく。set_xen_guest_handleは

#define set_xen_guest_handle(_hnd, _val)                        \
    do {                                                        \
        xc_hypercall_buffer_t _hcbuf_hnd1;                      \
        typeof(XC__HYPERCALL_BUFFER_NAME(_val)) *_hcbuf_hnd2 =  \
                HYPERCALL_BUFFER(_val);                         \
        (void) (&_hcbuf_hnd1 == _hcbuf_hnd2);                   \
        set_xen_guest_handle_raw(_hnd, (_hcbuf_hnd2)->hbuf);    \
    } while (0)

#define set_xen_guest_handle_raw(hnd, val)  do { (hnd).p = val; } while (0)

#define HYPERCALL_BUFFER(_name)                                 \
    ({  xc_hypercall_buffer_t _hcbuf_buf1;                      \
        typeof(XC__HYPERCALL_BUFFER_NAME(_name)) *_hcbuf_buf2 = \
                &XC__HYPERCALL_BUFFER_NAME(_name);              \
        (void)(&_hcbuf_buf1 == _hcbuf_buf2);                    \
        (_hcbuf_buf2)->param_shadow ?                           \
                (_hcbuf_buf2)->param_shadow : (_hcbuf_buf2);    \
     })

たぶん、buffer.pにinfoを代入してるんだろう。

で、パラメータ設定したらxc_sysctlしてる。

やっぱり、マクロはよくわからんな。