xen_internal.c 7.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * xen_internal.c: direct access to Xen hypervisor level
 *
 * Copyright (C) 2005 Red Hat, Inc.
 *
 * See COPYING.LIB for the License of this software
 *
 * Daniel Veillard <veillard@redhat.com>
 */

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>

#include <xen/dom0_ops.h>
22
#include <xen/version.h>
23 24 25
#include <xen/xen.h>

#ifndef __LINUX_PUBLIC_PRIVCMD_H__
26
typedef struct hypercall_struct {
27 28 29 30 31 32 33 34 35 36 37
    unsigned long op;
    unsigned long arg[5];
} hypercall_t;
#endif


#include "internal.h"
#include "xen_internal.h"

#define XEN_HYPERVISOR_SOCKET "/proc/xen/privcmd"

38 39 40 41 42 43 44 45 46
/**
 * virXenError:
 * @conn: the connection if available
 * @error: the error number
 * @info: extra information string
 *
 * Handle an error at the xend daemon interface
 */
static void
47 48
virXenError(virErrorNumber error, const char *info, int value)
{
49
    const char *errmsg;
50

51 52 53 54 55
    if (error == VIR_ERR_OK)
        return;

    errmsg = __virErrorMsg(error, info);
    __virRaiseError(NULL, NULL, VIR_FROM_XEN, error, VIR_ERR_ERROR,
56
                    errmsg, info, NULL, value, 0, errmsg, info, value);
57 58
}

59 60
/**
 * xenHypervisorOpen:
61
 * @quiet: don'r raise an error on failure if set
62 63 64 65 66
 *
 * Connects to the Xen hypervisor.
 *
 * Returns the handle or -1 in case of error.
 */
67 68 69
int
xenHypervisorOpen(int quiet)
{
70 71 72
    int ret;

    ret = open(XEN_HYPERVISOR_SOCKET, O_RDWR);
73
    if (ret < 0) {
74 75 76
        if (!quiet)
            virXenError(VIR_ERR_NO_XEN, XEN_HYPERVISOR_SOCKET, 0);
        return (-1);
77
    }
78

79
    return (ret);
80 81 82 83 84 85 86 87 88 89
}

/**
 * xenHypervisorClose:
 * @handle: the handle to the Xen hypervisor
 *
 * Close the connection to the Xen hypervisor.
 *
 * Returns 0 in case of success or -1 in case of error.
 */
90 91 92
int
xenHypervisorClose(int handle)
{
93 94 95
    int ret;

    if (handle < 0)
96
        return (-1);
97 98 99

    ret = close(handle);
    if (ret < 0)
100 101
        return (-1);
    return (0);
102 103 104 105 106 107 108 109 110 111 112 113
}

/**
 * xenHypervisorDoOp:
 * @handle: the handle to the Xen hypervisor
 * @op: pointer to the hyperviros operation structure
 *
 * Do an hypervisor operation, this leads to an hypervisor call through ioctl.
 *
 * Returns 0 in case of success and -1 in case of error.
 */
static int
114 115
xenHypervisorDoOp(int handle, dom0_op_t * op)
{
116
    int ret;
117
    unsigned int cmd;
118 119 120 121
    hypercall_t hc;

    op->interface_version = DOM0_INTERFACE_VERSION;
    hc.op = __HYPERVISOR_dom0_op;
122
    hc.arg[0] = (unsigned long) op;
123

124 125
    if (mlock(op, sizeof(dom0_op_t)) < 0) {
        virXenError(VIR_ERR_XEN_CALL, " locking", sizeof(dom0_op_t));
126
        return (-1);
127
    }
128

129 130
    cmd = _IOC(_IOC_NONE, 'P', 0, sizeof(hc));
    ret = ioctl(handle, cmd, (unsigned long) &hc);
131 132 133
    if (ret < 0) {
        virXenError(VIR_ERR_XEN_CALL, " ioctl ", cmd);
    }
134

135 136
    if (munlock(op, sizeof(dom0_op_t)) < 0) {
        virXenError(VIR_ERR_XEN_CALL, " releasing", sizeof(dom0_op_t));
137
        ret = -1;
138
    }
139 140

    if (ret < 0)
141 142 143
        return (-1);

    return (0);
144 145
}

146 147 148 149 150 151 152 153 154
/**
 * xenHypervisorGetVersion:
 * @handle: the handle to the Xen hypervisor
 *
 * Call the hypervisor to extracts his own internal API version
 *
 * Returns the hypervisor running version or 0 in case of error.
 */
unsigned long
155 156
xenHypervisorGetVersion(int handle)
{
157 158 159 160 161
    int ret;
    unsigned int cmd;
    hypercall_t hc;

    hc.op = __HYPERVISOR_xen_version;
162
    hc.arg[0] = (unsigned long) XENVER_version;
163 164 165 166 167
    hc.arg[1] = 0;

    cmd = _IOC(_IOC_NONE, 'P', 0, sizeof(hc));
    ret = ioctl(handle, cmd, (unsigned long) &hc);

168 169
    if (ret < 0) {
        virXenError(VIR_ERR_XEN_CALL, " getting version ", XENVER_version);
170
        return (0);
171
    }
172 173 174 175
    /*
     * use unsigned long in case the version grows behind expectations
     * allowed by int
     */
176
    return ((unsigned long) ret);
177 178
}

179 180 181 182 183 184 185 186 187 188 189
/**
 * xenHypervisorGetDomainInfo:
 * @handle: the handle to the Xen hypervisor
 * @domain: the domain ID
 * @info: the place where informations should be stored
 *
 * Do an hypervisor call to get the related set of domain informations.
 *
 * Returns 0 in case of success, -1 in case of error.
 */
int
190 191 192
xenHypervisorGetDomainInfo(int handle, int domain,
                           dom0_getdomaininfo_t * info)
{
193 194 195 196
    dom0_op_t op;
    int ret;

    if (info == NULL)
197
        return (-1);
198 199 200

    memset(info, 0, sizeof(dom0_getdomaininfo_t));

201
    if (mlock(info, sizeof(dom0_getdomaininfo_t)) < 0) {
202 203 204
        virXenError(VIR_ERR_XEN_CALL, " locking",
                    sizeof(dom0_getdomaininfo_t));
        return (-1);
205
    }
206 207 208 209 210

    op.cmd = DOM0_GETDOMAININFOLIST;
    op.u.getdomaininfolist.first_domain = (domid_t) domain;
    op.u.getdomaininfolist.max_domains = 1;
    op.u.getdomaininfolist.buffer = info;
211 212
    op.u.getdomaininfolist.num_domains = 1;
    info->domain = domain;
213 214 215

    ret = xenHypervisorDoOp(handle, &op);

216
    if (munlock(info, sizeof(dom0_getdomaininfo_t)) < 0) {
217 218
        virXenError(VIR_ERR_XEN_CALL, " release",
                    sizeof(dom0_getdomaininfo_t));
219
        ret = -1;
220
    }
221

222
    if (ret < 0)
223 224
        return (-1);
    return (0);
225 226
}

227 228 229 230 231 232 233 234 235 236
/**
 * xenHypervisorPauseDomain:
 * @handle: the handle to the Xen hypervisor
 * @domain: the domain ID
 *
 * Do an hypervisor call to pause the given domain
 *
 * Returns 0 in case of success, -1 in case of error.
 */
int
237 238
xenHypervisorPauseDomain(int handle, int domain)
{
239 240 241 242 243 244 245 246 247
    dom0_op_t op;
    int ret;

    op.cmd = DOM0_PAUSEDOMAIN;
    op.u.pausedomain.domain = (domid_t) domain;

    ret = xenHypervisorDoOp(handle, &op);

    if (ret < 0)
248 249
        return (-1);
    return (0);
250 251 252 253 254 255 256 257 258 259 260 261
}

/**
 * xenHypervisorResumeDomain:
 * @handle: the handle to the Xen hypervisor
 * @domain: the domain ID
 *
 * Do an hypervisor call to resume the given domain
 *
 * Returns 0 in case of success, -1 in case of error.
 */
int
262 263
xenHypervisorResumeDomain(int handle, int domain)
{
264 265 266 267 268 269 270 271 272
    dom0_op_t op;
    int ret;

    op.cmd = DOM0_UNPAUSEDOMAIN;
    op.u.unpausedomain.domain = (domid_t) domain;

    ret = xenHypervisorDoOp(handle, &op);

    if (ret < 0)
273 274
        return (-1);
    return (0);
275 276 277 278 279 280 281 282 283 284 285 286
}

/**
 * xenHypervisorDestroyDomain:
 * @handle: the handle to the Xen hypervisor
 * @domain: the domain ID
 *
 * Do an hypervisor call to destroy the given domain
 *
 * Returns 0 in case of success, -1 in case of error.
 */
int
287 288
xenHypervisorDestroyDomain(int handle, int domain)
{
289 290 291 292 293 294 295 296 297
    dom0_op_t op;
    int ret;

    op.cmd = DOM0_DESTROYDOMAIN;
    op.u.destroydomain.domain = (domid_t) domain;

    ret = xenHypervisorDoOp(handle, &op);

    if (ret < 0)
298 299
        return (-1);
    return (0);
300 301
}

302 303 304 305 306 307 308 309 310 311 312
/**
 * xenHypervisorSetMaxMemory:
 * @handle: the handle to the Xen hypervisor
 * @domain: the domain ID
 * @memory: the max memory size in kilobytes.
 *
 * Do an hypervisor call to change the maximum amount of memory used
 *
 * Returns 0 in case of success, -1 in case of error.
 */
int
313 314
xenHypervisorSetMaxMemory(int handle, int domain, unsigned long memory)
{
315 316 317 318 319 320 321 322 323 324
    dom0_op_t op;
    int ret;

    op.cmd = DOM0_SETDOMAINMAXMEM;
    op.u.setdomainmaxmem.domain = (domid_t) domain;
    op.u.setdomainmaxmem.max_memkb = memory;

    ret = xenHypervisorDoOp(handle, &op);

    if (ret < 0)
325 326
        return (-1);
    return (0);
327
}